Pythonのscikit-learn LDAが正しく機能しないのはなぜですか?また、SVDを介してLDAを計算する方法


26

私はscikit-learn次元削減のために機械学習ライブラリ(Python)の線形判別分析(LDA)を使用していましたが、結果に少し興味がありました。私は今、LDAが何をしているのか疑問に思っていscikit-learnます。その結果、例えば、手動でのアプローチやRで行われたLDAとは異なった結果になります。

基本的に最も懸念さscikit-plotれるのは、相関0があるはずの2つの変数間の相関を示すことです。

テストでは、Irisデータセットを使用し、最初の2つの線形判別式は次のようになりました。

IMG-1 scikit-learn経由のLDA

ここに画像の説明を入力してください

これは、私がscikit-learn ドキュメントで見つけた結果と基本的に一致しています。

今、私はLDAを段階的に通り抜けて、異なる予測を得ました。何が起こっているのかを知るために、さまざまなアプローチを試しました。

IMG-2。生データのLDA(センタリングなし、標準化なし)

ここに画像の説明を入力してください

そして、最初にデータを標準化(zスコア正規化;単位分散)した場合のステップバイステップのアプローチになります。同じことを平均中心化のみで行いました。これにより、同じ相対投影画像が得られるはずです(実際にそうなりました)。

IMG-3。平均中心化または標準化後の段階的なLDA

ここに画像の説明を入力してください

IMG-4。RのLDA(デフォルト設定)

IMG-3のLDAは、データを中央に配置したため(推奨されるアプローチ)、RでLDAを実行した誰かが投稿で見つけたものとまったく同じに見えます。 ここに画像の説明を入力してください


参照用コード

すべてのコードをここに貼り付けたくはありませんでしたが、LDAプロジェクションで使用したいくつかのステップ(以下を参照)に分けてIPythonノートブックとしてアップロードしました。

  1. ステップ1:d次元平均ベクトルの計算
    m=1nバツDnバツk
  2. ステップ2:散布図の計算

    2.1クラス内散布行列は、次の方程式によって計算されますS W = C Σ I = 1、S I = C Σ I = 1 N ΣのxD IX - M ISW

    SW=i=1cSi=i=1cxDin(xmi)(xmi)T

    2.2クラス間散布行列は、次の方程式によって計算されます ここで、は全体の平均です。SB

    SB=i=1cni(mim)(mim)T
    m
  3. ステップ3.行列の一般化された固有値問題を解くSW1SB

    3.1。固有値を減らして固有ベクトルを並べ替える

    3.2。最大の固有値を持つk個の固有ベクトルを選択します。2つの固有ベクトルと最高の固有値を組み合わせて、次元の固有ベクトル行列d×kW

  4. ステップ5:サンプルを新しい部分空間変換します

    y=WT×x.

違いを探しに行ったことはありませんが、ソースで scikit-learnが何をしているのかを正確に見ることができます。
ドゥーガル

それらは標準化されているようにも見えます(センタリングしてから、標準偏差による除算によってスケーリングします)。これは、私は私の第三のプロットの1(及びR)プロット...うーんと同様の結果を期待

奇妙なことに、scikit(およびドキュメントに示されているもの)で得たプロットは意味がありません。LDAは常に相関ゼロの投影を生成しますが、明らかに判別軸1と2上のscikitの投影の間には非常に強い相関があります。
アメーバは2014

@ameobaはい、私もそう思います。:何も奇妙なのは、私がscikitため表示しています同じプロットは例のドキュメントであるということですscikit-learn.org/stable/auto_examples/decomposition/...私はscikitの私の使用量は、それが正しいと思いますが、何か奇妙であることをLDA機能について

@SebastianRaschka:はい、気づきました。それは確かに奇妙です。ただし、最初の(非scikit)LDAプロットもゼロ以外の相関関係を示しているため、同様に何らかの問題があるはずです。データを集中させましたか?2番目の軸の投影の平均はゼロではないようです。
アメーバは、モニカーを復活14

回答:


20

更新:この議論のおかげで、scikit-learn更新され、正しく動作するようになりました。LDAのソースコードはこちらにあります。元の問題は小さなバグが原因で(このgithubの説明を参照)、私の答えは実際には正しく指摘していませんでした(混乱が生じた場合の謝罪)。これはすべて重要ではないので(バグは修正されています)、SVDを介してLDAを解決する方法に焦点を当てるように回答を編集しましたscikit-learn。これはのデフォルトアルゴリズムです。


クラス内およびクラス間散布行列および定義した後、質問で指摘したように、標準LDA計算は判別軸として(たとえば、こちらを参照)。ただし、ホワイトニングマトリックスを利用して、同じ軸をわずかに異なる方法で計算できます。ΣWΣBΣW1ΣB

  1. 計算します。これは、プールされたクラス内共分散に関するホワイトニング変換です(詳細については、リンクされた回答を参照してください)。ΣW1/2

    固有分解場合、。プールされたクラス内データのSVDを実行して同じことを計算することにも注意してください。。ΣW=うんSうんΣW1/2=うんS1/2うんバツW=うんLVΣW1/2=うんL1うん

  2. 固有ベクトルを見つけ、それらをと呼びましょう。ΣW1/2ΣBΣW1/2A

    繰り返しますが、クラス間データをで変換したSVDを実行することで計算できることに注意してください。共分散。バツBΣW1/2

  3. 判別軸は、によって、つまり変換されたデータの主軸によって、再び変換されて与えられます。AΣW1/2A

    実際、が上記の行列の固有ベクトルの場合、および左からを掛けてを定義すると、すぐに得られます:a

    ΣW1/2ΣBΣW1/2a=λa
    ΣW1/2a=ΣW1/2a
    ΣW1ΣBa=λa

要約すると、LDAはクラス内共分散に関してクラス平均の行列を白色化し、クラス平均でPCAを実行し、結果の主軸を元の(白色化されていない)空間に逆変換することに相当します。

これは、例えば、統計学習の要素、セクション4.3.3 で指摘されています。ではscikit-learn、データ行列のSVDは、その共分散行列の固有値分解よりも数値的に安定であるため、この計算LDAへのデフォルトの方法です。

代わりに任意のホワイトニング変換を使用でき、すべてが同じように機能することに注意してください。で使用されている(代わりに)、及びそれはうまく機能します(元々私の答えに書かれていたものとは反対です)。ΣW1/2scikit-learn L1うんうんL1うん


1
このいい答えをありがとう。あなたがそれをうまく書いてくれたことに感謝します。たぶん、GitHubの議論でそれについて言及することができます。私は、SCI-キットの次のバージョンでLDAを修正する助けになるだろうと確信している

@SebastianRaschka:GitHubにアカウントを持っていません。ただし、必要に応じて、このスレッドへのリンクを提供できます。
アメーバは、Reinstate Monicaを言う14

ΣW1ΣBΣW1


2
ΣBΣW1ΣBΣW1μ1μ2μ
アメーバは、Reinstate Monicaを言う14

3

この質問を終了するために、LDAで議論された問題はscikit-learn 0.15.2で修正されました

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.