如何将犰狳矩阵转换为立方体?

Posted

技术标签:

【中文标题】如何将犰狳矩阵转换为立方体?【英文标题】:How do I convert an Armadillo matrix to cube? 【发布时间】:2018-02-07 16:28:12 【问题描述】:

我正在尝试重新创建以下 Python numpy 代码:

num_rows, num_cols = data.shape
N = 4
data = data.reshape(N, num_rows/N, num_cols)

在 C++ 中使用犰狳矩阵和立方体?怎样才能最有效地做到这一点。我不认为直接支持从 2d 矩阵移动到 3d 立方体的调整大小/重塑操作?

【问题讨论】:

【参考方案1】:

构造这种立方体的最快方法是使用advanced constructors 之一。这些允许您直接从内存的任意部分创建新对象,即使不复制任何数据。这在本质上最接近 NumPy 进行重塑的方式,其中返回原始数据的视图,而不是副本。

你会像这样使用构造函数:

// Assuming a is an arma::mat.
int N = 4;
arma::cube c(a.memptr(), N, a.n_rows / N, a.n_cols, false);

这直接从a获取内存,无需复制,将其用作c的数据。

当然,这很快,但很危险。只要c 存在,您就有责任保证指向的内存是有效的。这意味着c 的生命周期必须严格嵌套在a 的生命周期中。这很难确保,尤其是当ac 都在堆上创建时。

您还可以允许c 复制 a 的数据,方法是省略最后一个参数或将其设置为true。这比无复制构造函数花费更多时间,但可能比从 a 的数据分配每个切片要少,因为此构造函数对基础数据执行单个批量 memcpy

所有这些都取决于@ewcz 的回答提出的行与列的主要观点。确保您知道在重塑时会得到什么,尤其是在您使用高级构造函数时。

【讨论】:

使用构造函数很诱人,但我认为它在这种情况下不适用-data.reshape(N, num_rows/N, num_cols) 本质上是通过将data 的行划分为N 组来创建N 切片.由于犰狳以列为主的方式存储数据,这样的切片在内存中不会是连续的,需要做一些“重新洗牌”。构造函数方法适用于data.reshape(N, num_rows, num_cols/N) 之类的东西,即将矩阵拆分为“列”空间... @tangy 这就是我最后评论的重点。您需要处理原始数组的转置,因为 Armadillo 使用列优先排序,而 NumPy 使用行优先。但是如果你知道如何通过切片来得到你想要的东西,这个构造函数会明显更快。 我确实尝试过 - 我转置了矩阵,然后从上面应用了代码 - 它仍然不起作用。事实上,基于与犰狳相关的其他一些答案,我早些时候尝试过这种方法,无论是否有转置 - 都不起作用【参考方案2】:

由于犰狳使用数据的列主要排序(与依赖行主要排序的 numpy 相比),只需将矩阵放入具有 1 个切片的立方体中并对其进行整形将产生不同的结果(下面的矩阵 B)。另一种方法可能是手动构造切片:

#include <iostream>
#include <armadillo>

int main()

    const arma::uword N = 2;
    const arma::uword num_rows = 4;
    const arma::uword num_cols = 3;

    arma::mat A(num_rows, num_cols, arma::fill::randu);

    std::cout << A;

    arma::cube B(num_rows, num_cols, 1);
    B.slice(0) = A;
    B.reshape(num_rows/N, num_cols, N);
    std::cout << B;

    arma::cube C(num_rows/N, num_cols, N);
    for(arma::uword i = 0; i < N; ++i)
        C.slice(i) = A.rows(i*N, (i+1)*N-1);
    
    std::cout << C;


    return 0;

【讨论】:

考虑到为此付出的努力,我几乎觉得最好使用 2d 矩阵本身。这就是为什么我刚刚将我的 3d 切片操作转换为 2d 本身。

以上是关于如何将犰狳矩阵转换为立方体?的主要内容,如果未能解决你的问题,请参考以下文章

犰狳中是不是有类似稀疏立方体的东西,或者使用稀疏矩阵作为立方体中的切片的某种方式?

在犰狳中对立方体切片进行操作

如何将向量转换为犰狳矩阵?

使用 RcppArmadillo 时无法加载犰狳立方体<uword>

犰狳错误的字段索引

将二维数组转换为犰狳矩阵(垫)对象