我正在尝试重新创建以下Python numpy代码:
num_rows, num_cols = data.shape
N = 4
data = data.reshape(N, num_rows/N, num_cols)
如何在C++中使用Armadillo矩阵和立方体进行操作,以最高效的方式完成。我认为直接使用resize/reshape操作无法将2D矩阵转换为3D立方体。
// 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 答案中提出的行 vs. 列主要点的影响。请确保知道重塑时会得到什么,特别是如果您正在使用高级构造函数。由于armadillo使用列优先的数据排序方式(与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;
}
data.reshape(N,num_rows / N,num_cols)
本质上通过将data
的行分成N
组来创建N
个切片。由于armadillo以列优先的方式存储数据,因此这些切片在内存中不会是连续的,需要进行一些"重新洗牌"。构造函数方法适用于像data.reshape(N, num_rows, num_cols/N)
这样的东西,即在"列"空间中拆分矩阵... - ewcz