我有两个矩阵:B
大小为9x100x51
和K
大小为34x9x100
。我想将K(34)
全部与B(9)
中的每一个相乘,以便得到大小为34x9x100x51
的最终矩阵G
。Matlab:元素3D矩阵乘法
例如:元素G(:,5,60,25)
由如下
G(:,5,60,25)=K(:,5,60)*B(5,60,25).
我希望示例有助于明白我想做的事情。 谢谢
我有两个矩阵:B
大小为9x100x51
和K
大小为34x9x100
。我想将K(34)
全部与B(9)
中的每一个相乘,以便得到大小为34x9x100x51
的最终矩阵G
。Matlab:元素3D矩阵乘法
例如:元素G(:,5,60,25)
由如下
G(:,5,60,25)=K(:,5,60)*B(5,60,25).
我希望示例有助于明白我想做的事情。 谢谢
你可以用嵌套循环做到这一点,尽管它可能不会非常快:
B = rand(9,100,51);
K = rand(34,9,100);
G = nan(34,9,100,51)
for ii = 1:size(B,1)
for jj = 1:size(B,2);
for kk = 1:size(B,3)
G(:, ii, jj, kk) = K(:,ii,jj) .* B(ii,jj,kk);
end
end
end
它是一个漫长的一天,我的大脑有点炸,荣誉给任何人谁可以改进这个!
任何时候当你发现自己在matlab中编写嵌套循环时,都有可能使用内置的向量化函数形式加速很多次。代码的结果通常会比较短(但通常对读者来说不太明显,所以请评论您的代码!)。
在这种情况下,是否避免嵌套循环有所作为?绝对!我们去工作吧。 @slayton提供了一个3回路解决方案。我们可以变得更快。
重新说明了一下问题,B
有51 9x100
矩阵和K
有矩阵。对于51x34
的每个组合,您希望将来自B
和K
的各个9x100
矩阵按元素方式相乘。
逐元素乘法是bsxfun
一项伟大的工作,所以我们可以在概念上减少这种问题沿两个维度(的B
第三个维度的K
第一维)工作:
初始,双回路解决方案:
B = rand(9,100,51);
K = rand(34,9,100);
G = nan(34,9,100,51);
for b=1:size(B,3)
for k=1:size(K,1)
G(k,:,:,b) = bsxfun(@times,B(:,:,b), squeeze(K(k,:,:)));
end
end
好吧,两个循环正在取得进展。我们可以做得更好吗?那么,让我们认识到,矩阵B
和K
可以沿着适当的维度进行复制,然后一次全部元素相乘。
B = rand(9,100,51);
K = rand(34,9,100);
B2 = repmat(permute(B,[4 1 2 3]), [size(K,1) size(B)]);
K2 = repmat(K, [size(K) size(B,3)]);
G = bsxfun(@times,B2,K2);
那么,解决方案如何比较速度?我测试了八度在线实用程序,并且没有包括生成初始B
和K
矩阵的时间。我确实包括为需要预分配的解决方案预分配G
矩阵的时间。代码如下。
3环(@斯雷顿的回答):4.024471小号
2环溶液:1.616120小号
0环repmat/bsxfun溶液:1.211850小号
0环repmat/bsxfun溶液,没有临时对象:0。605838 s
警告:时机可能取决于您的机器,我不会相信在线实用程序进行大时间测试。改变循环执行的顺序(即使注意不要重复使用变量并弄乱分配时间)确实改变了一点,即2循环解决方案有时与临时存储的无循环解决方案一样快。然而,你能得到的矢量化越多,你就会越好。
下面的代码的速度测试:
B = rand(9,100,51);
K = rand(34,9,100);
tic
G1 = nan(34,9,100,51);
for ii = 1:size(B,1)
for jj = 1:size(B,2);
for kk = 1:size(B,3)
G1(:, ii, jj, kk) = K(:,ii,jj) .* B(ii,jj,kk);
end
end
end
t=toc;
printf('Time for 3 loop solution: %f\n' ,t)
tic
G2 = nan(34,9,100,51);
for b=1:size(B,3)
for k=1:size(K,1)
G2(k,:,:,b) = bsxfun(@times,B(:,:,b), squeeze(K(k,:,:)));
end
end
t=toc;
printf('Time for 2 loop solution: %f\n' ,t)
tic
B2 = repmat(permute(B,[4 1 2 3]), [size(K,1) 1 1 1]);
K2 = repmat(K, [1 1 1 size(B,3)]);
G3 = bsxfun(@times,B2,K2);
t=toc;
printf('Time for 0-loop repmat/bsxfun solution: %f\n' ,t)
tic
G4 = bsxfun(@times,repmat(permute(B,[4 1 2 3]), [size(K,1) 1 1 1]),repmat(K, [1 1 1 size(B,3)]));
t=toc;
printf('Time for 0-loop repmat/bsxfun solution, no temporaries: %f\n' ,t)
disp('Are the results equal?')
isequal(G1,G2)
isequal(G1,G3)
Time for 3 loop solution: 4.024471
Time for 2 loop solution: 1.616120
Time for 0-loop repmat/bsxfun solution: 1.211850
Time for 0-loop repmat/bsxfun solution, no temporaries: 0.605838
Are the results equal?
ans = 1
ans = 1
非常感谢您!它工作,而且速度很快。 – Kostas 2013-02-27 01:35:45
@Kostas,然后请投票和/或接受这个答案 – slayton 2013-02-27 02:20:34
@slayton我想出了几个越来越向量化的解决方案,更快(在网上八度测试,因为我目前没有matlab)。如果您想在您的机器上测试它们,您会对所看到的速度差异感到好奇。 – tmpearce 2013-02-27 06:28:25