看要点:https://blog.csdn.net/wong2016/article/details/88851819
from: https://zhuanlan.zhihu.com/p/47185756 by 信陵君魏无忌
本文侧重于Boosting的理论知识!
Boosting的思想如下图所示:
Boosting模型可以抽象为一个前向加法模型(additive model)
其中x 为输入样本, f 为每个基学习器,alpha 为每个基学习器的参数,treeBoost论文里面讨论的基学习器都是CART回归树。Boost是"提升"的意思,一般Boosting算法都是一个迭代的过程,每一次新的训练都是为了改进上一次的结果,这要求每个基学习器的方差足够小,即足够简单(weak machine),因为Boosting的迭代过程足以让bias减小,但是不能减小方差。
Boosting模型是通过最小化损失函数得打最优模型的,这是一个NP难问题,一般通过贪心法在每一步贪心地得到最优的基学习器。可以通过梯度下降的带每个最优基学习器的方向!
过去我们使用的梯度下降都是在参数空间的梯度下降,变量是参数,而Boosting算法是在函数空间的梯度下降。通过不断梯度下降,我们得到很多个基学习器(函数),将每个阶段得到的基学习器相加得到最终的学习器。直观地说,当前基学习器的训练需要知道所有学习器在每一个样本上的表现都差了多少,然后当前基学习器努力地学习如何将每个样本上差了的部分给补充上来。回忆一下,之前在调模型参数的时候,我们通过梯度下降知道每个参数与下一个可能的loss最小的点都差了多少,根据这个信息去更新参数,这启发我们可以把学习器在每个样本上的输出值F作为参数,通过梯度下降求出使loss变小的最快的时候,每个样本上的输出值应该如何变化,那么,我们在训练一个基学习器在这些样本上补充上这个输出值不就ok啦!
可以理解为对于每一个特征x,都有一个函数数值F(x)与之对应,函数空间的指标就是这些函数数值F(x),因此函数空间有无数个坐标,但是在Machine的训练过程,一般只有有限个训练样本(x),因此函数空间的维度也是有限的
但是,这个负梯度只是定义在有限的训练样本支撑起的函数空间里面,如果泛化到其他的数据点呢?其实很简单,就是训练一个基学习器,这个基学习器在训练样本上的取值尽可能拟合负梯度,以AdaBoost为例,负梯度为:
也就是最小化错误率,不过每个样本需要乘上权值,权值越大,表示之前分类器搞这个样本不定,提醒当前分类器要注意点,权值越小,表示之前的分类器在这个样本上表现不错,当前分类器你训练这个样本时做做样子就行了,重点放在权值大的样本上。
求出负梯度的目的是为给下一个基学习器的学习指明方向,下一个基学习器的学习目标就是拟合这些负梯度,如果loss在某个样本函数值上的负梯度大于0,说明在下一个基学习器应该增加在这个样本上的函数值。
其实函数空间跟参数空间的梯度下降过程很相似,只不过函数空间的“参数”是每个样本的函数值。那么,如何找到与残差拟合程度最好的基学习器呢?其实,主要是要采用一种贪心的策略,找到使得loss最小的基学习器作为当前的基学习器:
因此,这还是相当于前面举的Adaboost的例子,拟合负梯度,可以理解为在函数空间里面,通过最大化点积,得到与负梯度最相似的基学习器。实际上,loss函数的最小化至少要考虑二阶梯度信息在内,不然,对于回归任务,拟合负梯度不应该是点积最大化。
回归树
TreeBoost的基学习器采用回归树,就是鼎鼎大名的GBDT(Gradient Boosting Decision Tree),采用树模型作为基学习器的优点是:
1、可解释性强;
2、可处理混合类型特征 ;
3、具体伸缩不变性(不用归一化特征);
4、有特征组合的作用;
5、可自然地处理缺失值;
6、对异常点鲁棒;
7、有特征选择作用;
8、 可扩展性强;
9、容易并行,
缺点是:
1、 缺乏平滑性(回归预测时输出值只能输出有限的若干种数值)
2、不适合处理高维稀疏数据。
CART决策树实际上是将空间用超平面进行划分的一种方法,每次分割的时候,都将当前的空间一分为二, 这样使得每一个叶子节点都是在空间中的一个不相交的区域,在进行决策的时候,会根据输入样本每一维feature的值,一步一步往下,最后使得样本落入N个区域中的一个(假设有N个叶子节点)。回归树的例子如下图所示:
回归树的参数主要有两个,一个叶子节点对应的区域(如何划分特征),另一个是叶子节点的取值(图中的The Height in each segment),其intuition就是使得划到特征空间每个区域的样本的方差足够小,足以用一个数值来代表,因此每个节点的分裂标准是划分到左右子树之后能不能是样本方差变小,即回归树使用方差衡量样本“纯度”(波动性),而分类树采用Gini系数或者熵来衡量样本纯不纯。回归树可以表示为:
这样GBDT的参数就由原来的两组减小为一组。
gbdt 无论用于分类还是回归一直都是使用的CART 回归树。不会因为我们所选择的任务是分类任务就选用分类树,这是因为gbdt 每轮的训练是在上一轮的训练的残差基础之上进行训练的。这里的残差就是当前模型的负梯度值 。这个要求每轮迭代的时候,弱分类器的输出的结果相减是有意义的。GBDT的核心就在于,每一棵树学的是之前所有树结论和的残差,这个残差就是一个加预测值后能得真实值的累加量。比如A的真实年龄是18岁,但第一棵树的预测年龄是12岁,差了6岁,即残差为6岁。那么在第二棵树里我们把A的年龄设为6岁去学习,如果第二棵树真的能把A分到6岁的叶子节点,那累加两棵树的结论就是A的真实年龄。
GBDT用于回归
回归问题采用least square error,其形式如下:
下面我来举个例子,通过购物金额以及是否去百度提问预测一个人的年龄,例子参考GBDT算法整理 - 算法改变人生 - CSDN博客
训练集:(A, 14岁)、(B,16岁)、(C, 24岁)、(D, 26岁);
训练数据的均值:20岁; (这个很重要,因为GBDT与i开始需要设置预测的均值,即第0个基学习器,这样后面才会有残差!)
决策树的个数:2棵;
开始GBDT学习了~
首先,输入初值20岁,根据第一个特征(具体选择哪些特征可以根据信息增益来计算选择),可以把4个样本分成两类,一类是购物金额<=1K,一类是>=1K的。假如这个时候我们就停止了第一棵树的学习,这时我们就可以统计一下每个叶子中包含哪些样本,这些样本的均值是多少,因为这个时候的均值就要作为所有被分到这个叶子的样本的预测值了。比如AB被分到左叶子,CD被分到右叶子,那么预测的结果就是:AB都是15岁,CD都是25岁。和他们的实际值一看,结果发现出现的残差,ABCD的残差分别是-1, 1, -1, 1。这个残差,我们要作为后面第二棵决策树的学习样本。
然后学习第二棵决策树,我们把第一棵的残差样本(A, -1岁)、(B,1岁)、(C, -1岁)、(D, 1岁)输入。此时我们选择的特征是经常去百度提问还是回答。这个时候我们又可以得到两部分,一部分是AC组成了左叶子,另一部分是BD组成的右叶子。那么,经过计算可知左叶子均值为-1,右叶子均值为1. 那么第二棵数的预测结果就是AC都是-1,BD都是1. 我们再来计算一下此时的残差,发现ABCD的残差都是0!停止学习~
这样,我们的两棵决策树就都学习好了。进入测试环节:
测试样本:请预测一个购物金额为3k,经常去百度问淘宝相关问题的女生的年龄~
我们提取2个特征:购物金额3k,经常去百度上面问问题;
第一棵树 —> 购物金额大于1k —> 右叶子,初步说明这个女生25岁
第二棵树 —> 经常去百度提问 —> 左叶子,说明这个女生的残差为-1;
叠加前面每棵树得到的结果:25-1=24岁,最终预测结果为24岁
GBDT用于分类
二分类
GBDT用于分类的时候,并不是用Gini或者熵的方式划分特征空间实现分类,由于需要拟合残差,GBDT实际上是在学习样本在每个类别上的得分,首先考虑二分类 {-1, 1} 的情况,loss函数可以表示为:
多分类
GBDT用于多分类的时候,每一轮需要训练K棵树,K是类别数,K棵树的目标是拟合上一阶段在类别K上分类得分的残差。举例说明,目前样本有三类,也就是 K = 3。样本 x 属于 第二类。那么针对该样本 x 的分类结果,可以用一个 三维向量 [0,1,0] 来表示。0表示样本不属于该类,1表示样本属于该类。针对样本有 三类的情况,我们实质上是在每轮的训练的时候是同时训练三颗树。第一颗树针对样本x的第一类,输入为(x,0)(x,0)。第二颗树输入针对 样本x 的第二类,输入为(x,1)(x,1)。第三颗树针对样本x 的第三类,输入为(x,0)(x,0)
下面给出多分类的算法流程:
下面举个例子帮助理解
假设输入数据x可能属于5个分类(分别为1,2,3,4,5),训练数据中,x属于类别3,则y = (0, 0, 1, 0, 0),假设模型估计得到的F(x) = (0, 0.3, 0.6, 0, 0),则经过softmax变换后得到样本点属于每一个类的概率p(x) = (0.16,0.21,0.29,0.16,0.16),y - p得到梯度g:(-0.16, -0.21, 0.71, -0.16, -0.16)。观察这里可以得到一个比较有意思的结论:
假设gk为样本的某一维(某一个分类)上的梯度:
- gk>0时,越大表示其在这一维上的概率p(x)越应该提高,比如说上面的第三维的概率为0.29,就应该提高。这属于往“正确的方向”前进,越小表示这个估计越“准确”,需要前进的步幅越小,反之越大
- gk<0时,越小,负得越多表示在这一维上的概率应该降低,比如说第二维0.21就应该得到降低。属于朝着“错误的反方向”前进,负得越少表示这个估计越“不错误 ”,需要前进的步幅越小。
总的来说,对于一个样本,最理想的梯度是越接近0的梯度。所以,我们要能够让函数的估计值能够使得梯度往反方向移动(>0的维度上,往负方向移动,<0的维度上,往正方向移动)最终使得梯度尽量=0),并且该算法在会严重关注那些梯度比较大的样本,跟Boost的意思类似。
正则化
boosting machine的正则化其实是控制基学习器个数M和学习速率,对于GBDT而言,学习速率已经乘到每个叶子节点里面去,因此控制学习速率其实是对之后的函数表达式乘上一个0-1之间的数(本质上是要控制每个叶子节点的值,因此xgboost里面的正则化项是叶子节点的值以及叶子节点的个数),称为shrinkage,意义是要削减每棵树的影响,让后面的树有更大的学习空间,同时也能减小variance。一般而言,减小shrinkage意味着每棵树的学习能力受到限制,所以需要更多的基学习器,M会增大,计算量也会随之加大。下表是boosting tree作者设计的实验,揭示了这种关系。
还有一个有意思的实验,作者探究了几种boosting算法的误差与轮数和shrinkage大小的关系,可见当基学习器即轮数越多的时候,shrinkage越小,误差反而越低,这归功与shrinkage为后面的学习器保留了足够大的学习空间。