Тема була про те, що PCA — це геометрія, а не заклинання. Тому й завдання перевіряють
не вміння викликати PCA(), а розуміння: що саме метод максимізує, чого він не бачить
і де він бреше, якщо його неправильно поставити.
рівень 1Рівень 1 — База
Візьми зошит із практики й доведи до кінця те, що там залишилось незакритим: графік накопиченої поясненої дисперсії.
- По горизонталі — кількість компонент від 1 до 7, по вертикалі — накопичений відсоток.
- Постав горизонтальну пунктирну лінію на рівні 90 %.
- Виділи (кольором або підписом) ту точку, у якій крива вперше перетинає поріг.
- Поруч намалюй стовпчики внеску кожної окремої компоненти — так, як це зроблено в другому інтерактиві лекції.
Далі — те саме на іншому наборі: візьми sklearn.datasets.load_wine (13 числових ознак,
178 рядків, завантажується локально), стандартизуй його й побудуй такий самий графік.
Зроблено, якщо: є два графіки з підписаними осями й порогом 90 %, і є одне речення на кожен набір: скільки компонент потрібно для 90 % і скільки відсотків тримають перші дві. Числа для нашої дошки мають збігтися з лекцією (5 компонент, 55.8 % на двох).
рівень 2Рівень 2 — Плюс
Перевір на числах, що PCA справді знаходить надлишкові ознаки, а не «найкорисніші».
Зроби три версії таблиці ознак і для кожної порахуй PCA на стандартизованих даних:
| версія | що в ній |
|---|---|
| A | сім ознак як у практиці |
| B | без оцінка_каталогу — тієї, що корелює з типова_ціна на 0.989 |
| C | сім ознак плюс восьма: ціна_в_тисячах = ціна / 1000 |
Для кожної версії випиши: усі власні числа, накопичену частку на двох компонентах і кількість компонент, потрібну для 90 %.
Питання, на які треба відповісти словами:
- чому у версії C останнє власне число дорівнює нулю (а не просто маленькому числу, як сьоме власне число у версії A, хоча пара 0.989 там теж була);
- версія B втратила майже-дублікат — і все одно для 90 % їй потрібна та сама кількість компонент, що й версії A. Чому викидання надлишкової колонки не скоротило список? Підказка: подивись, як змінилася накопичена частка на двох компонентах.
Зроблено, якщо: є таблиця з трьох рядків із трьома числами в кожному, і є дві відповіді по два-три речення. У відповіді про версію C має бути сказано, що дві ознаки повʼязані точно, а не приблизно, і тому один вимір зникає повністю. У відповіді про версію B має прозвучати, що надлишкова колонка займала не цілий вимір, а лише десяту частку відсотка — і викинути її означає прибрати саме стільки.
рівень 3Рівень 3 — Виклик
Напиши власну функцію PCA й доведи, що вона працює.
def мій_pca(X, скільки_компонент):
"""Повертає (координати, компоненти, пояснена_дисперсія)."""
...
Вимоги до реалізації:
- центрування робиш сам,
StandardScalerдля нього не використовуєш; - власні числа й вектори береш через
np.linalg.eighі сортуєш за спаданням; - функція повертає координати обʼєктів у нових осях, самі компоненти й вектор поясненої дисперсії;
- знак кожної компоненти фіксуєш за домовленістю: найбільша за модулем вага в компоненті має бути додатною — інакше порівняння з бібліотекою впаде на знаку.
Далі — три перевірки, кожна окремим assert:
- пояснена дисперсія збігається з
PCA().fit(X).explained_variance_; - компоненти збігаються з
pca.components_після приведення знака; - сума квадратів відстаней від точок до їхніх відновлених копій для k компонент дорівнює сумі відкинутих власних чисел, помноженій на (n − 1). Це і є те саме твердження з розділу 4 лекції, тільки для семи вимірів замість двох.
Останню перевірку сформулюй сам і поясни в коментарі, звідки береться множник (n − 1).
Зроблено, якщо:
- функція запускається на нашій матриці
Xі наload_wine, і всі триassertпроходять на обох; - у коді немає жодного виклику
sklearn.decomposition.PCA, окрім як усередині перевірок; - є коментар, який пояснює множник (n − 1) у третій перевірці.
Підказки
- Власні вектори
eighстоять у стовпцях, а не в рядках.sklearnтримає компоненти в рядках. Якщо забути транспонувати, порівняння з бібліотекою впаде — і причина буде зовсім не там, де ти її шукатимеш. - Знак не помилка. Якщо твоя перша компонента дорівнює бібліотечній з протилежним
знаком — це той самий напрямок. Порівнюй
np.abs(...)або фіксуй знак за домовленістю з пункту 4. - Для третього рівня не потрібна нова математика. Втрачена частина — це та сама d² зі схеми 1 лекції, тільки просумована по всіх точках і всіх викинутих напрямках. Спочатку перевір формулу на шести точках із розділу 5, де ти вже знаєш відповідь (140 і 20), і лише потім на семи ознаках.
- Версія C другого рівня зламається красиво. Останнє власне число не просто мале —
воно порядку
1e-16, тобто нуль із точністю до похибки обчислень. Це нормально: дві точно повʼязані колонки живуть в одному вимірі, а не у двох.