GBDT算法原理

GBDT算法既能解决回归问题,也能解决分类问题。本文从回归和分类角度解析GBDT原理,介绍GBDT如何通过一系列CART回归树拟合残差,逐步减小预测误差。文章还探讨了GBDT在不同损失函数下的表现,包括对异常值的敏感性,并讨论了正则化策略以防止过拟合。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

GBDT即可用于解决回归问题,也能用于解决分类问题。在初步理解GBDT时,最好从回归和分类的角度分别理顺思路,发现其中的不同和关键点,就能初步明白GBDT的算法原理。接下来从回归和分类的角度分别记录下:

1、回归的角度——初步:

GBDT的思想可以用一个通俗的例子解释,假如有个人30岁,我们首先用20岁去拟合,发现损失有10岁,这时我们用6岁去拟合剩下的损失,发现差距还有4岁,第三轮我们用3岁拟合剩下的差距,差距就只有一岁了。如果我们的迭代轮数还没有完,可以继续迭代下面,每一轮迭代,拟合的岁数误差都会减小。

直观的解释:GBDT是一系列回归树(CART)的加法组合,后一颗树拟合之前预测结果与目标的“残差”。具体说明如下:假设样本集 D=(x_{1},y_{1}), (x_{2},y_{2}),...,(x_{n},y_{n}) ,第一轮用一个模型,如 F(x) 去拟合这些数据,使得这批样本的平方损失函数(即 \frac{1}{2}\sum_{i=1}^{n}({y_{i}- F(x_{i})})^2 )最小。但是发现虽然模型的拟合效果很好,但仍然有一些差距,比如预测值 F(x_{1})=0.8,而真实值 y_{1}=0.9F(x_{2})=1.4 ,y_{2}=1.3等等。第二轮用一个新的模型 f(x) 来拟合 F(x) 未完全拟合真实样本的残差,即 y-F(x) 。所以对于每个样本来说,拟合的样本集就变成了: (x_{1},y_{1}-F(x_{1})), (x_{2},y_{2}-F(x_{2})),...,(x_{n},y_{n}-F(x_{n})) 。依次类推第三轮、第四轮,……,直到满足终止条件,将所有学得的模型相加得到最终的结果,这就是GBDT。

 ({y_{i}- F(x_{i})}) 被称为残差,这一部分也就是前一模型F({x_{i}})未能完全拟合的部分,所以交给新的模型来完成。GBDT的全称是Gradient Boosting Decision Tree,其中gradient被称为梯度,更一般的理解,可以认为是一阶导,那么这里的残差与梯度是什么关系呢。在第一部分,我们提到了一个叫做平方损失函数的东西,具体形式可以写成 \frac{1}{2}\sum_{i=1}^{n}({y_{i}- F(x_{i})})^2 ,熟悉其他算法的原理应该知道,这个损失函数主要针对回归类型的问题,分类则是用熵值类的损失函数。具体到平方损失函数的式子,它的一阶导其实就是残差的形式,所以基于残差的GBDT是一种特殊的GBDT模型,它的损失函数是平方损失函数,只能处理回归类的问题。具体形式可以如下表示:

损失函数:L(y,F(x)) = \frac{1}{2}(y-F(X))^{2}

所以我们想最小化J = \frac{1}{2}\sum_{0}^{n}{}(y_{i}-F(x_{i}))^{2}

损失函数的一阶导:\frac{\partial J}{\partial F({x}) }=\frac{\partial \sum_{i=1}^{n}(L(y_{i},F(x_{i})))}{\partial F({x_{i}}) }= \frac{\partial L(y_{i},F(x_{i}))}{\partial F({x_{i}}) }=F(x_{i})-y_{i}

 

正好残差就是负梯度:-\frac{\partial J}{\partial F({x_{i}}) }=y_{i} - F(x_{i})

1.1为什么基于残差的GBDT不是一个好的选择

首先基于残差的GBDT只能处理回归类的问题,不能处理分类问题,这是损失函数所限制的,所以更一般化的GBDT是基于梯度的算法,这也就意味着只要给出的损失函数是可导的,那么就能用GBDT的思想去解决问题。具体解决的问题就不会仅仅限于回归了。

另外,基于残差的GBDT在解决回归问题上也不算是一个好的选择,一个比较明显的缺点就是对异常值过于敏感。来看一个例子(注:这个和本文要介绍的内容关系不是很大,只是在这个位置涉及到了,举个例子说明下损失函数的优劣对比,证明下基于残差的GBDT不是最好的选择。为啥是残差,其根源是损失函数选择了平方损失函数):

很明显后续的模型会对第4个值关注过多,这不是一种好的现象,所以一般回归类的损失函数会用绝对损失或者huber损失函数来代替平方损失函数:


以上从回归的角度,以特例的方式初步对GBDT进行了解释(平方损失函数)。接下从回归的角度进一步深入解释,得到通用的GBDT(负梯度)


2、回归的角度——深入:

2.1、GBDT的负梯度拟合

GBDT也是集成学习Boosting家族的成员,但是却和传统的Adaboost有很大的不同。回顾下Adaboost,我们是利用前一轮迭代弱学习器的误差率来更新训练集的权重,这样一轮轮的迭代下去。GBDT也是迭代,使用了前向分布算法,但是弱学习器限定了只能使用CART回归树模型,同时迭代思路和Adaboost也有所不同。在GBDT的迭代中,假设我们前一轮迭代得到的强学习器是f_{t-1}(x), 损失函数是L(y,{f_{t-1}(x)}), 本轮迭代的目标是找到一个CART回归树模型的弱学习器h_{t}(x),让本轮的损失函数L(y, f_{t}(x)) = L(y,{f_{t-1}(x)+h_{t}(x)})最小。也就是说,本轮迭代找到决策树,要让样本的损失尽量变得更小。从上面的例子看这个思想还是蛮简单的,但是有个问题是这个损失的拟合不好度量,损失函数各种各样,怎么找到一种通用的拟合方法呢?

上一段中介绍了GBDT的基本思路,但是没有解决损失函数拟合方法的问题?。针对这个问题,大牛Freidman提出了用损失函数的负梯度来拟合本轮损失的近似值,进而拟合一个CART回归树。第t轮的第i个样本的损失函数的负梯度表示为

{r_{ti}}=-[\frac{\partial L(y_{i},f(x_{i}))}{\partial f(x_{i})}]_{f(x)=f_{t-1}(x)}

利用(x_{i},r_{ti}) (i=1,2,...,n),可以拟合一颗CART回归树,得到的第t棵回归树,其对应的叶节点区域{R_{tj}}, j=1,2,...,J。其中J为叶子节点的个数。针对每一个叶子节点里的样本,求出使损失函数最小,也就是拟合叶子节点最好的的输出值c_{tj}如下(注:这里的c代表的是未知变量,其求得的使损失函数L最小的值是c_{tj}):

                                                           c_{tj} = argmin\sum_{x_{i}\epsilon {R_{tj}}}{L(y_{i},f_{t-1}(x_{i})}+c)

这样就得到了本轮的决策树拟合函数如下:

                                                                             h_{t}(x)= \sum_{j=1}^{J}c_{tj}I(x\epsilon {R_{tj}})

经过本轮(第 t 轮)学习后得到的强学习器的表达式如下:

                                                                   f_{t}(x)= f_{t-1}(x) + \sum_{j=1}^{J}c_{tj}I(x\epsilon {R_{tj}})

通过损失函数的负梯度来拟合,找到了一种通用的拟合损失误差的办法,这样无轮是分类问题还是回归问题,通过其损失函数的负梯度的拟合,就可以用GBDT来解决分类和回归问题。区别仅仅在于损失函数不同导致的负梯度不同而已。

2.2、GBDT回归算法

    基于上面的思路,下面总结下GBDT的回归算法。为什么没有加上分类算法一起?因为分类算法的输出是不连续的类别值,需要一些处理才能使用负梯度(定义损失函数时处理,我认为没啥区别,其本质是损失函数的设计,因为分类问题不能一步步拟合“残差”,以LR的对数似然函数作为损失函数来拟合“残差”,其本质是用类别的预测概率值来拟合正确的概率值),下一节讲。输入是训练集样本D={(x_{1},y_{1}),(x_{2},y_{2}),...,(x_{n},y_{n})}, 最大迭代次数T, 损失函数L

输出是强学习器f(x)

    1) 初始化弱学习器(这里初始化一个c的值,通常为所有样本点的平均值)

                                               f_{0}(x)=argmin\sum_{i=1}^{n}L(y_{i},c)

    2) 对迭代轮数 t=1,2,...,T 有:

      a)对样本 i=1,2,...,n,计算负梯度

                                           {r_{ti}}=-[\frac{\partial L(y_{i},f(x_{i}))}{\partial f(x_{i})}]_{f(x)=f_{t-1}(x)}

      b)利用(x_{i},r_{ti}) (i=1,2,...,n),拟合一颗CART回归树,得到第 t 颗回归树,其对应的叶子节点区域为R_{tj}, j=1,2,...,J。其中J为回归树 t 的叶子节点的个数。

      c) 对叶子区域j =1,2,3,...,J,计算最佳拟合值

                                        c_{tj} = argmin\sum_{x_{i}\epsilon {R_{tj}}}{L(y_{i},f_{t-1}(x_{i})}+c)

      d) 更新强学习器

                                           f_{t}(x)= f_{t-1}(x) + \sum_{j=1}^{J}c_{tj}I(x\epsilon {R_{tj}})

    3) 得到强学习器f(x)的表达式

                                     f(x)=f_{T}(x)=f_{0}(x)+\sum_{t=1}^{T}\sum_{j=1}^{J}{c_{tj}}I(x\epsilon {R_{tj}})

3、分类的角度:

3.1、GBDT分类算法

    接着再看看GBDT分类算法,GBDT的分类算法从思想上和GBDT的回归算法没有区别,但是由于样本输出不是连续的值,而是离散的类别,导致无法直接从输出类别去拟合类别输出的误差。为了解决这个问题,主要有两个方法,一个是用指数损失函数,此时GBDT退化为Adaboost算法。另一种方法是用类似于逻辑回归的对数似然损失函数的方法。也就是说,用的是类别的预测概率值和真实概率值的差来拟合损失。接下来讨论用对数似然损失函数的GBDT。而对于对数似然损失函数,又有二元分类和多元分类的区别。

3.2 二元GBDT分类算法

对于二元GBDT,如果用类似于逻辑回归的对数似然损失函数,则损失函数为:

                                                L(y,f(x))=log(1 + exp(-yf(x)))

其中y\epsilon\left \{ \right -1,+1\}。则此时的负梯度误差为

                                r_{ti}= -[\frac{\partial L(y,f(x))}{\partial f(x)}]_{f(x)=f_{t-1}(x)}=\frac{y_{i}}{1+exp(y_{i}f(x_{i})))}

对于生成的决策树,各个叶子节点的最佳残差拟合值为

                                  c_{tj}=argmin\sum_{x_{i}\epsilon R_{tj}}(log(1+exp(y_{i}f_{t-1}(x_{i}+c))))

由于上式比较难优化,一般使用近似值代替

                                                  c_{tj}=\frac{\sum_{x_{i\epsilon R_{tj}}}^{ }r_{ti}}{\sum_{x_{i\epsilon R_{tj}}}^{ }|r_{ti}|*(1-|r_{ti}|)}

除了负梯度计算和叶子节点的最佳残差拟合的线性搜索,二元GBDT分类和GBDT回归算法过程相同?

3.3、多元GBDT分类算法

  参见:https://www.cnblogs.com/pinard/p/6140514.html

4、GBDT常用损失函数

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

    a) 如果是指数损失函数,则损失函数表达式为

                                                                              L(y,f(x)) = exp(-yf(x))

    其负梯度计算和叶子节点的最佳残差拟合参见Adaboost原理篇

    b) 如果是对数损失函数,分为二元分类和多元分类两种,参见3.1节和3.2节。 

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

    a)均方差,这个是最常见的回归损失函数

                                                                             L(y,f(x))=(y-f(x))^2

    b)绝对损失,这个损失函数也很常见

                                                                              L(y,f(x))=|y-f(x)|

                    对应负梯度误差为:

                                                                                   sign(y_{i}-f(x_{i}))

    c)Huber损失,它是均方差和绝对损失的折衷产物,对于远离中心的异常点,采用绝对损失,而中心附近的点采用均方差。这个界限一般用分位数点度量。损失函数如下:

                                              

    对应的负梯度误差为:

                                                  

    d) 分位数损失。它对应的是分位数回归的损失函数,表达式为

                                             

      其中θθ为分位数,需要我们在回归前指定。对应的负梯度误差为:

                                                        

    对于Huber损失和分位数损失,主要用于健壮回归,也就是减少异常点对损失函数的影响。

5. GBDT的正则化

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

第一种是和Adaboost类似的正则化项,即步长(learning rate)。定义为νν,对于前面的弱学习器的迭代

                                                                           f_{t}(x) = f_{t-1}(x)+h_{t}(x)

如果加上了正则化项(v的取值范围为00< v\leq 1。对于同样的训练集学习效果,较小的v意味着需要更多的弱学习器的迭代次数。通常用步长和迭代最大次数一起来决定算法的拟合效果。),则有:

                                                                        f_{t}(x) = f_{t-1}(x)+v*h_{t}(x)

第二种正则化的方式是通过子采样比例(subsample)。取值为(0,1]。注意这里的子采样和随机森林不一样,随机森林使用的是放回抽样,而这里是不放回抽样。如果取值为1,则全部样本都使用,等于没有使用子采样。如果取值小于1,则只有一部分样本会去做GBDT的决策树拟合。选择小于1的比例可以减少方差,即防止过拟合,但是会增加样本拟合的偏差,因此取值不能太低。推荐在[0.5, 0.8]之间。使用了子采样的GBDT有时也称作随机梯度提升树(Stochastic Gradient Boosting Tree, SGBT)。由于使用了子采样,程序可以通过采样分发到不同的任务去做boosting的迭代过程,最后形成新树,从而减少弱学习器难以并行学习的弱点(不理解!不是还是要串行的训练?)。

第三种是对于弱学习器即CART回归树进行正则化剪枝。

6、其他:

1、GBDT有很多简称,有GBT(Gradient Boosting Tree), GTB(Gradient Tree Boosting ), GBRT(Gradient Boosting Regression Tree), MART(Multiple Additive Regression Tree),其实都是指的同一种算法,本文统一简称GBDT。GBDT在BAT大厂中也有广泛的应用。

7、参考文献:

1、https://zhuanlan.zhihu.com/p/29765582

2、https://www.cnblogs.com/pinard/p/6140514.html(主要复制自这篇blog)

8、遗留问题

1、GBDT用于多分类的公式推导。

2、正则化的第二种,不甚理解。

3、损失函数选择为指数函数,退化为Adaboost?

### GBDT算法原理 GBDT(Gradient Boosting Decision Tree)是一种基于决策树的Boosting方法,其核心思想在于通过迭代优化决策树的预测误差来逐步构建模型[^1]。具体来说,在每一轮迭代中,当前模型的残差被当作目标变量用于拟合下一棵树,从而使得新加入的树能够尽可能减少整体损失函数。 #### 损失函数与梯度下降 GBDT的核心机制依赖于可微分的损失函数以及梯度下降的思想。对于给定的目标值 \( y \),模型预测值记作 \( F(x) \),则定义一个损失函数 \( L(y, F(x)) \)[^3]。为了最小化该损失函数,GBDT采用负梯度方向作为伪残差: \[ r_{i}^{(m)} = -\left[\frac{\partial L(y_i, F(x_i))}{\partial F(x_i)}\right]_{F(x)=F_{m-1}(x)} \] 其中,\( r_{i}^{(m)} \) 表示第 \( m \) 轮迭代时样本 \( i \) 的伪残差;\( F_{m-1}(x) \) 是前 \( m-1 \) 棵树所构成的模型。 #### CART回归树的作用 在GBDT框架下,每一棵新增加的树都是用来拟合上述计算得到的伪残差。由于CART回归树具有较强的表达能力,并且可以通过分裂节点捕捉复杂的非线性关系,因此非常适合用作弱学习器。 另外值得注意的是,尽管单一棵决策树可能存在较大方差,但在集成过程中这种高方差特性反而有助于提高整个系统的泛化性能。 ### 公式推导过程 假设我们已经拥有了由 \( M-1 \) 颗树组成的初步模型: \[ F_{M-1}(x) = \sum_{m=1}^{M-1} h_m(x), \] 现在要寻找新的基分类器 \( h_M(x) \) 来改进现有模型。为此我们需要解决如下最优化问题: \[ h_M=\argmin_h\sum_{i=1}^N L(y_i,F_{M-1}(x_i)+h(x_i)). \] 然而直接求解此问题是困难的,所以转而考虑泰勒展开近似处理。当只保留到二阶项的时候可以写成下面形式: \[ L'(y_i,z)\approx g_il+h(z), \] 这里 \(g_i\) 和 \(h_i\) 分别代表一阶导数和二阶导数关于z处取值的结果。进一步简化后得出更新规则为: ```python def update_rule(gamma_j): numerator = sum([gi for gi in gradients if instance_in_region]) denominator = sum([(hi + lambda_reg)*indicator(instance_in_region)]) gamma_j = -numerator / (denominator + epsilon) ``` 以上代码片段展示了如何利用局部区域内的梯度信息调整叶节点权重参数gamma_j的过程。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值