Dlaczego LDA Python scikit-learn LDA nie działa poprawnie i jak oblicza LDA przez SVD?

26

Użyłem liniowej analizy dyskryminacyjnej (LDA) z scikit-learnbiblioteki uczenia maszynowego (Python) do redukcji wymiarów i byłem trochę ciekawy wyników. Zastanawiam się teraz, czym scikit-learnzajmuje się LDA, aby wyniki wyglądały inaczej niż np. Ręczne podejście lub LDA wykonane w R. Byłoby wspaniale, gdyby ktoś mógł dać mi tutaj jakieś spostrzeżenia.

Zasadniczo najbardziej niepokojące jest to, że scikit-plotpokazuje korelację między dwiema zmiennymi, gdzie powinna istnieć korelacja 0.

Do testu użyłem zestawu danych Iris, a pierwsze 2 liniowe dyskryminatory wyglądały tak:

IMG-1. LDA poprzez scikit-learn

wprowadź opis zdjęcia tutaj

Jest to zasadniczo zgodne z wynikami, które znalazłem w dokumentacji scikit-learn tutaj.

Teraz przeszedłem LDA krok po kroku i otrzymałem inną projekcję. Próbowałem różnych podejść, aby dowiedzieć się, co się dzieje:

IMG-2. LDA na surowych danych (bez centrowania, bez standaryzacji)

wprowadź opis zdjęcia tutaj

I tutaj byłoby podejście krok po kroku, gdybym najpierw ustandaryzował (normalizacja z-score; wariancja jednostkowa) dane. Zrobiłem to samo z samym tylko średnim środkiem, co powinno prowadzić do tego samego względnego obrazu projekcji (i co rzeczywiście zrobiło).

IMG-3. LDA krok po kroku po centralizacji lub standaryzacji

wprowadź opis zdjęcia tutaj

IMG-4. LDA w R (ustawienia domyślne)

LDA w IMG-3, gdzie wyśrodkowałem dane (co byłoby preferowanym podejściem), wygląda również dokładnie tak samo jak ten, który znalazłem w poście przez osobę, która wykonała LDA w R wprowadź opis zdjęcia tutaj


Kod referencyjny

Nie chciałem tutaj wklejać całego kodu, ale przesłałem go tutaj jako notes IPython z podziałem na kilka kroków, których użyłem (patrz poniżej) do projekcji LDA.

  1. Krok 1: Obliczanie wektorów średnich wymiarów d
    mi=1nixDinxk
  2. Krok 2: Obliczanie macierzy rozproszenia

    SW

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

    2.2 Macierz rozproszenia między klasami jest obliczana według następującego równania: gdzie jest ogólną średnią.S B = c i = 1 n i ( m i - m ) ( m i - m ) T mSb

    S.b=ja=1donja(mja-m)(mja-m)T.
    m
  3. Krok 3. Rozwiązanie ogólnego problemu wartości własnej dla macierzyS.W.-1S.b

    3.1 Sortowanie wektorów własnych przez zmniejszenie wartości własnych

    3.2 Wybór k wektorów własnych z największych wartości własnych. Łączenie dwóch wektorów własnych z najwyższymi wartościami własnymi w celu skonstruowania naszej macierzy wektorów wymiarowych wymiarowejW.re×kW.

  4. Krok 5: Przekształcenie próbek w nową podprzestrzeń

    y=W.T.×x.
ameba mówi Przywróć Monikę
źródło
Nie szukałem różnic, ale możesz zobaczyć dokładnie, co robi scikit-learn w źródle .
Dougal
Wygląda na to, że są one również standaryzowane (centrowanie, a następnie skalowanie poprzez podział przez odchylenie standardowe). Spodziewałbym się wyniku podobnego do tego z mojego trzeciego wykresu (i wykresu R) ... hmm
Dziwne: fabuła uzyskana za pomocą scikit (i ta, którą pokazują w swojej dokumentacji) nie ma sensu. LDA zawsze daje prognozy, które mają zerową korelację, ale oczywiście istnieje bardzo silna korelacja między prognozami Scikita na osiach dyskryminacyjnych 1 i 2. Coś tam jest wyraźnie nie tak.
ameba mówi Przywróć Monikę
@ameoba Tak, też tak myślę. Dziwne jest również to, że ten sam wykres, który pokazuję dla scikit, znajduje się w przykładowej dokumentacji: scikit-learn.org/stable/auto_examples/decomposition/... To sprawia, że ​​myślę, że moje użycie scikit jest prawidłowe, ale jest w tym coś dziwnego o funkcji LDA
@SebastianRaschka: Tak, zauważyłem. To naprawdę dziwne. Zauważ jednak, że pierwszy z twoich własnych (nie-scikitowych) wykresów LDA pokazuje również niezerową korelację, a zatem coś też musi być z nią nie tak. Czy wyśrodkowałeś dane? Projekcja na drugiej osi nie wydaje się mieć średniej zerowej.
ameba mówi Przywróć Monikę

Odpowiedzi:

20

Aktualizacja: Dzięki tej dyskusji scikit-learnzostał zaktualizowany i działa teraz poprawnie. Jego kod źródłowy LDA można znaleźć tutaj . Pierwotny problem był spowodowany drobnym błędem (patrz ta dyskusja na githubie ), a moja odpowiedź właściwie nie wskazywała na to poprawnie (przepraszam za jakiekolwiek zamieszanie). Ponieważ to wszystko nie ma już znaczenia (błąd został naprawiony), zredagowałem moją odpowiedź, aby skupić się na tym, jak LDA można rozwiązać za pomocą SVD, który jest domyślnym algorytmem scikit-learn.


ΣW.ΣbΣW.-1Σb

  1. ΣW.-1/2)

    ΣW.=US.UΣW.-1/2)=US.-1/2)UXW.=UL.V.ΣW.-1/2)=UL.-1U

  2. ΣW.-1/2)ΣbΣW.-1/2)ZA

    XbΣW.-1/2)

  3. ZAΣW.-1/2)ZA

    za

    ΣW.-1/2)ΣbΣW.-1/2)za=λza,
    ΣW.-1/2)za=ΣW.-1/2)za
    ΣW.-1Σbza=λza.

Podsumowując, LDA jest równoważne wybieleniu macierzy średnich klas w odniesieniu do kowariancji wewnątrz klasy, wykonaniu PCA na średnich klas i ponownym przekształceniu uzyskanych głównych osi w pierwotną (niebieloną) przestrzeń.

Wskazano na to np. W elementach statystycznego uczenia się , sekcja 4.3.3. W scikit-learnten sposób jest domyślnym obliczyć LDA ponieważ SVD macierzy danych jest numerycznie bardziej stabilne niż eigen-rozkładu jego matrycy kowariancji.

ΣW.-1/2)scikit-learn L.-1UUL.-1U

ameba mówi Przywróć Monikę
źródło
1
Dzięki za tę miłą odpowiedź. Doceniam to, że poświęciłeś tyle czasu na napisanie tego tak ładnie. Może mógłbyś wspomnieć o tym w dyskusji na GitHub; Jestem pewien, że to pomogłoby naprawić LDA w następnej wersji sci-kit
@SebastianRaschka: Nie mam konta na GitHub. Ale jeśli chcesz, możesz podać link do tego wątku.
ameba mówi Przywróć Monikę
ΣW.-1ΣbΣW.-1
2
ΣbΣW.-1ΣbΣW.-1(μ1-μ2))μja
ameba mówi Przywróć Monikę
3

Aby zamknąć to pytanie, omawiany problem z LDA został naprawiony w scikit-learn 0.15.2 .


źródło