Warum funktioniert Pythons Scikit-Learn-LDA nicht richtig und wie berechnet es LDA über SVD?


26

Ich habe die lineare Diskriminanzanalyse (LDA) aus der scikit-learnmaschinellen Lernbibliothek (Python) zur Dimensionsreduktion verwendet und war ein wenig neugierig auf die Ergebnisse. Ich frage mich jetzt, was die LDA scikit-learntut, damit die Ergebnisse anders aussehen als beispielsweise ein manueller Ansatz oder eine in R durchgeführte LDA. Es wäre großartig, wenn mir jemand hier einige Einblicke geben könnte.

Was im Grunde am meisten betrifft, ist, dass das scikit-ploteine Korrelation zwischen den beiden Variablen zeigt, wobei es eine Korrelation 0 geben sollte.

Für einen Test habe ich den Iris-Datensatz verwendet und die ersten beiden linearen Diskriminanten sahen folgendermaßen aus:

IMG-1. LDA via Scikit-Learn

Bildbeschreibung hier eingeben

Dies stimmt im Wesentlichen mit den Ergebnissen überein, die ich in der Dokumentation zu scikit-learn hier gefunden habe.

Nun ging ich Schritt für Schritt die LDA durch und bekam eine andere Projektion. Ich habe verschiedene Ansätze ausprobiert, um herauszufinden, was los war:

IMG-2. LDA auf Rohdaten (keine Zentrierung, keine Standardisierung)

Bildbeschreibung hier eingeben

Und hier wäre der schrittweise Ansatz, wenn ich zuerst die Daten standardisieren würde (z-Score-Normalisierung; Einheitsvarianz). Ich habe dasselbe nur mit Mittelwertzentrierung gemacht, was zu demselben relativen Projektionsbild führen sollte (und was es tatsächlich tat).

IMG-3. Schrittweise LDA nach Mittelwertzentrierung oder Standardisierung

Bildbeschreibung hier eingeben

IMG-4. LDA in R (Standardeinstellungen)

LDA in IMG-3, in dem ich die Daten zentriert habe (was der bevorzugte Ansatz wäre), sieht genauso aus wie der, den ich in einem Beitrag von jemandem gefunden habe, der die LDA in R durchgeführt hat Bildbeschreibung hier eingeben


Code als Referenz

Ich wollte nicht den gesamten Code hier einfügen, habe ihn jedoch als IPython-Notizbuch hier hochgeladen und in die verschiedenen Schritte unterteilt (siehe unten), die ich für die LDA-Projektion verwendet habe.

  1. Schritt 1: Berechnen der d-dimensionalen Durchschnittsvektoren
    mi=1nixDinxk
  2. Schritt 2: Berechnen der Streumatrizen

    2.1 Die Streumatrix wird nach folgender Gleichung berechnet:SW

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

    2.2 Die Zwischenklassen-Streumatrix wird durch die folgende Gleichung berechnet: wobei der Gesamtmittelwert ist.S B = c i = 1 n i ( m i - m ) ( m i - m ) T mSB

    SB=i=1cni(mim)(mim)T
    m
  3. Schritt 3. Lösen des verallgemeinerten Eigenwertproblems für die MatrixSW1SB

    3.1. Sortieren der Eigenvektoren durch Verringern der Eigenwerte

    3.2. Auswahl von k Eigenvektoren mit den größten Eigenwerten. Kombinieren der beiden Eigenvektoren mit den höchsten Eigenwerten, um unsere dimensionale Eigenvektormatrix zu konstruierenWd×kW

  4. Schritt 5: Transformieren der Samples in den neuen Unterraum

    y=WT×x.

Ich habe noch nicht nach den Unterschieden gesucht, aber Sie können genau sehen, was Scikit-Learn in der Quelle tut .
Dougal

Es sieht so aus, als würden sie sich auch standardisieren (Zentrieren und dann Skalieren durch Division durch die Standardabweichung). Dies würde ich zu einem ähnlichen Ergebnis führen wie in meinem dritten Plot (und dem R-Plot) ... hmm

Seltsam: Die Handlung, die Sie mit scikit erhalten haben (und die, die sie in ihrer Dokumentation zeigen), ergibt keinen Sinn. LDA liefert immer Projektionen mit einer Korrelation von Null, aber offensichtlich besteht eine sehr starke Korrelation zwischen den Projektionen von scikit auf den Diskriminanzachsen 1 und 2. Da stimmt eindeutig etwas nicht.
Amöbe sagt Reinstate Monica

@ameoba Ja, das denke ich auch. Seltsam ist auch, dass die gleiche Handlung, die ich für scikit zeige, in der Beispieldokumentation enthalten ist: scikit-learn.org/stable/auto_examples/decomposition/… Das lässt mich denken, dass meine Verwendung von scikit korrekt ist, aber dass es etwas Seltsames gibt über die LDA-Funktion

@SebastianRaschka: Ja, mir ist aufgefallen. Es ist in der Tat komisch. Beachten Sie jedoch, dass die ersten Ihrer eigenen (Nicht-Scikit-) LDA-Diagramme auch eine Korrelation ungleich Null aufweisen und daher auch etwas damit nicht stimmt. Haben Sie die Daten zentriert? Die Projektion auf der zweiten Achse scheint keinen Mittelwert von Null zu haben.
Amöbe sagt Reinstate Monica

Antworten:


20

Update: Dank dieser Diskussion scikit-learnwurde das Update durchgeführt und funktioniert nun korrekt. Den LDA-Quellcode finden Sie hier . Das ursprüngliche Problem war auf einen kleinen Fehler zurückzuführen (siehe diese Github-Diskussion ), und meine Antwort zeigte tatsächlich nicht richtig darauf (entschuldige mich für die verursachte Verwirrung). Da das alles keine Rolle mehr spielt (Fehler behoben), habe ich meine Antwort überarbeitet, um mich darauf zu konzentrieren, wie LDA über SVD gelöst werden kann, was der Standardalgorithmus in ist scikit-learn.


Nach der Definition von Streumatrizen innerhalb und zwischen Klassen und besteht die in Ihrer Frage Standard-LDA-Berechnung darin, Eigenvektoren von als diskriminante Achsen ( siehe zB hier ). Dieselben Achsen können jedoch auf eine etwas andere Weise berechnet werden, indem eine Weißmachermatrix verwendet wird:ΣWΣBΣW1ΣB

  1. Berechne . Dies ist eine Aufhellungstransformation in Bezug auf die gepoolte Kovarianz innerhalb der Klasse (siehe meine verknüpfte Antwort für Details).ΣW1/2

    Beachten Sie, dass wenn Sie EIGEN-Zersetzung , dann . Man beachte auch, dass man dasselbe berechnet, indem man eine SVD gepoolter Daten innerhalb einer Klasse durchführt: .ΣW=USUΣW1/2=US1/2UXW=ULVΣW1/2=UL1U

  2. Finden Eigenvektoren von , nennen wir sie . A *ΣW1/2ΣBΣW1/2A

    Man beachte wiederum, dass man es berechnen kann, indem man eine SVD von Daten zwischen Klassen , die mit transformiert wurden , dh Daten zwischen Klassen, die in Bezug auf die innerhalb der Klasse weiß werden Kovarianz.XBΣW1/2

  3. Die Diskriminanzachsen werden durch , dh durch die Hauptachsen transformierter Daten, die erneut transformiert werden .AΣW1/2A

    In der Tat, wenn ein Eigenvektor der obigen Matrix ist, dann ist und Multiplikation von links mit und Definition von wir sofort :a

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

Zusammenfassend ist LDA gleichbedeutend damit, die Matrix der Klassenmittelwerte in Bezug auf die Kovarianz innerhalb der Klasse aufzuhellen, PCA für die Klassenmittelwerte durchzuführen und die resultierenden Hauptachsen in den ursprünglichen (nicht aufgehellten) Raum zurück zu transformieren.

Dies wird z. B. in den Elementen des statistischen Lernens in Abschnitt 4.3.3 erläutert. In scikit-learndieser Art und Weise ist die Standard - LDA zu berechnen , weil SVD eine Datenmatrix numerisch stabiler als Eigenzerlegung der Kovarianzmatrix ist.

Beachten Sie, dass Sie anstelle von eine beliebige Whitening-Transformation verwenden können, und dass trotzdem alles genauso funktioniert. In verwendet (anstelle von ), und Es funktioniert einwandfrei (im Gegensatz zu dem, was ursprünglich in meiner Antwort geschrieben wurde).ΣW1/2scikit-learn L1UUL1U


1
Danke für diese nette Antwort. Ich weiß es zu schätzen, dass du dir die Zeit genommen hast, es so schön aufzuschreiben. Vielleicht könntest du es in der Diskussion auf GitHub erwähnen; Ich bin mir sicher, dass dies hilfreich sein würde, um die LDA in der nächsten Version von sci-kit

@SebastianRaschka: Ich habe keinen Account auf GitHub. Aber wenn du willst, kannst du dort einen Link zu diesem Thread geben.
Amöbe sagt Reinstate Monica

@amoeba: Lehrbücher beschreiben die LDA normalerweise so wie Sie - eine Eigenwertzerlegung von . Seltsamerweise verfolgen einige der mir bekannten LDA-Implementierungen einen anderen Ansatz. Ihre Achsen sind die Vektoren zu den mit transformierten . Ihre LDA-Lösung ist eine orthonormale Basis dieser Vektoren. Die LDA von Scikit-learn liefert die gleichen Ergebnisse wie diese Implementierungen, daher glaube ich nicht, dass tatsächlich ein Fehler vorliegt. Σ - 1 WΣW1ΣBΣW1
Kasemakase


2
@kazemakase: Nun, natürlich, wenn es nur zwei Klassen gibt, dann hat Rang 1 und alles vereinfacht sich sehr, da der einzige Eigenvektor von durch gegeben ist , wobei Klassenmittel sind. Ich denke, das haben Sie vorher gemeint? Dies wird z. B. in Bishops ML-Lehrbuch, Abschnitt 4.1.4, ausführlich behandelt. Die Verallgemeinerung auf mehrere Klassen erfordert jedoch eine Eigenanalyse (ebd., 4.1.6). Auch scikit Code (das wir hier diskutieren!) Macht Gebrauch SVD, zweimal tatsächlich. Σ - 1 W Σ BΣBΣW1ΣBμ iΣW1(μ1μ2)μi
Amöbe sagt Reinstate Monica

3

Um diese Frage zu schließen, wurde das mit der LDA diskutierte Problem in scikit-learn 0.15.2 behoben .

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.