Машинное обучение
PCA и снижение размерности
Датасет с 10 000 признаков. Модель обучается часами, переобучается, а визуализировать данные невозможно - как понять, что происходит в 10 000-мерном пространстве? Оказывается, большинство этих признаков дублируют друг друга, и реальная структура данных живёт в пространстве гораздо меньшей размерности. PCA, t-SNE и UMAP - три инструмента, которые находят эту скрытую структуру и сжимают данные без существенной потери информации.
- **Геномика:** экспрессия 20 000 генов на клетку. PCA сжимает до 50 компонент для кластеризации типов клеток, а UMAP визуализирует миллионы клеток в 2D - так обнаружили новые подтипы раковых клеток
- **Рекомендательные системы:** Netflix имеет миллионы пользователей и тысячи фильмов. PCA (через SVD) сжимает матрицу рейтингов до 100-200 латентных факторов - «любит экшн», «предпочитает европейское кино» - и на них строит рекомендации
- **NLP:** word embeddings (Word2Vec, GloVe) живут в 300-мерном пространстве. t-SNE и UMAP визуализируют их в 2D, показывая кластеры по смыслу: страны рядом со столицами, глаголы рядом с глаголами
Сначала линии наилучшего приближения, потом главные компоненты
PCA изобрели дважды, с двух разных сторон. В 1901 году британский статистик Карл Пирсон, более известный по коэффициенту корреляции, опубликовал работу «On Lines and Planes of Closest Fit to Systems of Points in Space». Его вопрос был геометрическим: какая прямая или плоскость минимизирует перпендикулярное расстояние до облака точек? Ответом, как выяснилось, оказывается именно направление максимальной дисперсии - первая главная ось. У Пирсона не было вычислительных средств, чтобы применить метод к реальным данным, поэтому он оставался скорее любопытным наблюдением. Тремя десятилетиями позже, в 1933 году, американский экономист Гарольд Хотеллинг переоткрыл технику со статистической точки зрения, задавшись вопросом, как описать множество коррелированных переменных несколькими некоррелированными. Именно Хотеллинг назвал их «главными компонентами» и связал всю конструкцию с собственными векторами ковариационной матрицы - в том виде, как её преподают сегодня. Два исследователя, геометрия и статистика - одни и те же оси максимального разброса.
Предварительные знания
Собственные значения и главные компоненты
Представьте, что вы анализируете датасет с 200 признаками: рост, вес, давление, уровень сахара, холестерин... Обучать модель на 200 признаках дорого, многие из них коррелируют друг с другом (рост и длина ног, вес и объём талии), а визуализировать 200-мерное пространство невозможно. **PCA (Principal Component Analysis)** решает эту проблему: находит новые оси координат, вдоль которых данные «растянуты» максимально, и позволяет отбросить оси, где данные почти не варьируются.
Ключевая идея PCA: если облако точек в 2D вытянуто под углом 45 градусов, то ось максимальной дисперсии не совпадает ни с x, ни с y. PCA находит **новую систему координат**, где первая ось (PC1) проходит вдоль максимального «растяжения» данных, вторая (PC2) - перпендикулярна первой и захватывает максимум из оставшейся дисперсии, и так далее. Эти новые оси называются **главными компонентами (principal components)**.
Математически PCA работает через **ковариационную матрицу**. Ковариационная матрица показывает, как каждая пара признаков связана между собой. Диагональные элементы - дисперсия каждого признака, недиагональные - ковариация между парами. PCA находит **собственные векторы (eigenvectors)** этой матрицы - они задают направления главных компонент. А **собственные значения (eigenvalues)** показывают, сколько дисперсии приходится на каждое направление. Чем больше eigenvalue - тем важнее компонента.
**Стандартизация обязательна перед PCA!** Если признаки в разных масштабах (рост в см: 150-200, зарплата в рублях: 30000-300000), то PCA «подумает», что зарплата важнее просто потому, что числа больше. StandardScaler приводит все признаки к среднему 0 и дисперсии 1 - после этого PCA сравнивает направления честно.
Почему перед PCA необходимо стандартизировать данные?
Explained Variance: сколько информации сохранено
Мы научились проецировать данные на главные компоненты, но ключевой вопрос остаётся: **сколько компонент оставить?** Если данные 100-мерные, а мы возьмём 2 компоненты - может, потеряем 80% информации. А может, 2 компоненты сохранят 95%. Ответ даёт **explained variance ratio** - доля общей дисперсии, которую объясняет каждая компонента.
Собственное значение (eigenvalue) каждой компоненты показывает, сколько дисперсии она захватывает. **Explained variance ratio** - это eigenvalue, делённый на сумму всех eigenvalues. Если у нас 4 компоненты с eigenvalues [2.93, 0.93, 0.14, 0.02], то PC1 объясняет 2.93 / (2.93 + 0.93 + 0.14 + 0.02) = **72.8%** дисперсии. PC2 добавляет ещё **23.0%**. Вместе - **95.8%**. Значит, 2 компоненты из 4 сохраняют почти всю информацию.
**Правила выбора n_components:** - **Визуализация:** n_components=2 или 3 (для графиков) - **Порог дисперсии:** n_components=0.95 - sklearn автоматически выберет минимум компонент, сохраняющих 95% - **Elbow method:** строим scree plot, ищем «локоть» - точку, после которой прирост дисперсии резко замедляется - **Практика:** для preprocessing перед ML обычно 95-99%; для визуализации - 2-3 компоненты
Реальный пример: датасет MNIST (рукописные цифры) имеет 784 признака (28x28 пикселей). PCA с порогом 95% сжимает их до **~150 компонент** - в 5 раз меньше. При этом классификатор на 150 PCA-признаках работает почти так же точно, как на 784, но обучается в разы быстрее. А для визуализации (2 компоненты) - кластеры цифр уже хорошо различимы, хотя сохранено лишь ~25% дисперсии.
Датасет имеет 50 признаков. PCA показывает cumulative explained variance: PC1=40%, PC1+PC2=65%, PC1-PC5=88%, PC1-PC10=96%. Сколько компонент выбрать для порога 95%?
t-SNE: визуализация в 2D
PCA отлично сжимает данные для preprocessing, но у него есть фундаментальное ограничение: **PCA - линейный метод**. Он проецирует данные на плоскость, и если кластеры в исходном пространстве разделены нелинейно (например, один кластер окружает другой), PCA их смешает. Для **визуализации** сложных многомерных структур придумали нелинейные методы, и самый популярный из них - **t-SNE** (t-distributed Stochastic Neighbor Embedding, van der Maaten & Hinton, 2008).
Идея t-SNE: сохранить **локальную структуру** данных. Если точки A и B - близкие соседи в 100-мерном пространстве, они должны остаться соседями и на 2D-графике. t-SNE строит распределение вероятностей пар «кто чей сосед» в исходном пространстве и пытается воспроизвести то же распределение в 2D. Близкие точки притягиваются, далёкие - отталкиваются. Результат - чёткие кластеры, где структура данных видна невооружённым глазом.
**Perplexity - ключевой гиперпараметр t-SNE:** - Интуиция: «сколько ближайших соседей учитывать» при построении вероятностей - Малая perplexity (5-10): фокус на очень локальной структуре, мелкие плотные кластеры - Большая perplexity (30-50): учитывает больше соседей, более глобальная картина - Правило: perplexity должна быть меньше количества точек. Для 1000 точек: 5-50, для 100: 5-20 - Рекомендуют попробовать несколько значений (5, 15, 30, 50) и сравнить результаты
**Ограничения t-SNE - почему его нельзя использовать для preprocessing:** - **Нестабильность:** разные запуски дают разные результаты (зависит от random_state) - **Нет transform():** нельзя спроецировать новые точки - только fit_transform() на всех данных сразу - **Расстояния на графике обманчивы:** расстояние между кластерами не отражает реальное расстояние в исходном пространстве - **Медленный:** O(n^2) по времени и памяти, на 100K+ точек работает минуты-часы - **Только 2-3D:** предназначен исключительно для визуализации, не для сжатия
Почему t-SNE не подходит для preprocessing данных перед обучением ML-модели?
UMAP и практические советы
В 2018 году Лиланд МакИннес представил **UMAP (Uniform Manifold Approximation and Projection)** - алгоритм, который решает главные проблемы t-SNE. UMAP значительно быстрее (от O(n^2) у t-SNE к приблизительно O(n*log(n)) у UMAP), лучше сохраняет **глобальную структуру** данных (расстояния между кластерами имеют смысл) и - критически - имеет метод **transform()** для новых данных.
**Гиперпараметры UMAP:** - **n_neighbors** (default=15): аналог perplexity в t-SNE. Малое значение (5) - фокус на микроструктуре, большое (50) - на макроструктуре. Начните с 15. - **min_dist** (default=0.1): минимальное расстояние между точками на 2D-графике. min_dist=0.0 - плотные кластеры, min_dist=0.5 - разреженные, «размазанные» кластеры. - **metric** (default='euclidean'): метрика расстояния. Можно использовать 'cosine', 'manhattan' и другие - гибче, чем PCA.
Ещё одно применение PCA: **denoising (удаление шума)**. Идея проста - шум обычно случайный и распределён по всем направлениям, а полезный сигнал сконцентрирован в нескольких главных компонентах. Если спроецировать данные на первые k компонент, а потом восстановить обратно в исходное пространство - шум исчезнет, а сигнал сохранится. Это работает потому, что последние компоненты (с малыми eigenvalues) содержат преимущественно шум.
PCA, t-SNE и UMAP делают одно и то же - снижают размерность, и можно использовать любой из них для любой задачи
Каждый метод имеет свою нишу: PCA - для preprocessing и denoising (линейный, стабильный, с transform()), t-SNE - для визуализации малых датасетов (нелинейный, но медленный и без transform()), UMAP - для визуализации любых датасетов и нелинейного preprocessing (быстрый, с transform())
PCA линеен и не разделяет нелинейные кластеры при визуализации. t-SNE нестабилен и не имеет transform() - нельзя применить к тестовым данным. UMAP - компромисс, но менее интерпретируем, чем PCA. Выбор метода зависит от задачи: preprocessing, визуализация или denoising
У вас датасет из 500K точек и 300 признаков. Нужно визуализировать кластеры в 2D. Какой метод лучше выбрать?
Ключевые идеи
- **PCA** находит направления максимальной дисперсии (eigenvectors ковариационной матрицы) и проецирует данные на них. Eigenvalues показывают важность каждого направления. Стандартизация обязательна
- **Explained variance ratio** определяет, сколько информации сохраняет каждая компонента. Порог 95% или elbow method помогают выбрать оптимальное количество компонент
- **t-SNE** - нелинейный метод для визуализации: отлично разделяет кластеры, но медленный (O(n^2)), нестабильный и без transform(). Только для визуализации, не для preprocessing
- **UMAP** - быстрая альтернатива t-SNE с transform() и сохранением глобальной структуры. PCA для preprocessing, UMAP для визуализации больших датасетов - именно так геномика визуализирует миллионы клеток, а NLP показывает структуру word embeddings, о чём мы говорили в начале
Связанные темы
Снижение размерности тесно связано с математическими основами ML, методами, работающими в пространстве признаков, и подготовкой данных:
- Математические основы ML — PCA опирается на линейную алгебру - собственные векторы и значения, матричные разложения. Эти концепции подробно разобраны в уроке по математическим основам
- k-NN (k ближайших соседей) — k-NN страдает от проклятия размерности - в высокомерном пространстве все точки равноудалены. PCA снижает размерность и делает k-NN эффективным
- Кластеризация K-Means — PCA + K-Means - классическая связка: сначала PCA снижает размерность и удаляет шум, затем K-Means находит кластеры в сжатом пространстве
- Feature Engineering — PCA - один из методов автоматического feature engineering. Он создаёт новые признаки (главные компоненты) как линейные комбинации исходных
Вопросы для размышления
- PCA находит линейные комбинации признаков. Что произойдёт, если реальная структура данных нелинейна - например, точки лежат на поверхности сферы? Сможет ли PCA корректно снизить размерность?
- t-SNE визуализирует кластеры чётко, но расстояния между кластерами на графике не имеют смысла. Как это может ввести в заблуждение при анализе данных? Приведите конкретный пример.
- Если PCA для denoising отбрасывает последние компоненты как «шумовые», что будет, если в этих компонентах содержится важный, но слабый сигнал - например, редкая аномалия в данных?
Связанные уроки
- ml-03-math-foundations — PCA опирается на собственные значения и SVD из основ математики
- ml-42-feature-engineering — Сжатые компоненты дают более чистые признаки далее
- ml-16-clustering-kmeans — Проецировать в меньшую размерность перед кластеризацией
- la-15-svd — SVD - прямой алгебраический движок PCA
- stat-14-pca — Статистика трактует PCA через ковариацию и дисперсию