Чому LDA, що вивчає Scitit Python, не працює належним чином і як він обчислює LDA за допомогою SVD?


26

Я використовував лінійний дискримінантний аналіз (LDA) з scikit-learnбібліотеки машинного навчання (Python) для зменшення розмірності і трохи цікавився результатами. Мені зараз цікаво, чим scikit-learnзаймається LDA , щоб результати виглядали інакше, ніж, наприклад, ручний підхід або LDA, зроблені в Р. Було б чудово, якби хтось міг дати мені тут деяку інформацію.

Що в основному найбільше стосується, це те, що scikit-plotпоказує кореляцію між двома змінними, де має бути кореляція 0.

Для тесту я використовував набір даних Iris, і перші 2 лінійних дискримінанта виглядали так:

IMG-1. LDA через scikit-learn

введіть тут опис зображення

Це в основному відповідає результатам, які я знайшов у документації, що навчається тут.

Тепер я пройшов крок за кроком LDA і отримав іншу проекцію. Я спробував різні підходи, щоб з’ясувати, що відбувається:

IMG-2. LDA щодо необроблених даних (без центрування, без стандартизації)

введіть тут опис зображення

І тут був би покроковий підхід, якби я спочатку стандартизував (нормалізація z-балів; відхилення одиниці). Я робив те саме, що робив лише середнє центрування, що повинно призвести до того самого відносного зображення проекції (і це було насправді).

IMG-3. Покрокова LDA після середнього центрування або стандартизації

введіть тут опис зображення

IMG-4. LDA в R (настройки за замовчуванням)

LDA в IMG-3, де я зосереджував дані (який був би кращим підходом), виглядає також точно так само, як той, який я знайшов у Пості від когось, хто зробив LDA в R введіть тут опис зображення


Код довідки

Я не хотів вставляти сюди весь код, але я завантажив його як зошит IPython, розбитий на кілька кроків, які я використав (див. Нижче) для проекції LDA.

  1. Крок 1: Обчислення середньовимірних векторів
    mi=1nixDinxk
  2. Крок 2: Обчислення матриць розсіювання

    2.1 Матриця розсіювання всередині класу обчислюється таким рівнянням:S W = c i = 1 S i = c i = 1 n xD i ( x - m i )SW

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

    2.2 Матриця розсіювання між класом обчислюється наступним рівнянням: де - загальне середнє значення.S B = c i = 1 n i ( m i - m ) ( m i - m ) T mSB

    SB=i=1cni(mim)(mim)T
    m
  3. Крок 3. Розв’язування узагальненої задачі власного значення для матриціSW1SB

    3.1. Сортування власних векторів шляхом зменшення власних значень

    3.2. Вибір k власних векторів з найбільшими власними значеннями. Об'єднання двох власних векторів з найвищими власними значеннями для побудови нашої -вимірної матриці власних векторівWd×kW

  4. Крок 5: Перетворення зразків на новий підпростір

    y=WT×x.

Я не проходив пошуки відмінностей, але ви можете точно бачити, що робить наука у джерелі .
Дугал

Схоже, вони також стандартизуються (центрування, а потім масштабування за допомогою поділу за стандартним відхиленням). Це, я б очікував на результат, схожий на той, що в моєму 3-му сюжеті (і на R), сюжет ... хм

Дивно: сюжет, який ви отримали з scikit (і той, який вони показують у своїй документації), не має сенсу. LDA завжди дає прогнози, які мають нульову кореляцію, але очевидно, що між прогнозами scikit на дискримінантні осі 1 і 2. існує дуже сильна кореляція. Щось там явно не так.
амеба каже: Відновити Моніку

@ameoba Так, я теж думаю. Що також дивно, що той самий сюжет, який я демонструю для scikit, є у прикладі документації: scikit-learn.org/stable/auto_examples/decomposition/… Це змушує мене думати, що моє використання scikit правильно, але що є щось дивне про функцію LDA

@SebastianRaschka: Так, я помітив. Це справді дивно. Однак зауважте, що перший із ваших власних (non-scikit) сюжетів LDA також показує ненульову кореляцію, а значить, і з цим щось має бути не так. Ви відцентрували дані? Проекція на другу вісь, здається, не має нульової середньої величини.
амеба каже, що повернеться до Моніки

Відповіді:


20

Оновлення: Завдяки цій дискусії scikit-learnоновлено та працює коректно зараз. Його вихідний код LDA можна знайти тут . Первісна проблема була пов’язана з незначною помилкою (див. Цю дискусію про Github ), і моя відповідь насправді не вказала на неї правильно (вибачте за будь-яку причину плутанини). Оскільки все це вже не має значення (виправлена ​​помилка), я відредагував свою відповідь, щоб зосередитись на тому, як LDA можна вирішити за допомогою SVD, що є алгоритмом за замовчуванням scikit-learn.


Після визначення матриць розсіювання та між класами та , стандартним розрахунком LDA, як зазначено у вашому запитанні, є прийняття власних векторів як дискримінантні осі ( див. наприклад тут ). Однак ті ж осі можна обчислити дещо по-іншому, використовуючи матрицю відбілювання:ΣWΣBΣW1ΣB

  1. Обчислити . Це трансформація відбілювання відносно об'єднаної коваріації в межах класу (детальніше див. Мою пов'язану відповідь).ΣW1/2

    Зауважте, що якщо у вас є власне-розкладання , то . Зауважте також, що один обчислити те ж саме, виконавши SVD об'єднаних даних у межах класу: .ΣW=USUΣW1/2=US1/2UXW=ULVΣW1/2=UL1U

  2. Знайдіть власні вектори , назвемо їх .ΣW1/2ΣBΣW1/2A

    Знову зауважте, що ви можете обчислити це, зробивши SVD даних між класом , трансформованими з , тобто дані між класами, побілені щодо внутрішнього класу коваріація.XBΣ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це шлях за замовчуванням для обчислення LDA , тому що SVD матриці даних чисельно більш стабільні , ніж про власних розкладанні його ковариационной матриці.

Зауважте, що замість можна використовувати будь-яке відбілювання, і все одно працюватиме точно так само. У використовується (замість ), і це працює чудово (всупереч тому, що спочатку було написано у моїй відповіді).ΣW1/2scikit-learn L1UUL1U


1
Дякую за цю приємну відповідь. Я ціную це, що ви знайшли час, щоб це красиво написати. Можливо, ви могли б згадати це в дискусії на GitHub; Я впевнений, що це може допомогти виправити LDA у наступній версії sci-kit

@SebastianRaschka: У мене немає облікового запису на GitHub. Але якщо хочете, ви можете надати там посилання на цю тему.
амеба каже, що повернеться до Моніки

@amoeba: Підручники зазвичай описують LDA так, як ви робили - власне значення розкладання . Цікаво, що для багатьох реалізацій LDA я знаю різний підхід. Їх осі є векторами до класових засобів, перетворених на . Ваше рішення LDA є ортонормальною основою цих векторів. LDA Scikit-learn дає такі самі результати, як і ці реалізації, тому я не думаю, що насправді є помилка. Σ - 1 WΣW1ΣBΣW1
каземакасе


2
@kazemakase: Ну, звичайно, якщо є лише два класи, то має ранг 1, і все значно спрощує, оскільки єдиний власний вектор задається , де - засоби класу. Я думаю, що це ви мали на увазі раніше? Це добре висвітлено, наприклад, у підручнику Bishop ML, розділ 4.1.4. Але узагальнення до кількох класів вимагає власного аналізу (Там само, 4.1.6). Крім того , код scikit ( в тому , що ми обговорюємо тут!) Робить використання СВД, два рази на насправді. Σ - 1 W Σ B Σ - 1 W ( μ 1 - μ 2 ) μ iΣBΣW1ΣBΣW1(μ1μ2)μi
амеба каже, що повернеться до Моніки

3

Щоб закрити це питання, обговорене питання з LDA було виправлене в scikit-learn 0.15.2 .

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.