XGB算法梳理

1 算法原理

  算法思想就是不断地添加树,不断地进行特征分裂来生长一棵树,每次添加一个树,其实是学习一个新函数,去拟合上次预测的残差。当我们训练完成得到 k k k棵树,我们要预测一个样本的分数,其实就是根据这个样本的特征,在每棵树中会落到对应的一个叶子节点,每个叶子节点就对应一个分数,最后只需要将每棵树对应的分数加起来就是该样本的预测值。 y ^ = ϕ ( x i ) = ∑ k = 1 K f k ( x i ) \hat y=\phi(x_i)=\sum_{k=1}^K{f_k(x_i)} y^=ϕ(xi)=k=1Kfk(xi) w h e r e F = { f ( x ) = w q ( x ) } ( q : R m → T , w ∈ R T ) whereF=\left\{f(x)=w_{q(x)}\right\}(q:R^m\rightarrow T,w\in R^T) whereF={f(x)=wq(x)}(q:RmT,wRT)注: w q ( x ) w_q(x) wq(x)为叶子节点 q q q的分数, f ( x ) f(x) f(x)为其中一棵回归树。

2 损失函数

  对于回归问题,我们常用的损失函数是MSE,即: L ( θ ) = ∑ i ( y i − y i ^ ) 2 L(\theta)=\sum_i{(y_i-\hat {y_i})^2} L(θ)=i(yiyi^)2  对于分类问题,我们常用的损失函数是对数损失函数: L ( θ ) = ∑ i [ y i ln ⁡ ( 1 + e − y i ^ ) + ( 1 − y i ) ln ⁡ ( 1 + e y i ^ ) ] L(\theta)=\sum_i{\left[y_i\ln (1+e^{-\hat{y_i}})+(1-y_i)\ln{(1+e^{\hat{y_i}})}\right]} L(θ)=i[yiln(1+eyi^)+(1yi)ln(1+eyi^)]  XGBoost目标函数定义为: O b j = ∑ i = 1 n l ( y i , y i ^ ) + ∑ k = 1 K Ω ( f k ) Obj=\sum_{i=1}^{n}{l(y_i,\hat{y_i})}+\sum_{k=1}^{K}{\Omega(f_k)} Obj=i=1nl(yi,yi^)+k=1KΩ(fk) w h e r e Ω ( f k ) = γ T + 1 2 λ ∥ w ∥ 2 where\Omega(f_k)=\gamma T+\frac{1}{2}\lambda{\Vert{w}\Vert}^2 whereΩ(fk)=γT+21λw2  目标函数由两部分构成,第一部分用来衡量预测分数和真实分数的差距,另一部分则是正则化项。正则化项同样包含两部分, T T T表示叶子结点的个数, w w w表示叶子节点的分数。 γ \gamma γ可以控制叶子结点的个数, λ \lambda λ可以控制叶子节点的分数不会过大,防止过拟合。
  正如上文所说,新生成的树是要拟合上次预测的残差的,即当生成t棵树后,预测分数可以写成: y i ^ ( t ) = y i ^ ( t − 1 ) + f t ( x i ) \hat{y_i}^{(t)}=\hat{y_i}^{(t-1)}+f_t(x_i) yi^(t)=yi^(t1)+ft(xi)  同时,可以将目标函数改写成: L ( t ) ≃ ∑ i = 1 n ( l ( y i , y ^ ( t − 1 ) ) + f t ( x i ) ) + Ω ( f t ) \mathcal{L}^{(t)}\simeq\sum_{i=1}^n{(l(y_i,\hat{y}^{(t-1)})+f_t(x_i))}+\Omega(f_t) L(t)i=1n(l(yi,y^(t1))+ft(xi))+Ω(ft)  很明显,我们接下来就是要去找到一个 f t f_t ft能够最小化目标函数。XGBoost的想法是利用其在 f t = 0 f_t=0 ft=0处的泰勒二阶展开近似它。所以,目标函数近似为: L ( t ) ≃ ∑ i = 1 n [ l ( y i , y ^ ( t − 1 ) ) + g i f t ( x i ) + 1 2 h i f t 2 ( x i ) ] + Ω ( f t ) \mathcal{L}^{(t)}\simeq\sum_{i=1}^n{\left[l(y_i,\hat{y}^{(t-1)})+g_if_t(x_i)+\frac{1}{2}h_if_t^2(x_i)\right]}+\Omega(f_t) L(t)i=1n[l(yi,y^(t1))+gift(xi)+21hift2(xi)]+Ω(ft)  其中 g i g_i gi为一阶导数, h i h_i hi为二阶导数: g i = ∂ y ^ ( t − 1 ) l ( y i , y ^ ( t − 1 ) ) , h i = ∂ y ^ ( t − 1 ) 2 l ( y i , y ^ ( t − 1 ) ) g_i=\partial_{\hat{y}^{(t-1)}}{l(y_i,\hat{y}^{(t-1)})},h_i=\partial_{\hat{y}^{(t-1)}}^2{l(y_i,\hat{y}^{(t-1)})} gi=y^(t1)l(yi,y^(t1)),hi=y^(t1)2l(yi,y^(t1))  由于前 ( t − 1 ) (t-1) (t1)棵树的预测分数与 y y y的残差对目标函数优化不影响,可以直接去掉。简化目标函数为: L ~ ( t ) ≃ ∑ i = 1 n [ g i f t ( x i ) + 1 2 h i f t 2 ( x i ) ] + Ω ( f t ) \widetilde{L}^{(t)}\simeq\sum_{i=1}^n{\left[g_if_t(x_i)+\frac{1}{2}h_if_t^2(x_i)\right]}+\Omega(f_t) L (t)i=1n[gift(xi)+21hift2(xi)]+Ω(ft)  上式是将每个样本的损失函数值加起来,我们知道,每个样本都最终会落到一个叶子结点中,所以我们可以将所以同一个叶子结点的样本重组起来,过程如下: O j b ( 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 = ∑ i = 1 n [ ( ∑ i ∈ I j g i ) w j + 1 2 ( ∑ i ∈ I j h i + λ ) w j 2 ] + γ T \begin{aligned} Ojb^{(t)} & \simeq \sum_{i=1}^n{\left[g_if_t(x_i)+\frac{1}{2}h_if_t^2(x_i)\right]}+\Omega(f_t) \\ & = \sum_{i=1}^n{\left[g_iw_q(x_i)+\frac{1}{2}h_iw_{q(x_i)}^2\right]}+\gamma T+\frac{1}{2}\lambda \sum_{j=1}^T{w_j^2} \\ & =\sum_{i=1}^n{\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} Ojb(t)i=1n[gift(xi)+21hift2(xi)]+Ω(ft)=i=1n[giwq(xi)+21hiwq(xi)2]+γT+21λj=1Twj2=i=1n(iIjgi)wj+21(iIjhi+λ)wj2+γT  因此通过上式的改写,我们可以将目标函数改写成关于叶子结点分数 w w w的一个一元二次函数,求解最优的 w w w和目标函数值就变得很简单了,直接使用顶点公式即可。因此,最优的 w w w和目标函数公式为: w j ∗ = − G j H j + λ w_j^*=-\frac{G_j}{H_j+\lambda} wj=Hj+λGj O b j = − 1 2 ∑ j = 1 T G j 2 H j + λ + γ T Obj=-\frac{1}{2}\sum_{j=1}^{T}{\frac{G_j^2}{H_j+\lambda}}+\gamma T Obj=21j=1THj+λGj2+γT

3 分裂结点算法

  在上面的推导中,我们知道了如果我们一棵树的结构确定了,如何求得每个叶子结点的分数。但我们还没介绍如何确定树结构,即每次特征分裂怎么寻找最佳特征,怎么寻找最佳分裂点。
  正如上文说到,基于空间切分去构造一颗决策树是一个NP难问题,我们不可能去遍历所有树结构,因此,XGBoost使用了和CART回归树一样的想法,利用贪婪算法,遍历所有特征的所有特征划分点,不同的是使用上式目标函数值作为评价函数。具体做法就是分裂后的目标函数值比单子叶子节点的目标函数的增益,同时为了限制树生长过深,还加了个阈值,只有当增益大于该阈值才进行分裂。

4 正则化

  XGBoost使用了如下的正则化项: Ω ( f ) = γ T + 1 2 λ ∑ j = 1 T w j 2 \Omega(f)=\gamma T+\frac{1}{2}\lambda \sum_{j=1}^T{w_j^2} Ω(f)=γT+21λj=1Twj2注意:这里出现了 γ γ γ λ λ λ,这是XGBoost自己定义的,在使用XGBoost时,你可以设定它们的值,显然, γ γ γ越大,表示越希望获得结构简单的树,因为此时对较多叶子节点的树的惩罚越大。 λ λ λ越大也是越希望获得结构简单的树。

5 对缺失值处理

  XGBoost模型却能够处理缺失值,模型允许缺失值存在。
  原始论文中关于缺失值的处理将其看与稀疏矩阵的处理看作一样。在寻找split point的时候,不会对该特征为missing的样本进行遍历统计,只对该列特征值为non-missing的样本上对应的特征值进行遍历,通过这个技巧来减少了为稀疏离散特征寻找split point的时间开销。在逻辑实现上,为了保证完备性,会分别处理将missing该特征值的样本分配到左叶子结点和右叶子结点的两种情形,计算增益后选择增益大的方向进行分裂即可。可以为缺失值或者指定的值指定分支的默认方向,这能大大提升算法的效率。如果在训练中没有缺失值而在预测中出现缺失,那么会自动将缺失值的划分方向放到右子树。

6 优缺点
6.1 优点

(1)XGBoost支持线性分类器,相当于引入L1和L2正则化项的逻辑回归(分类问题)和线性回归(回归问题);
(2)XGBoost对代价函数做了二阶Talor展开,引入了一阶导数和二阶导数;
(3)当样本存在缺失值是,XGBoost能自动学习分裂方向;
(4)XGBoost借鉴RF的做法,支持列抽样,这样不仅能防止过拟合,还能降低计算;
(5)XGBoost的代价函数引入正则化项,控制了模型的复杂度,正则化项包含全部叶子节点的个数,每个叶子节点输出的score的L2模的平方和。从贝叶斯方差角度考虑,正则项降低了模型的方差,防止模型过拟合;
(6)XGBoost在每次迭代之后,为叶子结点分配学习速率,降低每棵树的权重,减少每棵树的影响,为后面提供更好的学习空间;
(7)XGBoost工具支持并行,但并不是tree粒度上的,而是特征粒度,决策树最耗时的步骤是对特征的值排序,XGBoost在迭代之前,先进行预排序,存为block结构,每次迭代,重复使用该结构,降低了模型的计算;block结构也为模型提供了并行可能,在进行结点的分裂时,计算每个特征的增益,选增益最大的特征进行下一步分裂,那么各个特征的增益可以开多线程进行;
(8)可并行的近似直方图算法,树结点在进行分裂时,需要计算每个节点的增益,若数据量较大,对所有节点的特征进行排序,遍历的得到最优分割点,这种贪心法异常耗时,这时引进近似直方图算法,用于生成高效的分割点,即用分裂后的某种值减去分裂前的某种值,获得增益,为了限制树的增长,引入阈值,当增益大于阈值时,进行分裂;

6.2 缺点

(1)XGBoost采用预排序,在迭代之前,对结点的特征做预排序,遍历选择最优分割点,数据量大时,贪心法耗时,LightGBM方法采用histogram算法,占用的内存低,数据分割的复杂度更低;
(2)XGBoost采用level-wise生成决策树,同时分裂同一层的叶子,从而进行多线程优化,不容易过拟合,但很多叶子节点的分裂增益较低,没必要进行跟进一步的分裂,这就带来了不必要的开销;LightGBM采用深度优化,leaf-wise生长策略,每次从当前叶子中选择增益最大的结点进行分裂,循环迭代,但会生长出更深的决策树,产生过拟合,因此引入了一个阈值进行限制,防止过拟合.

7 应用场景

  可用于所有回归问题(线性/非线性),适用面非常广。

8 sklearn参数
8.1 超参数

(1)eta [默认 0.3]
  和 GBM 中的 learning rate 参数类似。 通过减少每一步的权重,可以提高模型的稳定性。 典型值为 0.01-0.2。
(2)min_child_weight [默认 1]
  决定最小叶子节点样本权重和。和 GBM 的 min_child_leaf 参数类似,但不完全一样。XGBoost 的这个参数是最小样本权重的和,而 GBM 参数是最小样本总数。这个参数用于避免过拟合。当它的值较大时,可以避免模型学习到局部的特殊样本。但是如果这个值过高,会导致欠拟合。这个参数需要使用 CV 来调整。
(3)max_depth [默认 6]
  和 GBM 中的参数相同,这个值为树的最大深度。这个值也是用来避免过拟合的。max_depth 越大,模型会学到更具体更局部的样本。需要使用 CV 函数来进行调优。 典型值:3-10。
(4)max_leaf_nodes
  树上最大的节点或叶子的数量。 可以替代 max_depth 的作用。因为如果生成的是二叉树,一个深度为 n 的树最多生成 n2 个叶子。 如果定义了这个参数,GBM 会忽略 max_depth 参数。
(5)gamma [默认 0]
  在节点分裂时,只有分裂后损失函数的值下降了,才会分裂这个节点。Gamma 指定了节点分裂所需的最小损失函数下降值。 这个参数的值越大,算法越保守。这个参数的值和损失函数息息相关,所以是需要调整的。
(6)max_delta_step[默认 0]
  这参数限制每棵树权重改变的最大步长。如果这个参数的值为 0,那就意味着没有约束。如果它被赋予了某个正值,那么它会让这个算法更加保守。 通常,这个参数不需要设置。但是当各类别的样本十分不平衡时,它对逻辑回归是很有帮助的。 这个参数一般用不到,但是你可以挖掘出来它更多的用处。
(7)subsample [默认 1]
  和 GBM 中的 subsample 参数一模一样。这个参数控制对于每棵树,随机采样的比例。 减小这个参数的值,算法会更加保守,避免过拟合。但是,如果这个值设置得过小,它可能会导致欠拟合。 典型值:0.5-1。
(8)colsample_bytree [默认 1]
  和 GBM 里面的 max_features 参数类似。用来控制每棵随机采样的列数的占比 (每一列是一个特征)。 典型值:0.5-1。
(9)colsample_bylevel [默认 1]
  用来控制树的每一级的每一次分裂,对列数的采样的占比。 我个人一般不太用这个参数,因为 subsample 参数和 colsample_bytree 参数可以起到相同的作用。但是如果感兴趣,可以挖掘这个参数更多的用处。
(10)lambda [默认 1]
  权重的 L2 正则化项。(和 Ridge regression 类似)。 这个参数是用来控制 XGBoost 的正则化部分的。虽然大部分数据科学家很少用到这个参数,但是这个参数在减少过拟合上还是可以挖掘出更多用处的。
(11)alpha [默认 1]
  权重的 L1 正则化项。(和 Lasso regression 类似)。 可以应用在很高维度的情况下,使得算法的速度更快。
(12)scale_pos_weight [默认 1]
  在各类别样本十分不平衡时,把这个参数设定为一个正值,可以使算法更快收敛。

8.2 学习目标参数

  这个参数用来控制理想的优化目标和每一步结果的度量方法。
(1)objective [默认 reg:linear]
  这个参数定义需要被最小化的损失函数。最常用的值有:
  binary:logistic 二分类的逻辑回归,返回预测的概率 (不是类别)。
  multi:softmax 使用 softmax 的多分类器,返回预测的类别 (不是概率)。
 &emsp在这种情况下,你还需要多设一个参数:num_class(类别数目)。multi:softprob 和 multi:softmax 参数一样,但是返回的是每个数据属于各个类别的概率。
2. eval_metric [默认值取决于 objective 参数的取值]
  对于有效数据的度量方法。对于回归问题,默认值是 rmse,对于分类问题,默认值是 error。 典型值有:
  rmse 均方根误差、mae 平均绝对误差、logloss 负对数似然函数值、error 二分类错误率 (阈值为 0.5)、merror 多分类错误率、mlogloss 多分类 logloss 损失函数、auc 曲线下面积。
3. seed [默认 0]
  随机数的种子设置它可以复现随机数据的结果,也可以用于调整参数。

引用与感谢
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值