Как мне получить вектор из среза Tensor в Eigen 3? - PullRequest
0 голосов
/ 05 февраля 2019

Я рву свои волосы, пытаясь получить доступ к столбцу данных в Eigen::Tensor<double, 3> как Eigen::VectorXd.

Нарезка, , согласно этому ответу , работает нормальночтобы получить мне колонку, которую я хочу.Но тогда я не могу присвоить это вектору.

Что у меня есть:

Eigen::Tensor<double, 3> my_tens(2, 3, 4);
my_tens.setRandom();

Eigen::array<Eigen::Index, 3> dims = my_tens.dimensions();

Eigen::array<Eigen::Index, 3> offsets = {0, 1, 0};
Eigen::array<Eigen::Index, 3> extents = {dims[0], 1, 1};

// This works perfectly, and is exactly the column I want:
std::cout << my_tens.slice(offsets, extents);

// ... and I want it as a VectorXd, so:
Eigen::VectorXd my_vec(dims[0]);

Следующие вещи, которые я пробовал, НЕИСПРАВНЫ:

// Direct assignment (won't compile, no viable overloaded '=')
my_vec = my_tens.slice(offsets, extents);

// Initialisation (won't compile, no viable overloaded '<<')
my_vec << my_tens.slice(offsets, extents);

// Same problem with reshaping:
g_a = signature_a.g.slice(offsets, extents).reshape(Eigen::array<Eigen::Index, 2>{dims[0], 1});

// Converting the base (won't compile, no member 'matrix')
my_vec << my_tens.slice(offsets, extents).matrix();

Я также попытался сопоставить как в этом ответе , но это тоже не работает ( РЕДАКТИРОВАТЬ: я думал, что это было связано с упорядочением хранилища, но на самом деле из-за неправильного смещения, см. Мой ответ):

// This produces a part of a row of the tensor, not a column. Gah!
auto page_offset = offsets[2] * dims[0] * dims[1];
auto col_offset = offsets[1] * dims[0];
auto bytes_offset = sizeof(double) * (page_offset + col_offset)
Eigen::Map<Eigen::VectorXd> my_mapped_vec(my_tens.data() + bytes_offset, dims[0]);

Неужели это действительно сложно, или я что-то упустил? Спасибо за любую помощь!

1 Ответ

0 голосов
/ 05 февраля 2019

Ответил на мой вопрос: да, я упустил что-то простое.Сравнивая, какие числа я получил из операции Map, я понял, что смещения были в 8 раз больше;т.е. на sizeof(double).

Я не понял, что операция my_tens.data() + bytes_offset принимает my_tens.data(), const double *, и вместо добавления фиксированного числа байтов для смещения указателя, смещает его наэто количество элементов.

Вот правильный код:

Eigen::Tensor<double, 3> my_tens(2, 3, 4);
my_tens.setRandom();
Eigen::array<Eigen::Index, 3> dims = my_tens.dimensions();
Eigen::array<Eigen::Index, 3> offsets = {0, 1, 0};
Eigen::array<Eigen::Index, 3> extents = {dims[0], 1, 1};

// Compute the offset, correctly this time!
auto page_offset = offsets[2] * dims[0] * dims[1];
auto col_offset = offsets[1] * dims[0];
auto elements_offset = page_offset + col_offset;

// Map into the array
Eigen::Map<Eigen::VectorXd> my_mapped_vec(my_tens.data() + elements_offset, dims[0]);

// Compare the two:
std::cout << my_tens.slice(offsets, extents) << std::endl;
std::cout << my_mapped_vec.transpose() << std::endl;
...