3. XGBoost算法原理:从GBDT到正则化树

说实话,很多同学一开始接触XGBoost,只觉得它是一个“黑盒神器”——扔数据进去,分数就出来了。但真要拿它做信用评分,不懂原理迟早要踩坑。我个人习惯是:先用GBDT把梯度提升的直觉建立起来,再看XGBoost在哪些地方做了升级。今天我们就来把这套逻辑讲透。

3.1 梯度提升决策树(GBDT)

GBDT的全称是Gradient Boosting Decision Tree。说白了,它就是把一堆弱分类器(通常是CART回归树)串起来,每棵树去纠正前一棵树的错误。

具体怎么纠错?用损失函数的负梯度方向来拟合残差。我刚开始做项目时,觉得这跟“拟合残差”没啥区别,后来发现不是——残差只是均方损失的特例,换成逻辑损失就不一样了。想想看,你的目标函数可能是二分类的logloss,残差根本定义不出来,但负梯度永远可以用。

用公式表达更清楚:对于第t轮,我们有前t-1棵树的集成模型F_{t-1}(x),那么第t棵树去拟合的是:

r_i = - [∂L(y_i, F(x_i)) / ∂F(x_i)] |_{F=F_{t-1}}

这玩意儿就叫伪残差(Pseudo-Residual)。我在银行做信用评分时,最早用的就是GBDT来做申请评分卡。模型上线后KS值0.42,但稳定性不太好。后来换了XGBoost,效果就稳多了——原因就在XGBoost加了正则项。

要点总结

  • GBDT是加法模型,每次迭代新增一棵树
  • 拟合方向是损失函数的负梯度(不是简单的残差)
  • 每棵树都是回归树,不管分类还是回归任务

3.2 XGBoost的优化目标

XGBoost在GBDT的基础上做了两件大事:显式加入正则项和对目标函数做二阶泰勒展开。

先说二阶展开。GBDT只用了一阶负梯度,而XGBoost把损失函数L(y, F)在F_{t-1}处做泰勒展开到二阶:

Obj^{(t)} = Σ_{i=1}^n [L(y_i, F_{t-1}(x_i)) + g_i f_t(x_i) + ½ h_i f_t^2(x_i)] + Ω(f_t)

其中g_i是一阶导数,h_i是二阶导数。f_t(x)是第t棵树的预测值,Ω(f_t)是正则项。

我做过对比实验:同样数据集,GBDT的迭代次数要300轮才能收敛,XGBoost差不多150轮就停了。说白了,二阶导数用了梯度的“变化率”,收敛路径更直。

⚠️ 注意:XGBoost的默认目标函数是reg:logistic或binary:logistic,输出是概率值,不是类别标号。做信用评分时,直接用概率值去算违约风险就行。

3.3 正则项

正则项是XGBoost的杀手锏。没有正则的GBDT特别容易过拟合——我在一个5000样本的小数据集上试过,GBDT训练集AUC 0.99,测试集0.72,简直是灾难。

XGBoost的正则项长这样:

Ω(f_t) = γ T + ½ λ Σ_{j=1}^T w_j^2 + ½ α Σ_{j=1}^T |w_j|

解释一下各个参数:

参数 含义 作用
γ 叶子节点数T的惩罚系数 控制树复杂度,越大树越简单
λ L2正则权重 防止叶子权重过大,提高泛化
α L1正则权重 使叶子权重稀疏,可用作特征选择

我个人习惯:信用评分场景下γ默认设为0,然后通过CV调λ和α。如果特征很多(50+),我会把α设成1左右,自动砍掉无关特征。

曾经有个同事,把γ设成100,结果树深度全是1,KS不到0.2。记住:正则不是越大越好,要结合交叉验证来调。

3.4 树结构:分枝策略

XGBoost的树是怎么生长的?它不像ID3算信息增益,也不像C4.5算增益率。它用的是结构化损失下降,也叫“增益”(Gain)。

对于当前节点的分裂候选(某个特征+切分点),增益公式:

Gain = ½ [ G_L^2/(H_L+λ) + G_R^2/(H_R+λ) - (G_L+G_R)^2/(H_L+H_R+λ) ] - γ

其中G_L、H_L是左子节点的一阶、二阶梯度之和,右子同理。γ就是刚才的正则项。如果Gain ≤ 0,这个分裂点就不用了——树会提前停止分裂。

你知道这意味着什么吗?XGBoost天然支持剪枝,不需要像CART那样先生成再后剪枝。我特别喜欢这点,因为它把正则的钱花在了刀刃上。

另外,XGBoost还支持列采样——就是每棵树只随机选一部分特征做分裂。这跟随机森林的思路一样,能降低树之间的相关性。我在信用评分建模时,行采样0.8、列采样0.7,效果最好。

XGBoost树结构——分裂与增益计算 根节点 左子节点 右子节点 叶子1 叶子2 叶子3 叶子4 增益计算公式(以根节点分裂为例) Gain = ½ [ G_L²/(H_L+λ) + G_R²/(H_R+λ) - (G_L+G_R)²/(H_L+H_R+λ) ] - γ 其中 G_L、H_L 为左子节点一阶、二阶梯度之和;G_R、H_R 为右子节点 若 Gain ≤ 0,则停止分裂(内置剪枝)

3.5 实际建模中的参数策略

讲完原理,我分享一个在信用评分项目中常用的参数配置模板。这并不是万能药,但可以作为起点:

参数 建议值 说明
n_estimators 100~200 配合早停,看验证集评价指标
learning_rate 0.05~0.1 越小越不会过拟合,但树的数量要增加
max_depth 4~6 信用评分特征较少(20~50),太深容易过拟合
subsample 0.8 行采样,防止样本扰动
colsample_bytree 0.7~0.9 列采样,降低树相关性
lambda 1~5 L2正则,我一般先设1,效果不好再加大
alpha 0~1 L1正则,特征多时可以开启

💡 如果你训练数据里正负样本严重不平衡(比如信用卡欺诈),可以设置scale_pos_weight参数,让模型更关注少数类。公式:scale_pos_weight = 负样本数 / 正样本数。

3.6 小结

这一章我们走完了从GBDT到XGBoost的核心进化路径。记住三个关键词:二阶导数(加速收敛)、正则项(防止过拟合)、结构增益剪枝(自动决定分裂点)。我个人觉得,XGBoost之所以成为Kaggle和金融风控的主流,就是因为它把“控过拟合”这件事做到了极致的工程化。后面的章节我们会一步步把它用到信用评分数据集上,到时候你就能直观感受这些参数的实际效果了。