梯度提升树GBDT
1.提升树
提升树模型实际采用加法模型(即基函数的线性组合)与前向分步算法,以决策树为基函数的提升方法称为提升树(Boosting Tree)。提升树模型可以表示为决策树的加法模型:
其中,
1.1提升树算法
提升树算法采用前向分步算法。首先确定初始提升树
其中,
由于树的线性组合可以很好的拟合训练数据,即使数据中的输入和输出之间的关系很复杂也是如此,所以提升树是一个高功能的学习算法。
对于二分类问题,提升树算法只需将AdaBoost算法中的基本分类器限定为二分类树即可 。这里不再讨论,下边主要讨论回归问题的提升树。
已知训练集
其中,参数
回归问题提升树使用以下前向分步算法:
在前向分步算法的第
得到
这里,
只看算法本身很难理解为什么直接拟合残差就可以,引用别人博客的例子来加强理解:每一棵树学的是之前所有树结论和的残差,这个残差就是一个加预测值后能得真实值的累加量。比如A的真实年龄是18岁,但第一棵树的预测年龄是12岁,差了6岁,即残差为6岁。那么在第二棵树里我们把A的年龄设为6岁去学习,如果第二棵树真的能把A分到6岁的叶子节点,那累加两棵树的结论就是A的真实年龄;如果第二棵树的结论是5岁,则A仍然存在1岁的残差,第三棵树里A的年龄就变成1岁,继续学。
1.2提升树算法流程
输入:训练数据
输出:提升树
(1)初始化
(2)对
(a)计算残差
(b)拟合残差
(c)更新
(3)得到回归问题的提升树
1.3例子
训练数据见下表,
求训练数据的切分点,根据所给数据,考虑如下切分点:
对各个切分点,求出对应的
当
由上表可知,当
用
用
第二步求
用
继续求得:
用
假设此时已满足误差要求,那么
2.梯度提升
当提升树的损失函数是平方损失和指数损失函数时,每一步优化是比较简单的,但对于一般损失函数而言,往往每一步优化比较困难。针对该问题,Freidman提出了梯度提升算法。这是利用最速下降法的近似方法,利用损失函数的负梯度在当前模型的值
作为回归问题提升树算法中的残差的近似值,拟合一个回归树。
梯度提升树算法流程
输入:训练数据
输出:回归树
(1)初始化
(2)对
(a)对
(b)对
(c)对
利用线性搜索估计叶结点区域的值,使损失函数极小化;
(d)更新
(3)得到回归树
Shrinkage
Shrinkage的思想认为,每次走一小步逐渐逼近结果,要比每次迈一大步很快逼近结果的方式更容易避免过拟合。即它不完全信任每一个棵残差树,它认为每棵树只学到了真理的一小部分,累加的时候只累加一小部分,通过多学几棵树弥补不足。
Shrinkage树的更新方式
3.XGBoost
xgboost(eXtreme Gradient Boosting)是提升树模型,它与决策树是息息相关,它通过将很多的决策树集成起来,从而得到一个很强的分类器,xgboost中主要的思想与CART回归树类似.
3.1 原理
3.1.1 树的复杂度
对数据集
其中
如下图:

树的复杂度函数:
定义树的结构和复杂度的原因很简单,这样就可以衡量模型的复杂度,从而可以有效控制过拟合。
3.1.2 boosting tree模型

和传统的boosting tree模型一样,xgboost的提升模型也是采用的残差(或梯度负方向(牛顿法)),不同的是分裂结点选取的时候不一定是最小平方损失。 正则化的目标函数:
3.1.3 目标函数的设计
由于
泰勒展开:
并定义:
对目标函数使用泰勒展开并简化:
最终的目标函数只依赖于每个数据点的在误差函数上的一阶导数和二阶导数。去除常数项,并定义了分裂候选集合
其中
把
3.1.4 结构的打分函数
上一节中的Obj代表了当我们指定一个树的结构的时候,我们在目标上面最多减少多少。我们可以把它叫做结构分数(structure score)。如图:

对于每一次尝试去对已有的叶子加入一个分割,计算分割前后的分数差:

其中
基于这个分裂的评分函数,我们还可以用来处理缺失值。处理的方法就是,我们把缺失值部分额外取出来,分别放到
3.1.4 树节点分裂方法
(1)暴力枚举,显然效率低下。
(2)近似方法
对于每个特征,只考察分位点,减少计算复杂度;学习每棵树前,提出候选切分点;每次分裂前,重新提出候选切分点。XGBoost不是简单地按照样本个数进行分位,而是以二阶导数值作为权重,如下图:

把目标函数整理成以下形式,可以看出
3.1.5 LightGBM
LightGBM速度更快,内存占用更低,准确率更高(优势不明显,与XGBoost相当).
(1)直方图算法
把连续的浮点特征值离散化成k个整数,同时构造一个宽度为k的直方图。在
遍历数据的时候,根据离散化后的值作为索引在直方图中累积统计量,当遍
历一次数据后,直方图累积了需要的统计量,然后根据直方图的离散值,遍
历寻找最优的分割点,如下图:

当离散为256个bin时,只需要8bit,比原始的浮点数节省7/8的内存占用。并
且减小了分裂时计算增益的计算量。
(2)直方图差加速
一个叶子的直方图可以由它的父亲节点的直方图与它兄弟节点的直方图做差得到,提升一倍速度,如图:

• 带深度限制的Leaf-wise的叶子生长策略
• 直接支持类别特征
• Cache命中率优化
• 多线程优化