Обучение модели на структурированных данных (XGBoost, LightGBM, CatBoost)
Gradient boosting алгоритмы — рабочие лошадки ML для структурированных табличных данных. XGBoost, LightGBM и CatBoost доминируют в соревнованиях Kaggle и production системах там, где нейронные сети проигрывают из-за небольшого объёма данных, категориальных признаков и требований к интерпретируемости.
Сравнение алгоритмов
| Критерий | XGBoost | LightGBM | CatBoost |
|---|---|---|---|
| Скорость обучения | Средняя | Высокая | Высокая |
| Категориальные признаки | Нужен encoding | Нужен encoding | Нативная поддержка |
| Память | Высокое потребление | Низкое | Среднее |
| GPU поддержка | Да | Да | Да |
| Пропуски в данных | Нативно | Нативно | Нативно |
LightGBM: полный pipeline
import lightgbm as lgb
from sklearn.model_selection import StratifiedKFold
from sklearn.metrics import roc_auc_score
import optuna
def train_lgbm_with_cv(X: pd.DataFrame, y: pd.Series,
n_splits: int = 5) -> lgb.LGBMClassifier:
# Оптимизация гиперпараметров через Optuna
def objective(trial):
params = {
'n_estimators': trial.suggest_int('n_estimators', 100, 1000),
'num_leaves': trial.suggest_int('num_leaves', 20, 300),
'max_depth': trial.suggest_int('max_depth', 3, 12),
'learning_rate': trial.suggest_float('learning_rate', 0.005, 0.1, log=True),
'subsample': trial.suggest_float('subsample', 0.6, 1.0),
'colsample_bytree': trial.suggest_float('colsample_bytree', 0.6, 1.0),
'reg_alpha': trial.suggest_float('reg_alpha', 1e-8, 10.0, log=True),
'reg_lambda': trial.suggest_float('reg_lambda', 1e-8, 10.0, log=True),
'min_child_samples': trial.suggest_int('min_child_samples', 5, 100),
}
cv = StratifiedKFold(n_splits=5, shuffle=True, random_state=42)
scores = []
for train_idx, val_idx in cv.split(X, y):
model = lgb.LGBMClassifier(**params, random_state=42, verbose=-1)
model.fit(
X.iloc[train_idx], y.iloc[train_idx],
eval_set=[(X.iloc[val_idx], y.iloc[val_idx])],
callbacks=[lgb.early_stopping(50, verbose=False)]
)
pred = model.predict_proba(X.iloc[val_idx])[:, 1]
scores.append(roc_auc_score(y.iloc[val_idx], pred))
return np.mean(scores)
study = optuna.create_study(direction='maximize')
study.optimize(objective, n_trials=100, n_jobs=4)
best_model = lgb.LGBMClassifier(**study.best_params, random_state=42)
best_model.fit(X, y)
return best_model
def explain_model(model, X: pd.DataFrame):
import shap
explainer = shap.TreeExplainer(model)
shap_values = explainer.shap_values(X)
# Feature importance plot
shap.summary_plot(shap_values, X, plot_type="bar")
# Dependence plot для топ-признака
top_feature = X.columns[np.abs(shap_values).mean(0).argmax()]
shap.dependence_plot(top_feature, shap_values, X)
CatBoost с категориальными признаками
from catboost import CatBoostClassifier, Pool
def train_catboost(X_train: pd.DataFrame, y_train: pd.Series,
X_val: pd.DataFrame, y_val: pd.Series,
cat_features: list[str]) -> CatBoostClassifier:
train_pool = Pool(X_train, y_train, cat_features=cat_features)
val_pool = Pool(X_val, y_val, cat_features=cat_features)
model = CatBoostClassifier(
iterations=1000,
learning_rate=0.03,
depth=6,
l2_leaf_reg=3.0,
bootstrap_type='Bayesian',
bagging_temperature=1.0,
eval_metric='AUC',
use_best_model=True,
early_stopping_rounds=100,
random_seed=42,
verbose=100
)
model.fit(train_pool, eval_set=val_pool)
return model
Stacking ансамбль
from sklearn.ensemble import StackingClassifier
from sklearn.linear_model import LogisticRegression
stacking = StackingClassifier(
estimators=[
('lgbm', lgb.LGBMClassifier(**lgbm_best_params)),
('xgb', XGBClassifier(**xgb_best_params)),
('catboost', CatBoostClassifier(**cat_best_params, verbose=0)),
],
final_estimator=LogisticRegression(C=0.1),
cv=5,
stack_method='predict_proba'
)
stacking.fit(X_train, y_train)
Для большинства бизнес-задач (churn, fraud, scoring): LightGBM с правильно подобранными гиперпараметрами даёт AUC 0.80-0.95. Stacking добавляет 0.5-2% к AUC за счёт диверсификации ошибок. Полное время обучения production пайплайна с 1M строк: 10-30 минут.







