データのSVDによるデータのPCAが必要な理由


22

この質問は、主成分を計算する効率的な方法に関するものです。

  1. casewise dataの特異値分解を使用した線形PCAの多くのテキスト。つまり、データあり、変数(その)を主成分で置き換えたい場合、SVDを実行します。、特異値(固有値の平方根)の主対角を占める、右固有ベクトルは、軸変数から軸コンポーネントへの直交回転行列です。左固有ベクトルは、場合のみに似ています。その後、コンポーネント値をとして計算できます。XX=USVSVUVC=XV=US

  2. 変数のPCAを行う別の方法は、分解を経由している(つまり正方行列でき相関または共分散の変数の間、など)。分解は、固有分解または特異値分解である可能性があります:正方対称正定行列では、前述の\ bf Lおよび\ bf Vの対角要素と同じ固有値を持つ\ bf R = VLV 'と同じ結果が得られます。コンポーネントの値は\ bf C = XVになります。R=XXR R=VLVLVC=XV

さて、私の質問:データXが大きな行列であり、ケースの数が(多くの場合)変数の数よりはるかに大きい場合、ウェイ(1)ウェイ(2 )、方法(1)は非常に高価なアルゴリズム(SVDなど)を大きなマトリックスに適用するため。巨大な行列Uを計算して保存しますが、この場合は実際には必要ありません(変数のPCA)。もしそうならなぜそんなに多くのtexbookが主張しているように見える、または単に方法(1)だけに言及しているように見えるのでしょうか?たぶんそれ効率的で、私は何かが欠けていますか?


2
一般的に、ほとんどの分散を説明する少数の主成分のみに関心があります。SVDを削減することは可能です。たとえば場合X次元であるN \倍のP pが<< Nが、その後の機能のみを最初に計算されますのpデフォルトで左と右特異ベクトルを。N×pp<<NRsvdp
M.バーク

1
@ M.Berk:ただし、は両方のアプローチで同じです。同等の結果が得られます(符号の変化まで等しくなります)。また、たとえば、R は要求された場合にのみ計算します。CpC
cbeleitesは、モニカをサポートします

方法(1)のリファレンスはありますか?PCAが共分散行列(つまり、方法2)でSVDを介して実装されていることのみを知っています。これにより、いくつかの数値問題が回避され、データセットサイズではなく次元で明らかにスケーリングされます。方法(1)私はPCAではなくSVDを呼び出します。実際に完全な分解を実行しない純粋なSVDコンテキストでのみ見ました。
アノニムース14

@ Anony-Mousse、言及するだけで、Joliffe, Principal component analysis, 2nd ed.実際、Joliffeは両方の方法を説明しますが、PCAのコアの章では、私が覚えている限り、方法1についてだけ述べています。
ttnphns 14年

@ Anony-Mousse、私にとっての方法1は、PCAが単純なコレスポンデンス分析に直接関係する方法を明確に示しているため、理論的な点から重要です。
ttnphns 14年

回答:


7

トピックに関する私の2ctはここにあります

  • 私が最初にPCAを学んだケモメトリックスレクチャーはソリューション(2)を使用しましたが、数値指向ではなく、私の数値レクチャーは単なる紹介であり、思い出す限りSVDについては話しませんでした。

  • ホームズ:大規模行列の高速SVDを正しく理解していれば、長い行列の計算上高速なSVDを取得するためにあなたのアイデアが使用されています。
    それは、適切な行列に遭遇した場合、優れたSVD実装が内部的に(2)に続く可能性があることを意味します(さらに良い可能性があるかどうかはわかりません)。つまり、高レベルの実装では、SVD(1)を使用し、BLASに任せて、内部で使用するアルゴリズムを処理する方がよいことを意味します。

  • 簡単な実用的なチェック:OpenBLASのsvdは、5e4 x 100のマトリックスでsvd (X, nu = 0)は、中央値3.5秒svd (crossprod (X), nu = 0)かかりますが、54ミリ秒かかります(Rから呼び出されmicrobenchmarkます)。
    固有値の二乗はもちろん高速であり、それまでは両方の呼び出しの結果は同等です。

    timing  <- microbenchmark (svd (X, nu = 0), svd (crossprod (X), nu = 0), times = 10)
    timing
    # Unit: milliseconds
    #                      expr        min         lq    median         uq        max neval
    #            svd(X, nu = 0) 3383.77710 3422.68455 3507.2597 3542.91083 3724.24130    10
    # svd(crossprod(X), nu = 0)   48.49297   50.16464   53.6881   56.28776   59.21218    10
    

更新:Wu、W.をご覧ください。Massart、D.&de Jong、S .:ワイドデータ用のカーネルPCAアルゴリズム。パートI:理論とアルゴリズム、ケモメトリックスとインテリジェントラボシステム、36、165-172(1997)。DOI:http://dx.doi.org/10.1016/S0169-7439(97)00010-5

このペーパーでは、PCAの4つの異なるアルゴリズム、SVD、固有分解(EVD)、NIPALS、およびPOWERの数値および計算特性について説明します。

それらは次のように関連しています。

computes on      extract all PCs at once       sequential extraction    
X                SVD                           NIPALS    
X'X              EVD                           POWER

論文の文脈は広い であり、(カーネルPCA)で機能します。これは、あなたが尋ねる状況とは正反対の状況です。したがって、長いマトリックスの動作に関する質問に答えるには、「カーネル」と「クラシック」の意味を交換する必要があります。X(30×500)XX

性能比較

当然のことながら、EVDとSVDは、クラシックアルゴリズムを使用するかカーネルアルゴリズムを使用するかによって場所が変わります。この質問の文脈では、これは、マトリックスの形状に応じてどちらか一方が優れている可能性があることを意味します。

しかし、「古典的な」SVDおよびEVDの議論から、分解がPCAを計算する非常に一般的な方法であることは明らかです。ただし、Matlabの関数を使用すること以外は、使用するSVDアルゴリズムを指定しません。XXsvd ()


    > sessionInfo ()
    R version 3.0.2 (2013-09-25)
    Platform: x86_64-pc-linux-gnu (64-bit)

    locale:
     [1] LC_CTYPE=de_DE.UTF-8       LC_NUMERIC=C               LC_TIME=de_DE.UTF-8        LC_COLLATE=de_DE.UTF-8     LC_MONETARY=de_DE.UTF-8   
     [6] LC_MESSAGES=de_DE.UTF-8    LC_PAPER=de_DE.UTF-8       LC_NAME=C                  LC_ADDRESS=C               LC_TELEPHONE=C            
    [11] LC_MEASUREMENT=de_DE.UTF-8 LC_IDENTIFICATION=C       

    attached base packages:
    [1] stats     graphics  grDevices utils     datasets  methods   base     

    other attached packages:
    [1] microbenchmark_1.3-0

loaded via a namespace (and not attached):
[1] tools_3.0.2

$ dpkg --list libopenblas*
[...]
ii  libopenblas-base              0.1alpha2.2-3                 Optimized BLAS (linear algebra) library based on GotoBLAS2
ii  libopenblas-dev               0.1alpha2.2-3                 Optimized BLAS (linear algebra) library based on GotoBLAS2

したがって、テスト(3.5秒対54ミリ秒)は、「方法1」がかなり遅いという私の回線をサポートします。右?
ttnphns

1
@ttnphns:はい。ただし、svdはBLASによって提供されるため、異なるBLASでは異なる可能性があります。適切に最適化されたBLASがこのようなことをすると予想していました。ただし、OpenBLASには当てはまらないようです。私は他のBLASをチェックするのが面倒ですが、多分数人が他のBLASをチェックできるので、このケースに最適化されているものとそうでないものを見つけます。(私はので、多分、彼は、にアルゴリズムをスイッチングしていないためなどの理由からいくつかの情報を追加することができ、OpenBLASの開発者を電子メールで送信し、この質問に彼にリンクを送ったsvd (X'X)長い行列のために。)
cbeleitesサポートモニカ

いくつかの点は明確にする必要があります(私にとって)。「カーネル法は、」「での作業のように要約することができるの代わりに、X N < P」?もしそうなら、それは非常に簡単です。POWERはわかりませんが、NIPALSは知っています。NIPALSは、u n + 1 = X X u n / |を繰り返してX Xの固有ベクトルを計算します | X X u n | | (彼は最初の固有ベクトルv 1に収束し、Xを更新する必要がありますXXn<pXXun+1=XXun/||XXun||v1X2番目を計算するなど)。NIPALSを実行するには2つの方法があります。(1)事前計算できます。または(2)製品をX × X u nとして実行できます。(1)が使用されていると思いますが、これは不公平な場合があります。XXX×(Xun)
エルビス14

@Elvis:a)カーネルメソッドには、での単なる計算以上のものがあり ます。たとえば、stats.stackexchange.com / questions / 2499 /…を参照してください。PCAの場合、等価性は自明です(右または左の特異ベクトルを取得することから始めるかどうかは関係ありません)が、他の方法ではそうではありません。b)「NIPALSを行う方法」は、同じ全体原則に依存しています。SVDにどのアルゴリズムが使用されるかは、BLASに依存します。実際、NIPALSはここには含まれていません。私のタイミングには、外積の計算が含まれていることに注意してください。XXT
-cbeleitesはモニカをサポートします14

Nipalsが関与しているあなたのアップデートについて話していました。NipacksはLapackのSVDに関与していないことを確認します。ベンチマーク実験についても、同様のmicrobenchmark(X <- matrix(rnorm(5e6), ncol=100), Y <- t(X), svd(X), svd(Y), control=list(order="inorder"), times = 5)ことが興味深い場合があります。
エルビス

18

SVDは低速ですが、数値精度が高いため、多くの場合、推奨される方法と見なされます。

質問で述べているように、主成分分析(PCA)は、中心データ行列 SVD (詳細についてはこのQ&Aスレッドを参照)または共分散行列1の固有分解によって実行できます。X(又は、代替的に、XXもしN«Pここで詳細を参照)。1n1XXXXnp

以下は、MATLABのpca()関数ヘルプに記述されているものです。

pca主成分分析の実行に使用する主成分アルゴリズム[...]:

'svd'-デフォルト。Xの特異値分解(SVD)。

np

最後の文は、ここで重要な速度と精度のトレードオフを強調しています。

1000×100

X = randn([1000 100]);

tic; svd(X); toc         %// Elapsed time is 0.004075 seconds.
tic; svd(X'); toc        %// Elapsed time is 0.011194 seconds.
tic; eig(X'*X); toc      %// Elapsed time is 0.001620 seconds.
tic; eig(X*X'); toc;     %// Elapsed time is 0.126723 seconds.

npXX

XXXX

X=(111ϵ000ϵ000ϵ),
3+ϵ2ϵ2ϵ2ϵ=105
eps = 1e-5;
X = [1 1 1; eye(3)*eps];
display(['Squared sing. values of X: ' num2str(sort(svd(X),'descend').^2')])
display(['Eigenvalues of X''*X:       ' num2str(sort(eig(X'*X),'descend')')])

同じ結果を得る:

Squared sing. values of X: 3       1e-10       1e-10
Eigenvalues of X'*X:       3       1e-10       1e-10

ϵ=1010

Squared sing. values of X: 3       1e-20       1e-20
Eigenvalues of X'*X:       3           0 -3.3307e-16

XX

私は、この潜在的な[小さな]精度の損失を無視して、より高速な方法を使用することをしばしば喜んで追加する必要があります。


1
XTX

答えと、賛否両論の徹底的な検討に感謝します。
ttnphns 14

アメーバ、それはあなたがeig()アプローチによって数値の安定性が損なわれる具体的な例を示す時間を見つけることでしょうか?(読者は恩恵を受けるでしょう:速度と安定性の間にはトレードオフのポイントがあります。具体的な実際の状況でどのように決定できるでしょうか?)
ttnphns

@ttnphns具体的な例を提供して、答え全体を書き直しました。ご覧ください。
アメーバは、モニカーを復活させる

1
@amoeba、戻ってきて例を挙げてくれてありがとう!SPSSで両方のイプシロンの例を試してみましたが、最後の行を除いて、あなたのような結果が得られました:3 0 -3.3307e-16spssのeigenの代わりに返されました3 0 0。この関数は、それを超えるとゼロオフする組み込みの固定許容値を持っているように見えます。この例では、関数は、小さな固有値、「0」と「-16」の両方をゼロにすることにより、数値不安定性の結び目をハックするように見えました。
ttnphns
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.