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

Введение в ML: Градиентный Бустинг (XGBoost & CatBoost)

Лабораторная работа №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

  1. Загрузите данные fetch_california_housing.
  2. Разделите на Train/Test (80/20, random_state=42).
  3. Обучите XGBRegressor. Используйте 100 деревьев (n_estimators=100) и learning_rate=0.1.
  4. Посчитайте 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: Валидационный сет и Остановка

  1. Нам нужен отдельный кусочек данных для валидации (чтобы не подглядывать в тест). Отделите от X_train еще 15% под X_val (или просто передайте eval_set в fit, используя тестовую выборку, если данных мало, но это “грех” пуристов). Для простоты используем X_test как валидацию в этом учебном примере.
  2. Обучите модель с параметрами:
    • 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 вручную или циклом, чтобы побить рекорд.

Что крутить:

  1. max_depth: Глубина дерева (обычно 3-10). Чем глубже, тем сложнее модель.
  2. learning_rate: Чем меньше (0.01), тем точнее, но нужно больше деревьев.
  3. subsample: Доля данных для обучения одного дерева (например, 0.7). Борется с переобучением.
  4. 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}")

# Напишите в комментарии ваш лучший результат.

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

Для чего используется техника Early Stopping при обучении моделей градиентного бустинга?

В чем заключается главное преимущество библиотеки CatBoost при работе с датасетами, содержащими текстовые признаки (например, названия городов или пол)?