matlab

2012-02-13 16 views
10

में कॉलम सहसंबंध द्वारा कॉलम की गणना करने का एक तेज़ तरीका क्या है मेरे पास दो बहुत बड़ी matrices (60x25000) हैं और मैं केवल दो मैट्रिक्स के बीच कॉलम के बीच सहसंबंध की गणना करना चाहता हूं। उदाहरण के लिए: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

इसके अलावा, लूप के लिए स्पष्ट क्या गलत है? – Jacob

+0

संपादन सही है, धन्यवाद! इसके अलावा लूप – slayton

उत्तर

15

मैं हाथ से कंप्यूटिंग से एक X100 गति सुधार प्राप्त कर सकते हैं।

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

दो परिणाम के बीच का अंतर बहुत छोटा है:

mean(abs(C-C2)) 

ans = 
    3.0968e-17 

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 

यहाँ कंप्यूटिंग समय है:

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 

आपको लगता है कि कोड का उपयोग तुलना कर सकते हैं

संपादित करें: स्पष्टीकरण

bsxfun कॉलम-बाय-कॉलम ऑपरेशन (या इनपुट के आधार पर पंक्ति-दर-पंक्ति) करता है।

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

इस लाइन को हटा देगा (@minus) A के प्रत्येक कॉलम को प्रत्येक स्तंभ (mean(A,1)) का मतलब ... तो मूल रूप से यह A शून्य मतलब के कॉलम में आता है।

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

यह लाइन प्रत्येक मानदंड को अपने मानदंड के विपरीत से गुणा (@ टाइम्स) गुणा करें। तो यह उन्हें एल -2 सामान्यीकृत करता है।

एक बार कॉलम शून्य मतलब हैं और एल 2-सामान्यीकृत, सहसंबंध की गणना करने के, तो आप सिर्फ B के प्रत्येक स्तंभ के साथ An के प्रत्येक स्तंभ के डॉट उत्पाद बनाने के लिए है।तो आप उन्हें तत्व-वार An.*Bn गुणा करते हैं, और फिर आप प्रत्येक कॉलम को जोड़ते हैं: sum(An.*Bn);

+0

वाह तेज़ है। क्या आप मुझे एक त्वरित स्पष्टीकरण दे सकते हैं कि यह क्यों काम करता है? – slayton

+1

मैंने कुछ स्पष्टीकरण जोड़ा है। मुझे उम्मीद है कि यह अस्पष्ट नहीं है ... – Oli

+0

@ ओली: महान जवाब! – 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

रुको, मुझे क्या याद आ रही है? निदान (corr (ए, बी)); मेरे लिए 10 सेकंड लेता है। –

+0

हाँ। मुझे भी। – Jacob