优化MATLAB代码(嵌套循环计算相似矩阵)



我正在MATLAB中计算基于欧几里得距离的相似矩阵。我的代码如下:

for i=1:N % M,N is the size of the matrix x for whose elements I am computing similarity matrix
 for j=1:N
  D(i,j) = sqrt(sum(x(:,i)-x(:,j)).^2)); % D is the similarity matrix
 end
end

我的矩阵x的维数是256x30000,我能帮我优化这个=减少for循环吗?

非常感谢!

——Aditya

在matlab中执行此操作的函数称为pdist。不幸的是,它非常慢,并且没有考虑到matlab的矢量化能力。

下面是我为一个项目写的代码。让我知道你得到了什么样的加速。

   Qx=repmat(dot(x,x,2),1,size(x,1));
   D=sqrt(Qx+Qx'-2*x*x');

请注意,只有当数据点在行中,维度在列中时,这才有效。例如,假设我有256个数据点和100000个维度,然后在我的mac上使用x=rand(256,100000),上面的代码在大约半秒内生成一个256x256的矩阵。

可能有更好的方法来做到这一点,但我注意到的第一件事是,你可以通过利用对称性D(i,j)==D(i,j)

将运行时间减半。

您也可以使用norm(x(:,i)-x(:,j),2)

函数

我想这就是你要找的。

D=zeros(N);    
jIndx=repmat(1:N,N,1);iIndx=jIndx'; %'# fix SO's syntax highlighting
D(:)=sqrt(sum((x(iIndx(:),:)-x(jIndx(:),:)).^2,2));

在这里,我假设距离向量x被初始化为NxM数组,其中M是系统的维数,N是点的数量。因此,如果您的排序不同,则必须进行相应的更改。

首先,您计算的量是这里需要的两倍,因为D将是对称的。你不需要分别计算(i,j)项和(j,i)项。将内循环更改为for j=1:i,并在循环体中添加D(j,i)=D(i,j);

之后,这段代码所做的事情真的没有太多冗余,所以你唯一剩下的改进空间就是并行化它:如果你有并行计算工具箱,将你的外部循环转换为parfor,在运行它之前,说matlabpool(n),其中n是要使用的线程数。

最新更新