2012-02-13 13 views
10

2つの非常に大きな行列(60x25000)があり、2つの行列間の列間の相関関係を計算したいと思います。例えば:小さい行列の場合matlabの列ごとの相関関係を計算する方法は簡単です

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秒

かかります
+0

あなたの投稿を編集しました。それが正しいかどうか確認してください。 – Jacob

+1

また、明白なforループで何が問題になっていますか? – Jacob

+0

編集が正しいです、ありがとう!また、ループは遅くなる方法です – slayton

答えて

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. 

2つの結果の差は非常に小さい:

mean(abs(C-C2)) 

ans = 
    3.0968e-17 

EDIT:説明

bsxfun入力ごとに(または行単位で)行を行います。

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

このラインは、したがって、基本的には、Aゼロ平均の列を作る... Aの各列に各列(mean(A,1))の平均値を(@minus)を削除します。

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

この行は、各列にそのノルムの逆数を掛けます(@times)。それで、L-2を正規化します。

列がゼロ平均とL2正規化された後、相関を計算するには、各列の内積をBとしてAnとする必要があります。したがって、要素ごとにAn.*Bnを掛けて、各列を合計します(sum(An.*Bn);)。

+0

すごく速いです。なぜこれが機能するのかを簡単に説明できますか? – slayton

+1

私はいくつかの説明を追加しました。私はそれが不明確でないことを願って... – Oli

+0

@Oli:素晴らしい答え! – Jacob

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 
+0

あなたの編集が表示されませんでした。うわー、診断は速いです。 –

+0

待って、私は何が欠けていますか? diag(corr(A、B));私のために10秒以上かかる。 –

+0

こっちも一緒。 – Jacob

関連する問題