我正在使用 Eigen 的张量方面C++ 中的库,并希望计算一个特征张量乘以第二个特征张量中元素的标量和的逐元素乘积。像这样的东西:
#include <Eigen/Dense>
Eigen::Tensor<float,2>u(5,5);
Eigen::Tensor<float,2>v(5,5);
u.setConstant(1.f);
v.setConstant(2.f);
Eigen::Tensor<float,2>ans(5,5);
ans = u*v.sum();
但是这种方式不支持 * 运算符。
README建议使用与 Tensor 对象关联的 .constant()
方法。同时
ans = u*u.constant(5.);
auto ans2 = u.sum();
正确编译和运行
ans = u*u.constant(v.sum());
没有。
error: no matching function for call to ‘Eigen::Tensor<float, 2>::constant(const Eigen::TensorReductionOp<Eigen::internal::SumReducer<float>, const Eigen::DimensionList<long int, 2ul>, const Eigen::Tensor<float, 2>, Eigen::MakePointer>)’
ans = u*u.constant(v.sum());
^
从进一步阅读看来,这是因为 u.constant()
期望将标量值传递给它,而 v.sum()
返回一个“非计算表达式”(参见 README 中的 Tensor Operations 和 C++“auto”)。还有进一步的建议,可以使用 .eval()
强制评估 v.sum()
,尽管这似乎返回另一个“未评估的表达式”类型,尽管末尾带有 ForcedEvalOp
标记。
error: no matching function for call to ‘Eigen::Tensor<float, 2>::constant(const Eigen::TensorForcedEvalOp<const Eigen::TensorReductionOp<Eigen::internal::SumReducer<float>, const Eigen::DimensionList<long int, 2ul>, const Eigen::Tensor<float, 2>, Eigen::MakePointer> >)’
ans = u*u.constant(v.sum().eval());
^
README 的 TODO 部分提及:
"标量值的表示: 标量值通常由大小为 1 且秩为 1 的张量表示。使用秩为 0 的张量会更合乎逻辑且对用户更友好。例如 Tensor::maximum() 当前返回一个张量。类似地,2 个一维张量的内积(通过收缩)返回一个一维张量。将来这些操作可能会更新为返回 0d 张量。”
这意味着 v.sum()
应该返回长度为 1 的 1 阶张量。但是通常用于索引的 ()
运算符似乎无法访问其u.constant()
的可用形式的值和:
ans = u*u.constant(v.sum()(0))
同样无法编译。
error: no match for call to ‘(const Eigen::TensorReductionOp<Eigen::internal::SumReducer<float>, const Eigen::DimensionList<long int, 2ul>, const Eigen::Tensor<float, 2>, Eigen::MakePointer>) (int)’
ans = u*u.constant(v.sum()(0));
^
同样
ans = u*u.constant(v.sum().eval()(0))
.
error: no match for call to ‘(const Eigen::TensorForcedEvalOp<const Eigen::TensorReductionOp<Eigen::internal::SumReducer<float>, const Eigen::DimensionList<long int, 2ul>, const Eigen::Tensor<float, 2>, Eigen::MakePointer> >) (int)’
ans = u*u.constant(v.sum().eval()(0));
最佳答案
根据 this exchange ,您应该能够通过分配减少的结果来强制评估:
Eigen::Tensor<float, 0> vSum = v.sum();
这应该适用于您的线路:
ans = u * u.constant(vSum);
原因是,如果您尝试使用 v.sum()
直接调用模板方法 constant
,它将尝试使用声明的返回类型作为 Scalar
,这是行不通的。 Eigen 使用许多复杂的、本质上不透明的类型来最大程度地减少不必要的计算和复制,但也使用了很多模板,因此像在这种情况下那样必须显式强制进行类型转换并不少见。
关于c++ - 如何在 C++ 中将特征张量乘以另一个特征张量的标量和?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52392465/