Лабораторная работа №15: Пайплайны, Кросс-валидация и GridSearch
Цель: Собрать все знания курса в единый профессиональный инструмент. Мы откажемся от ручного вызова fit/transform для каждого шага, чтобы избежать утечки данных. Мы построим Pipeline (конвейер), который объединит масштабирование, снижение размерности и классификацию, а затем автоматически подберем лучшие гиперпараметры с помощью GridSearchCV.
Инструменты:
sklearn.pipeline: Pipeline.sklearn.model_selection: GridSearchCV, cross_val_score, StratifiedKFold.sklearn.preprocessing: StandardScaler.sklearn.decomposition: PCA.sklearn.svm: SVC (Метод опорных векторов — модель, очень чувствительная к масштабу).
Данные: Breast Cancer Wisconsin. Бинарная классификация (Рак: Злокачественный/Доброкачественный).
Часть 1: Проблема ручного подхода
Когда вы пишете код ручной предобработки, он выглядит примерно так:
scaler.fit(X_train)
X_train_scaled = scaler.transform(X_train)
X_test_scaled = scaler.transform(X_test)
model.fit(X_train_scaled, y_train)
Проблема масштабируемости и утечки данных
Это работает. Но если вы захотите добавить PCA? А потом отбор признаков? Код превратится в лапшу. А если вы захотите сделать Кросс-валидацию? Вам придется руками делать scaler.fit внутри каждого фолда, иначе случится Data Leakage.
Pipeline решает эту проблему. Это “коробка”, в которую мы кладем шаги. Она ведет себя как одна модель.
Задание 1.1: Создание простого Пайплайна
- Загрузите датасет
load_breast_cancer. Разделите на Train/Test (80/20,random_state=42). - Создайте
Pipeline, состоящий из двух шагов:'scaler': StandardScaler()'svm': SVC() (Support Vector Classifier)
- Обучите пайплайн (
fit) наX_train. - Сделайте предсказание и оцените точность.
import pandas as pd
from sklearn.datasets import load_breast_cancer
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
from sklearn.svm import SVC
from sklearn.pipeline import Pipeline
from sklearn.metrics import accuracy_score
# Загрузка
data = load_breast_cancer()
X = data.data
y = data.target
# TODO: Split (80/20)
# X_train, X_test, y_train, y_test = ...
# TODO: Создайте Pipeline
# pipe_simple = Pipeline([
# ('scaler', ...),
# ('svm', ...)
# ])
# TODO: Обучение (как обычной модели)
# pipe_simple.fit(..., ...)
# TODO: Предсказание
# y_pred = pipe_simple.predict(...)
# print(f"Simple Pipeline Accuracy: {accuracy_score(y_test, y_pred):.4f}")
Часть 2: Кросс-валидация (Cross-Validation)
Одной оценки Accuracy на тесте мало. Может нам просто повезло с разбиением? Проверим устойчивость пайплайна на 5 фолдах.
Задание 2.1: cross_val_score
- Используйте
cross_val_score. - Передайте туда наш
pipe_simple,X_trainиy_train. - Число фолдов
cv=5.
Магия Пайплайна
Важный момент: Пайплайн сам позаботится о том, чтобы StandardScaler обучался заново на каждом фолде!
from sklearn.model_selection import cross_val_score
# TODO: Вычислите скоры на кросс-валидации
# cv_scores = cross_val_score(..., ..., ..., cv=5)
# print(f"CV Scores: {cv_scores}")
# print(f"Mean Accuracy: {cv_scores.mean():.4f} (+/- {cv_scores.std():.4f})")
Часть 3: Тюнинг архитектуры (GridSearch)
Теперь самое интересное. Мы не знаем:
- Какое ядро (
kernel) лучше для SVM: линейное или RBF? - Какой коэффициент регуляризации
Cвыбрать? - Нужен ли нам PCA перед SVM? И если да, сколько компонент оставить?
Мы можем перебрать это ВСЁ сразу с помощью GridSearchCV.
Задание 3.3: Запуск поиска
- Создайте
GridSearchCVс нашим пайплайном и сеткой. cv=5,n_jobs=-1(параллельно),verbose=1(чтобы видеть прогресс).- Запустите
fitнаX_train.
from sklearn.model_selection import GridSearchCV
# TODO: Инициализация GridSearch
# grid = GridSearchCV(estimator=pipe_advanced, param_grid=param_grid, cv=5, n_jobs=-1, verbose=1)
# TODO: Запуск перебора (может занять пару секунд)
# grid.fit(X_train, y_train)
# Результаты
# print(f"Лучшие параметры: {grid.best_params_}")
# print(f"Лучший кросс-валидационный скор: {grid.best_score_:.4f}")
Часть 4: Финальная проверка
grid после обучения автоматически ведет себя как лучшая найденная модель. Мы можем сразу делать grid.predict().
Задание 4.1: Оценка на отложенном тесте
- Сделайте предсказание на
X_testс помощью обученного объектаgrid. - Сравните точность с простым пайплайном из Части 1.
# TODO: Предсказание лучшей моделью
# y_pred_best = grid.predict(X_test)
# print(f"Final Test Accuracy: {accuracy_score(y_test, y_pred_best):.4f}")
Вопрос на понимание: Если GridSearch выбрал pca__n_components: None, что это значит? Помогло ли снижение размерности в этой задаче?