6.3 Gradient Boosting 与 XGBoost:每棵新树拟合当前损失的下降方向
随机森林让许多树分别判断再平均,但少数高代价样本仍可能被系统性低估。Boosting 每一轮都针对当前目标函数尚未解决的部分继续修正。
Gradient Boosting 构造一个加法模型。新树不是泛泛“关注错题”,而是在当前预测处拟合损失对函数值的负梯度;平方损失下,这个方向恰好与 residual 对应。
本课目标
- 用函数梯度解释 gradient boosting;
- 理解 squared loss residual 只是一个特例;
- 看懂 XGBoost 的二阶近似、叶权重和正则项;
- 正确划分 train、validation 与 test 并使用 early stopping;
- 联合分析学习率、树容量、采样、校准和工程成本。
1. 加法模型
从常数模型
其中
在函数空间的 gradient boosting 中,对每个样本计算 pseudo-residual:
新树拟合
2. Residual 是平方损失的特例
若:
则:
正好是 ordinary residual。
但 binary log loss 通常在 logit/raw-score 空间优化。令
负梯度是
3. XGBoost 的二阶局部目标
XGBoost 在第
对当前预测做二阶 Taylor expansion,去掉与新树无关的常数:
其中:
若一棵树有
(实现还可支持 L1 等项)。对落入叶
这个解要求固定树结构,且
候选分裂的 gain 来自“分裂后两个叶子的最佳目标值”与“未分裂叶子”之差,再扣除新叶复杂度。二阶信息不是抽象的“更准”,而是用于估计当前局部曲率和 Newton-style 更新。
4. 容量参数不是独立旋钮
Learning rate 与轮数
较小
树结构
max_depth、max_leaves/grow policy 控制交互复杂度;min_child_weight 约束叶中 Hessian 权重,不等同于固定样本数;gamma/minimum split loss 要求足够分裂收益。
叶权重正则
L2 reg_lambda、L1 reg_alpha 收缩叶值。不同目标下 Hessian 尺度不同,相同参数值不能脱离 objective 比较。
行列采样
subsample、colsample_bytree 等引入随机性,可降低相关性/成本,但太低会丢信号并增大随机波动。
这些参数相互作用。不存在通用的“先深度、再正则、最后采样”唯一调参顺序;应先固定验证协议和搜索预算,再围绕容量、步长与成本联合比较。
5. Histogram、稀疏与类别支持
精确扫描所有连续阈值成本高。Histogram 方法先把值映射到 bins,再在累计 gradient/Hessian 统计上评估切分。Bin 数影响速度、内存和近似精度。
XGBoost 等实现可为缺失值学习默认分支方向,但这不等于缺失机制已被正确建模。训练与部署的 NaN 含义应一致,并监控缺失率漂移。
原生 categorical、类别分组与 one-hot 策略随库和版本变化。不要把任意整数编码直接当连续数值;应查当前版本文档、固定依赖,并用未见类别做部署测试。
6. Early stopping 必须使用 validation
数据职责应分开:
- train:拟合每轮树与叶权重;
- validation:选择轮数、参数与阈值;
- test:在所有选择冻结后评估一次。
把 test 放进 eval_set 做 early stopping,会让 test 参与模型选择。最终数字不再是未接触数据上的估计。
以下 Python 3 片段已用 CPU 版 XGBoost 3.4.1、scikit-learn 1.9.0 核验。需提供 train/validation/test 数组,标签为 0/1,各集合含两类。预处理只在 train 拟合,再以相同变换处理其他集合,包括 eval_set 中的数组。
from xgboost import XGBClassifier
from sklearn.metrics import log_loss
model = XGBClassifier(
objective="binary:logistic",
eval_metric="logloss",
tree_method="hist",
n_estimators=2_000,
learning_rate=0.05,
max_depth=4,
min_child_weight=5,
subsample=0.8,
colsample_bytree=0.8,
reg_lambda=1.0,
early_stopping_rounds=50,
n_jobs=1,
random_state=42,
)
model.fit(
X_train,
y_train,
eval_set=[(X_valid, y_valid)],
verbose=False,
)
# sklearn interface 会在预测时使用 early stopping 选出的最佳轮次。
test_probability = model.predict_proba(X_test)[:, 1]
print("test log loss:", log_loss(y_test, test_probability))若继续根据 test loss 调参,这份数据就成了 validation。新的最终估计需要独立留出数据;事后改跑 nested CV,不能抹掉此前受 test 结果影响的选择。
7. Native API 的最佳轮次陷阱
使用 xgboost.train 时,early stopping 默认返回的是最后一轮模型,而不是把 booster 截断为最佳轮次。预测需要显式指定类似:
下面片段需要带提前停止记录的原生 booster,以及名为 dtest 的测试 DMatrix:
best_probability = booster.predict(
dtest,
iteration_range=(0, booster.best_iteration + 1),
)或使用支持 save_best=True 的 early-stopping callback。还要注意:多个 evals/metrics 时,具体哪个数据集与指标控制停止由 API 规则决定,必须核对日志和当前官方文档。
这类行为会随接口版本调整,所以代码审查不能只看“设置了 early_stopping_rounds”,还要验证最终预测实际用了哪几轮。
8. Bagging 与 Boosting 的差异
| 维度 | Random Forest / Bagging | Gradient Boosting |
|---|---|---|
| 训练依赖 | 树大体可独立、并行 | 第 |
| 组合 | 概率/预测平均 | 加法累积 raw score/预测 |
| 多样性来源 | bootstrap、特征随机等 | 当前梯度、采样与树约束 |
| 轮数作用 | 平均逐渐稳定,收益平台 | 持续改变模型容量,需选最佳轮次 |
| 常见风险 | 深树体积、相关误差、概率失准 | 对噪声/漂移敏感、调参耦合、串行训练 |
“Bagging 降方差、Boosting 降偏差”可作入门启发,但不是定律。Bagging 也会改变 bias,Boosting 也可能降低或放大 variance;结果取决于基学习器、损失、正则和数据生成过程。
9. 评估不能停在一个 AUC
Boosted trees 常有很强排序能力,但 sigmoid/softprob 输出不保证校准。Class weights、undersampling、目标错设和分布变化都会改变概率语义。
至少检查:
- validation/test 的 log loss、Brier、AUC/PR 与业务成本;
- reliability curve 和不同时间/群体的 calibration;
- 最佳轮次在 fold 间是否稳定;
- 特征缺失率、raw score 与预测分布漂移;
- 推理延迟、模型体积和峰值内存。
若做 post-hoc calibration,校准数据必须独立于 base learner 的拟合,或使用交叉拟合。
10. 解释与外推边界
Gain、weight、cover 等 importance 定义不同,都会受相关特征和训练路径影响。SHAP 等解释工具描述的是给定模型相对某个背景分布的贡献分解,不自动提供因果解释,背景数据选择也会改变结论。
树集成在训练范围外通常延续已有叶值,不能像正确设定的线性/机制模型那样自然外推趋势。面对长期趋势、价格曲线或物理约束,应显式做 out-of-range 测试,必要时加入单调约束、机制特征或选择其他模型。
常见误区
- Boosting 就是反复拟合错分样本:一般目标下拟合的是负梯度/Newton 方向。
- 二阶近似天然更准确:它利用局部曲率,结果仍取决于目标与近似条件。
- 深度 3–6 是固定答案:树生长策略、数据和交互阶数不同。
- 用了 early stopping 就没有泄漏:控制停止的数据集必须是 validation,不是 test。
- 更多轮数只会更好:轮数是模型容量的一部分。
练习
- 推导 squared loss 与 binary log loss 的 gradient/Hessian。
- 在固定 split 下画 train/validation loss,并标出 best iteration。
- 比较 sklearn interface 与 native API 是否使用同一最佳轮次预测。
- 联合改变 learning rate 与 rounds,比较性能、训练时间和模型大小。
- 构造超出训练范围的输入,比较线性模型、随机森林和 boosting 的外推。
小结
Gradient Boosting 顺序构造加法模型,新树沿当前损失的下降方向修正预测。XGBoost 用 gradient、Hessian、结构惩罚与采样把这个过程变成可扩展的树优化系统。真正可靠的训练流程还需要独立 validation、正确的最佳轮次预测、概率评估与部署监控。
下一章离开有标签监督:先问无监督方法究竟优化什么,再讨论聚类、降维和异常检测的验证边界。