xgboost是由多个CART(分类回归树,Classification And Regression Tree)集成,首先需要理解分类树和回归树的概念
分类树和回归树的概念较为相似,不同的是分类分析是预测结果所属的类别,例如预测房价是涨还是跌;回归分析则是预测结果的确切值,例如预测房价的具体值。
在解决分类树问题时一般使用信息增益(ID3)、信息增益率(C4.5)、基尼系数(CART)来判定树的节点分裂。决策树中对这几个概念有较详细的介绍。
所谓集成学习,是指构建多个分类器(弱分类器)对数据集进行预测,然后用某种策略将多个分类器预测的结果集成起来,作为最终预测结果,它要求每个弱分类器具备一定的“准确性”,分类器之间具备“差异性”。
集成学习根据各个弱分类器之间有无依赖关系,分为Boosting和Bagging两大流派:
AdaBoost,是英文"Adaptive Boosting"(自适应增强)的缩写,由Yoav Freund和Robert Schapire在1995年提出。它的自适应在于:前一个基本分类器分错的样本会得到加强,加权后的全体样本再次被用来训练下一个基本分类器。同时,在每一轮中加入一个新的弱分类器,直到达到某个预定的足够小的错误率或达到预先指定的最大迭代次数。
具体说来,整个Adaboost 迭代算法就3步:
- 初始化训练数据的权值分布。如果有N个样本,则每一个训练样本最开始时都被赋予相同的权值:1/N。
- 训练弱分类器。具体训练过程中,如果某个样本点已经被准确地分类,那么在构造下一个训练集中,它的权值就被降低;相反,如果某个样本点没有被准确地分类,那么它的权值就得到提高。然后,权值更新过的样本集被用于训练下一个分类器,整个训练过程如此迭代地进行下去。
- 将各个训练得到的弱分类器组合成强分类器。各个弱分类器的训练过程结束后,加大分类误差率小的弱分类器的权重,使其在最终的分类函数中起着较大的决定作用,而降低分类误差率大的弱分类器的权重,使其在最终的分类函数中起着较小的决定作用。换言之,误差率低的弱分类器在最终分类器中占的权重较大,否则较小。
与AdaBoost不同,GBDT每一次的计算是都为了减少上一次的残差,进而在残差减少(负梯度)的方向上建立一个新的模型。
形成一个回归树的关键在于:
xgboost本质上还是一个GBDT(Gradient Boosting Decision Tree),但是力争把速度和效率发挥到极致,所以叫X (Extreme) GBoosted。
GBDT的原理很简单,就是所有弱分类器的结果相加等于预测值,然后下一个弱分类器去拟合误差函数对预测值的梯度/残差(这个梯度/残差就是预测值与真实值之间的误差)。当然了,它里面的弱分类器的表现形式就是各棵树。如图所示:Y = Y1 + Y2 + Y3。
举一个非常简单的例子,比如我今年30岁了,但计算机或者模型GBDT并不知道我今年多少岁,那GBDT咋办呢?
最终,四棵树的结论加起来,就是真实年龄30岁。实际工程中,gbdt是计算负梯度,用负梯度近似残差。
下面以一个年龄预测的例子直观的表现出GBDT和传统决策树算法的区别:
简单起见,假定训练集只有4个人:A,B,C,D,他们的年龄分别是14,16,24,26。其中A、B分别是高一和高三学生;C,D分别是应届毕业生和工作两年的员工。
传统决策树做法如下图:
GBDT的做法如下:
所以,GBDT需要将多棵树的得分累加得到最终的预测得分,且每一次迭代,都在现有树的基础上,增加一棵树去拟合前面树的预测结果与真实值之间的残差。
本节的示意图基本引用自xgboost原作者陈天奇的讲义PPT中。
xgboost的定义
举个例子,我们要预测一家人对电子游戏的喜好程度,考虑到年轻和年老相比,年轻更可能喜欢电子游戏,以及男性和女性相比,男性更喜欢电子游戏,故先根据年龄大小区分小孩和大人,然后再通过性别区分开是男是女,逐一给各人在电子游戏喜好程度上打分,如下图所示。
训练出2棵树tree1和tree2,类似之前gbdt的原理,两棵树的结论累加起来便是最终的结论,小孩的预测分数就是两棵树中小孩所落到的结点的分数相加:2 + 0.9 = 2.9。爷爷的预测分数同理:-1 + (-0.9)= -1.9。
看起来和GDBT原理相同,事实上,如果不考虑工程实现、解决问题上的一些差异,xgboost与gbdt比较大的不同就是目标函数的定义。xgboost的目标函数如下图所示:
其中,l是损失函数, Ω是正则项,constant是常数项。利用了泰勒展开,可以发现,最终目标函数取决于误差函数上的一阶导数和二阶导数。
xgboost的核心思想如下:
把目标函数简化为:
这个目标函数分为两部分:损失函数和正则化项。且损失函数揭示训练误差(即预测分数和真实分数的差距),正则化定义复杂度。
T表示叶子节点的个数,w表示叶子节点的分数。直观上看,目标要求预测误差尽量小,且叶子节点T尽量少(γ控制叶子结点的个数),节点数值w尽量不极端(λ控制叶子节点的分数不会过大),防止过拟合。
训练误差
xgboost也是需要将多棵树的得分累加得到最终的预测得分(每一次迭代,都在现有树的基础上,增加一棵树去拟合前面树的预测结果与真实值之间的残差)。
在每一轮增加函数时选择使得我们的目标函数降低的函数。
为了简化目标函数,这里使用泰勒二阶展开式进行简化,并做了一些假设。
考虑到我们的第t 颗回归树是根据前面的t-1颗回归树的残差得来的,第一项对目标函数的优化不影响,可以直接去掉,得到:
再去掉常数得到:
实质是把样本分配到叶子结点会对应一个obj,优化过程就是obj优化。也就是分裂节点到叶子不同的组合,不同的组合对应不同obj,所有的优化围绕这个思想展开。
正则项:树的复杂度
首先应该明确以下几点:
对wj求导得到最优解:
代入得到:
打分函数
Obj代表了当我们指定一个树的结构的时候,我们在目标上面最多减少多少。我们可以把它叫做结构分数(structure score)
分裂节点
xgboost作者在原始论文中给出了两种分裂节点的方法:
(1)枚举所有不同树结构的贪心法
从树深度0开始,每一节点都遍历所有的特征,比如年龄、性别等等,然后对于某个特征,先按照该特征里的值进行排序,然后线性扫描该特征进而确定最好的分割点,最后对所有特征进行分割后,我们选择所谓的增益Gain最高的那个特征。
论文中的算法:
近似算法:
总结
boosted tree algorithm:
使用贪心+最优化求解
刚开始你有一群样本,放在第一个节点,这时候T=1,w多少呢,不知道,是求出来的,这时候所有样本的预测值都是w,带入样本的label数值,此时loss function变为
接下来要选个feature分裂成两个节点,变成一棵弱小的树苗,那么需要:
同时为了限制树生长过深,还加了个阈值,只有当增益大于该阈值才进行分裂。
凡是这种循环迭代的方式必定有停止条件,什么时候停止呢?简言之,设置树的最大深度、当样本权重和小于设定阈值时停止生长以防止过拟合。具体而言,则