Perché l'LDA di Python-scikit-learning non funziona correttamente e come calcola l'LDA tramite SVD?


26

Stavo usando Linear Discriminant Analysis (LDA) dalla scikit-learnlibreria di machine learning (Python) per la riduzione della dimensionalità ed ero un po 'curioso dei risultati. Mi chiedo ora cosa scikit-learnstia facendo l'ADL in modo che i risultati appaiano diversi, ad esempio, da un approccio manuale o da un ADL fatto in R. Sarebbe bello se qualcuno potesse darmi alcune intuizioni qui.

La cosa sostanzialmente più preoccupante è che scikit-plotmostra una correlazione tra le due variabili in cui dovrebbe esserci una correlazione 0.

Per un test, ho usato il set di dati Iris e i primi 2 discriminanti lineari si presentavano così:

IMG-1. LDA via scikit-learn

inserisci qui la descrizione dell'immagine

Ciò è sostanzialmente coerente con i risultati che ho trovato nella documentazione di scikit-learn qui.

Ora, ho seguito l'ADL passo dopo passo e ho ottenuto una proiezione diversa. Ho provato diversi approcci per scoprire cosa stava succedendo:

IMG-2. LDA su dati grezzi (nessun centraggio, nessuna standardizzazione)

inserisci qui la descrizione dell'immagine

E qui sarebbe l'approccio graduale se standardizzassi (normalizzazione del punteggio z; varianza dell'unità) i dati per primi. Ho fatto la stessa cosa solo con la centratura dei media, il che dovrebbe portare alla stessa immagine di proiezione relativa (e che in effetti ha fatto).

IMG-3. LDA dettagliata dopo centraggio della media o standardizzazione

inserisci qui la descrizione dell'immagine

IMG-4. LDA in R (impostazioni predefinite)

LDA in IMG-3 in cui ho centrato i dati (che sarebbe l'approccio preferito) sembra esattamente lo stesso di quello che ho trovato in un post da qualcuno che ha fatto l'LDA in R inserisci qui la descrizione dell'immagine


Codice di riferimento

Non volevo incollare tutto il codice qui, ma l'ho caricato come un notebook IPython qui suddiviso nei vari passaggi che ho usato (vedi sotto) per la proiezione LDA.

  1. Passaggio 1: calcolo dei vettori della media d-dimensionale
    mio=1nioΣXDionXK
  2. Passaggio 2: calcolo delle matrici a dispersione

    SW

    SW=Σio=1cSio=Σio=1cΣXDion(X-mio)(X-mio)T

    SB

    SB=Σio=1cnio(mio-m)(mio-m)T
    m
  3. SW-1SB

    3.1. Ordinamento degli autovettori diminuendo gli autovalori

    d×KW

  4. y=WT×X.

Non ho esaminato le differenze, ma puoi vedere esattamente cosa sta facendo scikit-learning nella fonte .
Dougal,

Sembra che stiano anche standardizzando (centrando e poi ridimensionando tramite divisione per deviazione standard). Questo, mi aspetterei un risultato simile a quello della mia terza trama (e della trama R) ... hmm

Strano: la trama che hai ottenuto con scikit (e quella che mostrano nella loro documentazione) non ha senso. LDA produce sempre proiezioni che hanno una correlazione zero, ma ovviamente esiste una correlazione molto forte tra le proiezioni di scikit sugli assi discriminatori 1 e 2. Qui c'è qualcosa di chiaramente sbagliato.
ameba dice Ripristina Monica il

@ameoba Sì, lo penso anche io. Ciò che è anche strano è che la stessa trama che sto mostrando per scikit è nella documentazione di esempio: scikit-learn.org/stable/auto_examples/decomposition/… Questo mi fa pensare che il mio uso di scikit sia corretto, ma che c'è qualcosa di strano sulla funzione LDA

@SebastianRaschka: Sì, l'ho notato. È davvero strano. Tuttavia, nota che il primo dei tuoi diagrammi LDA (non scikit) mostra anche una correlazione diversa da zero e quindi anche qualcosa deve essere sbagliato. Hai centrato i dati? La proiezione sul secondo asse non sembra avere media zero.
ameba dice Ripristina Monica il

Risposte:


20

Aggiornamento: grazie a questa discussione, è scikit-learnstato aggiornato e funziona correttamente ora. Il suo codice sorgente LDA può essere trovato qui . Il problema originale era dovuto a un bug minore (vedi questa discussione su github ) e la mia risposta in realtà non lo indicava correttamente (scuse per qualsiasi confusione causata). Poiché tutto ciò non ha più importanza (il bug è stato corretto), ho modificato la mia risposta per concentrarmi su come LDA può essere risolto tramite SVD, che è l'algoritmo predefinito scikit-learn.


Dopo aver definito le matrici di dispersione all'interno e tra le classi e , il calcolo LDA standard, come sottolineato nella tua domanda, è di prendere autovettori di come assi discriminanti ( vedi ad esempio qui ). Gli stessi assi, tuttavia, possono essere calcolati in un modo leggermente diverso, sfruttando una matrice sbiancante:ΣWΣBΣW-1ΣB

  1. Calcola . Questa è una trasformazione imbiancante rispetto alla covarianza all'interno della classe (vedi la mia risposta collegata per i dettagli).ΣW-1/2

    Nota che se hai decomposizione eigen , allora . Nota anche che uno calcola lo stesso facendo SVD di dati all'interno della classe raggruppati: .ΣW=USUΣW-1/2=US-1/2UXW=ULVΣW-1/2=UL-1U

  2. Trova autovettori di , chiamiamoli .ΣW-1/2ΣBΣW-1/2UN*

    Ancora una volta, si noti che è possibile calcolarlo facendo SVD di dati tra classi , trasformati con , cioè dati tra classi sbiancati rispetto alla classe interna covarianza.XBΣW-1/2

  3. Gli assi discriminanti saranno dati da , ovvero dagli assi principali dei dati trasformati , trasformati di nuovo .UNΣW-1/2UN*

    Infatti, se è un autovettore della matrice sopra, allora e moltiplicando da sinistra per e definendo , otteniamo immediatamente :Σ - 1 / 2 W Σ B Σ - 1 / 2 W un * =λ un * , Σ - 1 / 2 W a = Σ - 1 / 2 W un * Σ - 1 W Σ B a =À una .un'*

    ΣW-1/2ΣBΣW-1/2un'*=λun'*,
    ΣW-1/2un'=ΣW-1/2un'*
    ΣW-1ΣBun'=λun'.

In sintesi, LDA equivale a sbiancare la matrice dei mezzi di classe rispetto alla covarianza all'interno della classe, fare PCA sui mezzi di classe e trasformare indietro gli assi principali risultanti nello spazio originale (non sbiancato).

Ciò è sottolineato, ad esempio, in The Elements of Statistical Learning , sezione 4.3.3. In scikit-learnquesto è il modo predefinito di calcolare LDA perché SVD di una matrice di dati è numericamente più stabile della decomposizione degli automi della sua matrice di covarianza.

ΣW-1/2scikit-learn U L - 1 UL-1UUL-1U


1
Grazie per questa bella risposta Apprezzo il fatto che tu abbia dedicato del tempo a scriverlo così bene. Forse potresti menzionarlo nella discussione su GitHub; Sono sicuro che sarebbe di aiuto per risolvere l'LDA nella prossima versione di sci-kit

@SebastianRaschka: non ho un account su GitHub. Ma se vuoi, puoi dare lì un link a questa discussione.
ameba dice che ripristini Monica il

ΣW-1ΣBΣW-1


2
ΣBΣW-1ΣBΣW-1(μ1-μ2)μio
ameba dice di reintegrare Monica il

3

Solo per chiudere questa domanda, il problema discusso con l'ADL è stato risolto in scikit-learn 0.15.2 .

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.