2011-11-28 74 views
14

我在R中使用princomp來執行PCA。我的數據矩陣很大(10K x 10K,每個值最多4個小數點)。在至強2.27 GHz處理器上,需要3.5小時〜6.5 GB的物理內存。什麼是計算R中前兩個主成分的最快方法?

因爲我只想要前兩個組件,有沒有更快的方法來做到這一點?

更新:

除了速度,是否有記憶有效的方式做到這一點?

使用svd(,2,)需要約2小時和〜6.3 GB的物理內存來計算前兩個組件。

+1

可以使用NIPALS算法。搜索R軟件包。 –

回答

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

N = 200我的機器的打印速度最快(不是太多,基本上等於svd(,2,),所以結果可能會因處理器和擴展而有所不同 –

+0

「基準」功能在哪裏 –

+3

在rbenchmark軟件包中還有一個microbenchmark軟件包 –

0

您可以自己編寫函數,並停止在2個組件。這並不難。我把它放在某個地方,如果我找到它,我會發布它。

+0

可能是你可以給邏輯的功能,我可以嘗試編碼我自己! – 384X21

+0

作爲PCA的入門書,我做了一篇博客文章,試圖用OLS來解釋這一點:http://www.cerebralmastication。com/2010/09/principal-component-analysis-pca-vs-ordinary-least-squares-ols-a-visual-explination/ 在底部有一個鏈接到我發現的Lindsay I Smith的文章很有幫助。鏈接到史密斯PDF:http://www.cs.otago.ac.nz/cosc453/student_tutorials/principal_components.pdf –

+0

@JD龍:這是一個有趣的文章。讓我嘗試 ! – 384X21

1

power method可能是你想要的。如果你使用R編碼,這並不難,我認爲你可能會發現它不會比其他答案中提出的SVD方法更快,因爲它使用了LAPACK編譯的例程。

+0

我建議不要這是因爲功率方法的收斂速度非常慢 –

+0

在很多情況下都是如此,速度取決於最大特徵值對下一個特徵值的相對大小,所以它將依賴於問題。找到兩個特徵向量並且矩陣非常大。沒有嘗試就不知道的方法 –

5

'svd'包通過Lanczos算法提供了截斷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」包的東西,您可以使用所謂的「外部矩陣接口」,您只需定義如何將矩陣乘以矢量即可,就這些了。現在這個API只是C級別的,但有傳聞說一切都會很快傳播到普通的R級,所以人們可以在R中編寫自己的例程(並且肯定會利用矩陣的對稱性或稀疏性)。 –

4

我試過NIPALS算法的pcaMethods包的實現。默認情況下,它會計算前兩個主要組件。結果比其他建議的方法慢。

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 - 感謝您進行經驗性比較。 –

相關問題