【发布时间】:2011-11-07 00:44:02
【问题描述】:
我有两个矩阵 A 和 B,我想要得到的是:
trace(A*B)
如果我没记错的话,这叫做Frobenius inner product。
我关心的是效率。我只是担心这种直截了当的方法会首先进行整个乘法(我的矩阵是数千行/列),然后才对产品进行跟踪,而我真正需要的操作要简单得多。有没有一种函数或语法可以有效地做到这一点?
【问题讨论】:
我有两个矩阵 A 和 B,我想要得到的是:
trace(A*B)
如果我没记错的话,这叫做Frobenius inner product。
我关心的是效率。我只是担心这种直截了当的方法会首先进行整个乘法(我的矩阵是数千行/列),然后才对产品进行跟踪,而我真正需要的操作要简单得多。有没有一种函数或语法可以有效地做到这一点?
【问题讨论】:
正确...对元素乘积求和会更快:
n = 1000
A = randn(n);
B = randn(n);
tic
sum(sum(A .* B));
toc
tic
sum(diag(A * B'));
toc
Elapsed time is 0.010015 seconds.
Elapsed time is 0.130514 seconds.
【讨论】:
sum(sum(A.*B)) 避免进行全矩阵乘法
【讨论】:
用向量乘法怎么样?
(A(:)')*B(:)
比较大小为 1000×1000 的 A 和 B 的四个选项:
1.向量内积:A(:)'*B(:)(这个答案)只取了0.0011 sec。
2. 使用元素乘法sum(sum(A.*B))(John 的答案)取了0.0035 sec。
3. Trace trace(A*B')(由OP提议)占用0.054 sec。
4. 对角线sum(diag(A*B')) 的总和(被John 拒绝的选项)占0.055 sec。
重要信息:Matlab 在矩阵/向量积方面非常高效。使用向量内积比高效的逐元素乘法解决方案快 x3 倍。
基准代码 用于提供运行时检查的代码
t=zeros(1,4);
n=1000; % size of matrices
it=100; % average results over XX trails
for ii=1:it,
% random inputs
A=rand(n);
B=rand(n);
% John's rejected solution
tic;
n1=sum(diag(A*B'));
t(1)=t(1)+toc;
% element-wise solution
tic;
n2=sum(sum(A.*B));
t(2)=t(2)+toc;
% MOST efficient solution - using vector product
tic;
n3=A(:)'*B(:);
t(3)=t(3)+toc;
% using trace
tic;
n4=trace(A*B');
t(4)=t(4)+toc;
% make sure everything is correct
assert(abs(n1-n2)<1e-8 && abs(n3-n4)<1e-8 && abs(n1-n4)<1e-8);
end;
t./it
您现在可以在 click 中运行此基准测试。
【讨论】: