如何将 std::vector<std::vector<double>> 转换为 torch::Tensor?

7
我有一个`std::vector>`,我想将其转换为libtorch中的`torch::Tensor`。然而,似乎`torch::tensor()`或`torch::from_blob()`不能用于此目的!
我尝试使用`c10::ArrayRef`,并通过执行`c10::ArrayRef>> res(myvecs)`将其用于将数据转换为`torch::Tensor`,但这也似乎无用,因为我找不到一种将其转换为`torch::Tensor`的方法。
在libtorch中如何进行此转换?除了例如以下选项之外,还有哪些选择:
auto tensor = torch::zeros({ 46,85 });
for (size_t i = 0; i < 46; i++)
{
   for (size_t j = 0; j < 85; j++)
   {
       tensor[i][j] = probs[i][j];
   }
}
2个回答

6

最简单的方法是使用简单的std::vector<double>代替向量的向量。您将拥有连续的内存,并且torch::from_blob将起作用(如其他答案中所提到的)。

如果这不可行或不方便,我建议以下解决方法。我假设您的向量是(n,m)矩阵(即所有n个向量都具有相同的大小m):

int n = 5, m = 4;
// Just creating some dummy data for example
std::vector<std::vector<double>> vect(n, std::vector<double>(m, 0)); 
for (int i = 0; i < n; i++)
    for (int j = 0; j < m; j++)
        vect[i][j] = i+j;

// Copying into a tensor
auto options = torch::TensorOptions().dtype(at::kDouble);
auto tensor = torch::zeros({n,m}, options);
for (int i = 0; i < n; i++)
    tensor.slice(0, i,i+1) = torch::from_blob(vect[i].data(), {m}, options);

编辑:如果您无法确保向量将比张量更长寿(因为from_blob不拥有数据,因此在销毁向量时会删除其数据),则可能需要添加对clone的调用。


非常感谢。这个与简单的for循环相比如何?这里有任何并行化/优化吗?还是它们在性能上完全一样? - Hossein
谢谢,我明白了。我完全忘记了 from_blob 这个函数,非常感激。 - Hossein
1
嗯,你需要一个基准来确保这一点,但我相信它应该比手动制作的循环更快。大多数torch操作依赖于BLAS,这比任何手工操作都要高效得多(然而,这是一个非常简单的操作:一个向量复制到另一个向量中,因此在这里BLAS优化并不那么重要)。除此之外,如果你先将2D向量复制到1D向量中,然后再使用from_blob,每个元素就会被复制两次,而不是像我的答案中那样只复制一次。 - trialNerror
谢谢,非常感激。顺便问一下,如果我要将您的向量方法推广到更高维度的向量,例如形状为(1,2,4,6)的向量,那么我该怎么做呢?我应该先将它们展平成1D,然后再使用from_blob吗? - Hossein
1
在这种情况下,简单的概括是循环前三个维度(而不是我这里的一个循环),并像我这样切片。然而,我认为使用向量的向量的向量...会变得非常丑陋,所以你最好考虑使用另一种具有连续内存的数据结构,例如平坦的1D向量。 - trialNerror

3

我没有使用过你提到的任何库,但如果我要猜测,那么这些库可能期望一个连续的数组而不是散布在堆中的小段内存。

因此,将 std::vector<std::vector<double>> 转换为 std::vector<double>,并将 vec.data() 指针传递给 torch

std::vector<double> linearize(const std::vector<std::vector<double>>& vec_vec) {
    std::vector<double> vec;
    for (const auto& v : vec_vec) {
        for (auto d : v) {
            vec.push_back(d);
        }
    }
    return vec;
}

非常感谢您的时间和友善的回复。 - Hossein

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接