如何利用Matlab高效地计算矩阵项
我有一个稀疏矩阵的单元格数组,如何利用Matlab高效地计算矩阵项,matlab,Matlab,我有一个稀疏矩阵的单元格数组,mybase,B_n 我想用Matlab计算矩阵Q(I,j)=trace(B^T_I*B_j) 因此,我编写了以下代码: for i=1:n for j=1:n B=myBasis{i}; C=myBasis{j}; Q(i,j)=trace(B'*C); end end 当n=1226和B_i有50行和50列时,这已经需要68秒 有没有加快速度的机会?通常我在C++文件中从MA
mybase
,B_n
我想用Matlab计算矩阵Q(I,j)=trace(B^T_I*B_j)
因此,我编写了以下代码:
for i=1:n
for j=1:n
B=myBasis{i};
C=myBasis{j};
Q(i,j)=trace(B'*C);
end
end
当n=1226
和B_i
有50行和50列时,这已经需要68秒
有没有加快速度的机会?通常我在C++文件中从MATLAB代码中排除循环,但是我没有经验处理C++中的稀疏单元数组。 < P>,有几个想法 1) 基本材料:A'*B=(B'*A')和trace(A)=trace(A')。好吧,只有这个技巧能让你的计算量减少近50%。你的Q(i,j)矩阵是对称的,你只需要计算n(n+1)/2项(而不是n²) 2) 要计算轨迹,不需要计算B'*C的每一项,只需计算对角线。然而,我不知道在Matlab中创建一个脚本是否容易,它实际上比计算B'*C更快(Matlab在矩阵运算中相当快) 但我肯定会实施(1)
Q
所指出的,Q是对称的,因此您只需要显式地计算一半的条目trace(B.*C)
相当于B(:)。*C(:)
:trace(B.*C)
=sum_i[B.*C]\u ii
=sum_i sum_j B_ij*C_ij
它是元素乘积的总和,因此相当于B(:).*C(:)
当显式计算
trace(B.*C)
时,实际上是预先计算B.*C
的所有k-by-k条目,只是为了以后使用对角线。恕我直言,Matlab不会优化其计算以避免计算所有条目李>
有个办法
for ii = 1:n
B = myBasis{ii};
for jj = ii:n
C = myBasis{jj};
t = full( B(:).'*C(:) ); % equivalent to trace(B'*C)!
Q(ii,jj) = t;
Q(jj,ii) = t;
end
end
PS,这是最好的 PPS,
您应该注意到,Matlab中的运算符不是矩阵转置,但对于实际转置,您需要使用。在大多数情况下,不涉及复数,两个运算符之间也没有区别,但一旦引入复杂数据,两个运算符之间的混淆会使调试变得非常混乱……您可以尝试parfor并并行运行循环。实际上,这可能是C++中实现的一个不错的练习。@ PruttKek实际上我想在12800000000个Matrix上运行我的脚本,其中每个矩阵有400行、400列,最多405条。因此,我认为我应该使用稀疏矩阵。即使存储12800000个8字节的数字,也需要95TB的存储空间,这在我看来是胡说八道opinion@patrik我只是注意到我的计算错误不是12800000000,而是80000。对此很抱歉。您必须使用
full(t)
使其与跟踪的matlab实现相等trace
再次将t
转换为完整矩阵。这可能也是一个时间窃贼@亚当,你确定这里需要稀疏矩阵吗?1226*50*50是300万个元素。对于double,它意味着略小于30Mb。这还不错。是的,但myBasis只是一个1D数组,临时存储其他元素不会造成严重损坏。所以我想是1226*50*50。如果我遗漏了什么,请纠正我。@patrik,我收回它。感谢的完整评论。您可以直接评论有关将其全部转换为完整的问题。@Shai您确定这也适用于稀疏矩阵吗?我不明白为什么我需要全权指挥。Sry-我现在知道了。@Adam您只需要完整的结果-这是一个标量。代表性的东西。你可以不用它试试。