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 s
2回路解决方案: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)。如果你想在你的机器上测试它们,你会对你看到的速度差感到好奇。