在 MATLAB 中将 3 维数组操作为 2 维数组的有效方法
Efficient way to manipulate 3 dimensional array to 2 dimensional array in MATLAB
假设A是n_1乘n_1对称矩阵,B是n_2乘n_2对称矩阵,一般是n_1 > n_2 和 n_1 是从 10^3 到 10^5。我想通过 (n_1*n_2) 矩阵 C 得到以下 (n_1*n_2) 使得 C 的每个块都是 C_{ij}=\exp (A\text{.^}2/B_{i,j}^{1.5})/B_{i,j} 其中 i=1, ..., n_2; j=1,...,n_2。
我有两种方法可以在 MATLAB 中计算它,但这两种方法都不能给我令人满意的计时。下面我将给出一个最小的 MATLAB 代码示例。
n1 = 400; n2 = 15;
A = randn(n1); A = A + A' + 10*eye(n1);
B = randn(n2); B = B + B' + 5*eye(n2);
一种方式:
tic;
Atemp = repmat(A, n2, n2);
Btemp = kron(B, ones(n1));
C1 = exp(Atemp.^2./Btemp.^1.5)./Btemp;
toc;
Elapsed time is 2.402167 seconds.
另一种方式:
tic;
Btemp = reshape(B, [1 1 n2*n2]);
Ctemp = bsxfun(@(x,y) exp(x.^2/y.^1.5)/y, A, Btemp);
[a, b, c] = size(Ctemp);
Ctemp = reshape(mat2cell(Ctemp, a, b, ones(c,1)), sqrt(c), sqrt(c));
C2 = cell2mat(Ctemp);
toc;
Elapsed time is 2.923428 seconds.
我想知道在MATLAB中是否有更有效的方法来获取矩阵C? cholesky 分解需要生成的矩阵 C。
顺便说一句,在第二种方法中,必须有更有效的方法(即避免将 Ctemp 转换为单元格,然后将单元格转换为 C2)将 3 维数组 Ctemp 转换为二维数组 C2,但我想不通现在出来了。
非常感谢!
bsxfun
通常没有您预期的那么快。 Cell/mat 重塑也需要一些时间。所以你的第一种方法更好。但是 Atemp.^2./Btemp.^1.5
可以简化为 kron(1./(B.^1.5), A.^2)
以避免一些大的时间矩阵并提高速度。
这是修改后的代码和我机器上的时间。
n1 = 400; n2 = 15;
A = randn(n1); A = A + A' + 10*eye(n1);
B = randn(n2); B = B + B' + 5*eye(n2);
tic;
Btemp = kron(B, ones(n1));
C0 = exp(kron(1./(B.^1.5), A.^2))./Btemp;
toc;
tic;
Atemp = repmat(A, n2, n2);
Btemp = kron(B, ones(n1));
C1 = exp(Atemp.^2./Btemp.^1.5)./Btemp;
toc;
tic;
Btemp = reshape(B, [1 1 n2*n2]);
Ctemp = bsxfun(@(x,y) exp(x.^2/y.^1.5)/y, A, Btemp);
toc;
tic;
[a, b, c] = size(Ctemp);
Ctemp = reshape(mat2cell(Ctemp, a, b, ones(c,1)), sqrt(c), sqrt(c));
C2 = cell2mat(Ctemp);
toc;
Elapsed time is 0.426900 seconds.
Elapsed time is 0.900966 seconds.
Elapsed time is 2.850293 seconds.
Elapsed time is 0.706957 seconds.
假设A是n_1乘n_1对称矩阵,B是n_2乘n_2对称矩阵,一般是n_1 > n_2 和 n_1 是从 10^3 到 10^5。我想通过 (n_1*n_2) 矩阵 C 得到以下 (n_1*n_2) 使得 C 的每个块都是 C_{ij}=\exp (A\text{.^}2/B_{i,j}^{1.5})/B_{i,j} 其中 i=1, ..., n_2; j=1,...,n_2。
我有两种方法可以在 MATLAB 中计算它,但这两种方法都不能给我令人满意的计时。下面我将给出一个最小的 MATLAB 代码示例。
n1 = 400; n2 = 15;
A = randn(n1); A = A + A' + 10*eye(n1);
B = randn(n2); B = B + B' + 5*eye(n2);
一种方式:
tic;
Atemp = repmat(A, n2, n2);
Btemp = kron(B, ones(n1));
C1 = exp(Atemp.^2./Btemp.^1.5)./Btemp;
toc;
Elapsed time is 2.402167 seconds.
另一种方式:
tic;
Btemp = reshape(B, [1 1 n2*n2]);
Ctemp = bsxfun(@(x,y) exp(x.^2/y.^1.5)/y, A, Btemp);
[a, b, c] = size(Ctemp);
Ctemp = reshape(mat2cell(Ctemp, a, b, ones(c,1)), sqrt(c), sqrt(c));
C2 = cell2mat(Ctemp);
toc;
Elapsed time is 2.923428 seconds.
我想知道在MATLAB中是否有更有效的方法来获取矩阵C? cholesky 分解需要生成的矩阵 C。
顺便说一句,在第二种方法中,必须有更有效的方法(即避免将 Ctemp 转换为单元格,然后将单元格转换为 C2)将 3 维数组 Ctemp 转换为二维数组 C2,但我想不通现在出来了。
非常感谢!
bsxfun
通常没有您预期的那么快。 Cell/mat 重塑也需要一些时间。所以你的第一种方法更好。但是 Atemp.^2./Btemp.^1.5
可以简化为 kron(1./(B.^1.5), A.^2)
以避免一些大的时间矩阵并提高速度。
这是修改后的代码和我机器上的时间。
n1 = 400; n2 = 15;
A = randn(n1); A = A + A' + 10*eye(n1);
B = randn(n2); B = B + B' + 5*eye(n2);
tic;
Btemp = kron(B, ones(n1));
C0 = exp(kron(1./(B.^1.5), A.^2))./Btemp;
toc;
tic;
Atemp = repmat(A, n2, n2);
Btemp = kron(B, ones(n1));
C1 = exp(Atemp.^2./Btemp.^1.5)./Btemp;
toc;
tic;
Btemp = reshape(B, [1 1 n2*n2]);
Ctemp = bsxfun(@(x,y) exp(x.^2/y.^1.5)/y, A, Btemp);
toc;
tic;
[a, b, c] = size(Ctemp);
Ctemp = reshape(mat2cell(Ctemp, a, b, ones(c,1)), sqrt(c), sqrt(c));
C2 = cell2mat(Ctemp);
toc;
Elapsed time is 0.426900 seconds.
Elapsed time is 0.900966 seconds.
Elapsed time is 2.850293 seconds.
Elapsed time is 0.706957 seconds.