Машинне навчання · Блок 3 · Тема 13

PCA — метод головних компонент

Сім ознак не можна намалювати. Дві — можна. Питання лише в тому, які дві обрати — і чи обовʼязково це мають бути ознаки з таблиці.

Блок навчання без учителя почався з кластеризації: ми групували рядки, не маючи жодної правильної відповіді. Тепер друга задача того самого блоку, і вона дзеркальна — стискати треба не рядки, а стовпці. Замість «які оголошення схожі між собою» питання звучить так: скільки насправді чисел потрібно, щоб описати оголошення, якщо в таблиці їх сім?

Приклад на всю тему — та сама дошка про вживані телефони, що і в темі 08. Беремо 1 100 оголошень із відомою ціною і сім числових ознак: ціна, типова ціна для цієї моделі й року, оцінка з каталогу, рік випуску, памʼять, стан у балах від 1 до 4 і вік акаунта продавця. Сім чисел на оголошення. Побудувати з них одну картинку неможливо — людське око читає два виміри, з натяжкою три.

Метод головних компонент (principal component analysis, PCA) робить рівно це: із семи колонок він виготовляє дві нові, намагаючись викинути якнайменше. Не вибирає дві з наявних — саме виготовляє нові, і ця різниця виявиться головною в усій темі.

01 / МотивТри різні «навіщо»

«Зменшити розмірність» звучить як одне бажання, а насправді їх три, і вони вимагають різних інструментів. Плутанина між ними — джерело половини невдалих спроб застосувати PCA.

Перше: щоб побачити. Найчесніша й найчастіша причина. У тебе сім колонок, ти хочеш подивитись на дані очима — а очі працюють із площиною. Можна малювати всі пари колонок підряд, але для семи ознак це двадцять одна картинка, і жодна з них не показує сім вимірів одночасно. Тут зменшення розмірності потрібне рівно для однієї хвилини перегляду, і моделі воно не стосується взагалі.

Друге: щоб прискорити. Менше стовпців — менше обчислень і менше памʼяті. Для семи ознак це смішно, для семи тисяч (наприклад, зображення, розгорнуте в рядок пікселів) — вирішально. Тут важлива не картинка, а те, що після стиснення модель навчається за хвилини замість годин.

Третє: щоб прибрати шум і надлишковість. Якщо дві колонки говорять майже те саме, друга не додає інформації — лише зайвий вимір, у якому модель має щось оцінювати. А зайві виміри коштують дорого — і найдивніше те, що разом із ними ламається саме поняття «схожий».

Перевірити це можна за хвилину, і краще один раз побачити числа. Розкидаємо тисячу точок навмання по квадрату зі стороною 1, ставимо в цей же квадрат ще одну точку й питаємо дві речі: як далеко до найближчої з тисячі й як далеко до найдальшої. Для двох ознак виходить 0.015 і 1.047 — найдальша приблизно у сімдесят разів далі за найближчу, і слово «найближчий» тут справді щось означає. Повторюємо той самий дослід у десяти вимірах: 0.51 і 1.91, різниця вже лише вчетверо. У ста вимірах: 3.32 і 4.78 — різниця в півтора раза. Найближча точка стала майже такою ж далекою, як найдальша.

Це називають прокляттям розмірності (curse of dimensionality). Причина проста: кожна нова ознака додає до відстані ще один доданок, і чим більше доданків складається, тим менше окрема відмінність здатна змістити загальну суму. Точки розповзаються, і всі опиняються приблизно однаково далеко одна від одної. Страждає від цього не якийсь один метод, а будь-який, що міряє відстані або оцінює окремий параметр на кожен вимір: у високій розмірності йому потрібно в рази більше даних. Кластеризація з двох попередніх тем — теж у цьому списку.

Таблиця 1 · Навіщо зменшувати розмірність і чим це роблять

Три різні мети. Інструмент під кожну свій, і плутати їх дорого.

навіщощо це означає на практицічим це роблять
Побачитинамалювати всі ознаки на одній картинці й помітити групи, хвости, дивні точкиPCA — швидко й із формулою, яку можна застосувати до нових даних; t-SNE, UMAP — картинка красивіша, але одноразова
Прискоритисотні або тисячі стовпців перетворити на десятки, щоб навчання йшло хвилини, а не годиниPCA і його родичі; іноді достатньо просто викинути частину стовпців
Прибрати надлишковістьдві колонки говорять те саме — залишити один вимір замість двохPCA стискає їх в одну компоненту; відбір ознак просто викидає другу
Головна різниця в останній колонці. Відбір ознак (feature selection) залишає підмножину тих стовпців, що вже є, і після нього таблицю можна читати. PCA будує нові стовпці як суміші старих — після нього таблиця стає нечитабельною, зате коротшою. Це різні операції, і PCA не є способом «вибрати найкорисніші ознаки».

02 / НадлишокОзнака, яка нічого не додає

Почнемо з найпростішого випадку, у якому зайвий вимір видно неозброєним оком. У нашій таблиці є дві колонки, що відповідають на одне питання «скільки цей телефон приблизно коштує»: типова_ціна — медіана реальних цін на дошці для пари «модель + рік», і оцінка_каталогу — ціна нового апарата з каталогу, помножена на 18 % зношення за кожен рік. Порахуємо їхню кореляцію (тема 08):

кореляція(типова_ціна, оцінка_каталогу) = 0.989

Це майже одиниця. Знаючи одну колонку, ти передбачаєш другу з похибкою в кілька відсотків. Якщо намалювати оголошення в осях «типова ціна — оцінка каталогу», хмара виявиться не хмарою, а майже прямою лінією: точки розкидані вздовж діагоналі й майже не розкидані впоперек.

Тепер найважливіше спостереження всієї теми. Ця хмара живе у двох вимірах лише формально. Насправді, щоб описати положення точки з непоганою точністю, вистачить одного числа — того, наскільки далеко вона зайшла вздовж діагоналі. Другий вимір існує, але в ньому майже нічого не відбувається.

PCA — це машинка, яка знаходить такі напрямки автоматично й у будь-якій кількості вимірів, де малювати вже неможливо. У нашій семивимірній таблиці остання компонента виявиться саме різницею між цими двома колонками, і на неї припаде 0.15 % усього розкиду. Тобто одна з семи осей — це фактично шум округлення.

03 / ГеометріяНапрямок найбільшого розкиду

Забудьмо на кілька абзаців про формули. PCA — геометрія, і починати треба з неї.

Уяви хмару точок на площині. У неї є центр — точка, координати якої дорівнюють середнім по кожній осі. І в неї є форма: у якомусь напрямку хмара витягнута сильніше, ніж у решті. Візьми олівець, приклади до хмари й покрути навколо центру: є положення, у якому олівець «протикає» хмару вздовж, і положення, у якому він лежить упоперек. Напрямок, у якому хмара витягнута найсильніше, і є перша головна компонента. Ніякої іншої означеної суті тут немає — це просто напрямок найбільшої витягнутості.

Далі — друга компонента. Вона обирається за тим самим правилом (найбільший розкид), але з обмеженням: вона мусить бути перпендикулярною до першої. Чому перпендикулярною — питання не естетичне. Якби другий напрямок міг бути будь-яким, він просто зліг би з першим і повторив ту саму інформацію. Перпендикулярність гарантує, що нова компонента розповідає про хмару щось таке, чого перша не сказала.

Для семи ознак усе так само, просто хмара живе в семивимірному просторі: перша компонента — напрямок найбільшого розкиду, друга — найбільшого з того, що лишилось після першої, і так далі, аж поки напрямків не набереться стільки, скільки було ознак.

Тепер про те, що означає «стиснути». Візьмімо одну точку й одну пряму, що проходить через центр хмари. Опустимо з точки перпендикуляр на пряму — отримаємо проєкцію. Проєкція описується одним числом: наскільки далеко вздовж прямої вона стоїть від центру. Це число ми залишаємо. Довжина самого перпендикуляра — це те, що ми втратили: після стиснення точку вже не відрізнити від будь-якої іншої з таким самим положенням уздовж прямої.

Схема 1 · Що саме зберігається, а що втрачається

Три точки хмари, одна пряма через центр. Для кожної точки — координата вздовж прямої та перпендикуляр до неї.

Дві частини одного вектора. Вектор від центру хмари до точки розкладається на дві перпендикулярні частини: t — уздовж прямої, її ми зберігаємо, і d — упоперек, її ми викидаємо. За теоремою Піфагора t² + d² дорівнює квадрату довжини самого вектора, і ця довжина від кута прямої не залежить взагалі.
Пряму через хмару можна проводити по-різному. Зверни увагу, що відстань від точки до прямої ми міряємо перпендикуляром — найкоротшим шляхом. Її можна було б міряти й інакше: по вертикалі — тобто наскільки високо точка стоїть над прямою або нижче за неї, якщо рухатись строго вздовж осі y. Це не те саме, і на тій самій хмарі два способи дають дві різні прямі. Вертикальний спосіб має сенс тоді, коли осі нерівноправні: одна колонка щось пояснює, друга нею пояснюється, і ми хочемо вгадувати другу за першою. Далі в курсі ми дійдемо до методу, побудованого саме на цьому, — і корисно буде памʼятати, що PCA робить інакше. Тут обидві осі рівні в правах: ніякої «правильної» колонки немає, є тільки хмара, яку треба покласти на пряму з найменшою втратою.

04 / ЕквівалентністьДві задачі, одна відповідь

Ту саму задачу описують двома способами, і в підручниках вони трапляються порівну.

Постановка перша, «зберегти». Знайти напрямок, проєкції на який розкидані найсильніше. Логіка: якщо після стиснення точки злипнуться в одну купу, ми втратили все, що їх розрізняло; отже, шукаємо напрямок, де вони розрізняються найбільше.

Постановка друга, «не втратити». Знайти пряму, до якої точки в сумі лежать найближче — тобто мінімізувати суму квадратів перпендикулярів. Логіка: стиснення замінює кожну точку її проєкцією, тож помилка стиснення — це і є довжина перпендикуляра.

Ці дві постановки виглядають різними — одна про максимум, друга про мінімум, одна про розкид, друга про помилку. Насправді це буквально одна задача, і причина — теорема Піфагора зі схеми вище. Для кожної точки квадрат відстані до центру дорівнює t² + d². Складемо це по всіх точках:

Σ t2  +  Σ d2  =  Σ (відстань до центру)2

Права частина не містить кута прямої. Скільки не крути олівець, сума квадратів відстаней від точок до центру хмари не змінюється — це властивість самої хмари. Отже, ліва частина — стала. А якщо сума двох доданків стала, то збільшити перший можна рівно на стільки, на скільки зменшиться другий.

Максимум збереженого розкиду й мінімум втраченого — це та сама точка на шкалі кутів. Не «приблизно те саме» й не «зазвичай збігається»: строго те саме, з арифметики. Найкраще це видно, коли крутиш пряму сам.

Інтерактив 1 · Крути пряму й дивись на два числа

Шість оголошень, дві ознаки — ціна й оцінка каталогу, обидві в тисячах гривень. Проведи повзунок від 0 до 180 градусів і стеж за двома величинами внизу: вони дзеркальні.

розкид уздовж0.00
втрачено0.00
сума32.00
збережено0 %
Сума в третій комірці не змінюється ніколи — вона дорівнює 32.00 при будь-якому куті. Максимум першого числа (28.00) і мінімум другого (4.00) припадають на один і той самий кут 26.6°. Криві внизу — ті самі дві величини як функції кута: одна крива є другою, перевернутою догори дриґом.

І ось тепер — назва. Напрямок, який максимізує розкид проєкцій, у лінійній алгебрі зветься власним вектором коваріаційної матриці, а сам максимальний розкид — її власним числом. Це не інше означення PCA й не глибша суть: це просто те, як математики називають цей напрямок, і зручний спосіб його порахувати без перебору кутів. Далі ми зробимо це руками на шести точках.

05 / ЧислаПорахуймо руками

Візьмімо шість оголошень і дві ознаки: ціну, яку просить продавець, і оцінку каталогу. Обидві в тисячах гривень — тобто в тих самих одиницях, тому масштабувати нічого не треба (у розділі 7 буде видно, чому це важлива обмовка).

Крок 1 · центруємо

Середня ціна — 11, середня оцінка — 9. Віднімаємо середні від кожної точки: тепер центр хмари стоїть у нулі, і всі подальші формули стають коротшими. Центрування — обовʼязкова перша дія PCA, бо всі напрямки ми відлічуємо саме від центру.

Крок 2 · коваріаційна матриця

Це таблиця 2×2 із трьох чисел. По діагоналі — дисперсії кожної ознаки: наскільки сильно вона сама по собі розкидана. Поза діагоналлю — коваріація: наскільки ознаки розкидані разом. Ділимо на n−1 = 5, як це роблять numpy і scikit-learn.

Sxx = 116 / 5 = 23.2 (дисперсія ціни) Syy = 44 / 5 = 8.8 (дисперсія оцінки) Sxy = 48 / 5 = 9.6 (коваріація) ⎡ 23.2 9.6 ⎤ C = ⎢ ⎥ ⎣ 9.6 8.8 ⎦

Матриця симетрична: коваріація ціни з оцінкою — те саме число, що й коваріація оцінки з ціною. Сума діагоналі, 23.2 + 8.8 = 32, — це весь розкид хмари, і саме її ми далі розкладемо на дві частини.

Крок 3 · характеристичне рівняння

Власне число λ — це таке значення, при якому матриця C − λ·I перестає бути оборотною, тобто її визначник дорівнює нулю. Для матриці 2×2 визначник — це «добуток діагоналі мінус добуток антидіагоналі», і рівняння виходить звичайним квадратним:

(23.2 − λ)(8.8 − λ) − 9.6 · 9.6 = 0 204.16 − 32 λ + λ2 − 92.16 = 0 λ2 − 32 λ + 112 = 0
Крок 4 · власні числа

Дискримінант: 32² − 4·112 = 1024 − 448 = 576, а корінь із 576 — рівно 24.

λ1 = (32 + 24) / 2 = 28 λ2 = (32 − 24) / 2 = 4

Перевірка: 28 + 4 = 32 — рівно сума діагоналі C. Це не збіг, а загальне правило: власні числа ділять між собою весь розкид хмари й нічого не додають і не гублять. Перша компонента забирає 28 із 32, тобто 87.5 %, друга — решту 12.5 %.

Крок 5 · власний вектор

Тепер напрямок. Підставляємо λ1 = 28 у рівняння (C − λI)·u = 0 і беремо перший рядок:

(23.2 − 28) · u1 + 9.6 · u2 = 0 −4.8 · u1 + 9.6 · u2 = 0 u1 = 2 · u2

Тобто напрямок (2, 1): на два кроки праворуч — один крок угору. Довжина такого вектора дорівнює √5 ≈ 2.236, а нам потрібен вектор довжини 1, тому ділимо на неї:

u = (2, 1) / √5 = (0.894, 0.447) кут = 26.6°
Крок 6 · проєкції й перевірка

Координата точки вздовж напрямку — це скалярний добуток центрованої точки на u: беремо кожну координату, множимо на відповідне число з u й додаємо. Для першого оголошення це (−7)·0.894 + (−1)·0.447 = −6.71.

А тепер головна перевірка всієї теми: порахуємо дисперсію цих шести проєкцій. Вона має дорівнювати λ1 = 28 — тому що власне число і є збереженим розкидом.

Таблиця 2 · Той самий розрахунок повністю, у числах

Шість оголошень, центрування, проєкція на першу компоненту та відстань до неї.

оголошенняцінаоцінка ціна − 11оцінка − 9 t (уздовж)d (упоперек)
А48−7−1−6.71+2.24455
Б85−3−4−4.47−2.24205
В98−2−1−2.240.0050
Г1310+2+1+2.240.0050
Д169+50+4.47−2.24205
Е1614+5+5+6.71+2.24455
сума6654000.000.0014020
÷ (n−1)28.04.0
Останній рядок — уся суть методу. Дисперсія проєкцій дорівнює 28.0 — це рівно λ₁, порахований у кроці 4 через дискримінант. Середній квадрат перпендикулярів дорівнює 4.0 — це рівно λ₂. Разом 32.0, тобто весь розкид хмари, і жодне з цих трьох чисел ми не підбирали. Знак у колонці d показує лише те, з якого боку прямої лежить точка; у сумі квадратів він ролі не грає.

Прочитай таблицю ще раз і зістав із інтерактивом вище. Ці ж 140 і 20 стоять на табло, коли повзунок показує 27 градусів. Ніякої магії в PCA немає: центрування, три суми, квадратне рівняння й один скалярний добуток. Усе решта — та сама арифметика в більшій кількості вимірів, де замість квадратного рівняння працює numpy.linalg.eigh.

06 / ДисперсіяПояснена дисперсія

У прикладі з шести точок перша компонента забрала 87.5 % розкиду. Ця частка й зветься поясненою дисперсією (explained variance): власне число компоненти, поділене на суму всіх власних чисел. Слово «пояснена» тут не про причини — воно означає тільки «утримана», «не втрачена при стисненні».

Практичне питання завжди одне: скільки компонент лишити. Відповідь дає накопичена частка. Береш перші дві — дивишся, скільки відсотків розкиду вони разом тримають. Береш три — дивишся знову. Зупиняєшся там, де цифра тебе влаштовує; типовий поріг у роботі — 90 або 95 %, але це домовленість, а не закон.

Порахуємо на нашій дошці. Сім стандартизованих ознак, 1 100 оголошень.

Інтерактив 2 · Скільки компонент лишити

Стовпчики — внесок кожної з семи компонент, лінія — накопичена частка. Нижче видно, скільки розкиду кожної вихідної ознаки переживає стиснення.

накопичено55.8 %
втрачено44.2 %
внесок цієї15.9 %
відстань1.76
«Відстань» — середня відстань від оголошення до його відновленої копії у стандартизованих одиницях: беремо k координат, збираємо з них назад сім ознак і міряємо, наскільки схибили. При семи компонентах вона рівно нуль — нічого не втрачено, просто повернули систему координат.

Числа виявились не такими, як хотілося б. Перша компонента тримає 39.9 %, друга додає 15.9 % — разом лише 55.8 %. Щоб дійти до 90 %, потрібно пʼять компонент із семи (94.2 %); чотири дають 84.6 %. Наша таблиця стискається погано, і це нормальний результат, а не помилка розрахунку: сім ознак здебільшого справді розповідають про різні речі. Модель телефона, вік акаунта та стан корпусу між собою не повʼязані ніяк.

Єдиний вимір, який справді нічого не важить, — сьомий: 0.15 %. Подивись на його склад — це різниця між типова_ціна й оцінка_каталогу, тими самими двома колонками з кореляцією 0.989. PCA сам, без підказок, знайшов дублікат і склав його в один вимір із мізерною вагою.

Що робити з цим знанням. Якщо мета була «побачити», бери дві компоненти й памʼятай, що дивишся на 55.8 % розкиду — картинка приблизна за побудовою. Якщо мета була «прискорити», пʼять компонент замість семи економлять мало, і чесна відповідь — не стискати взагалі. PCA не зобовʼязаний давати виграш; коли не дає, про це треба сказати, а не витискати з нього результат.

07 / МасштабБез масштабу все брехня

Тепер про обмовку, яку я зробив у розділі 5. Там обидві ознаки були в тисячах гривень, і масштабувати не було потреби. У справжній таблиці одиниці різні — і це ламає PCA сильніше, ніж будь-яку іншу модель курсу.

Причина проста, якщо памʼятати означення. PCA шукає напрямок найбільшого розкиду, а розкид міряється у квадратах одиниць. Ось стандартні відхилення наших семи ознак:

ціна 8 689 ₴ рік 2.31 типова_ціна 5 077 ₴ памʼять_гб 123.78 оцінка_каталогу 6 150 ₴ стан_бал 0.85 вік_акаунта 407 днів

Ціна розкидана на 8 689 «одиниць», стан — на 0.85. У квадратах різниця стає стотисячною. Тому напрямок найбільшого розкиду майже напевно збігатиметься з ціною — не тому, що ціна важливіша, а тому, що вона виміряна в дрібніших одиницях. Перепиши ціну в тисячах гривень — і перша компонента миттєво стане іншою, хоча дані не змінились. Метод, який залежить від вибору одиниць вимірювання, у такому вигляді користі не має.

Ліки ті самі, що в темі 09: StandardScaler. Кожну колонку зводимо до середнього 0 і стандартного відхилення 1, після чого всі ознаки заходять у розрахунок на рівних. Подивись, що це міняє.

Інтерактив 3 · Одна кнопка, дві різні перші компоненти

Стовпчики — ваги семи ознак у першій компоненті. Перемкни режим і подивись, що лишається від решти ознак, коли ціна заходить у сирих гривнях.

режим
частка PC179.5 %
найбільша вагаціна
вага ціни0.758
вага стану0.000
Ваги — це числа з вектора першої компоненти, тобто коефіцієнти, з якими вихідні ознаки входять у нову. Сума їхніх квадратів завжди дорівнює 1: вектор має одиничну довжину, і ознаки конкурують за цю одиницю між собою. Висота стовпчика — модуль ваги, а підпис над ним іде зі знаком: мінус означає, що ознака входить у компоненту в протилежний бік.

У режимі «як є» на три цінові колонки припадає 99.9996 % квадрата довжини вектора. Рік, памʼять, стан і вік акаунта разом набирають 0.0000045 — їх у першій компоненті просто немає. Формально метод відпрацював; змістовно він побудував складну конструкцію, яка означає «ціна».

Правило без винятків для цієї теми. Якщо колонки виміряні в різних одиницях, стандартизація перед PCA обовʼязкова. Виняток один: коли всі ознаки вже в одних одиницях і різниця в їхньому розкиді змістовна (пікселі одного зображення, щомісячні продажі за рік). У таблиці, де поруч гривні, дні та бали, такого не буває.

08 / МежіЧого PCA не вміє

Тепер нарешті намалюймо ту саму картинку, заради якої все й починалось: 1 100 оголошень у площині перших двох компонент.

Схема 2 · Дошка в двох компонентах

Ті самі 1 100 оголошень двічі. Ліворуч колір — цінова сімʼя моделі (Alfa дешеві, Beta середні, Gamma дорогі). Праворуч ті самі точки пофарбовано за колонкою «шахрайське», якої PCA не бачив.

Ліворуч структура є, праворуч — немає. Медіана першої компоненти зростає рівно за ціновим класом моделі: Alfa A5 −1.16, Alfa A7 −0.71, Beta 12 −0.38, Beta 12 Pro +0.34, Gamma X +1.04, Gamma X Ultra +1.87. А медіана в шахрайських оголошень −0.38 проти −0.43 у чесних — тобто ніякої різниці.

Ліва картинка — успіх: PCA сам, без жодної підказки, вишикував телефони за ціновим класом. Колонки «модель» у нього не було взагалі, і все ж перша компонента впорядкувала оголошення саме за нею, бо ціна, типова ціна й оцінка каталогу разом і є ціновим класом. Це і є те, заради чого метод застосовують: знайти головну вісь варіації, коли ти сам не знаєш, що шукати.

Права картинка — чесний провал, і він повчальніший. Шахрайські оголошення розсипані по всій площині рівно так само, як чесні. Причини дві, і обидві варто памʼятати.

PCA не знає, що ти шукаєш. Він максимізує розкид, а не користь. Найрозкиданіший напрямок у цій таблиці — «дорогий телефон проти дешевого», і саме його метод і повернув. Ознака, за якою відрізняються шахраї, могла б жити в шостій компоненті з внеском 5.7 % — і, викинувши все, крім двох перших, ти б викинув її першою.

Компоненти лінійні. Шахрая на цій дошці видає не ціна, а відношення ціни до типової: 1 200 грн за телефон, що коштує 12 000. Відношення — дія нелінійна, і жодна сума виду a·ціна + b·типова її не відтворить. PCA будує тільки такі суми, тому ця структура для нього невидима в принципі. Дай методу колонку |ln(ціна ÷ типова)| з теми 10 — і все зміниться. Але придумав би цю колонку ти, а не PCA.

Третя втрата помітна на самому вигляді результату: компоненти нічого не означають. Ось перша, повністю:

PC1 = 0.44·ціна + 0.57·типова + 0.57·каталог + 0.39·рік + 0.06·памʼять + 0.02·стан − 0.03·вік

Як це назвати? «Загальна дорожнеча оголошення» — приблизно, з натяжкою. У якій це одиниці? Ні в якій. Що означає, що в оголошення PC1 = 2.3? Нічого, що можна сказати продавцеві. Модель на компонентах може працювати чудово, але пояснити її рішення людині — а це буває вимогою — стає майже неможливо. Поки що порівняй із тим, як пояснив би рішення живий модератор: «ціна втричі нижча за типову, акаунт молодший за тиждень» — дві зрозумілі умови, кожна названа своїм імʼям. Далі в курсі буде модель, яка пояснює себе саме так, ланцюжком простих умов. А тут показувати нічого: сім вихідних колонок змішані в одне число з вагами.

Коли потрібна саме картинка

Якщо мета була лише подивитись на дані, у PCA є сильніші конкуренти — t-SNE та UMAP. Вони нелінійні: намагаються зберегти не загальний розкид, а сусідство, тобто щоб точки, близькі у вихідному просторі, лишились близькими й на картинці. Групи на їхніх малюнках виглядають набагато виразніше.

Ціна за це висока й часто не проговорена. По-перше, вони не дають перетворення: PCA видає сім чисел на компоненту, які можна застосувати до будь-якого нового оголошення хоч через рік, а t-SNE просто розкладає наявні точки й для нової доведеться рахувати все заново. По-друге, відстані між далекими групами на таких картинках нічого не значать: дві купки поруч не означають, що вони схожі. По-третє, результат залежить від налаштувань, і на тих самих даних із різними параметрами виходять різні картинки. Тому правило просте: t-SNE та UMAP — для очей, PCA — для конвеєра.

09 / ВитікВитік через PCA

Тепер помилка, яку роблять майже всі, і майже завжди — з добрих міркувань. Виглядає вона так:

Z = StandardScaler().fit_transform(усі_дані) # ← ось тут T = PCA(n_components=5).fit_transform(Z) # ← і тут навч, тест = train_test_split(T, ...)

Логіка здається бездоганною: PCA — метод без учителя, він таргета не бачить, отже відповіді підглянути не може. Логіка хибна. Витік — це не тільки підглядання відповідей, а будь-яке використання тестових рядків при підготовці даних (тема 09). Середні й стандартні відхилення для StandardScaler пораховані по всіх рядках, зокрема тестових. Коваріаційна матриця — так само. Напрямки компонент підігнані під ту хмару, у якій уже лежить тест. Тест перестав бути незнайомими даними ще до того, як зʼявилась перша модель.

Ефект можна поміряти. Візьмемо просте питання: яку частку розкиду тестових рядків утримують дві компоненти?

1 100 оголошень чесно 54.6 % з витоком 56.1 % 40 оголошень чесно 53.4 % з витоком 62.8 %

На великій вибірці різниця півтора відсотка — не катастрофа, але вона є, і вона завжди в один бік, бо PCA припасувався до тесту. На сорока рядках розрив уже девʼять із половиною: чим менше даних, тим більше метод підганяється під конкретні рядки. І це та сама історія, що з масштабуванням у темі 09: помилка непомітна в коді, не викидає жодного попередження й завищує результат.

Правильно так. StandardScaler і PCA кладуться в Pipeline разом із моделлю. Тоді на кожному згині крос-валідації середні, відхилення й компоненти перераховуються заново — і тільки на навчальній частині згину (тема 09). Тестові рядки лише проходять через уже готове перетворення методом transform, і жодне число з них у нього не потрапляє.

10 / ДаліЩо далі

Підсумок теми в чотирьох рядках. PCA шукає напрямки найбільшого розкиду й будує з них нові координати. Перша компонента — напрямок, у якому хмара витягнута найсильніше; максимум збереженого розкиду й мінімум втрат — це одна й та сама задача. Скільки компонент лишити, вирішує накопичена пояснена дисперсія. Перед PCA стандартизація обовʼязкова, а сам PCA живе всередині конвеєра, а не до поділу даних.

І одне спостереження, яке дуже знадобиться в наступній темі. Стиснення до k компонент — це відновлення точки з неповних даних, і для кожного оголошення можна поміряти, наскільки погано воно відновилось. Для більшості ця відстань невелика: точка лежить там, де лежать усі. А от оголошення, яке PCA відновлює з великою похибкою, — це оголошення, не схоже на решту. Саме так з методу головних компонент виходить детектор дивних рядків, і на цьому будується пошук аномалій — наступна тема блоку. Там ця відстань стане не діагностикою, а самим прогнозом.

Далі в практиці. У practice.ipynb ми рахуємо PCA двічі: спершу вручну на numpy — центрування, коваріаційна матриця, linalg.eigh — а потім бібліотечним PCA, і звіряємо числа до знака. Далі — пояснена дисперсія, картинка у двох компонентах, вироджена перша компонента без масштабування й замір витоку в цифрах.

Далі в темі

Теорію прочитано. Тепер закріпи її на практиці.