集成学习与树模型
核心思想:多个弱模型组合起来比一个强模型更可靠。
Kaggle 表格类比赛的冠军方案里,90% 的核心是 GBDT(XGBoost / LightGBM / CatBoost)。这一篇是 L2 最实用的一节。
为什么集成有效
| 方法 | 原理 | 降低的是 | 代表 |
|---|---|---|---|
| Bagging | 并行训练多个模型,投票/平均 | 方差(过拟合) | 随机森林 |
| Boosting | 串行训练,每个模型修正前一个的残差 | 偏差(欠拟合) | XGBoost、LightGBM |
| Stacking | 用第二层模型学习如何组合第一层 | 两者 | 竞赛常用 |
一句话:Bagging 让结果更稳,Boosting 让结果更准。
一、随机森林
每棵树用「随机抽样的数据 + 随机抽样的特征」训练,最后平均。
python
from sklearn.ensemble import RandomForestClassifier
from sklearn.model_selection import cross_val_score
rf = RandomForestClassifier(
n_estimators=500, # 树的数量,越多越稳(到某个点后收益递减)
max_depth=None, # 让树长满,靠下面两个参数控制复杂度
min_samples_leaf=5,
max_features="sqrt", # 每次分裂考虑 sqrt(n) 个特征
n_jobs=-1,
random_state=42,
)
print(cross_val_score(rf, X_train, y_train, cv=5, scoring="roc_auc").mean())优点:几乎不用调参就有不错效果、天然抗过拟合、可给特征重要性、可并行。 缺点:不如 GBDT 准、模型文件大、外推能力差。
二、GBDT:梯度提升树
每一棵新树拟合「当前模型还差多少」(残差/负梯度),逐步逼近。
F₀ = 常数
F₁ = F₀ + 树₁(拟合 F₀ 的残差)
F₂ = F₁ + 树₂(拟合 F₁ 的残差)
...
F_M = 最终模型LightGBM(推荐首选)
快、省内存、精度高,工业界最常用。
python
import lightgbm as lgb
model = lgb.LGBMClassifier(
n_estimators=2000,
learning_rate=0.05, # 关键:小学习率 + 多树通常更好
num_leaves=31, # 叶子数,控制复杂度(2^max_depth 的替代)
max_depth=-1,
min_child_samples=20,
subsample=0.8, # 行采样
colsample_bytree=0.8, # 列采样
reg_alpha=0.0, # L1
reg_lambda=1.0, # L2
objective="binary",
random_state=42,
n_jobs=-1,
)
model.fit(
X_train, y_train,
eval_set=[(X_valid, y_valid)],
eval_metric="auc",
callbacks=[lgb.early_stopping(100), lgb.log_evaluation(0)],
)
print(f"最佳迭代轮数: {model.best_iteration_}")关键参数与其影响
| 参数 | 增大后 | 建议起点 |
|---|---|---|
learning_rate | 收敛快但容易过拟合 | 0.05(数据少)/ 0.1(数据多) |
n_estimators | 更准,但配合 early stopping 才有意义 | 1000–5000 |
num_leaves | 拟合能力↑,过拟合风险↑ | 31(小数据 15) |
min_child_samples | 更保守、抗噪 | 20–50 |
subsample / colsample | 越大越容易过拟合 | 0.8 |
reg_lambda | 正则更强 | 1–10 |
调参顺序(不要一起网格搜索)
- 先定
learning_rate=0.05+early_stopping,让树数自适应 - 再调
num_leaves与min_child_samples(复杂度) - 然后
subsample/colsample_bytree(随机性) - 最后
reg_alpha/reg_lambda(正则) - 用
Optuna做少量贝叶斯搜索,别暴力网格
三个 GBDT 怎么选
| XGBoost | LightGBM | CatBoost | |
|---|---|---|---|
| 训练速度 | 中 | 快 | 慢 |
| 精度 | 高 | 高 | 通常最高(尤其小数据) |
| 类别特征 | 需手动编码 | 支持 | 原生最优,无需编码 |
| 调参难度 | 中 | 中 | 低(默认参数就很强) |
| 何时用 | 通用 | 大数据、要速度 | 大量类别特征、小数据 |
三、特征重要性:一定要看
python
import pandas as pd
imp = pd.DataFrame({
"feature": X.columns,
"gain": model.booster_.feature_importance(importance_type="gain"),
}).sort_values("gain", ascending=False)
print(imp.head(15))| 类型 | 含义 | 陷阱 |
|---|---|---|
split(分裂次数) | 被用了几次 | 偏爱高基数特征 |
gain(增益) | 带来多少损失下降 | 更可靠,优先用 |
| permutation importance | 打乱该列后性能下降多少 | 最可信,但慢 |
重要性异常高 = 泄漏
某单个特征重要性 0.95+ 时,几乎一定是目标泄漏。回头查这列在预测时到底能不能拿到。
四、与业务沟通:SHAP
树模型能给出「为什么这一条被判为高风险」。
python
import shap
explainer = shap.TreeExplainer(model)
shap_values = explainer.shap_values(X_test[:200])
shap.summary_plot(shap_values, X_test[:200]) # 全局:哪些特征在推动预测
# 单样本解释
shap.waterfall_plot(shap.Explanation(
values=shap_values[0], base_values=explainer.expected_value,
data=X_test.iloc[0], feature_names=X_test.columns.tolist()))这在风控、医疗、信贷等需要解释给监管/客户的场景是刚需能力,比多 1 个点的 AUC 更有价值。
五、完整实战骨架
python
import numpy as np, pandas as pd, lightgbm as lgb
from sklearn.model_selection import StratifiedKFold
from sklearn.metrics import roc_auc_score
def train_lgb(X, y, X_test, n_splits=5):
oof = np.zeros(len(X))
pred = np.zeros(len(X_test))
cv = StratifiedKFold(n_splits=n_splits, shuffle=True, random_state=42)
for fold, (tr, va) in enumerate(cv.split(X, y), 1):
m = lgb.LGBMClassifier(
n_estimators=3000, learning_rate=0.05, num_leaves=31,
subsample=0.8, colsample_bytree=0.8, reg_lambda=1.0,
random_state=42, n_jobs=-1,
)
m.fit(X.iloc[tr], y.iloc[tr],
eval_set=[(X.iloc[va], y.iloc[va])], eval_metric="auc",
callbacks=[lgb.early_stopping(100, verbose=False)])
oof[va] = m.predict_proba(X.iloc[va])[:, 1]
pred += m.predict_proba(X_test)[:, 1] / n_splits
print(f"fold{fold} AUC={roc_auc_score(y.iloc[va], oof[va]):.4f}")
print(f"\nOOF AUC = {roc_auc_score(y, oof):.4f}")
return oof, predOOF(Out-of-Fold)预测是竞赛与 Stacking 的基础,也是判断「我的 CV 分数是否可信」的标准做法。
六、融合与 Stacking(进阶)
| 方法 | 做法 | 收益 |
|---|---|---|
| 简单平均 | 多个模型概率取均值 | 稳,几乎不亏 |
| 加权平均 | 按 CV 表现加权 | 小提升 |
| Stacking | 用 OOF 预测训练第二层(如逻辑回归) | 通常 +0.005~0.02 AUC |
| Blending | 用留出集代替 OOF | 简单但浪费数据 |
现实提醒
特征工程的收益 >> 融合的收益 >> 调参的收益。 先把时间和业务理解花在造特征上,等到 CV 已经完全上不去了,再考虑 Stacking。
通过标准
下一步
→ 无监督学习