Скажем, я хочу умножить a=shape(3, 2, 2) with b=shape(3, 2, 2)
матрицы вместе. С np.einsum
это легко можно выразить как np.einsum("sij,sjk->sil", a, b)
.
Я пытаюсь сделать что-то похожее в Eigen, используя Tensor.contract
, но в лучшем случае я смог создать (3,2,3,2)
форму вывода (см. Вывод c
ниже).
#include <iostream>
#include "third_party/eigen3/unsupported/Eigen/CXX11/Tensor"
int main(void)
{
// np.einsum("sij,sjk->sik")
Eigen::DefaultDevice my_device;
Eigen::Tensor<float, 3> a(3, 2, 2);
Eigen::Tensor<float, 3> b(3, 2, 2);
Eigen::array<Eigen::IndexPair<int>,1> dims = {Eigen::IndexPair<int>(2, 1)};
a.setConstant(1);
b.setConstant(2);
Eigen::Tensor<float, 4> c(3, 2, 3, 2);
Eigen::Tensor<float, 3> d(3, 2, 2);
Eigen::array<int, 1> reduce_dims({2});
c.device(my_device) = a.contract(b, dims);
d.device(my_device) = a.contract(b, dims).sum(reduce_dims);
std::cout << c << std::endl;
std::cout << d << std::endl;
}
Вопросы
Кажется, что contract
и reduce
должны быть объединены, чтобы произвести поведение einsum. Это правильно?
Это простой случай, но я хочу в конечном итоге выполнить более сложное поведение, аналогичное суммированию по Эйнштейну. Что-то с эффектом np.einsum("stacij,tacjk, tckl->tacil")
. Разумно ли использовать контракт Эйгена и сокращать его для достижения этого?
Размеры ijkl будут максимум 4, тогда как остальные размеры будут намного больше. Будет Eigen хорошо работать с этими размерами размеров.