xgboost 正则项_XGBoost基本原理

本文深入探讨了XGBoost相对于GBDT的改进,主要在于目标函数的泰勒展开项以及正则化项。XGBoost通过引入二次泰勒展开和树的复杂度正则化项,实现了更快的拟合速度和更优的模型性能。解释了正则化项的作用是防止过拟合,优化过程中目标函数加入变量平方项促使优化器选择更简洁的树结构。同时,文章介绍了单棵决策树的生成过程,包括贪婪算法的选择策略和分裂增益的计算方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

XGBoost的实现,我觉得主要还是在于对GBDT的改良上。对于GBDT还是不太熟悉的朋友,请看我这一篇文章《GBDT》。我个人认为这两者区别主要还是在于细节上,理解了GBDT我认为就差不多等于理解了XGBoost。

我重点比较一下XGBoost与GBDT两种算法的不同:

XGBoost的目标函数与GBDT存在泰勒展开项的不同:

最基本的差距就在于XGBoost比GBDT多了两项泰勒展开式。具体这个泰勒展开式是怎么得到的,是对于什么展开的呢?我们看:

XGBoost算法可以看成是由K棵树组成的加法模型:

XGBoost加法模型

其中F为所有树组成的函数空间(这里的回归树也就是一个分段函数,不同分段的不同取值就构成了一颗树),与一般机器学习算法不同的是,加法模型不是学习d维空间的权重,而是直接学习决策树的集合。

上述加法模型的目标函数定义为:

目标函数

其中Ω表示决策树的复杂度,那么该如何定义树的复杂度呢?比如,可以考虑树的节点数量、树的深度或者叶子节点所对应的分数的L2范数等等。

如何来学习加法模型呢?

解这一优化问题,可以用前向分布算法(forward stagewise algorithm)。有了之前GBDT的基础,我们知道,加法模型的学习器每次都用函数来拟合上一棵树没有拟合完整的残差,最后将这些残差全部加起来就会得到对于目标完整的预测,这也叫做Boosting。具体地,我们从一个常量预测开始,每次学习一个新的函数,过程如下:加法学习器的Boosting

这个公式看起来还是比较拗口,想要理解的话建议看我之前的文章《GBDT》,了解了工作模式这公式就好理解了。

这就会产生一个新的问题,那个新加入的函数f到底怎么得到的呢?这个原则还是最小化目标函数。我们可以将我们的目标函数写为:

目标函数变式

我们再用平方误差来衡量我们的损失函数:

平方误差衡量损失函数

其中

就是我们所谓的残差(residual)。我们每一次使用平方函数的时候,算法都是为了拟合这个残差。

可能有的朋友对于泰勒公式不是非常熟悉,我将基本的泰勒公式用法写在这:

泰勒公式基本形式

我们都知道,泰勒级数展开其实是有无穷多项的,在无穷多项形式里是严格等于,这里我们暂且只取了前三项省略了后面,所以就是约等于。

那有了泰勒公式的基础,我们将前面的目标函数变式可以转化为:

目标函数泰勒级数展开三项

其中,g与h分别是损失函数的一阶偏导数和二阶偏导数,具体数学形式如下:

泰勒展开的一次微分项与二次微分项

我们也可以将常数项直接去掉,并不会影响,那就使得目标函数是这个样子:

去掉常数项的目标函数

由于要学习的函数仅仅依赖于目标函数,从“去掉常数项的目标函数”可以看出只需为学习任务定义好损失函数,并为每个训练样本计算出损失函数的一阶导数和二阶导数,通过在训练样本集上最小化目标函数即可求得每步要学习的函数,从而根据加法模型可得最终要学习的模型。

GBDT的目标函数

就简单提一句GBDT与XGBoost的区别,明显可以看出,GBDT没有采用二次泰勒展开,这个看似很简单的区别,实际上带来更快的拟合,也大大缩减了生成树的规模,减少了运行时间。

XGBoost相比于GBDT加入了正则化项(Regularization)我们使用损失函数优化是为了避免欠拟合,而使用正则化项就是为了避免过拟合。正则化项与损失函数共同组成了我们的目标函数。XGBoost比GBDT多添加了以树复杂度构成的正则化项,也是XGBoost实际表现更为优秀的原因之一

何为正则化项?正则化项的作用是什么?

我们都知道,我们在优化目标函数的时候,总是希望它更加的“小”,也就是优化一般是最小化的意思。现在我们如果给目标函数加入一个变量的平方,那么如果这个变量一旦变大,那么目标函数为了“最小化”,一定很不喜欢这个变量变大的事实,选择的时候就会刻意避开会使变量变大的路径。这大概就是正则化的简单解释了。在XGBoost中,我们是将树的复杂度作为正则项加入,那么优化器在工作的时候,会尽量不让这个树更加复杂,也就达到我们的效果。

我们假设XGBoost决策树的叶子节点个数为T,该决策树是由所有叶子节点对应的值组成的向量w,以及一个把特征向量映射到叶子节点索引(Index)的函数

组成的,我们将树可以写成:

,我们也可以将决策树的复杂度定义成正则项:

决策树复杂度定义的正则化项

则目标函数我们可以写成:完整正则项的目标函数

用G与H代换一下原来的式子,我们就得到了简化后的式子:

简化后的目标函数

假设树的结构是固定的,即函数q(x)为固定的,令目标函数的一阶导数为0,则可以求出叶子节点j对应的值为:

叶子节点j对应的值

于是在这种条件下,目标函数的值就变成了:目标函数的值

为什么要计算这两个值呢?

是为了给大家描述单棵决策树的生成过程:

枚举所有可能的树的结构q

用目标函数值为每个q计算对应的分数Obj,分数越小说明结构越好

根据上一步结果,找到分数最小的子节点,生成新的分支,并为每个子节点计算预测值

XGBoost的分裂增益与GBDT的比较树结构数量是无穷的,所以实际上我们不可能枚举所有可能的树结构。通常情况下,我们采用贪心策略来生成决策树的每个节点。

我们来看看这个贪心算法是怎么工作的:

从深度为0的树开始,对每个叶节点枚举所有的可用特征

针对每个特征,把属于该节点的训练样本根据该特征值升序排列,通过线性扫描的方式来决定该特征的最佳分裂点,并记录该特征的最大收益(采用最佳分裂点时的收益)

选择收益最大的特征作为分裂特征,用该特征的最佳分裂点作为分裂位置,把该节点生长出左右两个新的叶节点,并为每个新节点关联对应的样本集

回到第1步,递归执行到满足特定条件为止

如何计算每次分裂的收益呢?假设当前节点记为C,分裂之后左孩子节点记为L,右孩子节点记为R,则该分裂获得的收益定义为当前节点的目标函数值减去左右两个孩子节点的目标函数值之和:Gain=ObjC-ObjL-ObjR,具体地,根据目标函数值公式可得:XGBoost的增益

### XGBoost 的基本工作原理 XGBoost 是一种基于梯度提升决策树(Gradient Boosting Decision Tree, GBDT)的高效实现,具有许多优化特性。以下是其核心原理: #### 1. **加法模型** XGBoost 使用加法模型的思想,在每一轮迭代中增加一颗新的决策树来拟合前序模型的残差[^4]。具体来说,每一颗新树的目标是减少整体损失函数中的误差部分。 #### 2. **目标函数定义** XGBoost 定义了一个可扩展的目标函数,该函数由两部分组成: - 预测误差项 \( L(y_i,\hat{y}_i) \),用于衡量预测值与真实值之间的差距。 - 正则化项 \( \Omega(f_k) \),用来控制模型复杂度并防止过拟合。 目标是最小化如下形式的目标函数: \[ Obj(\theta)=L(y_i,\hat{y}_i)+\sum_{k=1}^{K}\Omega(f_k) \] 其中,\( f_k(x) \) 表示第 k 棵树的预测贡献[^5]。 #### 3. **二阶泰勒展开近似** 为了更有效地优化上述目标函数,XGBoost 利用了二阶泰勒展开对损失函数进行了近似。这种做法使得每次更新都能快速找到最优解,并支持多种类型的损失函数[^2]。 #### 4. **树的分裂策略** 在构建每棵树的过程中,XGBoost 计算每个可能分割点处增益的最大值。如果某个节点继续划分带来的收益不足以抵消引入额外复杂性的成本,则停止进一步生长——这就是所谓的“提前剪枝”机制。 #### 5. **正则化处理** 相比传统 GBDT 方法仅关注降低偏差而不考虑方差问题,XGBoost 明确加入了两项重要的正则化措施:一是惩罚叶子数量;二是约束叶权重平方和大小。这些都体现在最终计算得到的最佳切分位置上。 #### 6. **并行计算加速** 虽然单次弱分类器之间存在依赖关系无法完全并行执行,但在寻找最佳特征阈值时可以充分利用现代 CPU/GPU 架构特点来进行多线程操作从而加快速度[^1]。 综上所述,XGBoost 不仅仅是简单地堆叠多个回归/分类器那么简单,而是通过对整个框架精心设计达到了既保持高精度又兼顾效率的目的. ```python import xgboost as xgb from sklearn.datasets import load_boston from sklearn.model_selection import train_test_split data = load_boston() X_train, X_test, y_train, y_test = train_test_split(data.data, data.target) dtrain = xgb.DMatrix(X_train, label=y_train) dtest = xgb.DMatrix(X_test, label=y_test) params = { 'objective': 'reg:squarederror', 'eval_metric': 'rmse' } model = xgb.train(params=params,dtrain=dtrain,num_boost_round=100) preds = model.predict(dtest) ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值