如何在Matlab中将矩阵A的每列乘以矩阵B的每行并求和?

6
我希望您能轻松解决我的问题。A是一个NG矩阵,B是NG矩阵。目标是获得矩阵C,如下所示: enter image description here 其中,矩阵C等于将转置的矩阵A的每一列与矩阵B的每一行相乘,并对结果矩阵求和;在求和之前,这样的矩阵总数为NN,它们的大小为GG。在MatLab中,可以通过两个for循环轻松完成此操作。
N=5;
G=10;
A=rand(N,G);
B=rand(N,G);
C=zeros(G);
for n=1:1:N
    for m=1:1:N
        C=C+A(m,:)'*B(n,:);
    end
end

然而,对于大型矩阵来说,这种方法非常缓慢。

因此,我的问题是: 在Matlab中有更有效的计算C矩阵的方法吗?

谢谢


2
对于良好表达、可工作的问题和自包含代码,给予+1。 - Luis Mendo
对于N=2;G=2;A=[1 2; 3 4];B=[5 6; 7 8];我的代码返回C=[48 56;72 84]和A'*B=[26 30;38 44]A'*B等于单一求和sum_{n} A_{ni}B_{nk},而不是我需要的双重求和sum_{m,n} A_{mi}B_{nk}。 - iVanguard
3个回答

7
如果你把两个3×3矩阵全部列出来,你会发现这个操作基本上等于这个:
C = bsxfun(@times, sum(B), sum(A).');

针对每个答案,分别在N=50G=100时运行,并重复每种方法100次:

Elapsed time is 13.839893 seconds. %// OP's original method
Elapsed time is 19.773445 seconds. %// Luis' method
Elapsed time is 0.306447 seconds.  %// Robert's method
Elapsed time is 0.005036 seconds.  %// Rody's method

(最快和最慢方法之间的比例约为4000倍...)

非常感谢,它起作用了。真是丢人,我自己没看到。 - iVanguard
+1 想得真好!分配律在这种情况下大大减少了操作次数。 - Luis Mendo

3

我认为这应该显著提高性能

C = zeros(G);
for n = 1:N
   C = C + sum(A,1)'*B(n,:);
end

你可以避免一次循环,还应该避免内存不足的问题。根据我的基准测试,这种方法比使用两个循环的方法快约20倍。(请注意,由于我在这台电脑上没有MATLAB,所以我必须在Octace中进行基准测试)。

2

使用bsxfun代替循环,然后两次使用sum:

C = sum(sum(bsxfun(@times, permute(A, [2 3 1]), permute(B,[3 2 4 1])), 3), 4);

@Adiel 关于arrayfun,我同意。但是关于bsxfun,我不太认同。 - Luis Mendo
谢谢您的回答,我已经检查过了,对于小的N和G它运行得很好。然而,对于G=1000和N=100(这比我的实际矩阵还要小),我已经超出了系统内存。 - iVanguard
@RodyOldenhuis 是的,我按照OP的描述文字进行了操作(先乘后加)。我没有意识到像你的答案一样先加再乘可以节省很多内存和操作。 - Luis Mendo

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接