我试图重新创建以下Python numpy代码:
num_rows, num_cols = data.shape
N = 4
data = data.reshape(N, num_rows/N, num_cols)
在C ++中使用Armadillo矩阵和立方体?如何最有效地完成这项工作。我不认为直接支持调整大小/重塑操作从2d矩阵移动到3d立方体?
答案 0 :(得分:2)
构建此类多维数据集的最快方法是使用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
的生命周期中。这可能很难确保,尤其是在堆上创建a
和c
时。
您还可以通过不使用最后一个参数或将其设置为c
来允许a
复制 true
的数据。这比无副本构造函数花费更多时间,但可能少于从a
数据中分配每个切片,因为此构造函数执行单个批量memcpy
基础数据。
所有这些都取决于@ ewcz答案提出的行与列主要观点。确保您知道重塑时得到的结果,特别是如果您正在使用高级构造函数。
答案 1 :(得分:1)
由于犰狳使用列主要的数据排序(与依赖于行主要排序的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;
}