文章目录

  • 背景
  • 定义损失函数
    • (1)原始目标函数Obj
    • (2)原始目标函数Obj的泰勒展开
    • (3)具体化目标函数的泰勒展开细节
    • (4)求解目标函数中的wjw_jwj​
  • 最优切分点算法
  • 基于分桶的划分策略
  • 正则化
    • 模型复杂度
    • Shrinkage
    • 特征采样和样本采样
    • Early Stopping
  • 缺失值处理
  • 优缺点
  • 总结

背景

讲XGBoost之前,先引入一个实际问题,即预测一家人每个人玩游戏的意愿值:

如果我们用XGBoost解决这个问题,步骤是:首先要训练出来第一棵决策树, 预测了一下小男孩想玩游戏的意愿是2, 然后发现离标准答案差一些,再训练出第二棵决策树, 预测了一下小男孩想玩游戏的意愿是0.9, 最后两个相加就是最终的答案2.9。也就是说,XGBoost是把训练出来的弱分类结果进行累加当作最终的结论。

XGBoost的思想和GBDT有相似之处,比较大的不同就是目标函数的定义,即XGBoost聚焦与标准答案的残差。准确来说它是一种GBDT的工业级实现。其主要原理是在GBDT的基础上,在损失函数加入正则化部分,并且每一轮迭代对损失函数做二阶泰勒展开,加快对损失函数的优化速度。

XGBoost算法也是采用分步前向加性模型,只不过与GBDT不同,在每次迭代中生成弱学习器后不再需要计算一个系数。XGBoost 是由 k 个基模型组成的一个加法运算式:
y^i=∑t=1kft(xi)\hat y_i = \sum^k_{t=1}f_t(x_i) y^​i​=t=1∑k​ft​(xi​)
其中,ftf_tft​是第t个模型,损失函数可以由真实值yiy_iyi​和预测值y^i\hat y_iy^​i​表示:
L=∑t=1Nl(yi,y^i)L = \sum^N_{t=1}l(y_i, \hat y_i) L=t=1∑N​l(yi​,y^​i​)
其中N是样本个数。

定义损失函数

对于第m棵树而言,XGBoost的损失函数在GBDT损失函数中加入了如下的正则化:
Ω(ft)=γTt+λ2∑j=1Tωj2\Omega(f_t)=\gamma T_t+\frac{\lambda}{2}\sum_{j=1}^{T}\omega_{j}^2 Ω(ft​)=γTt​+2λ​j=1∑T​ωj2​
TtT_tTt​:叶子节点数, wjw_jwj​:叶子上的节点权重,γ,λ\gamma,\lambdaγ,λ是超参数。当正则化为零时,目标回归到传统的梯度提升树。正则化起到了抑制模型复杂度的作用,从而避免了过拟合。

这里的 ωj\omega_{j}ωj​ 和在GBDT里面使用的 cjc_{j}cj​ 其实是一个意思,只是XGBoost论文里面使用 ω\omegaω 符号表示叶子区域的值,这里为了和论文保持一致。最终,XGBoost的目标(损失)函数可以表示为:
Obj=∑i=1nl(yi,y^i)+∑t=1kΩ(ft)Obj =\sum_{i=1}^n l(y_i,\hat y_i) + \sum_{t=1}^k \Omega(f_t) Obj=i=1∑n​l(yi​,y^​i​)+t=1∑k​Ω(ft​)
我们要极小化上面这个损失函数,得到第决策树最优的所有JJJ个叶子节点对应的区域和每个叶子节点区域的最优解ωj\omega_{j}ωj​。

接下来一步一步的对这个目标函数ObjObjObj 进行化简。主要由以下四步组成:

(1)原始目标函数Obj

(2)原始目标函数Obj的泰勒展开

(3)具体化目标函数的泰勒展开细节

(4)求解目标函数中的wjw_jwj​,并带入目标函数,得到最终版目标函数

(1)原始目标函数Obj

XGBoost在损失函数优化方面做了一些优化,基于损失函数的二阶泰勒展开式来求解。XGBoost算法也是采用分步前向加性模型,设第t−1t-1t−1步模型的输出为y^it−1\hat y_i^{t-1}y^​it−1​,则第ttt步模型的第iii个样本xix_ixi​ 的预测为:
y^it=y^it−1+ft(xi)\hat y_i ^t = \hat y_i^{t-1} + f_t(x_i) y^​it​=y^​it−1​+ft​(xi​)
ft(xi)f_t(x_i)ft​(xi​)是需要新加入的模型。将y^it\hat y_i ^ty^​it​ 带入Obj,则有:
Objt=∑i=1nl(yi,y^it)+∑i=1tΩ(ft)=∑i=1nl(yi,y^it−1+ft(xi))+∑i=1tΩ(ft)\begin{aligned} Obj^{t} &=\sum_{i=1}^n l(y_i,\hat y_i^t) + \sum_{i=1}^t \Omega(f_t) \\ &=\sum_{i=1}^n l\left(y_i, \hat y_i^{t-1} + f_t(x_i)\right) + \sum_{i=1}^t \Omega(f_t) \end{aligned} Objt​=i=1∑n​l(yi​,y^​it​)+i=1∑t​Ω(ft​)=i=1∑n​l(yi​,y^​it−1​+ft​(xi​))+i=1∑t​Ω(ft​)​
我们的目标是:求解当前的树ft(xi)f_t(x_i)ft​(xi​),使得Obj 最小。 也就是:新生成的决策树要不断地拟合残差。

(2)原始目标函数Obj的泰勒展开

将y^it−1\hat y_i^{t-1}y^​it−1​ 视为参数,将ft(xi)f_t(x_i)ft​(xi​)视为参数的增量,现在来看看这个损失函数的二阶泰勒展开式:
Obj(t)=∑i=1nl(yi,y^it−1+ft(xi))+∑i=1tΩ(ft)≈∑i=1N(l(yi,y^it−1)+gift(xi)+12hift2(xi))+∑i=1tΩ(ft)\begin{aligned} Obj^{(t)} &=\sum_{i=1}^n l\left(y_i, \hat y_i^{t-1} + f_t(x_i)\right) + \sum_{i=1}^t \Omega(f_t)\\ & \approx \sum_{i=1}^{N}\left(l(y_i,\hat y_i^{t-1})+g_if_t(x_i)+\frac{1}{2}h_if_t^2(x_i)\right)+\sum_{i=1}^t \Omega(f_t) \end{aligned} Obj(t)​=i=1∑n​l(yi​,y^​it−1​+ft​(xi​))+i=1∑t​Ω(ft​)≈i=1∑N​(l(yi​,y^​it−1​)+gi​ft​(xi​)+21​hi​ft2​(xi​))+i=1∑t​Ω(ft​)​
其中:
gi=∂l(yi,y^it−1)∂y^it−1hi=∂2l(yi,y^it−1)∂(y^it−1)2g_i =\frac{\partial l(y_i,\,\hat y_i^{t-1})}{\partial \hat y_i^{t-1}} \\ h_i =\frac{\partial^2 l(y_i,\,\hat y_i^{t-1})}{\partial (\hat y_i^{t-1})^2} gi​=∂y^​it−1​∂l(yi​,y^​it−1​)​hi​=∂(y^​it−1​)2∂2l(yi​,y^​it−1​)​
由于yi,y^it−1y_i,\hat y_i^{t-1}yi​,y^​it−1​ 均为已知值,所以 l(yi,y^it−1)l(y_i,\hat y_i^{t-1})l(yi​,y^​it−1​) 是常数。对优化目标函数的优化不会产生影响,所以舍去这一项:
Obj(t)≈∑i=1N(gift(xi)+12hift2(xi))+∑i=1tΩ(ft)\begin{aligned} Obj^{(t)} & \approx \sum_{i=1}^{N}\left(g_if_t(x_i)+\frac{1}{2}h_if_t^2(x_i)\right)+\sum_{i=1}^t \Omega(f_t) \end{aligned} Obj(t)​≈i=1∑N​(gi​ft​(xi​)+21​hi​ft2​(xi​))+i=1∑t​Ω(ft​)​

(3)具体化目标函数的泰勒展开细节

目标函数为:
Obj(t)≈∑i=1N(gift(xi)+12hift2(xi))+∑i=1tΩ(ft)\begin{aligned} Obj^{(t)} & \approx \sum_{i=1}^{N}\left(g_if_t(x_i)+\frac{1}{2}h_if_t^2(x_i)\right)+\sum_{i=1}^t \Omega(f_t) \end{aligned} Obj(t)​≈i=1∑N​(gi​ft​(xi​)+21​hi​ft2​(xi​))+i=1∑t​Ω(ft​)​
这里的变量ft(xi)f_t(x_i)ft​(xi​) 表示训练样本xix_ixi​ 经过决策树模型的预测值。把决策树模型定义成ft(xi)=wq(x)f_t(x_i)=w_q(x)ft​(xi​)=wq​(x),其中q(x)q(x)q(x) 代表了该样本在哪个叶子节点上,www 表示叶子结点的权重(也就是决策树的预测值:小男孩想玩游戏的意愿 2),所以wq(x)w_q(x)wq​(x)代表每个样本的预测值。

若定义Ij={i∣q(xi)=j}I_j=\{i|q(x_i)=j\}Ij​={i∣q(xi​)=j}为第jjj个叶子节点的样本集合,经过ttt轮迭代完毕以后每个决策树(弱学习器)的第jjj个叶子节点的取值(也就是该叶子节点对应的预测值)最终会是同一个值ωj\omega_{j}ωj​。由于一个叶子结点有多个样本,所以每一个叶子结点的一阶导数之和为∑i∈Ijgi\sum _{i \in I_j}g_i∑i∈Ij​​gi​,同理有二阶导之和∑i∈Ijhi\sum _{i \in I_j}h_i∑i∈Ij​​hi​ 。因此,可以对损失函数继续化简:
Obj(t)≈∑i=1N(gift(xi)+12hift2(xi))+Ω(ft)=∑j=1T[(∑i∈Ijgi)wj+12(∑i∈Ijhi)wj2]+γT+λ2∑j=1Jωj2=∑j=1T[(∑i∈Ijgi)wj+12(∑i∈Ijhi+λ)wj2]+γT\begin{aligned} Obj^{(t)} & \approx \sum_{i=1}^{N}\left(g_if_t(x_i)+\frac{1}{2}h_if_t^2(x_i)\right)+ \Omega(f_t) \\ &=\sum_{j=1}^{T}\left[(\sum _{i \in I_j}g_i)w_{j}+\frac{1}{2}(\sum _{i \in I_j}h_i)w_{j}^2\right] + \gamma T+\frac{\lambda}{2}\sum_{j=1}^{J}\omega_{j}^2 \\ &= \sum_{j=1}^{T}\left[(\sum _{i \in I_j}g_i)w_{j}+\frac{1}{2}(\sum _{i \in I_j}h_i + \lambda)w_{j}^2\right] + \gamma T \end{aligned} Obj(t)​≈i=1∑N​(gi​ft​(xi​)+21​hi​ft2​(xi​))+Ω(ft​)=j=1∑T​⎣⎡​(i∈Ij​∑​gi​)wj​+21​(i∈Ij​∑​hi​)wj2​⎦⎤​+γT+2λ​j=1∑J​ωj2​=j=1∑T​⎣⎡​(i∈Ij​∑​gi​)wj​+21​(i∈Ij​∑​hi​+λ)wj2​⎦⎤​+γT​
同样为了方便表示,记:
Gj=∑i∈IjgjHj=∑i∈IjhjG_{j}=\sum_{i \in I_{j}} g_{j}\\ H_{j}=\sum_{i \in I_{j}} h_{j} Gj​=i∈Ij​∑​gj​Hj​=i∈Ij​∑​hj​
于是有:
Obj(t)=∑j=1T[Gjwj+12(Hj+λ)wj2]+γTObj^{(t)}= \sum_{j=1}^{T}\left[G_jw_{j}+\frac{1}{2}(H_j + \lambda)w_{j}^2\right] + \gamma T Obj(t)=j=1∑T​[Gj​wj​+21​(Hj​+λ)wj2​]+γT
好,现在简化的损失函数有了,现在又多了两个问题。

(4)求解目标函数中的wjw_jwj​

第一个问题,前面我们假设树的第 j 个叶子节点的输出值为ωj\omega_{j}ωj​,这个数值具体是多少,怎么求?

因为Gj、HjG_{j}、H_{j}Gj​、Hj​ 求解均为已知值。只有最后一颗树的叶子节点wjw_jwj​ 的值是不确定的。要求得wjw_jwj​ 使得目标函数ObjObjObj 极小化。所以将目标函数对wjw_jwj​ 求一阶导,令其等于0,即:
wj∗=−GjHj+λw_j^* = -\frac{G_j}{H_j+\lambda} wj∗​=−Hj​+λGj​​
将上面的式子代入目标函数,又能进一步化简得到:
Obj=−12∑j=1T[Gj2Hj+λ]+γTObj =-\frac{1}{2}\sum_{j=1}^{T}[\frac{G_{j}^2}{H_{j}+\lambda}]+\gamma T Obj=−21​j=1∑T​[Hj​+λGj2​​]+γT
式子中的G和H,就需要明确的给出损失函数才能求得。给定不同的树,ObjObjObj的值也会不同,也就是说,我们可以用ObjObjObj 来给一颗树打分,作用类似于CART算法中的Gini值。

有了这个,我们就知道这棵树建的好不好了。回到预测每个人玩游戏意愿预测的例子:

假设建了右边的那棵树,那么每个样本都对应到了叶子节点上去,每一个样本都会对应一个g和h, 那么我们遍历叶子节点,就会得到每个叶节点的G和H,然后累加就可以得到这棵树的结构分数。

注意两个细节:

(1)每个样本的hi,gih_i,g_ihi​,gi​ 之间没有关系,可以并行计算。加快了训练速度。

(2) hi,gih_i,g_ihi​,gi​ 的计算要求损失函数二阶可导。

最优切分点算法

第二个问题,如何建立一颗树呢?XGBoost采用二叉树, 用了贪心策略。在开始的时候, 全部样本在一个叶子节点上, 然后叶子节点不断通过二分裂,逐渐生成一棵树。

叶节点分裂成树的过程中最关键的是应该在哪个特征的哪个点上进行分裂,也就是寻找最优切分点的过程。对XGBoost算法而言,分列前的目标函数可以写为:
Obj1=−12[(GL+GR)2HL+HR+λ]+γObj_1 =-\frac{1}{2}[\frac{(G_{L}+G_R)^2}{H_{L}+H_{R+}\lambda}]+\gamma Obj1​=−21​[HL​+HR+​λ(GL​+GR​)2​]+γ
令IL,IRI_L,\,I_RIL​,IR​分别表示分裂点之后加入左右叶子节点的样本集合,且有GL=∑i∈ILgi,GR=∑i∈IRgi,HL=∑i∈ILhi,HR=∑i∈IRhiG_L=\sum_{i\in I_L}g_{i},G_R=\sum_{i\in I_R}g_{i},H_L=\sum_{i\in I_L}h_{i},H_R=\sum_{i\in I_R}h_{i}GL​=i∈IL​∑​gi​,GR​=i∈IR​∑​gi​,HL​=i∈IL​∑​hi​,HR​=i∈IR​∑​hi​,则分裂后的目标函数可以写为:
Obj2=−12[GL2HL+λ+GR2HR+λ]+2γObj_2 =-\frac{1}{2}[\frac{G_{L}^2}{H_{L}+ \lambda} +\frac{G_{R}^2}{H_{R}+ \lambda} ] +2\gamma Obj2​=−21​[HL​+λGL2​​+HR​+λGR2​​]+2γ
则分裂后的收益(分裂前后损失的差)表示为Obj1−Obj2Obj_1 - Obj_2Obj1​−Obj2​:
Gain=12[GL2HL+λ+GR2HR+λ−(GL+GR)2HL+HR+λ]−γGain = \frac{1}{2}\left[\frac{G_{L}^2}{H_{L}+ \lambda} +\frac{G_{R}^2}{H_{R}+ \lambda}-\frac{(G_{L}+G_R)^2}{H_{L}+H_{R+}\lambda}\right] - \gamma Gain=21​[HL​+λGL2​​+HR​+λGR2​​−HL​+HR+​λ(GL​+GR​)2​]−γ
基于上面的描述,得到最优切分点的划分算法:

  • 从深度为 0 的树开始,对每个叶节点枚举所有的可用特征;
  • 针对每个特征,把属于该节点的训练样本根据该特征值进行升序排列,通过线性扫描的方式来决定该特征的最佳分裂点,并记录该特征的分裂收益;(这个过程每个特征的收益计算是可以并行计算的)
  • 选择收益最大的特征作为分裂特征,用该特征的最佳分裂点作为分裂位置,在该节点上分裂出左右两个新的叶节点,并为每个新节点关联对应的样本集
  • 回到第 1 步,递归执行到满足特定条件为止
    如下图所示:

回到玩游戏的那个例子,假设我有每个人有性别,年龄,兴趣等几个特征,我想用XGBoost建立一棵树预测玩游戏的意愿值。首先,五个人都聚集在根节点上,现在就考虑根节点分叉,我们就遍历每个特征,对于当前的特征,我们要去寻找最优切分点以及带来的最大收益。比如当前特征是年龄,我们需要知道两点:

  1. 按照年龄分是否有效,即,是否减少了损失值 ?
  2. 如果真的可以分,特征收益比较大, 那么我们从哪个年龄点分开呢?

对于这两个问题,首先是要对年龄排序,5个人可以找到4个切分点。对于每个切分点,计算HL,HR,GL,GRH_L,H_R,G_L,G_RHL​,HR​,GL​,GR​,取出使得$Gain $最大的划分点a:

然后哪个最大,就是年龄特征的最优切分点,而最大值就是年龄这个特征的最大信息收益。

遍历完所有特征后,我们就可以确定应该在哪个特征的哪个点进行切分。对切分出来的两个节点,递归地调用这个过程,我们就能获得一个相对较好的树结构, 有了树结构就比较容易找最优的叶子节点,这样就能对上面的样本进行预测了。当然,特征与特征之间的收益计算是互不影响的,所以这个遍历特征的过程其实可以并行运行。

要注意的是XGBoost在切分的时候就已经考虑了树的复杂度 λ ,所以,它不需要进行单独的剪枝操作。

基于分桶的划分策略

当数据量大,特征又多的时候,数据划分的计算量太大了。于是作者采用近似分割的方式(可以理解为分割点分桶的思路),选出一些候选的分裂点,然后再遍历这些较少的分裂点来找到最佳分裂点。

具体而言,作者这里采用了一种对loss的影响权重的等值percentiles(百分比分位数)划分算法(Weight Quantile Sketch)。也就是说,进行候选点选取的时候,考虑的是想让loss在左右子树上分布的均匀一些,而不是样本数量的均匀。

我们知道每个样本对于降低loss的贡献可能不-样,所以我们可以根据这个贡献程度给每个样本加上权值,这里用 hi 表示(即 hi 表示每个样本对降低 Ioss 的贡献程度) 。这样我们就可以画出下面这个图来,第一行表示每个样本在某个特征上取值情况,第二行代表每个样本对于降低loss的贡献程度:

划分的时候,我们是根据这个 hi 的取值进行分箱的,就是尽量的每个桶里面的 hi 分布相对均匀些,不让某些节点重要的样本多而且还大。比如最右边的子树,只要一 个权重特别大的样本就够了,而左边的子树,样本权值偏低,所以咱可以多给些样本,这样loss在树结构中才比较均匀,这样每个bin的贡献度都是0.6了,比较均匀。

现在又用了两个问题:

  1. hi 是啥,它为啥就能代表样本对降低loss的贡献程度?
  2. 这个bin是怎么分的,为啥是0.6一个箱?

对于第一个问题,hi 其实就是前面说到的二阶导,也就是下面损失函数中的 hih_{i}hi​:
KaTeX parse error: No such environment: align at position 8: \begin{̲a̲l̲i̲g̲n̲}̲ Obj^{(t)} …
对于上面的式子,可以凑完全平方项,并化简为如下的形式(这里不展开讲,有兴趣看看参考文章1):
Obj≈∑i=1N12hi(ft(xi)−(−gihi))2+Ω(ft)+ConstantObj \approx \sum_{i=1}^{N} \frac{1}{2}h_{i} \left( f_t(x_i)-(-\frac{g_{i}}{h_{i}}) \right)^2 +\Omega(f_t)+Constant Obj≈i=1∑N​21​hi​(ft​(xi​)−(−hi​gi​​))2+Ω(ft​)+Constant
也就是hih_{i}hi​是表示残差−gihi-\frac{g_{i}}{h_{i}}−hi​gi​​的重要程度,即每个样本对loss减少的贡献程度。

对于第二个如何分箱的问题,定义数据集Dk={(x1k,h1),(x2k,h2),...,(xnk,hn)}D_k=\{(x_{1k}, h_1), (x_{2k}, h_2),...,(x_{nk}, h_n)\}Dk​={(x1k​,h1​),(x2k​,h2​),...,(xnk​,hn​)}代表每个训练样本第k个特征的取值和二阶梯度值,定义一个排名函数
rk(z)=1∑(x,h)∈Dkh∑(x,h)∈Dk,x<zhr_k(z) = \frac{1}{\sum_{(x,h)\in D_k} h}\; \sum_{(x,h)\in D_k, x<z}h rk​(z)=∑(x,h)∈Dk​​h1​(x,h)∈Dk​,x<z∑​h
上面的式子中,z表示特征值小于z的样本的贡献度占比。

对于上图的第一个划分点,rk(z)=13r_k(z)=\frac{1}{3}rk​(z)=31​。加入有lll个划分点,我们用{sk1,sk2,..,skl}\{s_{k1}, s_{k2},..,s_{kl}\}{sk1​,sk2​,..,skl​}表示,目标是让相邻的划分点的贡献度都差不多,即指定ε,使得:
∣rk(skj)−rk(skj+1)∣<ε|r_k(s_{kj})-r_k(s_{kj+1})|<ε ∣rk​(skj​)−rk​(skj+1​)∣<ε
例如,设定ε=13ε=\frac{1}{3}ε=31​,那么划分点就是1/3分位点,2/3分位点。上面样本贡献度总和是1.8, 那么每个箱贡献度就是 1.8 * 1/3 = 0.6。

上面这些公式看起来挺复杂,可计算起来很简单,就是计算一下总的贡献度, 然后指定ε,两者相乘得到每个桶的贡献度进行分桶即可。这样我们就可以确定合理的候选切分点,然后进行分箱了。
过程如下图所示:

在树生成的过程中,每一个特征的划分点{sk1,sk2,..,skl}\{s_{k1}, s_{k2},..,s_{kl}\}{sk1​,sk2​,..,skl​}是否会发生改变呢?有如下两种情况:

  1. 全局近似:在构造树的初始阶段提出所有的候选分裂点,然后对各个层次采用相同的候选分裂点{sk1,sk2,..,skl}\{s_{k1}, s_{k2},..,s_{kl}\}{sk1​,sk2​,..,skl​}。候选分裂点不更新,每次的候选分裂点数目多。
  2. 局部近似:在每次分裂都重新提出候选分裂点,对层次较深的树更适合,候选分裂点的数目不需要太多

总结下,前面那一部分是围绕着如何建立一棵树进行的,即采用贪心的方式从根节点开始一层层的建立树结构(每一层争取最优),然后就是建树过程中一个关键的问题:如何寻找最优切分点,给出了最优切分点算法,基于这个算法就可以建立树了。

后面这一部分是一个优化的过程,提出了一种Weight Quantile Sketch的算法,这个算法可以将原来的分割点进行分桶,然后找到合适的候选分裂点,这样可以减少遍历时尝试的分裂点的数量,是XGBoost相比于GBDT做出的切分点优化策略,现在知道为啥XGBoost要快了吧,因为XGBoost寻找切分点的时候不用遍历所有的,而是只看候选点就可以了。而且在特征上,XGBoost是可以并行处理的。这样XGBoost的建树过程及优化策略基本上就是这些了。

正则化

总体上讲,XGBoost抵抗过拟合的方法与GBDT类似,主要也是从以下几方面考虑:

模型复杂度

正则化项的表达式:
Ω(ft)=γTt+λ2∑j=1Tωj2\Omega(f_t)=\gamma T_t+\frac{\lambda}{2}\sum_{j=1}^{T}\omega_{j}^2 Ω(ft​)=γTt​+2λ​j=1∑T​ωj2​
其中,TtT_tTt​ 是叶节点个数,ωj\omega_{j}ωj​是棵树第j个叶节点的最优值。第一项是用于对过多的叶节点个数进行惩罚,第二项对过于大的最优值(预测值)进行惩罚。

Shrinkage

Shrinkage的思想是,每次走一小步逼近最优值,比每次迈一大步很快逼近结果的方式更容易避免过拟合。因为这个过程不完全信任每一个棵残差树,它认为每棵树只学到了真理的一小部分,累加的时候只累加一小部分,通过多学几棵树弥补不足。用方程来看更清晰,即给每棵数的输出结果乘上一个步长α\alphaα(learning rate),于是原来的弱学习器迭代:
y^it=y^it−1+ft(xi)\hat y_i ^t = \hat y_i^{t-1} + f_t(x_i) y^​it​=y^​it−1​+ft​(xi​)

由于Shrinkage思想的加入,变成了:
y^it=y^it−1+αft(xi)\hat y_i ^t = \hat y_i^{t-1} + \alpha f_t(x_i) y^​it​=y^​it−1​+αft​(xi​)
其中,α\alphaα的取值范围为(0,1]。对于同样的训练集学习效果,较小α\alphaα的意味着需要更多的弱学习器的迭代次数。通常我们用步长α\alphaα和迭代最大次数一起决定算法的拟合效果。

特征采样和样本采样

XGBoost借鉴RF的思想,对特征和特征进行采样以达到降低过拟合的目的,根据用户反馈,特征采样比起样本采样效果更优(特征采样率:[0.5,0.8])。当然,XGBoost同时支持以上两种降低过拟合的采样方式。

Early Stopping

对于每一次分离后的增益,即前面的:
Gain=12[GL2HL+λ+GR2HR+λ−(GL+GR)2HL+HR+λ]−γGain = \frac{1}{2}\left[\frac{G_{L}^2}{H_{L}+ \lambda} +\frac{G_{R}^2}{H_{R}+ \lambda}-\frac{(G_{L}+G_R)^2}{H_{L}+H_{R+}\lambda}\right] - \gamma Gain=21​[HL​+λGL2​​+HR​+λGR2​​−HL​+HR+​λ(GL​+GR​)2​]−γ
在sklearn接口当中,如果GainGainGain出现负值,则提前停止;但是,被提前终止掉的分裂可能其后续的分裂会带来好处。在XBGoost原生接口当中是采用过后剪枝策略:将树分裂到最大深度,然后再基于上述增益计算剪枝。在具体实现时,还有learning rate等其它参数一起控制,给GainGainGain出现负值的后续轮留机会。

缺失值处理

XGBoost支持缺失值的处理,没有简单的假设缺失值一定进入左子树还是右子树,而是尝试通过枚举所有缺失值在当前节点是进入左子树,还是进入右子树更优,来决定一个处理缺失值默认的方向,这样处理起来更加的灵活和合理。如下图所示:

优缺点

xgboost相比于GBDT有以下的优点:

  • 精度更高:GBDT只用到一阶泰勒, 而xgboost对损失函数进行了二阶泰勒展开, 一方面为了增加精度, 另一方面也为了能够自定义损失函数,二阶泰勒展开可以近似大量损失函数
  • 灵活性更强:GBDT以CART作为基分类器,而Xgboost不仅支持CART,还支持线性分类器,另外,Xgboost支持自定义损失函数,只要损失函数有一二阶导数。
  • 正则化:xgboost在目标函数中加入了正则,用于控制模型的复杂度。有助于降低模型方差,防止过拟合。正则项里包含了树的叶子节点个数,叶子节点权重的L2范式。
  • Shrinkage(缩减):相当于学习速率。这个主要是为了削弱每棵树的影响,让后面有更大的学习空间,学习过程更加的平缓
  • 列抽样:这个就是在建树的时候,不用遍历所有的特征了,可以进行抽样,一方面简化了计算,另一方面也有助于降低过拟合
  • 缺失值处理:这个是xgboost的稀疏感知算法,加快了节点分裂的速度
  • 并行化操作:块结构可以很好的支持并行计算

缺点:

  • 时间复杂度高:虽然利用了预排序和近似算法可以降低寻找最优分裂点的计算量,但在节点分裂过程中仍需要遍历整个数据集。
  • 空间复杂度高:预排序过程的空间复杂度过高,不仅需要存储特征值,还需要存储特征对应样本梯度统计值的索引,相当于消耗了两倍的内存。

总结

简单的回顾一下本文内容:

XGBoost是好多弱分类器的集成,训练弱分类器的策略就是尽量的减小残差,使得答案越来越接近正确答案。XGBoost的精髓部分是目标函数的Taylor化简,这样就引入了损失函数的一阶和二阶导数。然后又把样本的遍历转成了对叶子节点的遍历,得到了最终的目标函数。这个函数就是衡量一棵树好坏的标准。在建树过程中,XGBoost采用了贪心策略,并且对寻找分割点也进行了优化。基于这个,才有了后面的最优点切分建立一棵树的过程。XGBoost训练的时候,是通过加法进行训练,也就是每一次只训练一棵树出来, 最后的预测结果是所有树的加和表示。

参考文章:

【白话机器学习】算法理论+实战之XGBoost算法

XGBoost算法梳理

XGBoost详解

XGBoost算法的相关知识相关推荐

  1. ML之XGBoost:XGBoost算法模型(相关配图)的简介(XGBoost并行处理)、关键思路、代码实现(目标函数/评价函数)、安装、使用方法、案例应用之详细攻略

    ML之XGBoost:XGBoost算法模型(相关配图)的简介.关键思路.代码实现(目标函数/评价函数).安装.使用方法.案例应用之详细攻略 目录 XGBoost算法模型(相关配图)的简介 1.XGB ...

  2. Unity开发-网络.算法.平台相关知识!

    A. 网络相关知识 一.TCP 1.面向数据流.可靠.能保证消息到达顺序. 2.滑动窗口.控制发送量,发送方只能发送窗口内大小的数据包.防止发送方发送的数据过多,接收方无法处理的情况. 3.Nagle ...

  3. 密集子图挖掘算法的相关知识

    1.子图密度的定义方法 (1)绝对密度:其度量的是构成一个密集子图的规则和参数值,是一个定量的描述.密度定义考量的只是密集子图内部节点和边的特性,与密集子图外部的拓扑结构无关.绝对的密集子图定义一般是 ...

  4. 神经网络算法的相关知识

    激活函数relu 从上面也可以看出sigmoid计算量比较大,relu计算量小 上面的224×224×64是卷积后的结果,pool后,也就是池化层后,就变成了112×112×64. 分类会有全连接层, ...

  5. FE之DR之线性降维:PCA/白化、LDA算法的数学知识(协方差矩阵)、相关论文、算法骤、代码实现、案例应用等相关配图之详细攻略

    FE之DR之线性降维:PCA/白化.LDA算法的数学知识(协方差矩阵).相关论文.算法骤.代码实现.案例应用等相关配图之详细攻略 目录 PCA 1.PCA的数学知识 1.协方差矩阵计算 2.PCA算法 ...

  6. 光斑定位技术在空间激光通信中扮演着重要的角色。本文将详细介绍光斑定位的相关知识,并使用Matlab实现一些相关的算法。

    光斑定位技术在空间激光通信中扮演着重要的角色.本文将详细介绍光斑定位的相关知识,并使用Matlab实现一些相关的算法. 一.光斑定位技术 光斑定位技术是一种通过计算像素位置来确定目标物体位置的技术,广 ...

  7. 【白话机器学习】算法理论+实战之Xgboost算法

    1. 写在前面 如果想从事数据挖掘或者机器学习的工作,掌握常用的机器学习算法是非常有必要的,在这简单的先捋一捋, 常见的机器学习算法: 监督学习算法:逻辑回归,线性回归,决策树,朴素贝叶斯,K近邻,支 ...

  8. Datawhale集成学习笔记:XGBOOST算法

    引用:Datawhale XGBoost算法 XGBoost是陈天奇等人开发的一个开源机器学习项目,高效地实现了GBDT算法并进行了算法和工程上的许多改进,被广泛应用在Kaggle竞赛及其他许多机器学 ...

  9. 工业相机参数之帧率相关知识详解

    点击上方"小白学视觉",选择加"星标"或"置顶"重磅干货,第一时间送达 工业相机是机器视觉系统的重要组成部分之一,在机器视觉系统中有着非常重 ...

最新文章

  1. 《深入理解计算机系统》第八章——异常控制流知识点总结
  2. l360废墨收集垫更换视频_更新原厂隔音垫你选对材料了吗?
  3. django前后端结合_简单4步用FLASK/Django部署你的Pyecharts项目
  4. python读写json_python 读写json数据
  5. c:\program files\microsoft visual studio\vc98\mfc\include\afxv_w32.h(14) : fatal error C1189:
  6. 数据结构(C语言)-串
  7. 计算机统计大数据库,统计数据库
  8. 【cocos源码学习】cocos2d-x-4.0 Android Demo工程结构的简析
  9. 学生计算机机房管理系统设计
  10. MATLAB机器人可视化
  11. 没想到国美竟然用oracle的团队来搭建电商平台
  12. 安全设计:加速传输软件镭速传输安全技术解读
  13. PS基础及选框工具笔记(CS6)
  14. V4L2采集yuv视频花屏:Linux视频采集与编码(一)
  15. 罚函数(内点罚函数和外点罚函数)
  16. CSS3渐变属性:线性渐变和径向渐变用法教程
  17. iOS开发之Code:-402653103,Code:5
  18. 看一遍就理解:IO模型详解
  19. jsp中taglib属性
  20. 抖音下载的视频电脑可以去水印吗,怎么去掉视频水印

热门文章

  1. vue的钩子函数created以及mounted的示意(转载)
  2. cython编码报错
  3. 大话数据结构:最短路径算法
  4. oracle 一次删除多张表
  5. The compiler compliance specified is 1.7 but a JRE
  6. ASP.NET MVC控制器获取前端视图FORM表单的方法
  7. node.js Stream Buffer FsPromise
  8. ios中base64编码
  9. WPF - 图形设计器(Diagram Designer)
  10. jvm 性能调优工具之 jstat