← Назад к вопросам
Какие знаешь методы борьбы с переобучением бустинга?
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
- Early stopping - most important
- Low learning rate + many trees - better than high LR + few trees
- Monitor train/val gap - stop when gap растет
- Simple model - предпочитай simple model с хорошо подобранными params
- Diversity - разные моделей в ensemble лучше чем одна идеальная