2

我有两个矩阵:Bwith size9x100x51Kwith size 34x9x100。我想将所有的K(34)与每一个相乘,B(9)以便得到一个G大小为的最终矩阵34x9x100x51

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

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

我希望这个例子有助于理解我想要做什么。谢谢

4

2 回答 2

3

每当您发现自己在 matlab 中编写嵌套循环时,很有可能使用函数的内置向量化形式加快速度。代码通常也会变得相当短(但通常对读者来说不太清楚,所以评论你的代码!)。

在这种情况下,避免嵌套循环会有所不同吗?绝对地!让我们开始工作吧。@slayton 提供了一个三环解决方案。我们可以变得更快。

稍微重述一下这个问题,B有 51 个9x100矩阵和K34个9x100矩阵。对于 的每个组合,您希望将和中的各个矩阵51x34逐元素相乘。9x100BK

逐元素乘法对于 来说是一项很好的工作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);

那么,解决方案如何比较速度呢?我测试了 octave 在线实用程序,并没有包括生成初始值BK矩阵的时间。我确实包括了G为需要预分配的解决方案预分配矩阵的时间。代码如下。

3 个循环(@slayton 的回答):4.024471 s
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    
于 2013-02-27T06:26:45.123 回答
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

这是漫长的一天,我的大脑有点炸了,感谢任何可以改善这一点的人!

于 2013-02-27T01:02:56.410 回答