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

Какие знаешь методы борьбы с переобучением бустинга?

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

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

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

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

Борьба с переобучением в бустинге

Бустинг мощный но легко переучивается. Есть много техник для контроля сложности.

1. Learning Rate (Shrinkage)

Уменьшение коэффициента обновления весов.

import xgboost as xgb
from sklearn.ensemble import GradientBoostingClassifier

# XGBoost
model = xgb.XGBClassifier(
    learning_rate=0.01,  # меньше = медленнее но стабильнее
    n_estimators=1000,   # компенсируем меньшим LR большим количеством
    max_depth=5,
    subsample=0.8
)

# Gradient Boosting sklearn
model = GradientBoostingClassifier(
    learning_rate=0.01,
    n_estimators=1000,
    max_depth=5,
    subsample=0.8
)

# Low learning rate требует больше деревьев
for lr in [0.1, 0.05, 0.01, 0.001]:
    model = GradientBoostingClassifier(
        learning_rate=lr,
        n_estimators=int(100 / lr),  # масштабируем n_estimators
        random_state=42
    )
    model.fit(X_train, y_train)
    train_score = model.score(X_train, y_train)
    val_score = model.score(X_val, y_val)
    print(f"LR={lr}: Train={train_score:.4f}, Val={val_score:.4f}")

Правило: Малый learning rate + много деревьев лучше чем большой LR + мало деревьев

2. Число итераций (Early Stopping)

Остановка обучения когда валидационная метрика перестает улучшаться.

import xgboost as xgb

# XGBoost с early stopping
model = xgb.XGBClassifier(
    learning_rate=0.1,
    max_depth=6,
    subsample=0.8,
    colsample_bytree=0.8,
    random_state=42,
    eval_metric='logloss'
)

model.fit(
    X_train, y_train,
    eval_set=[(X_val, y_val)],
    early_stopping_rounds=50,  # stop if no improvement for 50 rounds
    verbose=10
)

print(f"Best iteration: {model.best_iteration}")
print(f"Best score: {model.best_score}")

# LightGBM
import lightgbm as lgb

model = lgb.LGBMClassifier(
    learning_rate=0.05,
    num_leaves=31,
    max_depth=8
)

model.fit(
    X_train, y_train,
    eval_set=[(X_val, y_val)],
    callbacks=[
        lgb.early_stopping(50),
        lgb.log_evaluation(period=20)
    ]
)

Практический совет: Early stopping - самый важный способ бороться с переобучением

3. Tree Complexity Controls

max_depth (глубина дерева)

model = xgb.XGBClassifier(
    max_depth=3,  # маленькое = simpler trees
    learning_rate=0.01
)

Правило: Начни с max_depth=3-6, увеличивай если train/val близки

min_child_weight

model = xgb.XGBClassifier(
    max_depth=6,
    min_child_weight=1,  # минимум примеров в листе
    # 1 = может быть любое количество
    # 10 = хотя бы 10 примеров перед split
)

Больше min_child_weight → проще модель → меньше переобучение

4. Subsampling (использование subset данных)

model = xgb.XGBClassifier(
    subsample=0.8,  # используй 80% примеров для каждого дерева
    colsample_bytree=0.8,  # используй 80% признаков для каждого дерева
    colsample_bylevel=0.8,  # используй 80% признаков на каждом level
    max_depth=6,
    learning_rate=0.1
)

# Меньше = больше регуляризация
for subsample in [1.0, 0.8, 0.6, 0.4]:
    model = xgb.XGBClassifier(subsample=subsample, n_estimators=100)
    model.fit(X_train, y_train)
    train_score = model.score(X_train, y_train)
    val_score = model.score(X_val, y_val)
    print(f"Subsample={subsample}: Train={train_score:.4f}, Val={val_score:.4f}")

Эффект:

  • Больше randomness
  • Более diverse деревья
  • Лучше генерализация

5. Регуляризация

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

model = xgb.XGBClassifier(
    reg_alpha=0.01,  # L1 (лассо) регуляризация на weights
    reg_lambda=0.1,  # L2 (ridge) регуляризация на weights
    max_depth=6,
    learning_rate=0.1
)

# Больше значение = больше регуляризация
for alpha in [0, 0.01, 0.1, 1.0]:
    model = xgb.XGBClassifier(reg_alpha=alpha)
    model.fit(X_train, y_train)
    val_score = model.score(X_val, y_val)
    print(f"Alpha={alpha}: Val={val_score:.4f}")

Gamma (минимальный loss reduction для split)

model = xgb.XGBClassifier(
    gamma=1.0,  # требуй минимум 1.0 потерь уменьшения для split
    max_depth=6,
    learning_rate=0.1
)

# Больше gamma = меньше splits = проще дерево

6. Cross-Validation для выбора гиперпараметров

from sklearn.model_selection import GridSearchCV
import xgboost as xgb

param_grid = {
    'max_depth': [3, 5, 7],
    'learning_rate': [0.01, 0.05, 0.1],
    'subsample': [0.6, 0.8, 1.0],
    'colsample_bytree': [0.6, 0.8, 1.0],
    'reg_alpha': [0, 0.01, 0.1],
}

model = xgb.XGBClassifier(
    n_estimators=100,
    random_state=42,
    eval_metric='logloss'
)

grid_search = GridSearchCV(
    model,
    param_grid,
    cv=5,
    scoring='roc_auc',
    n_jobs=-1,
    verbose=1
)

grid_search.fit(X_train, y_train)

print(f"Best params: {grid_search.best_params_}")
print(f"Best CV score: {grid_search.best_score_:.4f}")

# Validate на тестовой выборке
best_model = grid_search.best_estimator_
test_score = best_model.score(X_test, y_test)
print(f"Test score: {test_score:.4f}")

7. Мониторинг переобучения

def monitor_overfitting(model, X_train, y_train, X_val, y_val):
    """
    Отслеживаем train и val метрики
    """
    
    train_scores = []
    val_scores = []
    
    for i, (train_pred, val_pred) in enumerate(
        zip(
            model.staged_predict(X_train),
            model.staged_predict(X_val)
        )
    ):
        train_score = accuracy_score(y_train, train_pred)
        val_score = accuracy_score(y_val, val_pred)
        
        train_scores.append(train_score)
        val_scores.append(val_score)
    
    # Визуализация
    import matplotlib.pyplot as plt
    
    plt.figure(figsize=(10, 5))
    plt.plot(train_scores, label='Train')
    plt.plot(val_scores, label='Validation')
    plt.xlabel('Number of Estimators')
    plt.ylabel('Accuracy')
    plt.legend()
    plt.title('Overfitting Monitoring')
    plt.show()
    
    # Найти точку где начинается переобучение
    gap = max(abs(np.array(train_scores) - np.array(val_scores)))
    optimal_iter = np.argmin(np.array(train_scores) - np.array(val_scores))
    
    print(f"Max gap between train and val: {gap:.4f}")
    print(f"Optimal iterations: {optimal_iter}")

8. Ensemble из ансамблей

from sklearn.ensemble import AdaBoostClassifier, VotingClassifier

# Комбинируем несколько бустинг моделей
model1 = xgb.XGBClassifier(max_depth=3, n_estimators=100, learning_rate=0.1)
model2 = xgb.XGBClassifier(max_depth=5, n_estimators=100, learning_rate=0.05)
model3 = lgb.LGBMClassifier(num_leaves=15, n_estimators=100, learning_rate=0.1)

ensemble = VotingClassifier(
    estimators=[('xgb1', model1), ('xgb2', model2), ('lgb', model3)],
    voting='soft'
)

ensemble.fit(X_train, y_train)

train_score = ensemble.score(X_train, y_train)
val_score = ensemble.score(X_val, y_val)

print(f"Train: {train_score:.4f}, Val: {val_score:.4f}")

9. Рекомендуемый процесс

def train_robust_boosting_model(X_train, y_train, X_val, y_val, X_test, y_test):
    """
    Best practice pipeline
    """
    
    # 1. Start simple
    baseline = xgb.XGBClassifier(
        max_depth=3,
        learning_rate=0.1,
        n_estimators=100,
        random_state=42
    )
    baseline.fit(X_train, y_train)
    
    # 2. Check if overfitting
    train_acc = baseline.score(X_train, y_train)
    val_acc = baseline.score(X_val, y_val)
    
    print(f"Baseline - Train: {train_acc:.4f}, Val: {val_acc:.4f}")
    
    if train_acc - val_acc > 0.05:  # 5% gap
        print("Overfitting detected, applying regularization...")
        
        # 3. Add regularization
        model = xgb.XGBClassifier(
            max_depth=4,
            learning_rate=0.05,  # decrease learning rate
            n_estimators=500,    # increase n_estimators
            subsample=0.8,       # subsample
            colsample_bytree=0.8,
            reg_alpha=0.01,
            reg_lambda=0.1,
            random_state=42,
            eval_metric='logloss'
        )
        
        # 4. Early stopping
        model.fit(
            X_train, y_train,
            eval_set=[(X_val, y_val)],
            early_stopping_rounds=50,
            verbose=10
        )
    
    # 5. Final evaluation
    test_acc = model.score(X_test, y_test)
    print(f"\nFinal Test Accuracy: {test_acc:.4f}")
    
    return model

Summary таблица

МетодСилаЛегкостьКогда использовать
Learning rateСильнаяЛегкоВсегда уменьшай
Early stoppingСильнаяЛегкоВсегда используй
max_depthСредняяЛегкоStart=3-5
subsampleСредняяЛегко0.6-0.8
РегуляризацияСредняяСреднеКогда gap большой
Tree controlsСлабаяЛегкоTune together

Golden Rules

  1. Early stopping - most important
  2. Low learning rate + many trees - better than high LR + few trees
  3. Monitor train/val gap - stop when gap растет
  4. Simple model - предпочитай simple model с хорошо подобранными params
  5. Diversity - разные моделей в ensemble лучше чем одна идеальная