Метод главных компонент (PCA): цель и реализация
🎯 Что такое PCA и зачем он нужен?
Представь, что у тебя есть данные с множеством признаков — например, рост, вес, возраст, зарплата, количество чашек кофе в день. Некоторые из этих признаков могут быть связаны между собой (например, рост и вес), и их слишком много, чтобы было удобно анализировать. Метод главных компонент (PCA) помогает упростить данные, сохранив самое важное!
Основные цели PCA:
- 📉 Уменьшение размерности: Сократить количество признаков, убрав менее значимые.
- 🔍 Визуализация: Представить многомерные данные в 2D или 3D.
- 📊 Шумоподавление: Убрать случайные колебания в данных.
💡 PCA не выбирает отдельные признаки, а создает новые — главные компоненты — которые являются комбинациями исходных.
🧮 Математическая основа PCA
PCA ищет направления в данных, где дисперсия (разброс) максимальна. Первая главная компонента — это направление наибольшей дисперсии, вторая — перпендикулярно первой и с следующей по величине дисперсией, и так далее.
Шаги алгоритма:
- 📏 Стандартизация данных: Приводим все признаки к одному масштабу (среднее = 0, стандартное отклонение = 1).
- 📐 Вычисление ковариационной матрицы: Показывает, как признаки связаны между собой.
- 🔢 Нахождение собственных векторов и собственных значений: Собственные векторы — это направления главных компонент, а собственные значения — их важность (дисперсия).
- 📊 Выбор главных компонент: Сортируем компоненты по убыванию собственных значений и выбираем нужное количество.
- 🔄 Преобразование данных: Проецируем исходные данные на выбранные главные компоненты.
Формула стандартизации:
z = (x - mean) / std
Ковариационная матрица для двух признаков:
cov(X,Y) = Σ[(xᵢ - mean_x) * (yᵢ - mean_y)] / (n-1)
📘 Собственные векторы ковариационной матрицы указывают направления максимальной дисперсии, а собственные значения показывают величину этой дисперсии.
🛠️ Реализация PCA на Python
Давай реализуем PCA шаг за шагом на примере простого набора данных!
Сначала импортируем необходимые библиотеки:
import numpy as np from sklearn.preprocessing import StandardScaler
Создадим синтетические данные для демонстрации:
# Создаем коррелированные данные np.random.seed(42) x = np.random.normal(0, 1, 100) y = 2 * x + np.random.normal(0, 0.5, 100) data = np.column_stack((x, y))
Теперь стандартизируем данные:
scaler = StandardScaler() data_scaled = scaler.fit_transform(data)
Вычисляем ковариационную матрицу:
cov_matrix = np.cov(data_scaled.T)
print("Ковариационная матрица:\n", cov_matrix)
Находим собственные значения и собственные векторы:
eigenvalues, eigenvectors = np.linalg.eig(cov_matrix)
print("Собственные значения:", eigenvalues)
print("Собственные векторы:\n", eigenvectors)
Выбираем главные компоненты (сортируем по убыванию собственных значений):
# Сортируем собственные значения и векторы idx = eigenvalues.argsort()[::-1] eigenvalues = eigenvalues[idx] eigenvectors = eigenvectors[:, idx] # Выбираем первую главную компоненту first_pc = eigenvectors[:, 0]
Преобразуем данные в новое пространство:
transformed_data = data_scaled.dot(eigenvectors)
💡 На практике обычно используют готовую реализацию PCA из библиотеки sklearn, но понимание математики важно!
📊 PCA с использованием Scikit-learn
Теперь покажем, как использовать PCA с помощью удобной библиотеки:
from sklearn.decomposition import PCA
# Создаем объект PCA с 2 компонентами
pca = PCA(n_components=2)
# Применяем к нашим данным
principal_components = pca.fit_transform(data_scaled)
# Смотрим результаты
print("Объясненная дисперсия:", pca.explained_variance_ratio_)
print("Главные компоненты:\n", principal_components[:5])
Визуализируем результат:
import matplotlib.pyplot as plt
plt.figure(figsize=(10, 4))
# Исходные данные
plt.subplot(1, 2, 1)
plt.scatter(data_scaled[:, 0], data_scaled[:, 1])
plt.title("Исходные данные (стандартизированные)")
plt.xlabel("Признак 1")
plt.ylabel("Признак 2")
# После PCA
plt.subplot(1, 2, 2)
plt.scatter(principal_components[:, 0], principal_components[:, 1])
plt.title("После PCA")
plt.xlabel("Первая главная компонента")
plt.ylabel("Вторая главная компонента")
plt.tight_layout()
plt.show()
🎯 Как выбрать количество компонент?
Один из ключевых вопросов — сколько главных компонент оставить. Есть несколько подходов:
| Метод | Описание | Пример |
|---|---|---|
| 📈 Правило локтя | Смотрим на график объясненной дисперсии и ищем "излом" | Оставляем компоненты до резкого спада важности |
| 🎯 Порог объясненной дисперсии | Накопленная объясненная дисперсия должна быть выше порога | Оставляем столько компонент, чтобы сохранить 95% дисперсии |
| 🔢 Правило Кайзера | Оставляем компоненты с собственными значениями > 1 | Для стандартизированных данных |
Пример выбора по порогу объясненной дисперсии:
pca = PCA()
pca.fit(data_scaled)
# Вычисляем накопленную объясненную дисперсию
cumulative_variance = np.cumsum(pca.explained_variance_ratio_)
# Находим, сколько компонент нужно для 95% дисперсии
n_components = np.argmax(cumulative_variance >= 0.95) + 1
print(f"Нужно {n_components} компонент для 95% дисперсии")
🧠 Практическая задача
Условие: У нас есть данные о покупателях с 10 признаками. Нужно уменьшить размерность так, чтобы сохранить 90% дисперсии и визуализировать данные в 2D.