xgboost的理解

参考July的博客对xgboost有了一些理解

1.回归树和分类树

xgboost是由多个CART(分类回归树,Classification And Regression Tree)集成,首先需要理解分类树和回归树的概念
分类树和回归树的概念较为相似,不同的是分类分析是预测结果所属的类别,例如预测房价是涨还是跌;回归分析则是预测结果的确切值,例如预测房价的具体值。
在解决分类树问题时一般使用信息增益(ID3)、信息增益率(C4.5)、基尼系数(CART)来判定树的节点分裂。决策树中对这几个概念有较详细的介绍。

熵是度量样本集合纯度常用的一种指标定义如下:
在这里插入图片描述

对于回归树,则需要一些评价误差来进行评估。
在这里插入图片描述

2.集成学习

所谓集成学习,是指构建多个分类器(弱分类器)对数据集进行预测,然后用某种策略将多个分类器预测的结果集成起来,作为最终预测结果,它要求每个弱分类器具备一定的“准确性”,分类器之间具备“差异性”。
集成学习根据各个弱分类器之间有无依赖关系,分为Boosting和Bagging两大流派:

  1. Boosting流派,各分类器之间有依赖关系,必须串行,比如Adaboost、GBDT(Gradient Boosting Decision Tree)、Xgboost
  2. Bagging流派,各分类器之间没有依赖关系,可各自并行,比如随机森林(Random Forest)

AdaBoost,是英文"Adaptive Boosting"(自适应增强)的缩写,由Yoav Freund和Robert Schapire在1995年提出。它的自适应在于:前一个基本分类器分错的样本会得到加强,加权后的全体样本再次被用来训练下一个基本分类器。同时,在每一轮中加入一个新的弱分类器,直到达到某个预定的足够小的错误率或达到预先指定的最大迭代次数。
具体说来,整个Adaboost 迭代算法就3步:

  1. 初始化训练数据的权值分布。如果有N个样本,则每一个训练样本最开始时都被赋予相同的权值:1/N。
  2. 训练弱分类器。具体训练过程中,如果某个样本点已经被准确地分类,那么在构造下一个训练集中,它的权值就被降低;相反,如果某个样本点没有被准确地分类,那么它的权值就得到提高。然后,权值更新过的样本集被用于训练下一个分类器,整个训练过程如此迭代地进行下去。
  3. 将各个训练得到的弱分类器组合成强分类器。各个弱分类器的训练过程结束后,加大分类误差率小的弱分类器的权重,使其在最终的分类函数中起着较大的决定作用,而降低分类误差率大的弱分类器的权重,使其在最终的分类函数中起着较小的决定作用。换言之,误差率低的弱分类器在最终分类器中占的权重较大,否则较小。

与AdaBoost不同,GBDT每一次的计算是都为了减少上一次的残差,进而在残差减少(负梯度)的方向上建立一个新的模型。

形成一个回归树的关键在于:

  1. 依据什么划分分裂点(如均方误差最小)
  2. 分类后的预测值是多少

3.GBDT

xgboost本质上还是一个GBDT(Gradient Boosting Decision Tree),但是力争把速度和效率发挥到极致,所以叫X (Extreme) GBoosted。
GBDT的原理很简单,就是所有弱分类器的结果相加等于预测值,然后下一个弱分类器去拟合误差函数对预测值的梯度/残差(这个梯度/残差就是预测值与真实值之间的误差)。当然了,它里面的弱分类器的表现形式就是各棵树。如图所示:Y = Y1 + Y2 + Y3。
在这里插入图片描述
举一个非常简单的例子,比如我今年30岁了,但计算机或者模型GBDT并不知道我今年多少岁,那GBDT咋办呢?

  1. 它会在第一个弱分类器(或第一棵树中)随便用一个年龄比如20岁来拟合,然后发现2误差有10岁;
  2. 接下来在第二棵树中,用6岁去拟合剩下的损失,发现差距还有4岁;
  3. 接着在第三棵树中用3岁拟合剩下的差距,发现差距只有1岁了;
  4. 最后在第四课树中用1岁拟合剩下的残差,完美。

最终,四棵树的结论加起来,就是真实年龄30岁。实际工程中,gbdt是计算负梯度,用负梯度近似残差。
下面以一个年龄预测的例子直观的表现出GBDT和传统决策树算法的区别:
简单起见,假定训练集只有4个人:A,B,C,D,他们的年龄分别是14,16,24,26。其中A、B分别是高一和高三学生;C,D分别是应届毕业生和工作两年的员工。
传统决策树做法如下图:
在这里插入图片描述
GBDT的做法如下:
在这里插入图片描述
所以,GBDT需要将多棵树的得分累加得到最终的预测得分,且每一次迭代,都在现有树的基础上,增加一棵树去拟合前面树的预测结果与真实值之间的残差。

3.xgboost

本节的示意图基本引用自xgboost原作者陈天奇的讲义PPT中。
xgboost的定义
举个例子,我们要预测一家人对电子游戏的喜好程度,考虑到年轻和年老相比,年轻更可能喜欢电子游戏,以及男性和女性相比,男性更喜欢电子游戏,故先根据年龄大小区分小孩和大人,然后再通过性别区分开是男是女,逐一给各人在电子游戏喜好程度上打分,如下图所示。
在这里插入图片描述
在这里插入图片描述
训练出2棵树tree1和tree2,类似之前gbdt的原理,两棵树的结论累加起来便是最终的结论,小孩的预测分数就是两棵树中小孩所落到的结点的分数相加:2 + 0.9 = 2.9。爷爷的预测分数同理:-1 + (-0.9)= -1.9。
看起来和GDBT原理相同,事实上,如果不考虑工程实现、解决问题上的一些差异,xgboost与gbdt比较大的不同就是目标函数的定义。xgboost的目标函数如下图所示:
在这里插入图片描述
其中,l是损失函数, Ω是正则项,constant是常数项。利用了泰勒展开,可以发现,最终目标函数取决于误差函数上的一阶导数和二阶导数。

xgboost的核心思想如下:

  1. 不断地添加树,不断地进行特征分裂来生长一棵树,每次添加一个树,其实是学习一个新函数,去拟合上次预测的残差。
    在这里插入图片描述
  2. 当我们训练完成得到k棵树,我们要预测一个样本的分数,其实就是根据这个样本的特征,在每棵树中会落到对应的一个叶子节点,每个叶子节点就对应一个分数
  3. 最后只需要将每棵树对应的分数加起来就是该样本的预测值。

把目标函数简化为:
在这里插入图片描述
这个目标函数分为两部分:损失函数和正则化项。且损失函数揭示训练误差(即预测分数和真实分数的差距),正则化定义复杂度。
在这里插入图片描述
T表示叶子节点的个数,w表示叶子节点的分数。直观上看,目标要求预测误差尽量小,且叶子节点T尽量少(γ控制叶子结点的个数),节点数值w尽量不极端(λ控制叶子节点的分数不会过大),防止过拟合。
训练误差
xgboost也是需要将多棵树的得分累加得到最终的预测得分(每一次迭代,都在现有树的基础上,增加一棵树去拟合前面树的预测结果与真实值之间的残差)。
在这里插入图片描述
在每一轮增加函数时选择使得我们的目标函数降低的函数。
在这里插入图片描述
为了简化目标函数,这里使用泰勒二阶展开式进行简化,并做了一些假设。
在这里插入图片描述
在这里插入图片描述

考虑到我们的第t 颗回归树是根据前面的t-1颗回归树的残差得来的,第一项对目标函数的优化不影响,可以直接去掉,得到:
在这里插入图片描述
再去掉常数得到:

在这里插入图片描述
总的指导原则如就职Google的读者crab6789所说:

实质是把样本分配到叶子结点会对应一个obj,优化过程就是obj优化。也就是分裂节点到叶子不同的组合,不同的组合对应不同obj,所有的优化围绕这个思想展开。

正则项:树的复杂度
首先应该明确以下几点:

  1. 用叶子节点集合以及叶子节点得分表示
  2. 每个样本都落在一个叶子节点上
  3. q(x)表示样本x在某个叶子节点上,wq(x)是该节点的打分,即该样本的模型预测值
    所以当我们把树成结构部分q和叶子权重部分w后,结构函数q把输入映射到叶子的索引号上面去,而w给定了每个索引号对应的叶子分数是什么。
    在这里插入图片描述
    xgboost对树的复杂度包含了两个部分:
  4. 一个是树里面叶子节点的个数T
  5. 一个是树上叶子节点的得分w的L2模平方(对w进行L2正则化,相当于针对每个叶结点的得分增加L2平滑,目的是为了避免过拟合)
    在这里插入图片描述
    因此目标函数又变为:
    在这里插入图片描述
    Ij被定义为每个叶结点j上面样本下标的集合,q(xi)表达的是:每个样本值xi都能通过函数 q(xi)映射到树上的某个叶子节点,从而通过这个定义把两种累加统一到了一起。
    接着我们定义(向量化):
    在这里插入图片描述
    因此公式可以简化为:

在这里插入图片描述
对wj求导得到最优解:
在这里插入图片描述
代入得到:
在这里插入图片描述
打分函数
在这里插入图片描述
Obj代表了当我们指定一个树的结构的时候,我们在目标上面最多减少多少。我们可以把它叫做结构分数(structure score)
分裂节点
xgboost作者在原始论文中给出了两种分裂节点的方法:
(1)枚举所有不同树结构的贪心法
从树深度0开始,每一节点都遍历所有的特征,比如年龄、性别等等,然后对于某个特征,先按照该特征里的值进行排序,然后线性扫描该特征进而确定最好的分割点,最后对所有特征进行分割后,我们选择所谓的增益Gain最高的那个特征。
在这里插入图片描述
论文中的算法:
在这里插入图片描述
近似算法:
在这里插入图片描述
总结
boosted tree algorithm:
在这里插入图片描述

使用贪心+最优化求解
刚开始你有一群样本,放在第一个节点,这时候T=1,w多少呢,不知道,是求出来的,这时候所有样本的预测值都是w,带入样本的label数值,此时loss function变为
在这里插入图片描述
接下来要选个feature分裂成两个节点,变成一棵弱小的树苗,那么需要:

  1. 用枚举/穷举(嗯,够粗暴),然后选择loss function效果最好的那个;
  2. 二次函数的求最值(计算二次的最值一般都有固定套路,即导数等于0的点) 。所以,选择一个feature分裂,计算loss function最小值,然后再选一个feature分裂,又得到一个loss function最小值,你枚举完,找一个效果最好的,把树给分裂,就得到了小树苗。

同时为了限制树生长过深,还加了个阈值,只有当增益大于该阈值才进行分裂。
在这里插入图片描述

凡是这种循环迭代的方式必定有停止条件,什么时候停止呢?简言之,设置树的最大深度、当样本权重和小于设定阈值时停止生长以防止过拟合。具体而言,则

  1. 当引入的分裂带来的增益小于设定阀值的时候,我们可以忽略掉这个分裂,所以并不是每一次分裂loss function整体都会增加的,有点预剪枝的意思,阈值参数为(即正则项里叶子节点数T的系数);
  2. 当树达到最大深度时则停止建立决策树,设置一个超参数max_depth,避免树太深导致学习局部样本,从而过拟合;
  3. 当样本权重和小于设定阈值时则停止建树。什么意思呢,即涉及到一个超参数-最小的样本权重和min_child_weight,和GBM的 min_child_leaf 参数类似,但不完全一样。大意就是一个叶子节点样本太少了,也终止同样是防止过拟合;

猜你喜欢

转载自blog.csdn.net/qq_24852439/article/details/88406551