Xgboost算法梳理

算法原理

想要了解XGBoost算法的原理,首先需要理解Boosting算法。简单来说,Boosting算法是将个体学习器集成为更复杂学习器的机器学习方法,它更强调个体学习器之间存在强依赖关系,因此也可认为是串行集成学习方法。相比下,Bagging算法则属于并行集成学习方法。

Boosting算法的基本原理是:首先用初始样本训练一个基学习器,根据学习表现对样本分布进行调整,使得表现差的样本获得更多的关注,然后不断迭代用调整分布后的样本训练下一个基学习器,直到基学习器数量达到指定数目。

Boosting算法族中最著名的即是Freund于1997年提出的AdaBoost算法,可将其理解为“加性模型”,即最终的学习器为 T T T个基学习器的“加权和”模型,每次使用训练错误的样本训练新的基学习器,并通过权重调整降低之前表现不佳的学习器的影响,最终降低集成学习器的结果偏差。

2001年,Freund又提出了Gradient Boosting框架,将损失函数扩展到更一般的情况,即通过梯度计算回归拟合的残差(准确应称之为伪残差),基于该残差生成新的基学习器,并计算其最优的叠加权重值。如果选择基分类器为决策树(如CART树),则对应为GBDT算法。

CART树是分类树,并不满足GB回归损失函数的要求,因此需要将分类GINI系数指标替换为最小均方差,即当所有分枝的预测结果唯一或是达到叶节点数量上限时,以该树所有节点的预测均值作为该分类器的预测结果。此外,GBDT还借鉴了Bagging集成学习的一些思想,例如通过随机抽样提高模型的泛化能力,通过交叉验证选择最优参数等。

2014年,陈天奇博士提出了XGBoost算法,它可认为是在GBDT算法基础上的进一步优化。首先,XGBoost算法在基学习器损失函数中引入了正则项,控制减少训练过程当中的过拟合;其次,XGBoost算法不仅使用一阶导数计算伪残差,还计算二阶导数可近似快速剪枝的构建新的基学习器;此外,XGBoost算法还做了很多工程上的优化,例如支持并行计算、提高计算效率、处理稀疏训练数据等等。

目标函数

xgboost是GBDT的一个变种,它对损失函数进行泰勒展开时,取得是二阶展开而非一阶展开,因此与实际 O b j Obj Obj函数的值更接近(前提条件是损失函数二阶可导)
泰勒公式的二阶展开为:
f ( x + Δ x ) ≈ f ( x ) + f ′ ( x ) Δ x + 1 2 f ′ ′ ( x ) Δ x 2 f(x+\Delta x) \approx f(x)+f^{\prime}(x) \Delta x+\frac{1}{2} f^{\prime \prime}(x) \Delta x^{2} f(x+Δx)f(x)+f(x)Δx+21f(x)Δx2

由此可得目标函数的公式为:
O b j ( t ) ≈ ∑ i = 1 n [ l ( y i , y ^ i t − 1 ) + g i f t ( x i ) + 1 2 h i f t 2 ( x i ) ] + Ω ( f t ) g i 是 l ( y i , y ^ i t − 1 ) 关于 y ^ t − 1 的一阶导 , h i 是 l ( y i , y ^ i t − 1 ) 关于 y ^ t − 1 的二阶导 O b j^{(t)} \approx \sum_{i=1}^{n}\left[l\left(y_{i}, \hat{y}_{i}^{t-1}\right)+g_{i} f_{t}\left(x_{i}\right)+\frac{1}{2} h_{i} f_{t}^{2}\left(x_{i}\right)\right]+\Omega\left(f_{t}\right)\\ g_i \text{是$l\left(y_{i}, \hat{y}_{i}^{t-1}\right)$关于$\hat{y}^{t-1}$的一阶导},h_i \text{是$l\left(y_{i}, \hat{y}_{i}^{t-1}\right)$关于$\hat{y}^{t-1}$的二阶导} Obj(t)i=1n[l(yi,y^it1)+gift(xi)+21hift2(xi)]+Ω(ft)gil(yi,y^it1)关于y^t1的一阶导,hil(yi,y^it1)关于y^t1的二阶导

对这个 o b j obj obj进行优化就得到第 t t t步的 f t ( x ) f_t(x) ft(x), 然后将每一步的 f ( x ) f(x) f(x)加在一起就得到了整体模型。

用决策树来表示 f t ( x ) f_{t}(x) ft(x) O b j ( t ) O b j^{(t)} Obj(t)
f t ( x ) = w q ( x ) q ( x ) 代表样本  x  位于哪个叶子结点 , w q 代表该叶子结点的取值 f_{t}(x)=w_{q(x)}\\ q(x) \text{代表样本 $x$ 位于哪个叶子结点},w_q \text{代表该叶子结点的取值} ft(x)=wq(x)q(x)代表样本 x 位于哪个叶子结点,wq代表该叶子结点的取值
若决策树的复杂度定义为:
Ω ( f t ) = γ T + 1 2 λ ∑ j = 1 T w j 2 \Omega\left(f_{t}\right)=\gamma T+\frac{1}{2} \lambda \sum_{j=1}^{T} w_{j}^{2} Ω(ft)=γT+21λj=1Twj2
假设 I j = { i ∣ q ( x i ) = j } I_{j}=\left\{i | q\left(x_{i}\right)=j\right\} Ij={iq(xi)=j} 为第 j j j 个叶子结点的样本集合,则目标函数就变为:

O b j ( t ) ≈ ∑ i = 1 n [ g i f t ( x i ) + 1 2 h i f t 2 ( x i ) ] + Ω ( f t ) = ∑ i = 1 n [ g i w q ( x i ) + 1 2 h i w q ( x i ) 2 ] + γ T + 1 2 λ ∑ j = 1 T w j 2 = ∑ j = 1 T [ ( ∑ i ∈ I j g i ) w j + 1 2 ( ∑ i ∈ I j h i + λ ) w j 2 ] + γ T = ∑ j = 1 T [ G j w j + 1 2 ( H j + λ ) w j 2 ] + γ T \begin{array}{c}{\quad O b j^{(t)} \approx \sum_{i=1}^{n}\left[g_{i} f_{t}\left(x_{i}\right)+\frac{1}{2} h_{i} f_{t}^{2}\left(x_{i}\right)\right]+\Omega\left(f_{t}\right)} \\ {=\sum_{i=1}^{n}\left[g_{i} w_{q\left(x_{i}\right)}+\frac{1}{2} h_{i} w_{q\left(x_{i}\right)}^{2}\right]+\gamma T+\frac{1}{2} \lambda \sum_{j=1}^{T} w_{j}^{2}} \\ {=\sum_{j=1}^{T}\left[\left(\sum_{i \in I_{j}} g_{i}\right) w_{j}+\frac{1}{2}\left(\sum_{i \in I_{j}} h_{i}+\lambda\right) w_{j}^{2}\right]+\gamma T}\end{array}\\ =\sum_{j=1}^{T}\left[G_{j} w_{j}+\frac{1}{2}\left(H_{j}+\lambda\right) w_{j}^{2}\right]+\gamma T Obj(t)i=1n[gift(xi)+21hift2(xi)]+Ω(ft)=i=1n[giwq(xi)+21hiwq(xi)2]+γT+21λj=1Twj2=j=1T[(iIjgi)wj+21(iIjhi+λ)wj2]+γT=j=1T[Gjwj+21(Hj+λ)wj2]+γT
令: G j = ∑ i ∈ I j g i , H j = ∑ i ∈ I j h i G_{j}=\sum_{i \in I_{j}} g_{i}, H_{j}=\sum_{i \in I_{j}} h_{i} Gj=iIjgi,Hj=iIjhi

其中 G j G_j Gj H j H_{j} Hj 是固定的

O b j Obj Obj 函数关于 w j w_j wj 的一阶导为 0, 即可求的最优的 w j w_j wj

w j ∗ = − G j H j + λ w_{j}^{*}=-\frac{G_{j}}{H_{j}+\lambda} wj=Hj+λGj

则针对于结构固定的决策树,最优的 O b j Obj Obj

O b j = − 1 2 ∑ j = 1 T G j 2 H j + λ + γ T O b j=-\frac{1}{2} \sum_{j=1}^{T} \frac{G_{j}^{2}}{H_{j}+\lambda}+\gamma T Obj=21j=1THj+λGj2+γT

分裂结点算法

xgboost中用的却是预剪枝。在目标函数 o b j obj obj 中既考虑了 l o s s loss loss函数拟合训练数据,又考虑了正则项 Ω \Omega Ω 来减少模型复杂度,故无需剪枝。

具体步骤如下:

  1. 从深度为0的书开始,对每个叶节点枚举所有的可用特征
  2. 针对每个特征,把属于该节点的训练样本的该特征值升序排列,通过线性扫描的方式来决定该特征的最佳分裂点,并采用最佳分裂点时的收益
  3. 选择收益最大的特征作为分裂特征,用该特征的最佳分裂点作为分裂位置,把该节点生成出左右两个新的叶子结点,并为每个新节点关联新的样本集
  4. 回到第一步,继续递归直到满足特定条件。

分类前的针对于该子节点的最优目标函数是: O b j = − 1 2 ( G L + G R ) 2 ( H L + H R ) + λ + γ O b j=-\frac{1}{2} \frac{\left(G_{L}+G_{R}\right)^{2}}{\left(H_{L}+H_{R}\right)+\lambda}+\gamma Obj=21(HL+HR)+λ(GL+GR)2+γ,分裂后则变成了 O b j = − 1 2 [ G L 2 H L + λ + G R 2 H R + λ ] + 2 γ O b j=-\frac{1}{2}\left[\frac{G_{L}^{2}}{H_{L}+\lambda}+\frac{G_{R}^{2}}{H_{R}+\lambda}\right]+2 \gamma Obj=21[HL+λGL2+HR+λGR2]+2γ,那么对于该目标函数来说,分裂后的收益为

Gain ⁡ = 1 2 [ G L 2 H L + λ + G R 2 H R + λ − ( G L + G R ) 2 ( H L + H R ) + λ ] − γ \operatorname{Gain}=\frac{1}{2}\left[\frac{G_{L}^{2}}{H_{L}+\lambda}+\frac{G_{R}^{2}}{H_{R}+\lambda}-\frac{\left(G_{L}+G_{R}\right)^{2}}{\left(H_{L}+H_{R}\right)+\lambda}\right]-\gamma Gain=21[HL+λGL2+HR+λGR2(HL+HR)+λ(GL+GR)2]γ
于是便可以用上式来决定最优分裂特征和最优特征分割点。

寻找到最优分割点,常见的方法是枚举所有可能的分割点,称之为 exact greedy algorithm。但exact greedy algorithm计算量过大,而且当数据量较大没法全填入内存时,会很慢。因此xgboost引入了 approximate算法。

该算法对于某个特征 X k X_{k} Xk,首先通过特征分布来确定若干值域分界点 { s k 1 , s k 2 , … , s k l } \left\{s_{k 1}, s_{k 2}, \dots, s_{k l}\right\} {sk1,sk2,,skl}。然后根据这些值域分界点把样本分入桶中,对每个桶内的样本统计值G,H进行累加,记为分界点的统计量。最后在分界点集合上进行贪心查找,得到的结果就是最佳分裂点的近似。

如何寻找值域分界点 { s k 1 , s k 2 , … , s k l } \left\{s_{k 1}, s_{k 2}, \dots, s_{k l}\right\} {sk1,sk2,,skl}?XGBoost中介绍了一种方法,叫加权分位数略图 Weighted Quantile Sketch。
为了尽可能的逼近最佳分裂点,我们需要保证采样后的数据分布和原始数据分布尽可能一直。令 D k = { ( x 1 k , h 1 ) , ( x 2 k , h 2 ) , … , ( x n k , h n ) } D_{k}=\left\{\left(x_{1 k}, h_{1}\right),\left(x_{2 k}, h_{2}\right), \ldots,\left(x_{n k}, h_{n}\right)\right\} Dk={(x1k,h1),(x2k,h2),,(xnk,hn)} 表示每个训练样本的第 k k k 维特征的值和对应的二阶导数。然后定义排序函数为
r k ( z ) = ∑ ( x , h ) ∈ D k , x &lt; z h ∑ ( x , h ) ∈ D k h 即函数特征值小于  z  的样本分布占比,二阶导  h  是权重 r_{k}(z)=\frac{\sum_{(x, h) \in D_{k}, x&lt;z} h}{\sum_{(x, h) \in D_{k}} h}\\ \text{即函数特征值小于 $z$ 的样本分布占比,二阶导 $h $ 是权重} rk(z)=(x,h)Dkh(x,h)Dk,x<zh即函数特征值小于 z 的样本分布占比,二阶导 h 是权重
然后找到一组点 { s k 1 , s k 2 , … , s k l } \left\{s_{k 1}, s_{k 2}, \dots, s_{k l}\right\} {sk1,sk2,,skl} 满足:
∣ r k ( s k , j ) − r k ( s k , j + 1 ) ∣ &lt; ε | r_k(s_{k, j}) - r_k(s_{k, j+1})| &lt; \varepsilon rk(sk,j)rk(sk,j+1)<ε
其中, s k 1 = m i n i x i k , s k l = m a x i x i k , ε s_{k1} = min_i x_{ik}, s_{kl}= max_i x_{ik}, \varepsilon sk1=minixik,skl=maxixik,ε是采样率,因为 0 &lt; r k ( z ) &lt; 1 0 &lt; r_k(z) &lt; 1 0<rk(z)<1,所以我们会得到 1 ε \frac{1}{\varepsilon} ε1个分界点。

正则化

目标函数中正则化项存在的原因是为了限制模型的复杂度,让模型在训练集上能够取得较好的结果的前提下尽可能地简单。从前面的推导中可以知道,在 XGBoost 中,对于采用前向分布方法一步步迭代的优化时,我们模型的复杂度就是当前要定义的决策树的复杂度。

对缺失值处理

对于这些缺失值,xgboost将样本分类到默认分支上去,而默认分支是由non-missing value学习得到的。具体算法如下:

由上可见,该算法只考虑non-missing entries I k I_k Ik,因此计算复杂度是数据中的非缺失值个数的线性比值,对于稀疏数据来说,计算的很快。

对于缺失值的样本,算法分别将它们放到左节点和右节点,选取增益最大的一侧作为默认分类。

优缺点

XGBoost是DMLC开源在Github的Gradient Boosting框架,主要作者是陈天奇。它支持C++/Java/Python/R等语言,同样也支持Hadoop/Spark/Flink等分布式处理框架,且在数据竞赛中拥有优异的表现。
相比于普通的GBDT,XGBoost主要优点在于:

  • 不仅支持决策树作为基分类器,还支持线性分类器
  • 用到了 l o s s loss loss 的二阶泰勒展开,因此与损失函数更接近,收敛更快 - 在代价函数中加入了正则项,用于控制模型复杂度。正则项里包括了树的叶子节点个数和叶子结点输出值的L2范数,可以防止模型过拟合。
  • Shrinkage,就是前面所述的 η \eta η主要用于削弱每科树的影响,让后面有更大的学习空间。实际应用中,一般把
    设小点,迭代次数设大点。
  • 列抽样(column sampling)。xgboost从随机森林算法中借鉴来的,支持列抽样可以降低过拟合,并且减少计算。
  • 支持对缺失值的处理。对于特征值缺失的样本,xgboost可以学习这些缺失值的分裂方向。
  • 支持并行。在对每颗树进行节点分裂时,需要计算每个特征的增益,选择最大的那个特征作为分裂特征,各个特征的增益计算可以开多线程进行
  • 近似算法(Approximate Algorithm),树节点在分裂时,需要枚举每个可能的分割点。当数据没法一次性载入内存时,这种方法会很慢。xgboost提出了一种近似的方法去高效的生成候选分割点。

xgboost参数

xgboost参数设置

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值