sla*_*ton 10 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);
Run Code Online (Sandbox Code Playgroud)
对于较小的矩阵,我可以简单地使用:
colCorr = diag( corr( mat1, mat2 ) );
Run Code Online (Sandbox Code Playgroud)
但这对于非常大的矩阵不起作用,因为我的内存不足.我已经考虑过切割矩阵来计算相关性然后组合结果,但是计算列组合之间的相关性似乎是一种浪费,我实际上并不感兴趣.
有没有快速的方法直接计算我感兴趣的东西?
编辑:我过去使用了一个循环,但它只是缓慢的方式:
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;
Run Code Online (Sandbox Code Playgroud)
这需要约1秒钟
tic;
corrVal = diag(corr(mat1,mat2));
toc;
Run Code Online (Sandbox Code Playgroud)
这需要约0.2秒
Oli*_*Oli 16
通过手动计算,我可以获得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
Run Code Online (Sandbox Code Playgroud)
您可以使用该代码进行比较:
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
Run Code Online (Sandbox Code Playgroud)
以下是计算时间:
Elapsed time is 10.822766 seconds.
Elapsed time is 0.119731 seconds.
Run Code Online (Sandbox Code Playgroud)
两个结果之间的差异非常小:
mean(abs(C-C2))
ans =
3.0968e-17
Run Code Online (Sandbox Code Playgroud)
编辑:解释
bsxfun 执行逐列操作(或逐行操作,具体取决于输入).
An=bsxfun(@minus,A,mean(A,1));
Run Code Online (Sandbox Code Playgroud)
这一行将删除(@minus)每列(mean(A,1))的每个列的平均值A...所以基本上它使列为A零均值.
An=bsxfun(@times,An,1./sqrt(sum(An.^2,1)));
Run Code Online (Sandbox Code Playgroud)
该行将每列乘以(@times)其范数的倒数.所以它使它们L-2归一化.
一旦列为零均值和L2标准化,为了计算相关性,您只需要使每列的An每个列的点积B.所以你将它们按元素相乘An.*Bn,然后你对每一列求和:sum(An.*Bn);.