什么是在matlab中逐列相关计算的快速方法

时间:2012-02-13 15:18:06

标签: matlab matrix correlation

我有两个非常大的矩阵(60x25000),我想计算两个矩阵之间的列之间的相关性。例如:

corrVal(1) = corr(mat1(:,1), mat2(:,1);
corrVal(2) = corr(mat1(:,2), mat2(:,2);
...
corrVal(i) = corr(mat1(:,i), mat2(:,i);

对于较小的矩阵,我可以简单地使用:

   colCorr = diag( corr( mat1, mat2 ) );

但是这对于非常大的矩阵不起作用,因为我的内存不足。我已经考虑过切割矩阵来计算相关性然后组合结果,但是计算列组合之间的相关性似乎是一种浪费,我实际上并不感兴趣。

有没有快速的方法可以直接计算我感兴趣的内容?

编辑:我过去曾经使用过一个循环,但它只是减速的方法:

mat1 = rand(60,5000);
mat2 = rand(60,5000);
nCol = size(mat1,2);
corrVal = zeros(nCol,1);

tic;
for i = 1:nCol
    corrVal(i) = corr(mat1(:,i), mat2(:,i));
end
toc; 

这需要约1秒

tic;
corrVal = diag(corr(mat1,mat2));
toc;

这需要约0.2秒

2 个答案:

答案 0 :(得分:15)

通过手动计算,我可以获得 x100 的速度提升。

An=bsxfun(@minus,A,mean(A,1)); %%% zero-mean
Bn=bsxfun(@minus,B,mean(B,1)); %%% zero-mean
An=bsxfun(@times,An,1./sqrt(sum(An.^2,1))); %% L2-normalization
Bn=bsxfun(@times,Bn,1./sqrt(sum(Bn.^2,1))); %% L2-normalization
C=sum(An.*Bn,1); %% correlation

您可以使用该代码进行比较:

A=rand(60,25000);
B=rand(60,25000);

tic;
C=zeros(1,size(A,2));
for i = 1:size(A,2)
    C(i)=corr(A(:,i), B(:,i));
end
toc; 

tic
An=bsxfun(@minus,A,mean(A,1));
Bn=bsxfun(@minus,B,mean(B,1));
An=bsxfun(@times,An,1./sqrt(sum(An.^2,1)));
Bn=bsxfun(@times,Bn,1./sqrt(sum(Bn.^2,1)));
C2=sum(An.*Bn,1);
toc
mean(abs(C-C2)) %% difference between methods

以下是计算时间:

Elapsed time is 10.822766 seconds.
Elapsed time is 0.119731 seconds.

两个结果之间的差异非常小:

mean(abs(C-C2))

ans =
  3.0968e-17

编辑:解释

bsxfun执行逐列操作(或逐行,具体取决于输入)。

An=bsxfun(@minus,A,mean(A,1));

此行会删除(@minus)每列mean(A,1)}的平均值A ... ...所以基本上它会生成A的列零均值。

An=bsxfun(@times,An,1./sqrt(sum(An.^2,1)));

此行将每列乘以(@times)其范数的倒数。所以它使它们L-2标准化。

一旦列为零均值和L2标准化,为了计算相关性,您只需要将每列An的点积与B的每列进行对比。因此,您将它们乘以元素An.*Bn,然后对每列进行求和:sum(An.*Bn);

答案 1 :(得分:1)

我认为明显的循环可能足以满足您的问题规模。在我的笔记本电脑上,执行以下操作只需不到6秒钟:

A = rand(60,25000);
B = rand(60,25000);
n = size(A,1);
m = size(A,2);

corrVal = zeros(1,m);
for k=1:m
    corrVal(k) = corr(A(:,k),B(:,k));
end