GBDT又称梯度提升树,是传统机器学习中效果最好的模型之一。在介绍GBDT之前,我们先来看一下回归问题的提升树算法。
对于回归任务,我们的基学习器自然也应该设置为适用于回归任务的模型,因此选用CART回归树。并且与用于分类的提升树不同的是,我们的损失函数从指数损失变成了均方误差损失。假设我们的回归树有 J J J个叶子节点 R j R_j Rj,每个叶子节点的输出值为 c j c_j cj,那么这棵树可以表示为:
T ( x ; θ ) = ∑ j = 1 J c j I ( x ∈ R j ) T(x;\theta)\ =\ \sum_{j=1}^{J}c_jI(x \in R_j) T(x;θ) = j=1∑JcjI(x∈Rj)
然后假设我们的损失函数选用均方误差损失,即 L ( y , f ( x ) ) = ( y − f ( x ) ) 2 L(y,f(x))\ =\ (y\ -\ f(x))^2 L(y,f(x)) = (y − f(x))2,于是我们在第 t t t轮迭代所找到的最优的回归树就应该满足:
θ t = a r g m i n θ ∑ i = 1 N L ( y i , f t − 1 ( x i ) + T ( x i ; θ ) ) \theta_t\ =\ argmin_{\theta}\ \ \sum_{i=1}^{N}L(y_i,\ f_{t-1}(x_i)+T(x_i;\theta)) θt = argminθ i=1∑NL(yi, ft−1(xi)+T(xi;θ))
以上是我们对每轮迭代单棵回归树拟合的过程。下面看整个算法流程。
具体算法流程如下:
输入:数据集 D D D
输出:提升树 f T ( x ) f_T(x) fT(x)
(1) 初始化 f 0 ( x ) = 0 f_0(x) = 0 f0(x)=0
(2) 对于 t = 1 , 2 , . . . , T t=1,2,...,T t=1,2,...,T
(a) 计算残差 r t i = y i − f t − 1 ( x i ) r_{ti}\ =\ y_i\ -\ f_{t-1}(x_i) rti = yi − ft−1(xi)
(b) 用残差代替原来的 y y y,即用 D = { ( x i , r t i ) } D\ =\ \{(x_i,r_{ti})\} D = {(xi,rti)}来拟合一棵回归树,得到 θ t \theta_t θt,并得到该回归树的叶节点区域 R t j , j = 1 , 2 , … , J R_{tj},\ j=1,2,\dots,J Rtj, j=1,2,…,J
© 对于 j = 1 , 2 , … , J j \ =\ 1,2,\dots,J j = 1,2,…,J,计算
c t j = a r g m i n c ∑ i = 1 N L ( y i , f t − 1 ( x i ) + c ) c_{tj}\ =\ argmin_{c}\ \sum_{i=1}^{N}L(y_i, \ f_{t-1}(x_i)\ +\ c) ctj = argminc ∑i=1NL(yi, ft−1(xi) + c)
(d) 更新 f t ( x ) = f t − 1 ( x ) + ∑ j = 1 J c t j I ( x ∈ R t j ) f_t(x) \ =\ f_{t-1}(x) + \sum_{j=1}^{J}c_{tj}I(x \in R_{tj}) ft(x) = ft−1(x)+∑j=1JctjI(x∈Rtj)
(3) 得到提升树模型:
f M ( x ) = ∑ t = 1 T ∑ j = 1 J c t j I ( x ∈ R t j ) f_M(x)\ =\ \sum_{t=1}^T \sum_{j=1}^{J}c_{tj}I(x \in R_{tj}) fM(x) = ∑t=1T∑j=1JctjI(x∈Rtj)
下面来看GBDT。对于指数损失函数和均方误差损失来说,优化是比较容易的,但对于一般的损失函数来说,优化并不容易,因此 F r i e d m a n Friedman Friedman提出了一个解决方法,即使用损失函数的负梯度作为残差进行拟合。
具体算法流程如下:
输入:数据集 D D D
输出:提升树 f T ( x ) f_T(x) fT(x)
(1) 初始化 f 0 ( x ) = a r g m i n c ∑ i = 1 N L ( y i , c ) f_0(x) = argmin_c\sum_{i=1}^{N}L(y_i,c) f0(x)=argminc∑i=1NL(yi,c)
(2) 对于$t=1,2,\dots,T $
(a) 计算残差 r t i = − ∂ L ( y i , f ( x i ) ) ∂ f ( x i ) r_{ti}\ =\ -\frac{\partial L(y_i, f(x_i))}{\partial f(x_i)} rti = −∂f(xi)∂L(yi,f(xi))
(b) 用残差代替原来的 y y y,即用 D = { ( x i , r t i ) } D\ =\ \{(x_i,r_{ti})\} D = {(xi,rti)}来拟合一棵回归树,得到 θ t \theta_t θt
© 更新 f t ( x ) = f t − 1 ( x ) + T ( x ; θ t ) f_t(x) \ =\ f_{t-1}(x) + T(x;\theta_t) ft(x) = ft−1(x)+T(x;θt)
(3) 得到提升树模型: f M ( x ) = ∑ t = 1 T T ( x ; θ t ) f_M(x)\ =\ \sum_{t=1}^T T(x;\theta_t) fM(x) = ∑t=1TT(x;θt)
其实这里所展示的GBDT主要适用于回归任务。
我们下面来讲一下分类问题,其实我们仍然可以用残差拟合的办法来做分类,只不过这里的残差是真实类标记与预测概率之间的残差。之前我们说提升树模型本质区别还是体现在损失函数上,那么对于分类问题,我们的损失函数无外乎就那么几种。假如使用的是指数损失函数,那么GBDT就退化到了AdaBoost。这里我们介绍采用对数似然函数作为损失函数的做法。
这里所谓的对数似然函数其实就是 s i g m o i d sigmoid sigmoid取对数,仿照了逻辑回归。
L ( y , f ( x ) ) = l o g ( 1 + e x p ( − y f ( x ) ) ) L(y,\ f(x))\ =\ log(1\ +\ exp(-yf(x))) L(y, f(x)) = log(1 + exp(−yf(x)))
剩下的步骤其实和我们上面的流程是完全一致的。只不过此时我们的优化会比较困难,即
c t j = a r g m i n c ∑ i = 1 N L ( y i , f t − 1 ( x i ) + c ) c_{tj}\ =\ argmin_{c}\ \sum_{i=1}^{N}L(y_i, \ f_{t-1}(x_i)\ +\ c) ctj = argminc i=1∑NL(yi, ft−1(xi) + c)
这一步不好优化,因此通常用近似值代替
c t j = ∑ x i ∈ R t j r t j ∑ x i ∈ R t j ∣ r t j ∣ ( 1 − ∣ r t j ∣ ) c_{tj}\ =\ \frac{\sum_{x_i \in R_{tj}}r_{tj}}{\sum_{x_i \in R_{tj}}|r_{tj}|(1-|r_{tj}|)} ctj = ∑xi∈Rtj∣rtj∣(1−∣rtj∣)∑xi∈Rtjrtj
那么对于多分类问题,其实这个规律也就摸索出来了,对症下药,采用的是CrossEntropy作为损失函数
L ( y , f ( x ) ) = − ∑ k = 1 K y i l o g ( p k ( x ) ) L(y,\ f(x))\ =\ -\sum_{k=1}^K{y_ilog(p_k(x))} L(y, f(x)) = −k=1∑Kyilog(pk(x))
其中 p k ( x ) p_k(x) pk(x)表示 x x x输入第 k k k类的概率,用softmax来计算
p k ( x ) = e x p ( f k ( x ) ) ∑ l = 1 K e x p ( f l ( x ) ) p_k(x)\ =\ \frac{exp(f_k(x))}{\sum_{l=1}^K exp(f_l(x))} pk(x) = ∑l=1Kexp(fl(x))exp(fk(x))
此时,我们的计算的是第 t t t轮迭代第 i i i个样本对类别 k k k的负梯度,即:
r t i k = − ∂ L ( y i , f ( x i ) ) ∂ f ( x i ) = y i k − p k , t − 1 ( x ) r_{tik}\ =\ -\frac{\partial L(y_i, f(x_i))}{\partial f(x_i)}\ =\ y_{ik}\ -\ p_{k, t-1}(x) rtik = −∂f(xi)∂L(yi,f(xi)) = yik − pk,t−1(x)
对于生成的决策树,我们各个叶子节点的最佳负梯度拟合值为:
由于上式比较难优化,我们一般使用近似值代替
GBDT有三种正则化方法: