提升树/GBDT原理总结

参考资料:
李航,《统计学习方法》
刘建平博客,梯度提升树(GBDT)原理小结
知乎,关于GBDT的几个不理解的地方?
知乎,gbdt的残差为什么用负梯度代替?
知乎,梯度提升树中为什么说目标函数关于当前模型的负梯度是残差的近似值?
————————————————————————————————————————————
之前说过Adaboost算法,Adaboost没有限制基学习器是什么。提升树也是一种boosting算法,之所以叫提升树是因为它基学习器只能用决策树模型,严格来说,是只能使用二叉树模型。提升树的原理依然是前向分布算法的决策树加法模型,每一轮迭代,新训练的基学习器拟合之前模型预测值与真是值的残差,多次迭代直至满足误差精。假如真实值是10,第一次弱学习器预测结果为7,下一轮的拟合目标就是3,然后依次类推。可以看出,提升树也是使得经验误差最小化的算法。

回归角度

上面说过提升树是加法模型,假设 T ( x ; θ m ) T(x;\theta_m) T(x;θm)表示决策树模型,也就是基学习器,那么提升树模型为:
f M ( x ) = ∑ m = 1 M T ( x ; Θ m ) f_{M}(x)=\sum_{m=1}^{M} T\left(x ; \Theta_{m}\right) fM(x)=m=1MT(x;Θm)这好像与我们在Adaboost中介绍的加法模型不同,对!就是没有加权,因为上面我们说过提升树的原理是拟合残差,所以等权平均加起来就好。

提升树首先要初始化第一个 f 0 ( x ) f_0(x) f0(x),中间的加法过程可以用通式表达,一般可以表达为以下:
f 0 ( x ) = 0 f m ( x ) = f m − 1 ( x ) + T ( x ; Θ m ) , m = 1 , 2 , ⋯   , M f M ( x ) = ∑ m = 1 M T ( x ; Θ m ) \begin{array}{l}{f_{0}(x)=0} \\ {f_{m}(x)=f_{m-1}(x)+T\left(x ; \Theta_{m}\right), m=1,2, \cdots, M} \\ {f_{M}(x)=\sum_{m=1}^{M} T\left(x ; \Theta_{m}\right)}\end{array} f0(x)=0fm(x)=fm1(x)+T(x;Θm),m=1,2,,MfM(x)=m=1MT(x;Θm)通过中间的迭代通式,我们可以轻松给出提升树饿损失函数(应该说第m步的损失):
Θ ^ m = arg ⁡ min ⁡ Θ m ∑ i = 1 N L ( y i , f m − 1 ( x i ) + T ( x i ; Θ m ) ) \hat{\Theta}_{m}=\arg \min _{\Theta_{m}} \sum_{i=1}^{N} L\left(y_{i}, f_{m-1}\left(x_{i}\right)+T\left(x_{i} ; \Theta_{m}\right)\right) Θ^m=argΘmmini=1NL(yi,fm1(xi)+T(xi;Θm))使损失函数最小来求出新一轮决策树的参数,是不是看起来与Adaboost非常像。

既然前面说新一轮的基学习器是在拟合残差,但似乎完全没有在损失函数上表现出来。别急,我们把平方误差损失函数带入看看,平方误差损失函数为:
L ( y , f ( x ) ) = ( y − f ( x ) ) 2 L(y,f(x))=(y-f(x))^2 L(y,f(x))=(yf(x))2将其带入上面的损失函数中,得到:
L ( y , f m − 1 ( x ) + T ( x ; Θ m ) ) = [ y − f m − 1 ( x ) − T ( x ; Θ m ) ] 2 = [ r − T ( x ; Θ m ) ] 2 \begin{aligned} L(y,& f_{m-1}(x)+T\left(x ; \Theta_{m}\right) ) \\ &=\left[y-f_{m-1}(x)-T\left(x ; \Theta_{m}\right)\right]^{2} \\ &=\left[r-T\left(x ; \Theta_{m}\right)\right]^{2} \end{aligned} L(y,fm1(x)+T(x;Θm))=[yfm1(x)T(x;Θm)]2=[rT(x;Θm)]2带入之后就显而易见了,想要使得损失函数最小,就得使得新的基学习器尽量接近残差 r r r,也就是新的基学习器目标是拟合残差。

这里就可以抛出出一个问题,如果不用平方误差损失函数,换一个损失函数呢?还能推导出和残差的关系吗?答案是不能。

GBDT(梯度提升树)

承接上面的问题,我们抛出梯度提升树的概念。梯度提升树是什么呢?就是为了解决上面的问题。不是所有的损失函数都可以推导出残差的关系的,针对这一问题,大佬Freidman提出用利用梯度提升的方法,原理类似最速下降法,用损失函数的负梯度在当前模型的值来作为前面残差的近似值,拟合一个回归树。公式如下:
− [ ∂ L ( y , f ( x i ) ) ∂ f ( x i ) ] f ( x ) = f m − 1 ( x ) -\left[\frac{\partial L\left(y, f\left(x_{i}\right)\right)}{\partial f\left(x_{i}\right)}\right]_{f(x)=f_{m-1}(x)} [f(xi)L(y,f(xi))]f(x)=fm1(x)很多地方介绍GBDT的时候都和上面这段话差不多,上面这段话几乎就是李航《统计学习方法》中的原画,但这其实是有问题的。至少在我看来在语言表达上有问题,容易产生歧义。

两个问题:
1、为什么要用负梯度近似残差?无论什么损失函数,我们都能计算出当前模型的残差,我们下一轮迭代继续拟合残差就肯定是往正确的方向走,为什么还要用负梯度呢?
2、负梯度为什么能近似残差?他俩有什么关系?

这是我在学习过程中产生的疑问,后来经过查阅资料和思考想通了。

首先说第一个问题,我们无论什么损失函数,确实都可以计算出每一轮迭代产生的残差,但朝着残差去拟合一定是正确的吗?未必永远是正确的,举个简单的例子就是当你不再单纯追求经验风向最小化时,一味朝着残差去拟合就未必会使整个损失函数最小化(因为还有结构风向最小化)。即使你只追求经验误差最小化,那也不能所有损失函数都去拟合残差,因为残差并不是所有损失函数的最速下降方向。
那为什么还要提出拟合残差的概念?这其实是一种特殊情况,我们可以返回去看看当损失函数为平方误差的时候,就会发现那时拟合残差就是在拟合负梯度在当前模型的值。不信我们就来推导一下。

根据最速下降法, f ( x ) f(x) f(x)的更新公式应该为:
f m ( x ) = f m − 1 ( x ) − [ ∂ L ( y , f ( x i ) ) ∂ f ( x i ) ] f ( x ) = f m − 1 ( x ) f_{m}(x)=f_{m-1}(x)-\left[\frac{\partial L\left(y, f\left(x_{i}\right)\right)}{\partial f\left(x_{i}\right)}\right]_{f(x)=f_{m-1}(x)} fm(x)=fm1(x)[f(xi)L(y,f(xi))]f(x)=fm1(x)(此处假设步长为1)
那么负梯度应该是什么呢?从平方损失函数来推导一下,平方损失函数为:
1 2 L ( y , f ( x ) ) = 1 2 [ y − f ( x ) ] 2 \frac{1}{2}L(y,f(x))=\frac{1}{2}[y-f(x)]^2 21L(y,f(x))=21[yf(x)]2前面的二分之一是为了求导方便,接下来我们求负梯度:
− [ ∂ L ( y , f ( x ) ) ∂ f ( x ) ] = y − f ( x ) -\left[\frac{\partial L\left(y, f\left(x\right)\right)}{\partial f\left(x\right)}\right]=y-f(x) [f(x)L(y,f(x))]=yf(x)代入 f m − 1 ( x ) f_{m-1}(x) fm1(x)就是第m-1次迭代后的残差。所以 f ( x ) f(x) f(x)的更新公式就是:
f m ( x ) = f m − 1 ( x ) + 残 差 f_m(x)=f_{m-1}(x)+残差 fm(x)=fm1(x)+又从加法模型的角度 f ( x ) f(x) f(x)的更新公式为:
f m ( x ) = f m − 1 ( x ) + T ( x ; Θ m ) f_{m}(x)=f_{m-1}(x)+T\left(x ; \Theta_{m}\right) fm(x)=fm1(x)+T(x;Θm)综上就可以说明,当损失函数为平方误差损失时,负梯度在当前模型的值与残差相等,拟合残差就是在拟合负梯度(但换了损失就不行了)。所以我们可以统一看作都是在拟合负梯度在当前模型的值,而这么做的原因,就是为了使算法不局限于平方误差损失,推广到更多的损失函数形式。

我们来看第二个问题。负梯度在当前的值为什么能近似残差?俗话说先问是不是再问为什么,这问题编的有瑕疵,答案是从原理角度负梯度在当前的值和残差是没有半毛钱关系的,但是他们在数值上往往接近,这是为啥?

我们可以从负梯度的原理出发想想,什么是负梯度,就是梯度向下的的那个方向。那什么是负梯度在当前的值呢?从几何上来理解其实和导数值有点像,二维的话就是那个切线与坐标轴夹脚的 t a n tan tan值嘛。我们继续从二维的角度像,负梯度在当前的值的意义就是沿着负梯度方向走,每走一步目标值就会下降这么多,而且这是下降最快的方向。但这里有个前提哦,那就是之后函数的负梯度必须一直保持才行,所以一般情况下走一步目标并不会严格下降这么多(当然这不是负梯度关注的点,人们往往只关注其局部下降速度最快这一点)。了解了几何意义回过头来我们再专注于问题,残差是目前值与最终值的差距,也可以认为是目前损失距离最低点的距离。负梯度在当前的值是沿着此方向走一步在以后梯度不变的情况下目标下降的距离,这显然是不同的,因为你走一步未必走到最优点。它们在数值上相似的原因是二者都是在朝着最优点走,所以差距不会很大。

总结一下,我们可以得到以下结论:

1、推出拟合负梯度是为了推广到更多的损失函数
2、GBDT算法本质是步长为1的梯度下降法(仅限以上介绍的简单的GBDT,GBDT也可以有权)
3、拟合残差是损失为平方损失时的特殊情况
4、负梯度在当前的值与残差在原理上没有半毛钱关系,但数值上近似

搞懂了负梯度的问题,我们下一轮拟合的“残差”就变成了:
r m i = − [ ∂ L ( y i , f ( x i ) ) ∂ f ( x i ) ] f ( x ) = f m − 1 ( x ) r_{m i}=-\left[\frac{\partial L\left(y_{i}, f\left(x_{i}\right)\right)}{\partial f\left(x_{i}\right)}\right]_{f(x)=f_{m-1}(x)} rmi=[f(xi)L(yi,f(xi))]f(x)=fm1(x)针对上述拟合一棵新的回归树,对应的叶节点区域为: R m j R_{mj} Rmj j = 1 , 2 , . . . , J j=1,2,...,J j=1,2,...,J,其中 J J J为叶子结点的个数。针对每一个叶子节点里的样本,我们求出使损失函数最小,也就是拟合叶子节点最好的的输出值 c m j c_{mj} cmj如下:
c m j = arg ⁡ min ⁡ c ∑ x i ∈ R m j L ( y i , f m − 1 ( x i ) + c ) c_{m j}=\arg \min _{c} \sum_{x_{i} \in R_{m j}} L\left(y_{i}, f_{m-1}\left(x_{i}\right)+c\right) cmj=argcminxiRmjL(yi,fm1(xi)+c)GBDT的更新公式此时为:
f m ( x ) = f m − 1 ( x ) + ∑ j = 1 J c m j I ( x ∈ R m j ) f_{m}(x)=f_{m-1}(x)+\sum_{j=1}^{J} c_{m j} I\left(x \in R_{m j}\right) fm(x)=fm1(x)+j=1JcmjI(xRmj)最终的回归树模型为:
f ^ ( x ) = f M ( x ) = f 0 ( x ) + ∑ m = 1 M ∑ j = 1 J c m j I ( x ∈ R m j ) \hat{f}(x)=f_{M}(x)=f_0(x)+\sum_{m=1}^{M} \sum_{j=1}^{J} c_{m j} I\left(x \in R_{m j}\right) f^(x)=fM(x)=f0(x)+m=1Mj=1JcmjI(xRmj)

分类角度

GBDT实现分类有两种方法,一种就是使用指数损失,说到这里有没有很熟悉?没错,使用指数损失就退化成了Adaboost算法,就不多说了。另一种方法是使用对数损失,类似逻辑回归,把分类的离散特性转换成概率上的连续。

关于分类的内容有人写的已经非常完美了,我直接搬运。

原文出处:

作者:刘建平Pinard
链接:https://www.cnblogs.com/pinard/p/6140514.html

二元GBDT分类算法

对于二元GBDT,如果用类似于逻辑回归的对数似然损失函数,则损失函数为:
L ( y , f ( x ) ) = log ⁡ ( 1 + exp ⁡ ( − y f ( x ) ) ) L(y, f(x))=\log (1+\exp (-y f(x))) L(y,f(x))=log(1+exp(yf(x)))其中 y ∈ − 1 , + 1 y∈{−1,+1} y1,+1。则此时的负梯度误差为:
r t i = − [ ∂ L ( y , f ( x i ) ) ) ∂ f ( x i ) ] f ( x ) = f t − 1 ( x ) = y i / ( 1 + exp ⁡ ( y i f ( x i ) ) ) r_{t i}=-\left[\frac{\partial L\left(y, f\left(x_{i}\right)\right))}{\partial f\left(x_{i}\right)}\right]_{f(x)=f_{t-1}(x)}=y_{i} /\left(1+\exp \left(y_{i} f\left(x_{i}\right)\right)\right) rti=[f(xi)L(y,f(xi)))]f(x)=ft1(x)=yi/(1+exp(yif(xi)))对于生成的决策树,我们各个叶子节点的最佳负梯度拟合值为
c t j = arg ⁡ min ⁡ ⏟ c ∑ x i ∈ R t j log ⁡ ( 1 + exp ⁡ ( − y i ( f t − 1 ( x i ) + c ) ) ) c_{t j}=\underbrace{\arg \min }_{c} \sum_{x_{i} \in R_{t j}} \log \left(1+\exp \left(-y_{i}\left(f_{t-1}\left(x_{i}\right)+c\right)\right)\right) ctj=c argminxiRtjlog(1+exp(yi(ft1(xi)+c)))由于上式比较难优化,我们一般使用近似值代替
c t j = ∑ x i ∈ R t j r t i / ∑ x i ∈ R t j ∣ r t i ∣ ( 1 − ∣ r t i ∣ ) c_{t j}=\sum_{x_{i} \in R_{t j}} r_{t i} / \sum_{x_{i} \in R_{t j}}\left|r_{t i}\right|\left(1-\left|r_{t i}\right|\right) ctj=xiRtjrti/xiRtjrti(1rti)除了负梯度计算和叶子节点的最佳负梯度拟合的线性搜索,二元GBDT分类和GBDT回归算法过程相同。

多元GBDT分类算法

多元GBDT要比二元GBDT复杂一些,对应的是多元逻辑回归和二元逻辑回归的复杂度差别。假设类别数为K,则此时我们的对数似然损失函数为:
L ( y , f ( x ) ) = − ∑ k = 1 K y k log ⁡ p k ( x ) L(y, f(x))=-\sum_{k=1}^{K} y_{k} \log p_{k}(x) L(y,f(x))=k=1Kyklogpk(x)其中如果样本输出类别为 k k k,则 y k = 1 y_k=1 yk=1。第 k k k类的概率 p k ( x ) p_k(x) pk(x)的表达式为:
p k ( x ) = exp ⁡ ( f k ( x ) ) / ∑ l = 1 K exp ⁡ ( f ( x ) ) p_{k}(x)=\exp \left(f_{k}(x)\right) / \sum_{l=1}^{K} \exp (f(x)) pk(x)=exp(fk(x))/l=1Kexp(f(x))集合上两式,我们可以计算出第 t t t轮的第 i i i个样本对应类别 l l l的负梯度误差为
r t i l = − [ ∂ L ( y i , f ( x i ) ) ) ∂ f ( x i ) ] f k ( x ) = f l , t − 1 ( x ) = y i l − p l , t − 1 ( x i ) r_{t i l}=-\left[\frac{\partial L\left(y_{i}, f\left(x_{i}\right)\right))}{\partial f\left(x_{i}\right)}\right]_{f_{k}(x)=f_{l, t-1}(x)}=y_{i l}-p_{l, t-1}\left(x_{i}\right) rtil=[f(xi)L(yi,f(xi)))]fk(x)=fl,t1(x)=yilpl,t1(xi)观察上式可以看出,其实这里的误差就是样本 i i i对应类别 l l l的真实概率和 t − 1 t−1 t1轮预测概率的差值。

对于生成的决策树,我们各个叶子节点的最佳负梯度拟合值为
c t j l = arg ⁡ min ⁡ ⏟ c j l ∑ i = 0 m ∑ k = 1 K L ( y k , f t − 1 , l ( x ) + ∑ j = 0 J c j l I ( x i ∈ R t j ) ) c_{t j l}=\underbrace{\arg \min }_{c_{jl} } \sum_{i=0}^{m} \sum_{k=1}^{K} L\left(y_{k}, f_{t-1, l}(x)+\sum_{j=0}^{J} c_{j l} I\left(x_{i} \in R_{t j}\right)\right) ctjl=cjl argmini=0mk=1KL(yk,ft1,l(x)+j=0JcjlI(xiRtj))除了负梯度计算和叶子节点的最佳负梯度拟合的线性搜索,多元GBDT分类和二元GBDT分类以及GBDT回归算法过程相同。

GBDT常用损失函数

这里我们再对常用的GBDT损失函数做一个总结。

对于分类算法,其损失函数一般有对数损失函数和指数损失函数两种:

a) 如果是指数损失函数,则损失函数表达式为
L ( y , f ( x ) ) = exp ⁡ ( − y f ( x ) ) L(y, f(x))=\exp (-y f(x)) L(y,f(x))=exp(yf(x))其负梯度计算和叶子节点的最佳负梯度拟合参见Adaboost原理篇。

b) 如果是对数损失函数,分为二元分类和多元分类两种,参见上述所讲。

对于回归算法,常用损失函数有如下4种:

a) 均方差,这个是最常见的回归损失函数了
L ( y , f ( x ) ) = ( y − f ( x ) ) 2 L(y, f(x))=(y-f(x))^{2} L(y,f(x))=(yf(x))2b) 绝对损失,这个损失函数也很常见
L ( y , f ( x ) ) = ∣ y − f ( x ) ∣ L(y, f(x))=|y-f(x)| L(y,f(x))=yf(x)对应负梯度误差为:
sign ⁡ ( y i − f ( x i ) ) \operatorname{sign}\left(y_{i}-f\left(x_{i}\right)\right) sign(yif(xi))c) Huber损失,它是均方差和绝对损失的折衷产物,对于远离中心的异常点,采用绝对损失,而中心附近的点采用均方差。这个界限一般用分位数点度量。损失函数如下:
L ( y , f ( x ) ) = { 1 2 ( y − f ( x ) ) 2 ∣ y − f ( x ) ∣ ≤ δ δ ( ∣ y − f ( x ) ∣ − δ 2 ) ∣ y − f ( x ) ∣ > δ L(y, f(x))=\left\{\begin{array}{ll}{\frac{1}{2}(y-f(x))^{2}} & {|y-f(x)| \leq \delta} \\ {\delta\left(|y-f(x)|-\frac{\delta}{2}\right)} & {|y-f(x)|>\delta}\end{array}\right. L(y,f(x))={ 21(yf(x))2δ(yf(x)2δ)yf(x)δyf(x)>δ对应的负梯度误差为:
r ( y i , f ( x i ) ) = { y i − f ( x i ) ∣ y i − f ( x i ) ∣ ≤ δ δ sig ⁡ n ( y i − f ( x i ) ) ∣ y i − f ( x i ) ∣ > δ r\left(y_{i}, f\left(x_{i}\right)\right)=\left\{\begin{array}{ll}{y_{i}-f\left(x_{i}\right)} & {\left|y_{i}-f\left(x_{i}\right)\right| \leq \delta} \\ {\delta \operatorname{sig} n\left(y_{i}-f\left(x_{i}\right)\right)} & {\left|y_{i}-f\left(x_{i}\right)\right|>\delta}\end{array}\right. r(yi,f(xi))={ yif(xi)δsign(yif(xi))yif(xi)δyif(xi)>δd) 分位数损失。它对应的是分位数回归的损失函数,表达式为
L ( y , f ( x ) ) = ∑ y ≥ f ( x ) θ ∣ y − f ( x ) ∣ + ∑ y < f ( x ) ( 1 − θ ) ∣ y − f ( x ) ∣ L(y, f(x))=\sum_{y \geq f(x)} \theta|y-f(x)|+\sum_{y<f(x)}(1-\theta)|y-f(x)| L(y,f(x))=yf(x)θyf(x)+y<f(x)(1θ)yf(x)其中 θ θ θ为分位数,需要我们在回归前指定。对应的负梯度误差为:
r ( y i , f ( x i ) ) = { θ y i ≥ f ( x i ) θ − 1 y i < f ( x i ) r\left(y_{i}, f\left(x_{i}\right)\right)=\left\{\begin{array}{ll}{\theta} & {y_{i} \geq f\left(x_{i}\right)} \\ {\theta-1} & {y_{i}<f\left(x_{i}\right)}\end{array}\right. r(yi,f(xi))={ θθ1yif(xi)yi<f(xi)对于Huber损失和分位数损失,主要用于健壮回归,也就是减少异常点对损失函数的影响。

GBDT的正则化

和Adaboost一样,我们也需要对GBDT进行正则化,防止过拟合。GBDT的正则化主要有三种方式。

第一种是和Adaboost类似的正则化项,即步长(learning rate)。定义为 ν ν ν,对于前面的弱学习器的迭代
f k ( x ) = f k − 1 ( x ) + h k ( x ) f_{k}(x)=f_{k-1}(x)+h_{k}(x) fk(x)=fk1(x)+hk(x)如果我们加上了正则化项,则有
f k ( x ) = f k − 1 ( x ) + ν h k ( x ) f_{k}(x)=f_{k-1}(x)+\nu h_{k}(x) fk(x)=fk1(x)+νhk(x) ν ν ν的取值范围为 0 < ν ≤ 1 0<ν≤1 0<ν1。对于同样的训练集学习效果,较小的 ν ν ν意味着我们需要更多的弱学习器的迭代次数。通常我们用步长和迭代最大次数一起来决定算法的拟合效果。

第二种正则化的方式是通过子采样比例(subsample)。取值为(0,1]。注意这里的子采样和随机森林不一样,随机森林使用的是放回抽样,而这里是不放回抽样。如果取值为1,则全部样本都使用,等于没有使用子采样。如果取值小于1,则只有一部分样本会去做GBDT的决策树拟合。选择小于1的比例可以减少方差,即防止过拟合,但是会增加样本拟合的偏差,因此取值不能太低。推荐在[0.5, 0.8]之间。

使用了子采样的GBDT有时也称作随机梯度提升树(Stochastic Gradient Boosting Tree, SGBT)。由于使用了子采样,程序可以通过采样分发到不同的任务去做boosting的迭代过程,最后形成新树,从而减少弱学习器难以并行学习的弱点。

第三种是对于弱学习器即CART回归树进行正则化剪枝。在决策树原理篇里我们已经讲过,这里就不重复了。

GBDT小结

GBDT终于讲完了,GDBT本身并不复杂,不过要吃透的话需要对集成学习的原理,决策树原理和各种损失函树有一定的了解。由于GBDT的卓越性能,只要是研究机器学习都应该掌握这个算法,包括背后的原理和应用调参方法。目前GBDT的算法比较好的库是xgboost。当然scikit-learn也可以。

最后总结下GBDT的优缺点。

GBDT主要的优点有:

1)可以灵活处理各种类型的数据,包括连续值和离散值。

2)在相对少的调参时间情况下,预测的准确率也可以比较高。这个是相对SVM来说的。

3)使用一些健壮的损失函数,对异常值的鲁棒性非常强。比如 Huber损失函数和Quantile损失函数。

GBDT的主要缺点有:

由于弱学习器之间存在依赖关系,难以并行训练数据。不过可以通过自采样的SGBT来达到部分并行。

猜你喜欢

转载自blog.csdn.net/zhaojc1995/article/details/88177939
今日推荐