机器学习笔记-Gradient Boosted Decision Tree

集成学习系列:

Gradient Boosted Decision Tree(梯度提升决策树)

上一篇介绍了Random Forest,该算法利用Bagging 中的bootstrap 机制得到不同的Decision Tree , 然后将这些Decision Tree 融合起来。除了基本的BaggingDecision Tree 之外,Random Forest 还在decision tree 中加入了更多的随机性。有了这些机制之后,我们发现这个算法可以利用OOB 数据做self validation , 进一步结合self validation 的机制和permutation test 的做法我们利用random forest 来做feature selection

提升方法(boosting) 的代表性算法是AdaBoost。提升树是以分类或者回归树为基本学习器的提升方法。由于树的线性组合可以很好的拟合训练数据,即使数据中的输入和输出之间的关系很复杂也没关系,所以提升树是一个高功能的学习算法。本篇讨论针对不同问题的提升树学习算法。其主要的区别在于使用的损失函数不同,首先介绍使用指数损失的分类问题,此时的提升树算法只需要将Adaboost 算法的弱分类器设置为加了限制的二分类树即可,可以说提升树算法用于分类是Adaboost 的特殊情况。接下来介绍提升树算法损失函数为平方损失时候的回归问题,之后我们会发现对回归问题的提升树算法来说,只需要在每一轮使得弱学习器来简单的拟合当前模型的残差就好了。提升树利用加法模型和前向分步算法实现优化过程,当损失函数为平方损失或者是指数损失时分别为我们上述讨论的回归问题和分类问题。但是对于一般的损失函数而言,每一步的优化并不简单。这样便有了梯度提升算法。其关键是利用损失函数的负梯度在当前模型的值作为回归问题提升树算法中的残差的近似值来进行回归树的拟合。

1 - 提升树模型

1.1 - 提升树用于分类-Adaboost的特殊情况

先再回顾下random forest 的算法的形式:外层是一个bagging , 可以使用bootstrap 的方式来得到不同的gt ,内层是一个加了更多randomnessrandomized-decision tree
再回忆下adaboost 算法的步骤:在这个算法中,每一轮每一个样本被赋予一个权重un(t) ,算法通过最小化被 un(t) 加权的 Ein 来得到gt ,再计算gt 的权重αt 来融合得到最终的G

我们之前将decision tree 搭配bagging 得到了random forest ,同样地,我们可以将decision tree 搭配adaboost 得到boosting tree提升树算法。但是现在我们需要面对的一个新的问题是,在算法boosting tree 中, 决策树作为弱学习器是处理不了加权的数据的, 而在adaboost 中每一轮的数据都是带有权重的数据, 也就是adaboost 中的base algorithm 要能够解决如下的最小化问题:

minimize Einu=1Nn=1Nunerr(yn,h(xn))

因为decision tree 有很多种实现,有很多技巧在里面。所以我们决定将decision tree 当做是一个黑盒子,我们不再要求这个黑盒子可以处理加权的数据,而是对加权的数据本身做处理,使之变为不加权的数据然后喂给decision tree

其实这一点是很容易做到, 权重是从bagging 中的bootstrap 中得到的,在做bootstrap 的时候,得到了几份(xn,yn) , 那么(xn,yn) 的权重就是几:(xn,yn) 的权重是3代表抽取到了3份(xn,yn) ,权重是4代表抽取到了4份(xn,yn) ,所以权重就代表了在资料中有几份(xn,yn) 的复制。所以我们就可以根据bootstrap 的计算机制得到的权重un(t) 先对资料进行抽样,这样就得到了一笔新的大小为N 资料D~t , 在这笔资料中就隐含了权重的信息。现在看来,在bagging 中我们是先bootstrap ,通过得到的样本数量获得权重;现在在boosting tree 中,我们利用了这个过程的逆过程,根据权重来得到样本的数量,这样做的目的是为了不改变底层的decision tree 算法。

所以在boosting tree 中,我们没有更改decision tree 的部分, 没有更改adaptive boosting 的部分, 而是在中间的环节按照样本的权重做了一个抽样的过程得到新的资料 D~t 然后喂给 decision tree


boosting tree
AdaBoost+samplingu(t)+DecisionTree(D~t)

1.2 - 提升树的一些改进

adaboost 中,当得到了一个gt 的时候,我们下一步需要作出的决定是这个gt 该以多大的权重加入到G 中。这个权重我们记为αtαt 的计算公式如下:

αt=lnt=ln1ϵtϵt

其中ϵt 指的是gt 的错误率。

这样可能会出现一个问题:
如果我们用于训练的资料完全是不同的,那么一棵完全长成的决策树的Ein 就是0 , 那么Einu=0 , 那么ϵt=0 ,所以αt= 。所以在这种情况下,最终只是得到了一棵“最好”的树,这就违背了我们的大主题:aggregation
问题出在哪里呢?因为我们把所有的数据都喂给了算法, 并且算法能得到的是一个完全长成的树。所以如果要解决这个问题的话,有两个方面可以着手:

  • 不要把所有的数据都喂给算法;
  • 对决策树构造算法做一些限制;

通过这样的技巧我们就可以得到一棵“弱”一点的树。其实我们通过bootstrap 抽样已经做到了不将所有的数据都喂给算法。另外通过采用简单的策略,例如限制决策树的高度也可以得到一棵比较“弱”的树。

所以在实际的应用中,提升树通常是如下的形式:原来的adaboost 算法的框架下,根据权重进行采样sampling ,从而得到隐含有权重意义的数据D~t ,并且通过这样的采样方式也可以避免得到一棵所谓“最好”的树,然后将D~t 喂给decision tree ,但是decision tree 的构造要加一点限制,通常是限制树的高度,也就是利用数据D~t 构造一棵pruned decision tree


boosting tree
AdaBoost+samplingu(t)+pruned Decision Tree(D~t)

1.3 - 提升树实例

上面提到在boosting tree 算法中,决策树在构造的时候需要限制树的高度, 得到一些“弱”一点的树, 再和adaboost 搭配起来。我们考虑一种极端的情况,如果我们限制树的高度小于等于1,此时的决策树变为决策树桩。那么adaboost 和这样的decision treeheight<=1 搭配起来会是什么样子的呢?其实这个时候的boosting tree 就退化为了boosting stump

因为针对每一个样本集合,这时decision treeCART 需要做的就只是选择一个分支条件 b(x) 将样本集合划分为两个子树。其划分的依据就是要使得划分之后的数据的不纯度最低

b(x)=argmindecision stump h(x)c=12|Dc with h|impurity(Dc with h)

这个时候就几乎不会出现ϵ=0 的情况, 那么这个时候也不见得会做抽样,而是直接在decision stump 中考虑权重。

所以简单来说,提升树用于分类只是将AdaBoost 算法框架中的弱分类器限制为二类分类树即可。

2 - 优化视角下的Adaboost

2.1 - Adaboost的指数损失函数

这一小节通过分析得到AdaBoost 算法的损失函数是实际上是指数损失L=exp(ys) 。并且可以证明,AdaBoost 算法是前向分步算法在损失函数为指数函数时的加法模型。

首先我们回忆一下AdaBoost 中每一个样本的权重的计算公式,un(t+1) 是根据un(t) 计算得到的。如果该样本划分不正确,那么un(t+1)=un(t)t ;如果该样本划分正确,那么un(t+1)=un(t)/t我们再来审视一下这个更新规则:样本划分不正确的意思就是:yngt(xn) ;样本划分正确的意思就是:yn=gt(xn)那么权重u 的更新规则就变为:

un(t+1)=un(t)tyngt(xn)


αt=ln(t)=ln(1ϵtϵt) ,所以t=eαt
更新规则进一步变为:

un(t+1)=un(t)exp(ynαtgt(xn))

通过这样的表达我们看到样本(xn,yn) 最终的权重un(T+1) 和初始的un(1) 的关系如下:

un(T+1)=un(1)t=1Texp(ynαtgt(xn))=1Nexp(ynt=1Tαtgt(xn))

我们将t=1Tαtgt(x) 称为voting score。因为最后我们需要根据这个分数加一个sign 的操作来做分类的决定,即我们最终得到的模型是:G(x)=sign(t=1Tαtgt(x)) 。从上面的式子可以看出AdaBoost 中的每一个数据点的权重un(T+1) 正比于负ynvoting score 的乘积的exponential

我们知道AdaBoostlinear blending 的延伸, 也就是要将g 线性的融合在一起。在linear blending 中我们可以将整个过程分为两步:1. 将所有的g 当做是一个特征转换;2. 将特征转换之后的结果使用一个线性的模型融合起来。

linear blending=linear model+hypothesis as transform

G(xn)=sign(t=1Tαtwtgt(xn)ϕt(xn))

因为gt(xn) 可以视为特征转换,我们将其记为ϕt(xn) ,将每一个gt(xn) 的权重记为wt 。这时, voting score 就变成了wTΦ(xn) 。这样我们就得到了一个我们比较熟悉的形式, 因为在硬间隔的SVM 中:margin=yn(wTϕ(xn)+b)||w|| , 表示这个数据点距离边界有多远。所以在这里voting score (虽然和上面的相比少了一些项)也是某一种距离, 也是某一种margin , 也是在某一个空间中这个点到分割线的距离的一种衡量。

所以 yn(voting score) 就相当于在SVM 中的没有归一化的margin ,也可以说是函数间隔。结合我们对SVM 的认识,我们希望 yn(voting score) 越大越好,即首先这个值要是个正的,正值保证了划分的正确性;其次要尽量的大,这样就能有更大的置信区间或者说更大的margin 。所以我们就会希望 exp(yn(voting score)) 越小越好。也就是每一个数据点的权重 un(T+1) 要越小越好。

通过上面的分析我们知道AdaBoost想要达到large margin 的效果,就是要努力的使所有的yn(voting score) 变大,就是要使所有的exp(yn(voting score)) 变小就是要最小化n=1Nun(T+1), 现在可以将adaboost 的损失函数定义为:

(1)L=n=1Nun(T+1)=1Nn=1Nexp(ynt=1Tαtgt(xn))

所以得到了AdaBoost 的损失函数为指数损失函数。

2.2 - 又一个0/1误差的上界

画出0/1 errorAdaBoost error 的曲线发现,exponential error(图中的曲线)是0/1 error (图中的折线)的一个上限。我们之前就碰到过0/1 error 的一些上限,SVMhinge error(max(1sy,0))logistic regressionscale cross entropy(ln(1+exp(ys)))都是0/1 error 的上限,我们之前都是利用这些上限将0/1 error 做到最小,从而将分类问题做好。

现在我们从另一个角度看到Adaboost 通过最小化n=1Nun(T+1) 以使得得到的边界有large margin 的效果,所以adaboost 算法在函数

(2)n=1Nexp(ynt=1Tαtgt(xn))

上做最小化,我们就将(2) 定义为adaboost error measure 。最终通过最小化errada^err0/1 做到最好。

  • err0/1(s,y)=|[ys0]|
  • errada^(s,y)=exp(ys)


这里写图片描述

AdaBoost 中既然我们想要所有的样本点的权重越小越好,也就是想要最后的权重的总和越小越好,也就是要在上式(1) 中做最小化。AdaBoost 就是要做如下的一个最优化的问题:

minhEADA=1Nn=1Nexp(ynt=1Tαtgt(xn))

解决上述最优化问题利用的工具是梯度下降法,梯度下降法的思路基本上是:当想要最小化一个函数的时候,可以看看从当前的点出发往哪个方向v 走一小步会使得结果变好。 通常的方法是在该点附近使用泰勒公式进行展开,之后通过分析可以得到能使得函数变小的最好的方向就是负梯度的方向。沿着这个方向走一个小小的步长η , 这样就离我们的目标更近了一步。

泰勒展开

(3)min||v||=1 Ein(wt+ηv)Ein(wt)+ηvTEin(wt)

现在如果我们想要找一个函数gt 当做方向,(向量和函数在本质上是一样的。当操作的对象是向量的时候,我们根据下标index 可以得到向量中的值;当操作的对象是函数的时候,我们根据输入x 可以得到函数的输出值,所以向量的index 是整数,函数的index 是实数。这样看来,函数就是无限维度的向量)。gradient descent 中,我们想要找一个好的向量方向,沿着这个向量方向走一个步长η 来做最优化;在这里我们想要找一个好的函数h(x) ,沿着这个函数走一个步长η 来做最优化。
当前的adaboost 已经得到函数是τ=1t1ατgτ(xn) , 所以就是要在τ=1t1ατgτ(xn) 上加一个好的函数h(xn) (向量方向)和步长 η 的乘积ηh(xn) 来使得最终的结果变好一点。

(4)minh Eada^=1Nn=1Nexp(yn(τ=1t1ατgτ(xn)+ηh(xn)))

现在我们要想办法将(4) 变成(3) 的形式,

minhEada^=1Nn=1Nexp(yn(τ=1t1ατgτ(xn)+ηh(xn)))=1Nn=1Nexp((yn)τ=1t1ατgτ(xn))exp(ynηh(xn))=n=1Nun(t)exp(ynηh(xn))taylorn=1Nun(t)(1ynηh(xn))=n=1Nun(t)ηn=1Nun(t)ynh(xn)

泰勒展开式:exp(x)=1+x+x22!+x33!++xNN!+

通过上面的操作得到了和在gradient descient 中类似的形式,现在我们的目标是要找到一个好的 h 来最小化n=1Nun(t)(ynh(xn)) 。对于二分类问题来说:

(1)n=1Nun(t)(ynh(xn))(2)=n=1Nun(t){1if yn=h(xn)1if ynh(xn)(3)=n=1Nun(t)+n=1Nun(t){0if yn=h(xn)2if ynh(xn)(4)=n=1Nun(t)+2Einu(t)N

我们的出发点是要找到一个好的h(x)n=1Nun(t)(ynh(xn)) 变小,经过上面的推导发现想要让n=1Nun(t)(ynh(xn)) 变小的就要让Einu(t) 变小。能够使得Einu(t) 变小的正是adaboost 中的base algorithm 算法 A 。所以 base algorithm 找到了一个好的函数方向。我们原来认为A 找到的gt 只是为了让Einu(t) 变小, 现在经过这样的推导发现,这个gt 是一个能够让Eada^ 变小的函数方向。

adaboost 通过大概的最小化Eada^=n=1Nun(t)exp(ynηh(xn)) 得到了一个好的函数(方向),按照gradient descent 的做法,现在要做的就是沿着这个方向走一小步。但是在这里我们不仅仅满足于只走一小步,而是想要走一大步。也就是说在gt 被固定了之后,想要选择一个最大的η 来使得Eada^ 最小:

minηEada^=n=1Nun(t)exp(ynηgt(xn))

那么怎么来得到这个最好的步长 η 呢?
  • yn=gt(xn) 的时候,=un(t)exp(η)
  • yngt(xn) 的时候,=un(t)exp(+η)

Eada^=(n=1Nun(t))((1ϵ)exp(η)+ϵt exp(+η))

η 求导来得到最优解:
Eada^η=0ηt=ln1ϵtϵ=αt

所以这样看来, adaboost 使用base algorithm A 来得到一个最好的函数方向,当最好的函数方向gt 得到之后,adaboost 给这个gt 一个权重或者说是票数αt现在我们知道了这个由adaboost 给出的权重αt 是一个最佳问题的解。所以adaboost 通过也可以称为steepest descent with approximate functional gradient

3 - Gradient Boosting

上一小节对adaboost 做了另一种解释,adaboost 的每一轮可以看做是在最小化exponential error在每一轮中首先找出一个h ,将这个h 作为gt ;然后再决定要沿着这个gt 走多远的距离,这个距离会变成gt 的权重αt。所以一共有两个最佳化的过程:一个是对h 的最佳化过程, 一个是对η 的最佳化过程。

(1)minηminh1Nn=1Nexp(yn(τ=1t1αtgτ(xn)+ηh(xn)))

这样的概念可以不可以用在不同的error function 上呢?也就是说不再仅仅只是(1) 中的exponential error 。例如如果我们想做的是logistic regression 的话,我们关注的errorcross entropy error ,如果我们想做的是regression 的话,我们关注的errorsquared error

3.1 - 前向分步算法优化加法模型

基于上述的讨论,将1 式进行扩展,将err 换掉,不再局限于使用exponential error ,而是可以使用任何我们感兴趣的error function

(1)minηminh1Nn=1Nerr(τ=1t1αtgτ(xn)+ηh(xn),yn)

这是一个新的aggregation 的模型:从当前已经得到的模型τ=1t1αtgτ(xn) 出发,沿着h(xn) 走步长η ,目的是为了让err 变小,所以同样的在每一轮都是做两件事:先决定一个好的方向h 作为gt ,然后决定要沿着这个gt 更新多远得到步长η 并作为权重αtgt 融入到最中的G 中。所以这样的模型很像是adaboost 只不过是对adaboost 做了延伸,我们称之为gradientBoost ,由不同的error funciton 就可以解决不同的问题例如regression 或者是soft classification

3.2 - 提升树用于回归

当我们想要使用boosting treeregression 的时候应该怎么做呢?我们关心的是squared errorerr(s,y)=(sy)2

minηminh1Nn=1Nerr(τ=1t1ατgτ(xn)sn+ηh(xn),yn)

我们将使用当前已经得到的模型τ=1t1ατgτ(xn) 对样本xn 做出的预测结果记为sn我们的目的就是要从sn 出发沿着某个h(xn) 更新某个步长η 来使得err 变小。 所以第一步我们首先找一个最好的h(x) 作为gt

minh1Nn=1Nerr(sn+ηh(xn),yn)tarlorminh1Nn=1Nerr(sn,yn)+1Nn=1Nηh(xn)err(s,yn)s|s=sn=minhconstants+ηNn=1Nh(xn)2(snyn)

我们现在是要找一个h(xn) 来使得 最小, 那么易知当h(xn)=(snyn) 的时候,上式可以取得最小。因为首先(snyn) 保证了结果是负数,再乘以一个 ,就是负的无穷大,这是最直观的该最小化问题的解。 但是因为在这里h(xn) 相当于一个方向, 所以应该对其长度进行一下限制,这样就可以避免出现 。并且长度的问题最后交给步长 η 来解决。
基于以上的讨论我们应该解决的问题是:

min||h||=1constants+ηNn=1Nh(xn)2(snyn)

但是这样的话变成了需要求解一个有条件||h||=1 的最佳化问题,因为我们并不在乎h 的大小,所以我们将其作为一个惩罚项放入目标函数中的,只是限制使得h(x) 不要太大即可,新的问题变为:

minhconstants+ηNn=1N(2h(xn)(snyn)+h(xn)2)=constants+ηNn=1N(constant+(h(xn)(ynsn)residual)2)

yn 是目标值,sn 是目前给出的预测值, 我们ynsn 定义为残差residual。为了达到最小化的目的,就是要找一个h , 使得对于所有的样本来说,h(xn)(ynsn) 尽可能的接近,即h(xn)(ynsn) 的均方误差要尽可能的小。

所以我们回归问题的提升树只要在每一轮都拟合当前模型的残差就好了, 即在数据{(xn,ynsn)} 上做一个regression 就好了。

所以当我们使用gradientboost 来做regression 的时候,我们需要利用base algorithmresidual 数据{(xn,ynsn)} 上找一个好的gt (方向); 而在adaboost 中的base algorithm 是根据加权的数据{xn,yn} 来找到一个好的gt

在上一步中我们知道了怎么找到一个好的gt 了,也就是要求解一个regression 问题来拟合xnynsn , 现在的问题是,当找到了一个好的gt 之后,我们要怎么决定这个gt 的权重 η 呢?同样是求解如下的一个最优化的问题:

minη1Nn=1N(sn+ηgt(xn)yn)2=1Nn=1N((ynsn)residualηgt(xn))2

为了最小化我们需要求解的是一个在数据集{(gt(xn),residual)} 上的单变量η 的线性回归问题。所以当使用gradientboost 来做regression 的时候,在需要求解gt 的权重αt 的时候是使用gt 来做一个特征转换,然后求解一个简单的linear regression

把以上讨论的东西都合在一起就得到了一个算法我们称之为Gradient Boosted Decision Tree(GBDT) 。刚刚只是讲解了gradient boosted ,这里的decision tree 用做base learner

Gradient Boosted Decision Tree(GBDT)
for regression
s1=s2==sN=0
for t=1,2,,T
1. obtain gt by A({(xn,ynsn)}) where A is a(squared error) regression algorithm
2. compute αt=OneVarLinearRegression({(gt(xn),ynsn)})
3. update snsn+αtgt(xn)
returnG(x)=αtgt(x)

因为初始的s1=s2==sN=0 ,所以在第一轮的时候base learner , 这里是用decision tree 做的是一个正常的regression , 从第二轮之后才在数据{(xn,ynsn)}上做regression 。 在得到了gt 之后我们要想办法得到一个αt ,这时就是在{(gt(xn),ynsn)}上做一个单变量的回归问题。当计算完成之后, 就需要对每一个样本的分数进行更新,snsn+αtgt(xn) 。这样做了T 轮之后就可以得到一堆decision tree 最后得到G


通过上述的推导可以引出gradient boosting 。 到现在为止我们分析了提升树算法的损失函数为指数损失函数和平方误差损失函数的情况,但是对于一般的损失函数而言,优化的过程并不是这么简单的。针对这一问题Feridman 提出了梯度提升(gradient boosting )。其关键有点类似提升树用于回归的推导:利用损失函数的负梯度在当前模型的值作为回归问题提升树中的残差的近似值,以此来拟合一个回归树。

rn[L(y,f(xi))f(xi)]f(x)=fm1(x)

4 - Summary of Aggregation Models

4.1 - Blending Models

用于当手头已经有了一些gt 的时候,将它们进行集成, 集成的方式有如下的三种:

  • uniform :每一个gt 都是同样的地位,可以通过voting 或者是averaging 来进行集成。
  • non -uniform :如果每一个gt 有不同的重要性的时候,可以将这些gt 看成是特征转换,然后再喂给一个linear model 来学习每一个gt 的权重。
  • conditional :如果要在不同的情况下使用不同的gt , 同样将每一个gt 看成是特征转换, 只是在第二个阶段的学习当中, 使用non linear model 而不是linear model 。这样的模型称为stacking

通过uniform 的方式,不同的gt 会取长补短,相互修正,得到的模型比较稳定。通过non uniform 或者是conditional 的方式可以得到比较复杂的模型,但是要小心overfitting 的风险。

4.2 - Aggregation-Learning Modeling

learning 指的是我们还没有g,我们要边学g 边考虑怎么样对它们进行集成,

  • Bagging:通过bootstrap 机制来得到不同的gt , 然后通过uniform 的形式进行集成
  • AdaBoostadaboost 通过更新每一笔资料的权重的方式来得到很不一样的gt ,在得到了gt 之后依据它们的表现来决定其在最终的G 中的权重αt 。从最佳化的角度来说,gt 是能够使得error 降低的最好的方向,类似于梯度下降中的负梯度方向,这个权重可以理解为要在gt 的方向上更新的最大的步长。
  • Decision Tree:通过寻找不同的特征划分数据,最后在不同的条件下使用不同的g
  • GradientBoost:将adaboost 延伸到gradientboost ,不同于adaboost ,在学习g 的时候不是通过更新样本的权重,例如在regression 的时候,是对residual 进行拟合从而得到好的g

4.3 - Aggregation of Aggregation Models

  • decision tree + bagging 可以得到random forest
  • decision tree + adaboost 可以得到boostin tree
  • decision tree + gradient boost 可以得到gradient boost decision tree

4.4 - Specialty of Aggregation Models

为什么aggregation 这样的模型可以表现的很好呢?主要由于两个方面的原因:首先aggregation 解决了underfitting ,因为集成了很多的g 的表现,可以把这些g 看成是对原始特征不同的feature transform ;另一个方面来说当集成了很多的g 之后,会得到一个比较“中庸”的结果,aggregation 达到了regularzation 的效果,


这里写图片描述

5 - 总结

这篇的主要内容是Gradient Boosted Decision Tree 。首先先讲述了如何将adaboostdecision tree 进行搭配来得到adaboost decision tree ,为此引入了sampling and pruning 来得到一棵棵比较弱的decisiontree ,这样adaboostdecision tree 的组合才能发挥最大的效果。之后我们使用optimization 的角度来重新的看adaboost , 发现adaboost 每一次找到一个gt 就是找了一个好的方向, 这个gt 的权重αt 其实就是一个适当的步长。我们将这个模型延伸得到了gradient boosting ,引入不同种类的error ,经过推导发现当gradient boosting 用于regression 的时候其实base learner 是在做一个residual fitting

发布了109 篇原创文章 · 获赞 102 · 访问量 40万+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章