【发布时间】:2013-02-27 00:55:14
【问题描述】:
我有两个矩阵: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).
我希望这个例子有助于理解我想要做什么。 谢谢
【问题讨论】:
标签: 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).
我希望这个例子有助于理解我想要做什么。 谢谢
【问题讨论】:
标签: matlab
每当您发现自己在 matlab 中编写嵌套循环时,您很有可能使用函数的内置向量化形式加快速度。代码通常也会变得相当短(但通常对读者来说不太清楚,因此请评论您的代码!)。
在这种情况下,避免嵌套循环会有所不同吗?绝对地!让我们开始工作吧。 @slayton 提供了一个 3-loop 解决方案。我们可以变得更快。
稍微重申一下问题,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 在线实用程序,并没有包括生成初始 B 和 K 矩阵的时间。我确实包括了为需要预分配的解决方案预分配 G 矩阵的时间。代码如下。
3 个循环(@slayton 的回答):4.024471 秒
2循环解决方案:1.616120 s
0-loop repmat/bsxfun 解决方案:1.211850 s
0-loop 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
【讨论】:
您可以使用嵌套循环执行此操作,尽管它可能不会非常快:
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
这是漫长的一天,我的大脑有点炸了,感谢任何可以改善这一点的人!
【讨论】: