上篇我们对boosting家族中的Adaboost算法进行了总结,本篇我们来探讨传统的梯度提升树(Gradient Boosting Decison Tree)算法。梯度提升树被认为是统计学习中性能最好的方法之一。
梯度提升树(GBDT)全称为Gradient Boosting Decison Tree,顾名思义,包含两部分内容:Gradient Boosting和Decison Tree。本篇我们首先Decison Tree进行简要回顾;然后探讨提升树算法;再重点探讨回归与分类问题对应的GBDT算法;最后对梯度提升树算法优缺点进行简单的总结。
在决策树(Decision Tree)算法原理总结中我们了解到,决策树的基本结构(如下图),决策树由节点和有向的边组成,节点按所处在决策树的位置可以分为根节点,中间节点和叶子节点。其中每个节点代表一个属性,每个分支代表一个决策(规则),每个叶子代表一个结果(分类值或连续值)。
决策树根据选择最优特征的标准不同,可以分为ID3,C4.5,CART决策树,其中CART决策树是前面两种算法的改进。CART决策树既可以处理分类任务,又可以处理回归任务,但决策树存在容易过拟合的缺点。因此,有了提升模型的泛化能力的随机森林算法。
那么,有没有其他的一种方法,在不改变原有模型的参数结构基础上提升模型的泛化能力呢?
既然不能更改原来模型的参数,那么意味着必须在原来模型的基础之上做改善,正好可以利用boosting的思想对决策树进行提升。这就是我们下面要探讨的提升树算法(Boosting Tree)。
如果我们选择以决策树为boosting框架的基学习器,那么这便是提升树(boosting tree)。对于分类问题决策树是二叉分类树,对于回归问题决策树是二叉回归树。
在AdaBoost算法原理详细总结我们解释了,boosting方法采用加法模型与前向分布算法。因此,提升树模型可以表示:
f M ( x ) = ∑ m = 1 M g m ( x ) f_M(x)=\sum_{m=1}^Mg_m(x) fM(x)=m=1∑Mgm(x)
其中, g m ( x ) g_m(x) gm(x)表示第 m m m颗决策树, M M M表示为决策树的颗数。
对于数据集 D = { ( x i , y i ) } i = 1 n D=\left\{ (x_i,y_i) \right\}^n_{i=1} D={(xi,yi)}i=1n, x i ∈ R d x_i\in R^d xi∈Rd,提升树训练的目标就是最小化损失 ∑ i = 1 n L ( y i , f M ( x i ) ) \sum_{i=1}^n L(y_i,f_M(x_i)) ∑i=1nL(yi,fM(xi)),即
a r g m i n ∑ i = 1 n L ( y i , f M ( x i ) ) = a r g m i n ∑ i = 1 n L ( y i , ∑ m = 1 M g m ( x ) ) argmin\sum_{i=1}^n L(y_i,f_M(x_i))=argmin\sum_{i=1}^nL(y_i,\sum_{m=1}^Mg_m(x)) argmini=1∑nL(yi,fM(xi))=argmini=1∑nL(yi,m=1∑Mgm(x))
对于不同问题的提升树算法,主要区别在于使用的损失函数不同。对于分类问题,损失函数一般有对数损失和指数损失;对于回归问题,损失函数一般有平方误差损失,绝对值损失,Huber损失。
对于二元分类情况下,采用指数损失时,提升树变成基学习器为分类树的Adaboost算法,可参考上篇AdaBoost算法原理详细总结第4部分。
下面我们探讨回归问题提升算法。
首先确定初始提升树 f 0 ( x ) = 0 f_0(x)=0 f0(x)=0
根据前向分步算法,第 m m m步的模型为:
f m ( x ) = f m − 1 ( x ) + g m ( x ) f_m(x) = f_{m-1}(x) + g_m(x) fm(x)=fm−1(x)+gm(x)
在 m m m次迭代中,算法的目标是找到一个基学习器 g m ( x ) g_{m}(x) gm(x)使得损失最小,即:
a r g m i n ∑ i = 1 n L ( y i , f m − 1 ( x i ) + g m ( x ) ) argmin\sum_{i=1}^n L(y_i,f_{m-1}(x_i)+g_m(x)) argmini=1∑nL(yi,fm−1(xi)+gm(x))
生成第 m m m颗决策树 g m ( x ) g_m(x) gm(x)。
当采用平方误差损失时,决策树拟合的就是残差。
L ( y , f m − 1 ( x ) + g m ( x ) ) L(y,f_{m-1}(x)+g_m(x)) L(y,fm−1(x)+gm(x))
= ( y − f m − 1 ( x ) − g m ( x ) ) 2 =(y - f_{m-1}(x)-g_m(x))^2 =(y−fm−1(x)−gm(x))2
= ( r − g m ( x ) ) 2 =(r-g_m(x))^2 =(r−gm(x))2
其中, r = y − f m − 1 ( x ) r=y-f_{m-1}(x) r=y−fm−1(x)为模型拟合数据的残差。所以,对于回归问题的提升树算法,只需要拟合当前模型的残差,即 { ( x 1 , y 1 − f m − 1 ( x 1 ) ) , ( x 2 , y 2 − f m − 1 ( x 2 ) ) , . . . ( x n , y n − f m − 1 ( x n ) } \left\{(x_1,y_1-f_{m-1}(x_1)), (x_2,y_2-f_{m-1}(x_2)),...(x_n,y_n-f_{m-1}(x_n)\right\} {(x1,y1−fm−1(x1)),(x2,y2−fm−1(x2)),...(xn,yn−fm−1(xn)}。
下面对回归问题提升树算法过程进行总结:
输入: 训练数据集 D = { ( x i , y i ) } i = 1 n D=\left\{ (x_i,y_i) \right\}^n_{i=1} D={(xi,yi)}i=1n, x i ∈ R d x_i\in R^d xi∈Rd
输出:回归提升树 h M ( x ) h_M(x) hM(x)
当提升树中的损失函数为平方误差时,残差计算很简单。但对于一般损失函数而言(比如对数损失),残差计算就不是很方便了。因此,Freidman提出了利用损失函数的负梯度在当前模型的值作为提升树模型残差的近似值的方法,这便是梯度提升树的思想精髓。损失函数的负梯度用数学语言表达为: [ ∂ L ( y , f ( x i ) ) ∂ f ( x i ) ] f ( x ) = f m − 1 ( x ) [\frac{\partial L(y,f(x_i))}{\partial f(x_i)}]_{f(x)=f_{m-1}(x)} [∂f(xi)∂L(y,f(xi))]f(x)=fm−1(x)
需要注意的是,梯度提升树使用损失函数负梯度作为残差的近似值,而梯度值是连续值,所以不管处理回归任务还是分类任务,基学习器都是CART回归树。
对于回归问题,如果选择均方误差作为损失函数,即:
L = ( y − f m − 1 ( x ) ) 2 L=(y - f_{m-1}(x))^2 L=(y−fm−1(x))2
对损失函数求导得:
[ ∂ L ( y , f ( x i ) ) ∂ f ( x i ) ] f ( x ) = f m − 1 ( x ) = [ ( y − f m − 1 ( x ) ) 2 ] ′ = 2 ( ( y − f m − 1 ( x ) ) [\frac{\partial L(y,f(x_i))}{\partial f(x_i)}]_{f(x)=f_{m-1}(x)}=[(y - f_{m-1}(x))^2]'=2((y - f_{m-1}(x)) [∂f(xi)∂L(y,f(xi))]f(x)=fm−1(x)=[(y−fm−1(x))2]′=2((y−fm−1(x))
此时,损失函数的一阶导和残差一致。
对于回归问题,梯度提升算法过程如下:
输入:训练数据集 D = { ( x i , y i ) } i = 1 n D=\left\{ (x_i,y_i) \right\}^n_{i=1} D={(xi,yi)}i=1n, x i ∈ R d x_i\in R^d xi∈Rd,损失函数 L ( y , f ( x ) ) L(y,f(x)) L(y,f(x))
输出:梯度提升树 h ( x ) h(x) h(x)
对于每一个样本 ( x i , y i ) (x_i,y_i) (xi,yi),计算其残差的近似值: r m , i = − [ ∂ L ( y , f ( x i ) ) ∂ f ( x i ) ] f ( x ) = f m − 1 ( x ) r_{m,i}=-[\frac{\partial L(y,f(x_i))}{\partial f(x_i)}]_{f(x)=f_{m-1}(x)} rm,i=−[∂f(xi)∂L(y,f(xi))]f(x)=fm−1(x)
利用 { ( x i , r m , i ) } i = 1 , 2... n \left\{ (x_i,r_{m,i}) \right\}_{i=1,2...n} {(xi,rm,i)}i=1,2...n训练出第 m m m颗回归树 g m g_m gm,其中叶节点的区域为 R m , j , j = 1 , 2 , . . . J m , J m R_{m,j},j=1,2,...J_m,J_m Rm,j,j=1,2,...Jm,Jm为第 m m m颗决策树叶子节点的个数。
利用回归树 g m g_m gm的每一个叶节点,计算最佳拟合值:
g m , j = a r g m i n g ∑ L ( y i , f m − 1 ( x i ) + g m ) g_{m,j}=argmin_g\sum L(y_i,f_{m-1}(x_i)+g_m) gm,j=argming∑L(yi,fm−1(xi)+gm)
更新 f m ( x ) = f m − 1 ( x ) + ∑ j = 1 J g m , j I ( x ∈ R m , j ) f_m(x)=f_{m-1}(x)+\sum_{j=1}^Jg_{m,j}I(x \in R_{m,j}) fm(x)=fm−1(x)+∑j=1Jgm,jI(x∈Rm,j)
在求解 g m , j g_{m,j} gm,j时,如果损失函数为平方损失函数,则求解与提升回归树一致,直接取均值即可。如果是其他损失函数,则需要求解函数 ∑ L ( y i , f m − 1 ( x i ) + g m ) \sum L(y_i,f_{m-1}(x_i)+g_m) ∑L(yi,fm−1(xi)+gm)取极值时对应的 g m , j g_{m,j} gm,j。
对于回归问题,损失函数很好定义,使用均方误差既可;那么对于分类问题,该何如转换成回归问题处理呢?
我们回想下逻辑回归的原理,利用 s i g m o i d sigmoid sigmoid函数,将预测类别转换成预测类别的概率。因此,对于分类问题,我们可以定义GBDT的损失函数为对数似然损失函数,将类别预测转换成概率预测,通过预测概率和真是概率的差值作为残差来拟合回归树。
下面探讨二分类问题,GBDT的算法详细过程。
在逻辑回归(Logistic Regression)原理详细总结中,我们知道逻辑回归的目标函数为:
L ( θ ) = − ∑ i = 1 n y i l o g y ^ i + ( 1 − y i ) l o g ( 1 − y ^ i ) L(\theta) =- \sum _{i=1}^ny_ilog\hat y_i+(1-y_i)log(1-\hat y_i) L(θ)=−i=1∑nyilogy^i+(1−yi)log(1−y^i)
其中 y ^ i = σ ( w T x i + b ) \hat y_i = \sigma(w^Tx_i+b) y^i=σ(wTxi+b)是逻辑回归预测的结果。第 M M M步迭代之后,学习器为 :
F ( x i ) = ∑ m = 0 M σ m ( w T x i + b ) F(x_i) = \sum_{m=0}^M \sigma_m(w^Tx_i+b) F(xi)=m=0∑Mσm(wTxi+b)
y ^ i = F ( x i ) \hat y_i=F(x_i) y^i=F(xi)
将 F ( x ) F(x) F(x)带入目标函数,得
L ( y i , F ( x i ) ) = − ∑ i = 1 n y i l o g 1 1 + e − F ( x i ) + ( 1 − y i ) l o g ( 1 − 1 1 + e − F ( x i ) ) L(y_i, F(x_i))= -\sum _{i=1}^ny_ilog\frac{1}{1+e^{-F(x_i)}}+(1-y_i)log(1-\frac{1}{1+e^{-F(x_i)}}) L(yi,F(xi))=−i=1∑nyilog1+e−F(xi)1+(1−yi)log(1−1+e−F(xi)1)
利用损失函数的负梯度作为残差的近似值(求导过程和逻辑回归一样,可参考逻辑回归算法博文,这里不再推导):
r m , i = − [ ∂ L ( y , F ( x i ) ) ∂ F ( x i ) ] F ( x ) = F m − 1 ( x ) = y i − 1 1 + e − F ( x i ) = y i − y ^ i r_{m,i}=-[\frac{\partial L(y,F(x_i))}{\partial F(x_i)}]_{F(x)=F_{m-1}(x)}=y_i-\frac{1}{1+e^{-F(x_i)}}=y_i-\hat y_i rm,i=−[∂F(xi)∂L(y,F(xi))]F(x)=Fm−1(x)=yi−1+e−F(xi)1=yi−y^i
利用残差近似值拟合回归树 g m g_m gm,对于生成的回归树 g m g_m gm,计算各叶子节点的最佳残差拟合值:
c m , j = a r g m i n c ∑ L ( y i , F m − 1 ( x i ) + g m ) c_{m,j}=argmin_c\sum L(y_i,F_{m-1}(x_i)+g_m) cm,j=argminc∑L(yi,Fm−1(xi)+gm)
由于上式比较复杂,很难优化,下面我们利用二阶泰勒展开式近似求解:
∑ L ( y i , F m − 1 ( x i ) + g m ) ≈ ∑ L ( y i , F m − 1 ( x i ) ) + ∂ L ( y i , F ( x i ) ) ∂ F ( x i ) g m + 1 2 ∂ 2 L ( y i , F ( x i ) ) ∂ F ( x i ) 2 g m 2 \sum L(y_i,F_{m-1}(x_i)+g_m) \approx \sum L(y_i,F_{m-1}(x_i))+\frac{\partial L(y_i,F(x_i))}{\partial F(x_i)}g_m+\frac{1}{2}\frac{\partial^2 L(y_i,F(x_i))}{\partial F(x_i)^2}g_m^2 ∑L(yi,Fm−1(xi)+gm)≈∑L(yi,Fm−1(xi))+∂F(xi)∂L(yi,F(xi))gm+21∂F(xi)2∂2L(yi,F(xi))gm2
为了简化推导,令 σ ( x i ) = 1 1 + e − F ( x i ) \sigma(x_i)=\frac{1}{1+e^{-F(x_i)}} σ(xi)=1+e−F(xi)1,其中 σ ( x i ) F ( x i ) = σ ( x i ) ( 1 − σ ( x i ) ) \frac{\sigma(x_i)}{F(x_i)}=\sigma(x_i)(1-\sigma(x_i)) F(xi)σ(xi)=σ(xi)(1−σ(xi))。
F ( x i ) F(x_i) F(xi)一阶导 ∂ L ( y , F ( x i ) ) ∂ F ( x i ) \frac{\partial L(y,F(x_i))}{\partial F(x_i)} ∂F(xi)∂L(y,F(xi)):
∂ L ( y , F ( x i ) ) ∂ F ( x i ) = ∂ L ( i , F ( x i ) σ ( x i ) ⋅ σ ( x i ) F ( x i ) \frac{\partial L(y,F(x_i))}{\partial F(x_i)}=\frac{\partial L(_i,F(x_i)}{\sigma(x_i)}\cdot \frac{\sigma(x_i)}{F(x_i)} ∂F(xi)∂L(y,F(xi))=σ(xi)∂L(i,F(xi)⋅F(xi)σ(xi)
= σ ( x i ) − y i =\sigma(x_i) -y_i =σ(xi)−yi
F ( x i ) F(x_i) F(xi)二阶导 ∂ 2 L ( y i , F ( x i ) ) ∂ F ( x i ) 2 \frac{\partial^2 L(y_i,F(x_i))}{\partial F(x_i)^2} ∂F(xi)2∂2L(yi,F(xi)):
∂ 2 L ( y i , F ( x i ) ) ∂ F ( x i ) 2 = ( σ ( x i ) − y i ) ′ = σ ( x i ) F ( x i ) \frac{\partial^2 L(y_i,F(x_i))}{\partial F(x_i)^2}=(\sigma(x_i) -y_i)'=\frac{\sigma(x_i)}{F(x_i)} ∂F(xi)2∂2L(yi,F(xi))=(σ(xi)−yi)′=F(xi)σ(xi)
= σ ( x i ) ( 1 − σ ( x i ) ) =\sigma(x_i)(1-\sigma(x_i)) =σ(xi)(1−σ(xi))
当损失函数取极值时,便可以利用二次方程求解思路对 g m ( x ) 求 解 g_m(x)求解 gm(x)求解。
g m = − b 2 a = − ∂ L ( y , F ( x i ) ) ∂ F ( x i ) 2 ∂ 2 L ( y i , F ( x i ) ) 2 ∂ F ( x i ) 2 = ∑ σ ( x i ) − y i ∑ σ ( x i ) ( 1 − σ ( x i ) ) g_m = -\frac{b}{2a}= -\frac{\frac{\partial L(y,F(x_i))}{\partial F(x_i)}}{2\frac{\partial^2 L(y_i,F(x_i))}{2\partial F(x_i)^2}}=\frac{\sum \sigma(x_i) -y_i}{\sum \sigma(x_i)(1-\sigma(x_i))} gm=−2ab=−22∂F(xi)2∂2L(yi,F(xi))∂F(xi)∂L(y,F(xi))=∑σ(xi)(1−σ(xi))∑σ(xi)−yi
又因为, r m , i = y i − σ ( x i ) r_{m,i}=y_i-\sigma(x_i) rm,i=yi−σ(xi),带入得最佳拟合值:
g m , j = ∑ r m , i ∑ ( y i − r m , i ) ( 1 − y i + r m , i ) g_{m,j}=\frac{\sum r_{m,i}}{\sum( y_i-r_{m,i})(1- y_i+r_{m,i})} gm,j=∑(yi−rm,i)(1−yi+rm,i)∑rm,i
有了最佳的拟合值,便可以进行下一次迭代了。
F m ( x ) = F m − 1 ( x ) + ∑ j = 1 J g m , j I ( x ∈ R m , j ) F_m(x)=F_{m-1}(x)+\sum_{j=1}^Jg_{m,j}I(x \in R_{m,j}) Fm(x)=Fm−1(x)+j=1∑Jgm,jI(x∈Rm,j)
对于二分类问题,GBDT的算法过程:
输入:训练数据集 D = { ( x i , y i ) } i = 1 n D=\left\{ (x_i,y_i) \right\}^n_{i=1} D={(xi,yi)}i=1n, x i ∈ R d x_i\in R^d xi∈Rd, y i ∈ { 0 , 1 } y_i\in\left\{ 0,1\right\} yi∈{0,1},损失函数 L ( y , f ( x ) ) L(y,f(x)) L(y,f(x))
输出:梯度提升回归树 h ( x ) h(x) h(x)
对于每一个样本 ( x i , y i ) (x_i,y_i) (xi,yi),利用损失函数负梯度计算残差近似值:
r m , i = − [ ∂ L ( y , F ( x i ) ) ∂ F ( x i ) ] F ( x ) = F m − 1 ( x ) = y i − 1 1 + e − F ( x i ) r_{m,i}=-[\frac{\partial L(y,F(x_i))}{\partial F(x_i)}]_{F(x)=F_{m-1}(x)}=y_i-\frac{1}{1+e^{-F(x_i)}} rm,i=−[∂F(xi)∂L(y,F(xi))]F(x)=Fm−1(x)=yi−1+e−F(xi)1
利用 { ( x i , r m , i ) } i = 1 , 2... n \left\{ (x_i,r_{m,i}) \right\}_{i=1,2...n} {(xi,rm,i)}i=1,2...n训练出第 m m m颗回归树 g m g_m gm,其中叶节点的区域为 R m , j , j = 1 , 2 , . . J m , J m R_{m,j},j=1,2,..J_m,J_m Rm,j,j=1,2,..Jm,Jm为第 m m m颗决策树叶子节点的个数。
利用回归树 g m g_m gm的每一个叶节点,计算最佳拟合值:
g m , j = ∑ r m , i ∑ ( y i − r m , i ) ( 1 − y i + r m , i ) g_{m,j}=\frac{\sum r_{m,i}}{\sum( y_i-r_{m,i})(1- y_i+r_{m,i})} gm,j=∑(yi−rm,i)(1−yi+rm,i)∑rm,i
更新 F m ( x ) = F m − 1 ( x ) + ∑ j = 1 J g m , j I ( x ∈ R m , j ) F_m(x)=F_{m-1}(x)+\sum_{j=1}^Jg_{m,j}I(x \in R_{m,j}) Fm(x)=Fm−1(x)+∑j=1Jgm,jI(x∈Rm,j)
下面对GBDT算法进行总结:
优点
缺点
下篇我们一起探讨sklearn中GBDT算法的使用。
(欢迎大家在评论区探讨交流,也欢迎大家转载,转载请注明出处!)
上篇:Scikit-learn AdaBoost算法库总结与实践
下篇:Scikit-learn GBDT算法库总结与实践