c++ - 如何对特征张量执行某些操作?
问题描述
我需要对特征张量执行某些操作。但我没有找到任何示例或文档。
我有两个张量:
Eigen::Tensor<float,3> feature_buffer(K,45,7); 特征缓冲区.setZero();
VectorXi number_buffer(K);
我需要对张量执行以下操作。
feature_buffer[:, :, -3:] = feature_buffer[:, :, :3] - \
feature_buffer[:, :, :3].sum(axis=1, keepdims=True)/number_buffer.reshape(K, 1, 1)
上面的代码是numpy代码。我做了一切,但我被困在最后一步。
有人可以帮我吗?我被这一整天困住了。
提前致谢
解决方案
我相信numpy
- 操作在尺寸不匹配的两个地方是不合适的。我对numpy ndarray
操作不是很熟悉,所以这可能是我的一个简单的误解,但如果操作成功,我的猜测是numpy
当某些维度匹配时可以做出有根据的猜测......
也就是说,我了解了您要完成的工作的要点,因此我逐步在下面写下了等效的 C++ 代码。我冒昧地重新解释了操作以使尺寸正确匹配:最后,如果它不是完全相同的操作,我希望只是阅读语法可以解决问题。
#include <unsupported/Eigen/CXX11/Tensor>
int main(){
long d0 = 10; // This is "K"
long d1 = 10;
long d2 = 10;
Eigen::Tensor<float,3> feature_buffer(d0,d1,d2);
Eigen::Tensor<float,1> number_buffer(d0);
feature_buffer.setRandom();
number_buffer.setRandom();
// Step 1) Define numpy "feature_buffer[:,:,-3:]" in C++
std::array<long,3> offsetA = {0, 0, d2-3};
std::array<long,3> extentA = {d0,d1,3};
auto feature_sliceA = feature_buffer.slice(offsetA,extentA);
// Note: feature_sliceA is a "slice" object: it does not own the data in feature_buffer,
// it merely points to a rectangular subregion inside of feature_buffer.
// If you'd rather make a copy of that data, replace "auto" with "Eigen::Tensor<float,3>".
// Step 2) Define numpy "feature_buffer[:, :, :3]" in C++
std::array<long,3> offsetB = {0, 0, 0};
std::array<long,3> extentB = {d0,d1,3};
auto feature_sliceB = feature_buffer.slice(offsetA,extentA);
// Step 3) Perform the numpy operation "feature_buffer[:, :, :3].sum(axis=1, keepdims=True)"
std::array<long,1> sumDims = {1};
std::array<long,3> newDims = {d0,1,3}; // This takes care of "keepdims=True": d1 is summed over, then kept as size 1.
Eigen::Tensor<float,3> feature_sum = feature_sliceB.sum(sumDims).reshape(newDims);
// Step 4) The numpy division "feature_buffer[:, :, :3].sum(axis=1, keepdims=True)/number_buffer.reshape(K, 1, 1)"
// looks ill-formed: There are fewer elements in [:, :, :3] than in number_buffer.reshape(K, 1, 1).
// To go head, we could interpret this as dividing each of the 3 "columns" (in dimension 2) by number_buffer:
// Something like: "feature_sum/number_buffer.reshape(d0, 1, 3)"
std::array<long,3> numBcast = {1,1,3};
std::array<long,3> numDims = {d0,1,1};
Eigen::Tensor<float,3> number_bcast = number_buffer.reshape(numDims).broadcast(numBcast);
// Step 5) Perform the division operation
Eigen::Tensor<float,3> feature_div = feature_sum/number_bcast;
// Step 6) Perform the numpy subtraction
// "feature_buffer[:, :, :3] - feature_buffer[:, :, :3].sum(axis=1, keepdims=True)/number_buffer.reshape(K, 1, 1)
// in our current program this corresponds to
// "feature_sliceB - feature_div"
// Actually, this is also ill-formed, since:
// feature_sliceB has dimensions (d0, d1, 3) = (10, 10, 3)
// feature_div has dimensions (d0, 1, 3) = (10, 1, 3)
//
// To go ahead we can reinterpret once again: Assume the subtraction happens once for each dimension 1.
// We use broadcast again to copy the contents of feature_div d1 times along dimension 1
std::array<long,3> divBcast = {1,10,1};
Eigen::Tensor<float,3> feature_div_bcast = feature_div.broadcast(divBcast);
// Step 7) Perform the main assignment operation
feature_sliceA = feature_sliceB - feature_div_bcast;
}
您可以在godbolt上看到相同的代码。
我根本没有考虑这里的表现。我相信你能找到更好的方法来整齐地写这个。
推荐阅读
- xamarin.forms - 调试器在解析 Rest API 响应 HttpClient、Xamarin Forms 时停止
- wordpress - 如何延迟wordpress中的自动播放?
- strophe - XMPP:如何查询特定名册的存在
- angular - ng 服务给出错误找不到模块“@angular-devkit/bsudouild-angular”
- javascript - 如何用其他东西替换字符串
- operating-system - 为什么CPU生成的地址称为“逻辑”地址?
- php - 如何在表格下设置 Php 标记以将字体大小设置为 x-large
- python - 定义一个用于定位两种类型 trs 的选择器时遇到问题
- python - 通过for循环构建dict而不重复
- laravel - 使用 Laravel 路由器主宰 vue 路由器