机器学习经典模型:集成学习——Boosting(Adaboost与gradient boosting)

集成学习中的boosting主要有两类思想,Adaboost和gradient boosting,而GBDT和XGboost都是gradient boosting的具体应用。

首先简单介绍一下boosting的一些要点,

  1. 和bagging相比,boosting的主要区别是基学习器之间不是相互独立的,而是相互联系的,当前的学习器的训练是依赖于上一个学习器的学习结果,对上一轮学习错误的数据给与更多的关注,这是boosting的一个重点。

  2. boosting本身是一个加法模型,即boosting模型的输出,等于各个学习器的输出之和(或者加权和)

  3. boosting乃至集成学习,集成的都是弱学习器,所谓弱学习器就是不论你怎么训练它,它的准确率都一般,这是一定要记住的地方,因为我一开始就想不懂,为什么要训练多个学习器,而不是集中训练一个学习器,就是因为集中训练它效果也不好。

Adaboost

Adaboost和gradient boosting的区别主要在于从不同的角度实现对上一轮训练错误的数据更多关注,Adaboost主要对数据引入权重,训练后调整学习错误的数据的权重,从而使得下一轮学习中给予学习错误的数据更多的关注。

首先我要强调一点,如果我们设定了Adaboost包含M个学习器(M是超参数),那么整个Adaboost就只学习M轮,或者说只进行M次梯度下降,这是重点,一定要记住。

接下来我们看看完整的训练流程,在训练前,我们会初始化权重,此时一般会让每条数据的权重都相等

D 1 = ( w 11 , … … , w 1 i , … … , w 1 N ) ,      w 1 i = 1 N ,      i = 1 , 2 , … … , N D_1 = (w_{11}, ……, w_{1i},……, w_{1N} ) ,\ \ \ \ w_{1i}=\frac{1}{N}, \ \ \ \ i=1, 2, ……, N D1=(w11,,w1i,,w1N),    w1i=N1,    i=1,2,,N

比如说,现在有100条数据,那么每条数据的初始化权重就是0.01。

确定好权重后,我们就可以训练第一个学习器,同时定义错误率,作为该学习器性能的指标,

e m = ∑ i = 1 N w m i I ( G m ( x i ) ≠ y i ) e_m = \sum _{i=1} ^N w_{mi} I(G_m (x_i) \neq y_i) em=i=1NwmiI(Gm(xi)=yi)

其中m表示第m个学习器,N表示训练数据数量,w表示第m个学习器对应的第i个训练数据的权重,I是一个指示函数,判断分类是否正确,在这里正确为0,错误为1,G则是学习器。

一般来说,我们会用准确率之类的指标去衡量一个学习器的性能,之所以这里使用错误率,主要是为了引入权重。

利用错误率,我们可以计算出该学习器的权重,

a m = 1 2 l o g ( 1 − e m e m ) a_m = \frac{1}{2} log(\frac{1-e_m}{e_m}) am=21log(em1em)

结合学习器的权重以及错误率,我们就可以根据学习的结果,更新数据的权重分布,

w m + 1 , i = w m i z m e x p ( − a m y i G m ( x i ) ) w_{m+1,i} = \frac{w_{mi}}{z_m} exp(-a_my_iG_m(x_i)) wm+1,i=zmwmiexp(amyiGm(xi))
z m = ∑ i = 1 N w m i e x p ( − a m y i G m ( x i ) ) z_m = \sum_{i=1}^N w_{mi} exp(-a_my_iG_m(x_i)) zm=i=1Nwmiexp(amyiGm(xi))

Zm其实就是规范化因子,重点在于

w m i e x p ( − a m y i G m ( x i ) ) w_{mi}exp(-a_my_iG_m(x_i)) wmiexp(amyiGm(xi))

在这里,yi和Gi的取值应该都是±1,这样当分类正确时,两者乘积为1,否则为-1,假设分类正确,因为前面的负号,导致最后计算出来的结果更小,从而使得更新后的权重更小。这样,整个权重的分布就会给与分类错误数据更大的权重。

当我们训练完M个学习器后,整个Adaboost的输出为

f ( x ) = ∑ m = 1 M a m G m ( x ) f(x) = \sum _{m=1} ^M a_m G_m (x) f(x)=m=1MamGm(x)

训练终止条件有两个,一个是训练完一开始设定的M个学习器,另一个则是错误率小于指定阈值。

gradient boosting

在介绍gradient boosting之前,我想先说一点,boosting本身作为一个加法模型,其实就是对多个弱学习器进行线性变换,假如弱学习器本身可以通过多项式表示,那么其实对多项式进行线性变换得到的还是多项式,这样是没法提高弱学习器的性能的,所以一般我们会采用决策树、回归树,就是因为他们都不能写成多项式的形式,特别是回归树,本质上他就是一个分段函数,根据不同的特征输出不同的结果,我们把回归树作为弱学习器进行集成,其实就是把多棵回归树整合在一起,和直接构建一棵复杂的回归树相比,主要优点在于,集成的回归树节点更少,能更好地避免过拟合,同时也保证了模型的拟合能力。这就是boosting一般使用决策树回归树的原因。

接下来我们正式看看gradient boosting,对于gradient boosting,我认为它更像是提升树的一般形式,所以我打算先从提升树说起。

举个简单的例子,我们现在做一个回归模型,

y = f 1 ( x ) + r e s i d u a l 1 y = f_1(x) + residual_1 y=f1(x)+residual1

提升树的思想就是用一个新的学习器f2去拟合f1产生的残差

r e s i d u a l 1 = f 2 ( x ) + r e s i d u a l 2 residual_1 = f_2(x) + residual_2 residual1=f2(x)+residual2

可是f2也不能完美地拟合,也会产生新的残差,所以可以继续用一个f3去拟合,

r e s i d u a l 2 = f 3 ( x ) + r e s i d u a l 3 residual_2 = f_3(x) + residual_3 residual2=f3(x)+residual3

我们可以不断用新的学习器去拟合上一个学习器产生的残差,理论上认为残差会变得越来越容易拟合,因此变得越来越小,此时把各个学习器的输出相加作为完整模型的输出,残差就会比单一的学习器更小,准确率更高

F ( x ) = f 1 ( x ) + f 2 ( x ) + f 3 ( x ) + … … F(x) = f_1(x) + f_2(x) + f_3(x) + …… F(x)=f1(x)+f2(x)+f3(x)+

这就是提升树的思想,但是实际的模型中,我们的目标往往不会只是减少残差,因为这样会导致过拟合,因此往往会采用更复杂的损失函数,在损失函数中引入正则项等等,我们能不能把提升树的思想进一步一般化呢,这就是gradient boosting所做的事情。

gradient boosting其实就是把最小化的目标从残差变为损失函数,接下来,我就说说我自己关于拟合负梯度的看法,因为只是我个人的看法,不知道是否准确,如果各位觉得有误,欢迎指出。

说到最小化损失函数,就能想到梯度下降法

w ′ = w − a ∗ ∂ L o s s ( y , x , w , γ ) ∂ w w' = w - a* \frac{\partial Loss(y, x, w, \gamma)}{\partial w} w=wawLoss(y,x,w,γ)

损失函数我写成一般的形式,其中y表示真实输出,x表示输入,a表示学习率,w表示模型参数,gamma表示正则项等等。

其实对于损失函数,能够改变的只有参数w,所以才会通过优化w从而最小化损失函数。通过上式更新参数w,就能使得损失函数不断下降,即

L o s s ( y , x , w ′ , γ ) < L o s s ( y , x , w , γ ) Loss(y, x, w', \gamma) < Loss(y, x, w, \gamma) Loss(y,x,w,γ)<Loss(y,x,w,γ)

假如我把w换成f(x),f(x)为模型本身,有

f ( x ) ′ = f ( x ) − a ∗ ∂ L o s s ( y , f ( x ) , γ ) ∂ f ( x ) f(x)'= f(x) - a*\frac{\partial Loss(y, f(x), \gamma)}{\partial f(x)} f(x)=f(x)af(x)Loss(y,f(x),γ)

L o s s ( y , f ( x ) ′ , γ ) < L o s s ( y , f ( x ) , γ ) Loss(y, f(x)', \gamma) < Loss(y, f(x), \gamma) Loss(y,f(x),γ)<Loss(y,f(x),γ)

f(x)'比起f(x),对应的损失函数也会更小。

如果不理解,我还可以用一个具体的例子来说明,假设使用MSE作为损失函数,

L o s s = ( y − f ( x ) ) 2 Loss = (y - f(x))^2 Loss=(yf(x))2

假设输入为1,输出为2,真实输出为3,学习率为0.1

L o s s 0 = ( 3 − f ( 1 ) ) 2 = 1 Loss_0 = (3 - f(1))^2 = 1 Loss0=(3f(1))2=1

a ∗ ∂ ( y − f ( x ) ) 2 ∂ f ( x ) = 0.1 ∗ ( 2 f ( x ) − 6 ) = − 0.2 a*\frac{\partial (y - f(x))^2}{\partial f(x)} = 0.1*(2f(x)-6) = -0.2 af(x)(yf(x))2=0.1(2f(x)6)=0.2

f ( x ) − a ∗ ∂ L o s s ( y , f ( x ) , γ ) ∂ f ( x ) = 2 − ( − 0.2 ) = 2.2 f(x)-a*\frac{\partial Loss(y, f(x), \gamma)}{\partial f(x)}=2-(-0.2)=2.2 f(x)af(x)Loss(y,f(x),γ)=2(0.2)=2.2

L o s s 1 = ( 3 − f ( 1 ) ) 2 = 0.64 Loss_1 = (3 - f(1))^2 = 0.64 Loss1=(3f(1))2=0.64

可以看到损失函数已经下降了。

进一步,我们继续推广(这里我省略了学习率),对f0进行n次梯度下降,并把每次梯度下降写出来,可得

f 1 ( x ) = f 0 ( x ) − ∂ L o s s ∂ f 0 ( x ) f_1(x)= f_0(x) - \frac{\partial Loss}{\partial f_0(x)} f1(x)=f0(x)f0(x)Loss

f 2 ( x ) = f 1 ( x ) − ∂ L o s s ∂ f 1 ( x ) f_2(x)= f_1(x) - \frac{\partial Loss}{\partial f_1(x)} f2(x)=f1(x)f1(x)Loss

f 3 ( x ) = f 2 ( x ) − ∂ L o s s ∂ f 2 ( x ) f_3(x)= f_2(x) - \frac{\partial Loss}{\partial f_2(x)} f3(x)=f2(x)f2(x)Loss

… … ……

f n ( x ) = f n − 1 ( x ) − ∂ L o s s ∂ f n − 1 ( x ) f_n(x)= f_{n-1}(x) - \frac{\partial Loss}{\partial f_{n-1}(x)} fn(x)=fn1(x)fn1(x)Loss

合并上式,得到

f n ( x ) = f 0 ( x ) − ∂ L o s s ∂ f 0 ( x ) − ∂ L o s s ∂ f 1 ( x ) − … … − ∂ L o s s ∂ f n − 1 ( x ) f_n(x)= f_0(x) - \frac{\partial Loss}{\partial f_0(x)} - \frac{\partial Loss}{\partial f_1(x)} - …… - \frac{\partial Loss}{\partial f_{n-1}(x)} fn(x)=f0(x)f0(x)Lossf1(x)Lossfn1(x)Loss

改写一下上式,

F ( x ) = T 0 ( x ) + T 1 ( x ) + T 2 ( x ) + … … + T n ( x ) F(x)= T_0(x) + T_1(x) + T_2(x) + …… + T_n(x) F(x)=T0(x)+T1(x)+T2(x)++Tn(x)

F(x)其实就是一个加法模型,其中每个学习器都在拟合上一个学习器的负梯度,这也就是gradient boosting的思想。

你可能感兴趣的:(机器学习)