machine-learning Лабораторная работа

Введение в ML: Снижение размерности (PCA и t-SNE)

Лабораторная работа №14: Снижение размерности (PCA и t-SNE)

Цель: Научиться бороться с проклятием размерности. Мы сожмем изображения рукописных цифр из 64 измерений в 2 измерения для визуализации, определим оптимальное количество компонент для сохранения информации и сравним эффективность линейного (PCA) и нелинейного (t-SNE) подходов.

Инструменты:

  • sklearn.decomposition: PCA.
  • sklearn.manifold: t-SNE.
  • sklearn.preprocessing: StandardScaler.
  • time: для замера скорости обучения моделей.

Данные: Digits Dataset (из sklearn). Картинки 8x8 пикселей.

  • Исходная размерность: 64 признака (пикселя).
  • Количество классов: 10 (цифры 0-9).

Часть 1: Подготовка и Стандартизация

Важность масштабирования

PCA работает, вращая оси координат. Если данные не отмасштабированы, ось с самым большим разбросом значений (например, центральный пиксель) перетянет всё внимание на себя.

Задание 1.1: Загрузка и Scaling

  1. Загрузите load_digits.
  2. Примените StandardScaler к матрице признаков X.
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
from sklearn.datasets import load_digits
from sklearn.preprocessing import StandardScaler

# Загрузка
digits = load_digits()
X = digits.data
y = digits.target

print(f"Исходная форма данных: {X.shape}") # (1797, 64)

# TODO: Примените StandardScaler
# scaler = ...
# X_scaled = ...

Часть 2: PCA для визуализации (2D)

Мы не можем представить 64-мерное пространство. Но мы можем сжать его до 2D и нарисовать.


Часть 3: Выбор оптимального числа компонент

Сколько измерений нужно оставить, чтобы сохранить 90% информации о цифре?

Задание 3.1: График кумулятивной дисперсии

  1. Обучите PCA на всех компонентах (по умолчанию n_components=None или min(n_samples, n_features)).
  2. Постройте график кумулятивной суммы (np.cumsum) объясненной дисперсии.
  3. Найдите количество компонент, необходимое для 90% дисперсии.
# TODO: PCA на всех компонентах
# pca_full = PCA(random_state=42)
# pca_full.fit(X_scaled)

# TODO: Кумулятивная сумма
# cumsum = np.cumsum(pca_full.explained_variance_ratio_)

# График
# plt.figure(figsize=(10, 6))
# plt.plot(cumsum, marker='o', linestyle='--')
# plt.axhline(y=0.90, color='r', linestyle='-')
# plt.text(0, 0.92, '90% Threshold', color = 'red', fontsize=12)
# plt.xlabel('Количество компонент')
# plt.ylabel('Сохраненная дисперсия')
# plt.grid()
# plt.show()

# TODO: Программно найдите индекс, где сумма > 0.90 (np.argmax поможет)
# n_90 = ...
# print(f"Нужно {n_90} компонент, чтобы сохранить 90% информации.")

Часть 4: PCA как ускоритель ML

Инженеры используют PCA не только для картинок, но и для ускорения тяжелых моделей. Если у вас 10 000 признаков, модель будет учиться вечность. Если сжать их до 500, качество почти не упадет, а скорость вырастет в разы.

Задание 4.1: Сравнение скорости

  1. Обучите LogisticRegression на исходных данных (X_scaled). Замерьте время.
  2. Обучите ту же модель на сжатых данных (количество компонент возьмите из задания 3.1, например 20-30). Замерьте время.
  3. Сравните Accuracy.
from sklearn.linear_model import LogisticRegression
from sklearn.model_selection import train_test_split
from sklearn.metrics import accuracy_score
import time

# Разделение (на оригинальных данных)
X_train, X_test, y_train, y_test = train_test_split(X_scaled, y, test_size=0.3, random_state=42)

# PCA трансформация
# pca_90 = PCA(n_components=n_90) # Используйте n_90 из прошлого шага (или поставьте 0.90 в n_components)
# X_train_pca = pca_90.fit_transform(X_train)
# X_test_pca = pca_90.transform(X_test)

# --- 1. Обучение на сырых данных ---
start = time.time()
# logit = LogisticRegression(max_iter=1000)
# logit.fit(X_train, y_train)
raw_time = time.time() - start
# raw_acc = accuracy_score(y_test, logit.predict(X_test))

# --- 2. Обучение на PCA данных ---
start = time.time()
# logit_pca = LogisticRegression(max_iter=1000)
# logit_pca.fit(X_train_pca, y_train)
pca_time = time.time() - start
# pca_acc = accuracy_score(y_test, logit_pca.predict(X_test_pca))

# print(f"Raw Data: {raw_time:.4f} sec, Accuracy: {raw_acc:.4f}")
# print(f"PCA Data: {pca_time:.4f} sec, Accuracy: {pca_acc:.4f}")

Вывод по производительности

На маленьком датасете Digits выигрыш во времени может быть небольшим, но на реальной Big Data разница колоссальная.


Часть 5: t-SNE (Визуализация многообразий)

PCA сжимает “блинчиком”. t-SNE пытается распутать “клубок ниток”. Это гораздо более мощный инструмент для визуализации кластеров.

Задание 5.1: t-SNE проекция

Долгие вычисления

Внимание: t-SNE работает долго. На этом датасете займет 10-30 секунд.

  1. Импортируйте TSNE.
  2. Примените его к X_scaled.
  3. Постройте Scatter plot.
from sklearn.manifold import TSNE

# TODO: Запустите t-SNE (n_components=2)
# tsne = TSNE(n_components=2, random_state=42, perplexity=30, n_iter=1000)
# X_tsne = tsne.fit_transform(X_scaled)

# Визуализация
# plt.figure(figsize=(10, 8))
# sns.scatterplot(x=X_tsne[:, 0], y=X_tsne[:, 1], hue=y, palette='tab10', legend='full')
# plt.title("t-SNE Projection")
# plt.show()

Сравнение: Посмотрите, насколько лучше t-SNE разделил классы по сравнению с PCA из Части 2. Группы цифр должны быть отчетливо видны и отделены друг от друга.


🧠 Проверка знаний

Почему перед применением метода главных компонент (PCA) необходимо обязательно масштабировать признаки с помощью StandardScaler?

В чем заключается главное преимущество алгоритма t-SNE перед PCA при визуализации данных в 2D или 3D пространстве?