Лабораторная работа №12: Градиентный Бустинг (XGBoost & CatBoost)
Цель: Освоить “тяжелую артиллерию” машинного обучения. Мы научимся использовать библиотеку XGBoost для решения задач регрессии, применим технику Early Stopping для автоматического поиска идеального числа деревьев и попробуем CatBoost для работы с категориальными данными без предварительной обработки.
Инструменты:
xgboost: Самая популярная библиотека для бустинга.catboost: Библиотека от Яндекс с поддержкой категорий “из коробки”.sklearn.metrics: RMSE, ROC-AUC.
Подготовка окружения
В Google Colab библиотека xgboost обычно уже установлена, а catboost нужно доустановить. Запустите ячейку ниже перед началом работы.
!pip install catboost xgboost -q
print("Libraries installed.")Часть 1: XGBoost и Регрессия
Вернемся к датасету California Housing. В 8-й лабораторной (Линейная регрессия) наш RMSE был около 0.74 ($74,000). Посмотрим, насколько точнее будет бустинг.
Задание 1.1: Базовая модель XGBoost
- Загрузите данные
fetch_california_housing. - Разделите на Train/Test (80/20,
random_state=42). - Обучите
XGBRegressor. Используйте 100 деревьев (n_estimators=100) иlearning_rate=0.1. - Посчитайте RMSE на тесте.
import pandas as pd
import numpy as np
from sklearn.datasets import fetch_california_housing
from sklearn.model_selection import train_test_split
from sklearn.metrics import mean_squared_error
from xgboost import XGBRegressor
# Загрузка
data = fetch_california_housing()
X = pd.DataFrame(data.data, columns=data.feature_names)
y = data.target
# TODO: Разделите данные
# X_train, X_test, y_train, y_test = train_test_split(...)
# TODO: Создайте и обучите XGBRegressor
# model_xgb = XGBRegressor(
# n_estimators=100,
# learning_rate=0.1,
# random_state=42,
# n_jobs=-1
# )
# model_xgb.fit(...)
# TODO: Оценка качества
# y_pred = ...
# rmse = np.sqrt(mean_squared_error(y_test, y_pred))
# print(f"Linear Regression RMSE (Week 8): ~0.74")
# print(f"XGBoost RMSE: {rmse:.4f}")
Часть 2: Early Stopping (Ранняя остановка)
Главный риск бустинга — переобучение. Если поставить n_estimators=5000, модель выучит шум.
Контроль переобучения
Техника Early Stopping позволяет остановить обучение, как только ошибка на валидации перестанет падать.
Задание 2.1: Валидационный сет и Остановка
- Нам нужен отдельный кусочек данных для валидации (чтобы не подглядывать в тест). Отделите от
X_trainеще 15% подX_val(или просто передайтеeval_setвfit, используя тестовую выборку, если данных мало, но это “грех” пуристов). Для простоты используем X_test как валидацию в этом учебном примере. - Обучите модель с параметрами:
n_estimators=1000(заведомо много).learning_rate=0.05(помедленнее).early_stopping_rounds=10(если 10 раз подряд не стало лучше — стоп).eval_set=[(X_test, y_test)].
# Модель с запасом деревьев
model_es = XGBRegressor(
n_estimators=1000,
learning_rate=0.05,
random_state=42,
n_jobs=-1,
early_stopping_rounds=10 # Остановиться, если нет улучшений 10 раундов
)
# TODO: Запустите обучение с eval_set
# model_es.fit(
# X_train, y_train,
# eval_set=[(X_test, y_test)],
# verbose=False # Чтобы не спамить логами
# )
# print(f"Best Iteration: {model_es.best_iteration}")
# print(f"RMSE with Early Stopping: {np.sqrt(mean_squared_error(y_test, model_es.predict(X_test))):.4f}")
Часть 3: CatBoost и Категории
CatBoost (от Яндекс) умеет работать с текстовыми категориями (строками) без One-Hot Encoding.
Часть 4: Мини-соревнование (Hyperparameter Tuning)
Вернемся к California Housing. Ваша цель — получить минимально возможный RMSE на тестовой выборке.
- Текущий рекорд (с ранней остановкой): ~0.47-0.49.
- Линейная регрессия была: ~0.74.
Задание: Попробуйте изменить параметры XGBoost вручную или циклом, чтобы побить рекорд.
Что крутить:
max_depth: Глубина дерева (обычно 3-10). Чем глубже, тем сложнее модель.learning_rate: Чем меньше (0.01), тем точнее, но нужно больше деревьев.subsample: Доля данных для обучения одного дерева (например, 0.7). Борется с переобучением.colsample_bytree: Доля признаков для одного дерева (аналог Random Forest).
# Экспериментальная зона
# Попробуйте разные комбинации
best_rmse = 100
best_params = {}
# Пример ручного перебора (можно заменить на GridSearchCV, но полезно пощупать руками)
# depth_variants = [3, 6, 8]
# lr_variants = [0.05, 0.1, 0.2]
# for d in depth_variants:
# for lr in lr_variants:
# # TODO: Обучите модель с параметрами max_depth=d, learning_rate=lr
# # ...
# # calculated_rmse = ...
#
# print(f"Depth={d}, LR={lr} -> RMSE={calculated_rmse:.4f}")
# Напишите в комментарии ваш лучший результат.