Matlab:元素三维矩阵乘法
我有两个矩阵:Matlab:元素三维矩阵乘法,matlab,Matlab,我有两个矩阵:B大小9x100x51和K大小34x9x100。我想将所有的K(34)与B(9)中的每一个相乘,从而得到一个大小为34x9x100x51的最终矩阵G 例如:元素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)
B
大小9x100x51
和K
大小34x9x100
。我想将所有的K(34)
与B(9)
中的每一个相乘,从而得到一个大小为34x9x100x51
的最终矩阵G
例如:元素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中编写嵌套循环时,很有可能使用内置的向量化函数形式来提高速度。代码通常也会缩短一点(但读者往往不太清楚,所以请评论您的代码!) 在这种情况下,避免嵌套循环是否会有所不同?绝对地让我们开始工作吧@斯莱顿提供了一个三回路解决方案。我们可以更快 稍微重复一下这个问题,
B
有51个9x100
矩阵,K
有34个9x100
矩阵。对于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);
那么,这些解决方案在速度方面如何比较?我在octave online实用程序上测试了,没有包括生成初始B
和K
矩阵的时间。我确实包括了为需要预先分配的解决方案预先分配G
矩阵的时间。代码如下
3圈(@slayton的回答):4.024471 s2回路解决方案:1.616120秒
0-loop repmat/bsxfun解决方案:1.211850秒
0-loop repmat/bsxfun解决方案,无临时值:0.605838秒 警告:计时可能在很大程度上取决于您的机器,我不相信在线实用程序可以进行出色的计时测试。改变循环执行的顺序(甚至注意不要重用变量和弄乱分配时间)确实会改变一些事情,即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
@slayton我提出了两个速度更快的矢量化解决方案(在octave online上测试,因为我目前没有matlab)。如果你想在你的机器上测试它们,你会对你看到的速度差感到好奇。