2011-11-28 20 views
14

मैं पीसीए करने के लिए आर में princomp का उपयोग कर रहा हूं। मेरा डेटा मैट्रिक्स विशाल है (10 दशमलव x 10K प्रत्येक मान के साथ 4 दशमलव अंक तक)। ज़ीऑन 2.27 गीगाहर्ट्ज प्रोसेसर पर ~ 3.5 घंटे और ~ 6.5 जीबी भौतिक मेमोरी लगती है।आर में पहले दो प्रमुख घटकों की गणना करने का सबसे तेज़ तरीका क्या है?

चूंकि मुझे केवल पहले दो घटक चाहिए, क्या ऐसा करने का एक तेज़ तरीका है?

अद्यतन:

गति के अलावा, वहाँ एक स्मृति कारगर तरीका यह करने के लिए है?

svd(,2,) का उपयोग करके पहले दो घटकों की गणना के लिए ~ 2 घंटे और ~ 6.3 जीबी भौतिक स्मृति लेता है।

+1

एनआईपीएएलएस एल्गोरिदम का उपयोग किया जा सकता है। इसके लिए आर पैकेज खोजें। –

उत्तर

17

आपको कभी-कभी तथाकथित 'किफायती' अपघटनों तक पहुंच मिलती है जो आपको ईजीनवे/ईजिनवेक्टरों की संख्या को कैप करने की अनुमति देती है। ऐसा लगता है कि eigen() और prcomp() यह ऑफर न करें, लेकिन svd() आपको गणना करने के लिए अधिकतम संख्या निर्दिष्ट करने की अनुमति देता है।

छोटे मैट्रिक्स पर, लाभ मामूली लगते हैं:

R> set.seed(42); N <- 10; M <- matrix(rnorm(N*N), N, N) 
R> library(rbenchmark) 
R> benchmark(eigen(M), svd(M,2,0), prcomp(M), princomp(M), order="relative") 
      test replications elapsed relative user.self sys.self user.child 
2 svd(M, 2, 0)   100 0.021 1.00000  0.02  0   0 
3 prcomp(M)   100 0.043 2.04762  0.04  0   0 
1  eigen(M)   100 0.050 2.38095  0.05  0   0 
4 princomp(M)   100 0.065 3.09524  0.06  0   0 
R> 

लेकिन तीन रिश्तेदार princomp() के कारक लायक हो सकता है आपके जबकि svd() से princomp() पुनर्निर्माण svd() के रूप में आप दो मानों के बाद बंद करने के लिए अनुमति देता है।

+0

एन = 200 के साथ मेरी मशीन सबसे तेज़ प्रिंसकंप करती है (अधिकतर नहीं, मूल रूप से svd (2,) के बराबर होती है, इसलिए परिणाम प्रोसेसर और स्केलिंग के साथ भिन्न हो सकते हैं। –

+0

"बेंचमार्क" फ़ंक्शन कहां है? –

+3

rbenchmark पैकेज में। माइक्रोबेंमार्क पैकेज भी है। –

0

आप स्वयं को फ़ंक्शन लिख सकते हैं और 2 घटकों पर रोक सकते हैं। यह बहुत मुश्किल नहीं है। मैंने इसे कहीं और बिछाया है, अगर मुझे लगता है कि मैं इसे पोस्ट करूंगा।

+0

हो सकता है कि आप फ़ंक्शन का तर्क दे सकें, मैं स्वयं को कोड करने का प्रयास कर सकता हूं! – 384X21

+0

पीसीए के प्राइमर के रूप में, मैंने एक ब्लॉग पोस्ट किया जहां मैंने इसे OLS के संदर्भ में समझाया: http: //www.cerebralmastication।कॉम/2010/09/प्रिंसिपल-घटक-विश्लेषण-पीसीए-बनाम-साधारण-कम-वर्ग-ओएलएस-ए-विज़ुअल-स्पष्टीकरण/ नीचे नीचे लिंडसे I स्मिथ द्वारा एक लेख का एक लिंक है जो मुझे वास्तव में मिला उपयोगी। स्मिथ से लिंक पीडीएफ: http://www.cs.otago.ac.nz/cosc453/student_tutorials/principal_components.pdf –

+0

@ जेडी लांग: यह एक दिलचस्प लेख है। मुझे कोशिश करने दो ! – 384X21

0

आप मुख्य घटक को खोजने के लिए तंत्रिका नेटवर्क दृष्टिकोण का उपयोग कर सकते हैं। बेसिक वर्णन .. यहाँ दिया जाता है http://www.heikohoffmann.de/htmlthesis/node26.html

प्रथम प्रमुख घटक, y = w1 * x 1 + डब्ल्यू 2 * x2 और दूसरा ओर्थोगोनल घटक के रूप में q = डब्ल्यू 2 * x 1-w1 * x2 गणना की जा सकती।

1

power method जो भी आप चाहते हैं हो सकता है। यदि आप इसे आर में कोड करते हैं, जो कि मुश्किल नहीं है, तो मुझे लगता है कि आप पाते हैं कि यह अन्य उत्तर में सुझाए गए एसवीडी दृष्टिकोण से तेज़ नहीं है, जो लैपैक संकलित दिनचर्या का उपयोग करता है।

+0

मैं इसके खिलाफ सलाह दूंगा चूंकि पावर विधि में बेहद धीमी अभिसरण है। –

+0

यह कई मामलों में सच है। गति अगले सबसे बड़े ईजेनवल्यू के सापेक्ष परिमाण पर निर्भर करती है, इसलिए यह समस्या निर्भर होगी। फिर भी, मुझे लगता है कि विधि केवल प्रतिस्पर्धी हो सकती है दो eigenvectors की मांग की जाती है और मैट्रिक्स बहुत बड़ा है। कोशिश किए बिना जानने का कोई तरीका नहीं। –

5

'svd' पैकेज लांज़ोस एल्गोरिदम के माध्यम से छिड़काव एसवीडी/ईइजेंडेम्पोजिशन के लिए दिनचर्या प्रदान करता है। आप इसे पहले दो प्रमुख घटकों की गणना करने के लिए उपयोग कर सकते हैं।

यहाँ मैं है:

> library(svd) 
> set.seed(42); N <- 1000; M <- matrix(rnorm(N*N), N, N) 
> system.time(svd(M, 2, 0)) 
    user system elapsed 
    7.355 0.069 7.501 
> system.time(princomp(M)) 
    user system elapsed 
    5.985 0.055 6.085 
> system.time(prcomp(M)) 
    user system elapsed 
    9.267 0.060 9.368 
> system.time(trlan.svd(M, neig = 2)) 
    user system elapsed 
    0.606 0.004 0.614 
> system.time(trlan.svd(M, neig = 20)) 
    user system elapsed 
    1.894 0.009 1.910 
> system.time(propack.svd(M, neig = 20)) 
    user system elapsed 
    1.072 0.011 1.087 
+0

मेरे डेटा के रूप में स्क्वायर मैट्रिक्स है, क्या किसी भी फ़ंक्शन (svd, princomp, prcomp) में केवल ऊपरी/निचले त्रिकोणीय मैट्रिक्स को इनपुट करने के लिए हैक है? इससे ऊपरी त्रिभुज के रूप में निचले त्रिकोण को डुप्लिकेट करने की स्मृति खपत चरण बचाएगा! – 384X21

+0

मुझे नहीं लगता कि यह "सामान्य" कार्यों के लिए संभव है। "Svd" पैकेज से सामग्री के लिए आप तथाकथित "बाहरी मैट्रिक्स इंटरफ़ेस" का उपयोग कर सकते हैं जहां आप बस एक वेक्टर द्वारा मैट्रिक्स को गुणा करने के तरीके को परिभाषित करते हैं, और यह सब कुछ है। अभी यह एपीआई केवल सी-स्तर है, लेकिन अफवाहें हैं कि सबकुछ सामान्य आर स्तर पर जल्द ही प्रचारित किया जाएगा, इसलिए कोई व्यक्ति आर में अपना खुद का दिनचर्या लिख ​​सकता है (और निश्चित रूप से समरूपता या मैट्रिक्स की चतुरता का फायदा उठा सकता है)। –

4

मैं nipals एल्गोरिथ्म के pcaMethods पैकेज के कार्यान्वयन की कोशिश की। डिफ़ॉल्ट रूप से यह पहले 2 प्रमुख घटकों की गणना करता है। अन्य सुझाए गए तरीकों से धीमे होने के लिए बाहर निकलता है।

set.seed(42); N <- 10; M <- matrix(rnorm(N*N), N, N) 
library(pcaMethods) 
library(rbenchmark) 
m1 <- pca(M, method="nipals", nPcs=2) 
benchmark(pca(M, method="nipals"), 
      eigen(M), svd(M,2,0), prcomp(M), princomp(M), order="relative") 

         test replications elapsed relative user.self sys.self 
3    svd(M, 2, 0)   100 0.02  1.0  0.02  0 
2     eigen(M)   100 0.03  1.5  0.03  0 
4     prcomp(M)   100 0.03  1.5  0.03  0 
5    princomp(M)   100 0.05  2.5  0.05  0 
1 pca(M, method = "nipals")   100 0.23  11.5  0.24  0 
+2

+1 - अनुभवजन्य तुलना करने के लिए धन्यवाद। –