XGboost
一、GBDT简述
GBDT:英文全称:Gradient Boosting Decision Tree 。GBDT中的树都是回归树。GBDT的主要是思想是每次把上一棵树的输出和label的残差作为下一棵树的label进行拟合,前面的树做不好的地方后面的补上,不断把拟合后的预测的残差值叠加上去,进行梯度的提升。一句话解释:以决策树为基模型(base model),以损失函数的负梯度为学习目标的boosting集成模型。
这句话有三个概念:决策树,损失函数的负梯度,boosting
第一个基本概念的解释(决策树):
决策树主流有三类ID3,C4.5,CRAT树。GBDT的基模型是CART树。
ID3使用信息增益作为分裂点选择
C4.5使用信息增益比作为分裂点选择
CART树使用基尼系数作为分裂点选择
第二个基本概念的解释(损失函数的负梯度):
损失函数的负梯度本身是优化算法中特征权重的更新方向和大小。为什么GDBT的基模型要去拟合损失负梯度,而不是拟合y,或者拟合y- ^y?
1.GBDT整体上是拟合y的,但是每个基模型不是去拟合y,如果是的话就是bagging集成模型,比如随机森林
2.GBDT的基模型为什么不是拟合残差。将下式一阶展开,可以发现若移动负梯度是最小化损失函数的方向。

如果不考虑正则项,并且使用平方误差,拟合残差是没有问题的。在有正则项的情况下就不再是损失函数最小了。
第三个基本概念的解释(boosting):
集成模型是把若干个基模型(也称“弱学习器”)按照一定的策略组合起来,发挥1+1>2的作用。集成模型主要有三种集成策略,bagging, stacking,boosting。
Bagging集成:各个基模型训练相互独立。在回归问题中,会把各个基模型的预测取平均。在分类问题中,则使用投票策略。比如随机森林就是使用bagging模型。
stacking集成:stacking的基模型之间也是相互独立。与bagging不同的是,stacking会把基模型预测结果作为第二层模型的输入,重新预测的结果作为最终的输出。stacking的基模型在工程实践中会选择强模型。比如xgboost。而且基模型一般会选择不同类型的强模型。第二层一般会选择线性回归或者逻辑斯特回归。理论上看,stacking模型已经证明其集成结果应该“渐进等价”第一层中的最优子模型。stacking的结果有点类似于两层神经网络,只不过第一层神经元都是强模型。
boosting集成:与前两种集成模型不同的是,boosting的基模型不是相互独立的,是相关的。(不是并联,是串联)。Boosting 是一种集成技术,另外boosting模型的基模型也是弱模型。其中添加新模型以纠正现有模型所造成的错误。模型按顺序添加,直到无法进行进一步改进。一个流行的例子是AdaBoost 算法,它对难以预测的数据点进行加权。梯度提升是一种创建新模型的方法,用于预测先前模型的残差或误差,然后将它们相加以进行最终预测。之所以称为梯度提升,是因为它使用梯度下降算法来最小化添加新模型时的损失。xgboost支持回归和分类预测建模问题。boosting比较经典的三个算法:提升树模型(adaboost),梯度提升树模型(gbdt),xgboost模型。
二、Xgboost简述
Xgboost可以拆成两部分X +gboost。gboost就是gbdt。x就是牛逼。要理解xgboost,gbdt是基础。X体现在1.损失函数二阶展开,2.快速查找分裂点,3.强大的防止过拟合能力,4.对缺失值的处理
Xgboost与GBDT最大的区别就是树的生成方式不同,加快了树的生成过程,以生成最优树。XGBoost 库实现了梯度提升决策树算法,该算法有很多不同的名称,例如梯度提升、多重加性回归树、随机梯度提升或梯度提升机。
1.损失函数二阶展开:
XGboost与GBDT都是每一步都只优化当前模型,然后将所有模型加起来。传统GBDT在优化时只用到一阶导数信息,xgboost为了加速算法的计算对代价函数进行了二阶泰勒展开,同时拟合一阶误差和二阶误差有利于提升精度。顺便提一下,xgboost工具支持自定义代价函数,只要函数可一阶和二阶求导。 —对损失函数做了改进(泰勒展开,一阶信息g和二阶信息h)
(1):精确贪婪算法
这种算法就是详细地遍历每个特征,然后遍历每个特征可能的取值,搜索出最优的分裂特征以及该特征的分裂值
(2):近似算法
在很多种情况下,每个特征的取值(离散的取值)可能有成千上万个,遍历每个取值的话时间开销会非常的大。很多时候,特征分裂的取值稍微差了一点也不会有太大的影响。为了对整个分裂过程进行加速,我们可以对特征值进行分箱。比如将样本种某个特征是连续值,取值有几万个,我们可以将其分箱为几十个,然后遍历每个特征的取值的时候,我们只需要遍历每个箱。这样的话极快地减少了计算的次数。关于分箱的方法在xgb的论文种提及了两种:global和local两种。global是在所有树生成开始之前,将需要的特征分好箱。整个训练过程每个特征都只需要分一次。local是在每次进行特征值遍历的时候进行分箱,一个训练过程会分裂很多很多次。
(3):加权分位数
这一步是对上一步近似算法补充,上一步我们说到对特征分箱,但是怎么对特征分箱?常用的方法是按照样本分布,比如100个样本我要分5箱,那么我可能会使得每箱中有20个样本,这样我就可以将样本排序后,在第20,40,60,80处对样本进行分箱。但是在xgboost中采用一种加权分为的分箱方法。将hi作为权重,每个区间中hi的权重相等。
xgboost与GBDT相比还有一个正则项,用于控制模型的复杂度。其中T为树f的叶节点的个数,wj为第j个叶节点的权重。很容易理解叶节点越少越不容易过拟合,但是为什么w叶节点的取值也可以作为正则项呢?(作者)的理解是:
xgboost是一个加法模型,每个样本最后的取值是每个树的值加起来。比如某个样本在n棵树中处于叶节点的取值分别为:wi。那么该样本最后的取值为:∑wi(这么一看的话和逻辑输入特征为0-1的逻辑回归还是很像的)。我们会倾向于该样本在每个树中的取值尽可能的小一些,那样样本最后的取值受某一个树的影响就会变小,更不容易过拟合。

在数据中经常会出现这些现象:1:缺失值,2:为0的值太多,3:特征one-hot(其实也是导致为0的值太多)。XGB中允许缺失值存在,采用稀疏感知策略来同时处理这类问题,将缺失值和稀疏0值等同视作缺失值,"绑定"在一起,节点分裂的时候不会遍历这些节点,减少计算,分配样本时,缺失的样本同时分到左右子树,计算哪边的增益大就自动分到哪边去。但在测试时如果遇到缺失值,会分到右子树。
三、优缺点
优点(快速高效可容错)
- 支持线性分类器(相当于引入L1 L2正则惩罚项的LR和线性回归,目标函数公式=误差平方和+正则项,似LR)
- 代价函数用了二阶Talor展开,引入一阶导和二阶导,提高模型拟和的速度(损失函数:一个样本的误差;代价函数:整个训练集上所有样本误差的平均;目标函数:代价函数 + 正则化项)
- 可以给缺失值自动划分方向;
- 同RF,支持样本(行)随机抽取,也支持特征(列)随机抽取,降低运算,防过拟合;
- 代价函数引入正则化项,控制模型(树)复杂度,
正则化项包含全部叶子节点个数,每个叶子节点得分的L2模的平方和(代表叶子节点权重的影响)
从贝叶斯(先验累积思想)方差角度考虑,正则降低了模型的方差,防过拟和; - 每次迭代后为叶子分配结合学习速率,减低每棵树权重,减少每棵树影响,灵活调整后面的学习空间;
- 支持并行,不是树并行,是把特征值先预排序,存起来,可以重复并行使用计算分裂点;
- 分裂依据分开后与未分前的差值增益,不用每个节点排序算增益,减少计算量,可以并行计算;
- 可以引入阈值限制树分裂,控制树的规模。
缺点:
- 容易过拟合;
- 调参困难。
sklearn参数
- learning_rate:学习率
- n_estimators:多少棵树
- max_depth=5:树最大深度
- min_child_weight:最小权重系数
- gamma=0:惩罚系数(力度)
- lambda:正则化
- alpha:正则化
- subsample:随机选样本的比例
- colsample_bytree:随机选特征
- objective = 'binary:logistic':损失函数loss function,求这个函数的一阶二阶导
- scale_pos_weight:要不要指定一个均衡的树
- seed=7 #随机种子,每次复现都是一样的
参考链接:https://www.jianshu.com/p/99d8f56ea536

浙公网安备 33010602011771号