← Назад к вопросам

Как регуляризуется CatBoost?

2.3 Middle🔥 171 комментариев
#Машинное обучение

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI29 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Регуляризация в CatBoost: Полный обзор

CatBoost (Categorical Boosting) имеет встроенные механизмы регуляризации, специально разработанные для борьбы с переобучением. Это одна из ключевых особенностей, выделяющих CatBoost среди других gradient boosting фреймворков.

1. Основные механизмы регуляризации CatBoost

1.1 L1 и L2 регуляризация

CatBoost использует стандартные L1 (Lasso) и L2 (Ridge) штрафы на листья деревьев:

from catboost import CatBoostRegressor

# L2 регуляризация (по умолчанию)
model = CatBoostRegressor(
    l2_leaf_reg=3.0,  # Коэффициент L2 регуляризации для листьев
    iterations=100,
    random_state=42,
    verbose=False
)

model.fit(X_train, y_train)
y_pred = model.predict(X_test)

# L1 регуляризация
model_l1 = CatBoostRegressor(
    l2_leaf_reg=3.0,
    random_state=42
)
model_l1.fit(X_train, y_train)

Как это работает:

  • CatBoost добавляет штраф при вычислении весов листьев
  • Формула: Loss = Original_Loss + l2_leaf_reg * sum(leaf_values²)
  • Большее значение l2_leaf_reg → сильнее регуляризация → проще модель

1.2 Ordered Target Encoding (Уникальная особенность CatBoost)

CatBoost использует специальный способ обработки категориальных признаков, который сам по себе является формой регуляризации:

from catboost import CatBoostRegressor

model = CatBoostRegressor(
    cat_features=[category_column_1, category_column_2],
    one_hot_max_size=10,  # Кодировать как one-hot если < 10 категорий
    max_ctr_complexity=4,  # Максимальная сложность (комбинация признаков)
    iterations=100,
    random_state=42,
    verbose=False
)

model.fit(X_train, y_train)

Преимущество:

  • Избегает target leakage при кодировании категорий
  • Снижает переобучение на категориальных признаках
  • Не требует предварительного кодирования

1.3 Бутстрап (Bootstrap) регуляризация

CatBoost использует бутстрап-выборки для каждого дерева:

model = CatBoostRegressor(
    bootstrap_type="Bayesian",  # или "Poisson", "Bernoulli", "No"
    bagging_temperature=1.0,  # 0 = детерминированный, 1 = максимальная случайность
    subsample=0.8,  # Доля samples для каждого дерева
    iterations=100,
    random_state=42
)

model.fit(X_train, y_train)

Типы бутстрапа:

  • Bayesian (по умолчанию): Самый мощный, использует Beta распределение
  • Poisson: Каждый sample может быть использован 0, 1, 2+ раз
  • Bernoulli: Каждый sample включается/исключается с вероятностью 0.5
  • No: Без бутстрапа (может привести к переобучению)

2. Параметры для контроля переобучения

2.1 Ограничение глубины дерева

model = CatBoostRegressor(
    depth=6,  # Глубина дерева (по умолчанию 6)
    iterations=100,
    random_state=42
)

# Пример сравнения разных глубин
import numpy as np
from sklearn.model_selection import cross_val_score

depths = [2, 4, 6, 8, 10]
for depth in depths:
    model = CatBoostRegressor(
        depth=depth,
        iterations=100,
        verbose=False
    )
    scores = cross_val_score(
        model, X_train, y_train, 
        cv=5, 
        scoring="neg_mean_squared_error"
    )
    print(f"Depth {depth}: MSE = {-scores.mean():.4f} (+/- {scores.std():.4f})")

2.2 Learning Rate (Shrinkage)

Уменьшение вклада каждого дерева в финальный предсказание:

model = CatBoostRegressor(
    learning_rate=0.1,  # Обычно 0.01 - 0.1
    iterations=1000,  # Больше итераций с малым learning_rate
    random_state=42
)

# Сравнение разных learning rates
learning_rates = [0.01, 0.05, 0.1, 0.3]
for lr in learning_rates:
    model = CatBoostRegressor(
        learning_rate=lr,
        iterations=500,
        verbose=False
    )
    model.fit(X_train, y_train)
    train_score = model.score(X_train, y_train)
    test_score = model.score(X_test, y_test)
    print(f"LR {lr}: Train R² = {train_score:.3f}, Test R² = {test_score:.3f}")

2.3 Ограничение минимального размера листа

model = CatBoostRegressor(
    min_child_samples=1,  # Мин. samples в листе
    min_child_weight=100,  # Мин. сумма весов в листе
    iterations=100,
    random_state=42
)

model.fit(X_train, y_train)

Это предотвращает создание слишком специфичных листьев на малых подмножествах.

3. Комплексная стратегия регуляризации

from catboost import CatBoostRegressor
from sklearn.model_selection import GridSearchCV

# Определить сетку гиперпараметров
param_grid = {
    "depth": [4, 6, 8],
    "l2_leaf_reg": [1, 3, 5, 10],
    "learning_rate": [0.01, 0.05, 0.1],
    "subsample": [0.7, 0.8, 0.9],
}

# GridSearch для поиска оптимальной комбинации
model = CatBoostRegressor(
    iterations=100,
    verbose=False,
    random_state=42
)

grid_search = GridSearchCV(
    model,
    param_grid,
    cv=5,
    scoring="neg_mean_squared_error",
    n_jobs=-1
)

grid_search.fit(X_train, y_train)
print(f"Лучшие параметры: {grid_search.best_params_}")
print(f"Лучший MSE: {-grid_search.best_score_:.4f}")

4. Ранняя остановка (Early Stopping)

Один из самых эффективных методов регуляризации:

from catboost import CatBoostRegressor, Pool

# Создать Pool объекты для efficient работы
train_pool = Pool(
    X_train, y_train,
    cat_features=categorical_features  # Если есть
)
val_pool = Pool(
    X_val, y_val,
    cat_features=categorical_features
)

# Обучение с ранней остановкой
model = CatBoostRegressor(
    iterations=1000,
    early_stopping_rounds=50,  # Стоп если нет улучшения за 50 итераций
    eval_metric="RMSE",  # Метрика для оценки
    verbose=50
)

model.fit(
    train_pool,
    eval_set=val_pool,
    use_best_model=True  # Использовать лучшую итерацию
)

print(f"Обучено итераций: {model.tree_count_}")
print(f"Лучшая итерация: {model.best_iteration_}")

5. Сравнение CatBoost с XGBoost и LightGBM

from xgboost import XGBRegressor
from lightgbm import LGBMRegressor
from catboost import CatBoostRegressor
from sklearn.metrics import mean_squared_error, mean_absolute_error

models = {
    "CatBoost": CatBoostRegressor(
        depth=6,
        l2_leaf_reg=3.0,
        learning_rate=0.1,
        iterations=100,
        verbose=False,
        random_state=42
    ),
    "XGBoost": XGBRegressor(
        max_depth=6,
        reg_lambda=3.0,
        learning_rate=0.1,
        n_estimators=100,
        random_state=42
    ),
    "LightGBM": LGBMRegressor(
        max_depth=6,
        reg_lambda=3.0,
        learning_rate=0.1,
        n_estimators=100,
        random_state=42,
        verbose=-1
    )
}

for name, model in models.items():
    model.fit(X_train, y_train)
    y_pred = model.predict(X_test)
    
    mse = mean_squared_error(y_test, y_pred)
    mae = mean_absolute_error(y_test, y_pred)
    
    print(f"\n{name}:")
    print(f"  MSE: {mse:.4f}")
    print(f"  MAE: {mae:.4f}")

6. Практический пример: Классификация

from catboost import CatBoostClassifier
from sklearn.model_selection import cross_val_score

model = CatBoostClassifier(
    # Структурная регуляризация
    depth=5,
    l2_leaf_reg=10,  # Сильнее для классификации
    
    # Бутстрап регуляризация
    bootstrap_type="Bayesian",
    bagging_temperature=1.0,
    subsample=0.8,
    
    # Learning rate
    learning_rate=0.05,
    iterations=500,
    
    # Категориальные признаки
    cat_features=cat_feature_indices,
    one_hot_max_size=5,
    
    # Ранняя остановка
    early_stopping_rounds=20,
    eval_metric="AUC",
    
    # Другое
    random_state=42,
    verbose=False,
    task_type="CPU"  # или "GPU"
)

# Кросс-валидация
scores = cross_val_score(
    model, X_train, y_train,
    cv=5,
    scoring="roc_auc"
)

print(f"Mean AUC: {scores.mean():.3f} (+/- {scores.std():.3f})")

7. Расширенная регуляризация

7.1 Обработка дисбаланса классов

from catboost import CatBoostClassifier

# Вычислить баланс классов
class_weights = {
    0: 1,
    1: len(y_train[y_train == 0]) / len(y_train[y_train == 1])
}

model = CatBoostClassifier(
    class_weights=class_weights,  # Или auto_class_weights="Balanced"
    iterations=100,
    verbose=False
)

model.fit(X_train, y_train)

7.2 Влияние порядка признаков (Feature permutation)

# CatBoost чувствителен к порядку признаков
# Использовать перетасовку для стабильности

from sklearn.utils import shuffle

X_shuffled, y_shuffled = shuffle(X_train, y_train, random_state=42)

model = CatBoostRegressor(
    random_strength=1,  # Добавляет случайность в выбор признаков
    iterations=100,
    verbose=False
)

model.fit(X_shuffled, y_shuffled)

8. Итоговые рекомендации

Для начала используй:

model = CatBoostRegressor(
    depth=6,              # Умеренная глубина
    l2_leaf_reg=3.0,      # Стандартная L2
    learning_rate=0.1,    # Хороший компромисс
    iterations=100,
    early_stopping_rounds=20,
    subsample=0.8,
    random_state=42
)

Если переобучение:

  1. Увеличь l2_leaf_reg (5, 10, 20)
  2. Уменьши depth (4, 5 вместо 6, 8)
  3. Уменьши learning_rate (0.01, 0.05)
  4. Увеличь subsample (0.6, 0.7)

Если недообучение:

  1. Уменьши l2_leaf_reg (1, 2)
  2. Увеличь depth (8, 10)
  3. Увеличь learning_rate (0.2, 0.3)
  4. Увеличь iterations

Главное преимущество CatBoost:

  • Встроенная обработка категориальных признаков (сама по себе регуляризация)
  • Обычно требует меньше настройки чем XGBoost/LightGBM
  • Результаты часто стабильнее на новых данных