2013-02-27 263 views
2

我有两个矩阵:B大小为9x100x51K大小为34x9x100。我想将K(34)全部与B(9)中的每一个相乘,以便得到大小为34x9x100x51的最终矩阵GMatlab:元素3D矩阵乘法

例如:元素G(:,5,60,25)由如下

G(:,5,60,25)=K(:,5,60)*B(5,60,25).

我希望示例有助于明白我想做的事情。 谢谢

回答

0

你可以用嵌套循环做到这一点,尽管它可能不会非常快:

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 

它是一个漫长的一天,我的大脑有点炸,荣誉给任何人谁可以改进这个!

+0

非常感谢您!它工作,而且速度很快。 – Kostas 2013-02-27 01:35:45

+0

@Kostas,然后请投票和/或接受这个答案 – slayton 2013-02-27 02:20:34

+0

@slayton我想出了几个越来越向量化的解决方案,更快(在网上八度测试,因为我目前没有matlab)。如果您想在您的机器上测试它们,您会对所看到的速度差异感到好奇。 – tmpearce 2013-02-27 06:28:25

3

任何时候当你发现自己在matlab中编写嵌套循环时,都有可能使用内置的向量化函数形式加速很多次。代码的结果通常会比较短(但通常对读者来说不太明显,所以请评论您的代码!)。

在这种情况下,是否避免嵌套循环有所作为?绝对!我们去工作吧。 @slayton提供了一个3回路解决方案。我们可以变得更快。

重新说明了一下问题,B有51 9x100矩阵和K有矩阵。对于51x34的每个组合,您希望将来自BK的各个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 

好吧,两个循环正在取得进展。我们可以做得更好吗?那么,让我们认识到,矩阵BK可以沿着适当的维度进行复制,然后一次全部元素相乘。

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); 

那么,解决方案如何比较速度?我测试了八度在线实用程序,并且没有包括生成初始BK矩阵的时间。我确实包括为需要预分配的解决方案预分配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