从提升树出发,——》回归提升树、二元分类、多元分类三个GBDT常见算法。
提升树
在说GBDT之前,先说说提升树(boosting tree)。说到提升(boosting),总是绕不过AdaBoost。
AdaBoost是利用前一轮迭代的误差率来更新训练集的权重,校正前一轮迭代被错误分类的样本,通俗一点的理解就是将重心放在分错的样本上。提升树也是boosting家族的成员,意味着提升树也采用加法模型(基学习器线性组合)和前向分步算法。
下面一个一个进行解释,提升树的基学习器是什么,加法模型和前向分步算法又是怎么用的。
提升树通常以决策树作为基学习器,对分类问题决策树是二叉分类树,回归问题就是二叉回归树。
加法模型,就是说提升树可以表示为以下形式:这里我们约定 T(x;Θm)表示第m棵决策树;Θm表示决策树的参数;M为树的个数。强分类器fM(x)可以由多个弱分类器T(x;Θm)线性相加而成。
fM(x)=M∑m=1T(x;Θm)
提升树的前向分步算法。第m步的模型可以写成:
fm(x)=fm−1(x)+T(x;Θm)
然后得到损失函数
L(fm(x),y)=L(fm−1(x)+T(x;Θm),y)
迭代的目的是构建T(x;Θm),使得本轮损失L(fm(x),y)最小。思想其实并不复杂,但是问题也很明显,对于不同的任务会有不同的损失函数,当损失函数是平方损失和指数损失函数时,每一步的优化还是简单的。但是对于一般损失函数而言,每一步的优化并不容易。
梯度提升树
下面关于GBDT的理解来自论文greedy function approximation: a gradient boosting machine
- 损失函数的数值优化可以看成是在函数空间,而不是在参数空间。
- 损失函数L(y,F)包含平方损失(y−F)2,绝对值损失|y−F|用于回归问题,负二项对数似然log(1+e−2yF),y∈{-1,1}用于分类。
- 关注点是预测函数的加性扩展。
最关键的点在于损失函数的数值优化可以看成是在函数空间而不是参数空间。怎么理解呢?
首先,我们已经知道强分类器是由多个弱分类器线性相加而成,那么可以写成如下形式:
F(x;{βm,am}M1)=M∑m=1βmh(x;am)
这里的h(x;am)指代回归树,例如CART。am是模型参数,这里指代每个节点的分裂特征(变量),最佳分割点,节点的预测值。M就是有多少个弱分类器。
然后,我们来回顾一下参数空间的数值优化。假设预测函数为F(x;P),那么损失函数就可以写成:
ϕ(P)=L(y,F(x,P))
优化以后得到的参数最优解为:
P =argminPϕ(P)
回想一下SGD(随机梯度下降)的优化方式,从山顶上选择梯度下降最快的方向挪动最优步长。我们是不是可以把最优参数表达成这个形式?
P =M∑m=0pm
pm=−ρmgm
从初始值p0开始,m对应每一步更新迭代,负梯度−gm就是最速下降方向,ρm就是在这个最速下降方向上进行线搜索得到的最优步长。
好了,现在我们说说函数空间的优化方法。
将预测函数F(x)对应参数P,最优解变成了:
F(x)=M∑m=0fm(x)
相当于在函数空间上作梯度下降。每一步梯度下降:
fm(x)=−ρmgm(x)
gm(x)=[−∂ϕ(F(x))∂F(x)]F(x)=Fm−1(x)
Fm−1(x)=m−1∑i=0fi(x)
现在把这个思想代入到gradient boosting,我们之前已经得到预测函数为:
F(x;{βm,am}M1)=M∑m=1βmh(x;am)
需要做的事情是得到预测函数的最优解,就是:
{βm,am}M1=argmin{βm,am}M1L(y,M∑m=1βmh(x;am))=argminβm,amL(y,Fm−1(x)+βmhm(x;am))
已知最速梯度下降方向为gm(x)=[−∂ϕ(F(x))∂F(x)]F(x)=Fm−1(x),每一个hm(x;am)都建立在最速梯度下降的方向,我们可以得到:
am=argminβm,am[−gm(x)−βmhm(x;am)]2
可以认为是用hm(x;a)去拟合伪标签~y=−gm(x)。这里为什么用最小二乘,我的理解是GBDT构造的树全是回归树,因此用最小二乘。
然后进行线搜索确定最优步长ρm:
ρm=argminρmL(y,Fm−1(x)+ρmhm(x;am))
Fm(x)=Fm−1(x)+ρmhm(x;am)
ok,现在来整理整个算法流程:
- 初始化:F0(x)=argmixρ∑Ni=1L(yi,ρ) ,N表示样本量
- For m=1 to M do:end for
- ~y=−[∂ϕ(F(x))∂F(x)]F(x)=F(m−1)(x),i=1,2,……,N
- am=argminβ,a∑Ni=1[~y−βhm(xi;a)]2
- ρm=argminρ∑Ni=1L(yi,Fm−1(xi)+ρhm(xi;am))
- Fm(x)=Fm−1(x)+ρmhm(x;am)
回归提升树
当基学习器h(x;a)是一个包含J个节点的回归树时,可以写成:
h(x;a)=h(x;{cj,Rj}J1)=J∑j=1cjI(X∈Rj)
写完公式发现原来可以写的这么复杂,简单点说就是,对于回归树h,如果x被归到某个叶子节点Rj,那么x在这个h中得到的预测值就是叶子节点Rj的值cj。一般用叶子节点上 {xi∈Rj}J1的{~yi}J1平均值近似节点Rj的值
cj=avexi∈Rj~yi
{Rj}J1是不相交的区域,集合覆盖预测值的空间。{cj}J1可以认为是回归树h的系数。什么意思?我们回想一下线性回归,预测函数是θTx,这个θ就是模型系数。同样的,也可以这么理解{cj}J1,是回归树h的系数。
ok,现在我们已经得到了回归提升树的预测函数:
Fm(x)=Fm−1(x)+ρmJ∑j=1cm,jI(x∈Rj)
令γm,j=ρmcm,j,这个值是叶子节点的最理想的常数更新值,也可以认为兼顾了下降方向和下降步长。
综上,整理一下回归提升树的整个算法流程:
- 输入:训练数据集T={(x1,y1),(x2,y2),……,(xN,yN)},迭代次数M
- 1. 初始化:F0(x)=argminρ∑Ni=1L(y,ρ) ,N表示样本量
- 2. For m=1 to M do:
- (a) 计算损失函数在当前模型Fm−1(x)的负梯度值:
~y=−[∂ϕ(F(x))∂F(x)]F(x)=Fm−1(x)=yi−Fm−1(xi),i=1,2,……,N
-
- (b) 根据~yi学习得到了第m棵回归树,对应的叶节点区域为{Rj}J1
- (c) γm,j=argminγ∑xi∈Rm,jL(yi,Fm−1(xi)+γ)
- (d) 得到本轮最佳拟合决策树为:
hm(x;a)=J∑j=1γm,jI(x∈Rm,j)
Fm(x)=Fm−1(x)+J∑j=1γm,jI(x∈Rm,j)
FM(x)=M∑m=1J∑j=1γm,jI(x∈Rm,j)
当当当~看到第3点,我们发现损失函数在当前模型Fm−1(x)的负梯度值刚刚好是y−Fm−1(x),也就是我们常说的残差!看到这里有没有很激动?这不就是我们常说的GBDT是在拟合前几轮迭代的残差吗?
下面给出证明:
令当前的预测函数模型为Fm−1(x),下一棵要学习的回归树为hm(x;a),则下一步要学习的预测函数为:
Fm(x)=Fm−1(x)+hm(x;am)
回归提升树的损失函数为平方损失:
Loss=L(Fm(x),y)=12(Fm(x)−y)2
对Fm(x)求关于am的偏导:
∂Loss∂am=(Fm(x)−y)=Fm−1(x)+hm(x;am)−y
我们要使经验风险极小化,令偏导为0:
hm(x;am)=y−Fm−1(x)
也就是说,构建的回归树要去拟合前面的残差,得证。可以这么理解,GBDT是在函数空间的梯度下降求最优值,当损失函数为平方损失时,恰好去拟合了残差。
下面给一个简单的例子方便理解,现在要通过购物金额和上网时长来预测年龄。假设有5个训练样本,标签分别14,17,13,25,27。第m轮迭代,通过前几轮的残差构建决策树,得到预测函数Fm(x)的预测年龄分别为16,15,12,19,29,计算残差-2,2,1,6,-2。第m+1轮迭代,就去学习这个残差,通俗一点说就是以残差作为第i+1轮迭代构建决策树的标签。
二元分类
我们使用负二项对数似然作为损失函数:
L(y,F)=log(1+exp(−2yF)),y∈{1,1}
其中,F(x)=12log[P(y=1|x)P(y=−1|x)]
看这个公式有没有很熟悉?是的,这个负二项对数似然可以推到逻辑回归的损失函数。
我们知道逻辑回归的预测函数为:
P(y=1|x)=11+exp(−θTx),y∈{0,1}
我们知道这里的负样本y=-1对应于逻辑回归里的负样本y=0,所以有:
F(x)=12log[P(y=1|x)P(y=−1|x)]=12log[P(y=1|x)P(y=0|x)]=12θTx
将上式代入L(y,F),可得L(y,F)=log(1+exp(−2yF))=log(1+exp(−yθTx)),y∈{−1,1}
当y=1时,L(y,F)=log(1+exp(−θTx))=ylog(1+exp(−θTx))=ylog(P(y=1|x))
当y=-1时,L(y,F)=log(1+exp(θTx))=log(1−P(y=1|x))
令y←0,L(y,F)=(1−y)log(1−P(y=1|x))
结合在一起,可以写成:
L(y,F)=ylog(P(y=1|x))+(1−y)log(1−P(y=1|x)),y∈{0,1}
与逻辑回归损失函数一致,得证。
预测函数Fm−1(x)的当前负梯度值,也可以说是伪响应~y为:
~y=−[∂L(F(x),y)∂F(x)]F(x)=Fm−1(x)=2y1+exp(2yFm−1(x))
我们仍然将回归树作为基学习器,进行线搜索得到最优叶子节点值:
γm,j=argminy∑x∈Rm,jlog(1+(−2y(Fm−1(x)+γ)))
一看这个公式就知道计算量不是一般的大,我们用[Newton-Raphson近似][2],得到:
γm,j=∑x∈Rm,j~yi∑x∈Rm,j|~yi|(2−|~y|)
总结一下算法流程如下:
- 1. 初始化:F0(x)=argmixρ∑Ni=1L(y,ρ) ,N表示样本量
- 2. For m=1 to M do:3. end For
- (a) ~yi=2yi1+exp(2yiFm−1(xi)),i=1,2,……,N
- (b) 根据~yi学习得到了第m棵回归树,对应的叶节点区域为{Rj}J1
- (c) γm,j=∑x∈Rm,j~yi∑x∈Rm,j|~yi|(2−|~yi|)
- (d) Fm(x)=Fm−1(x)+∑Jj=1γm,jI(x∈Rm,j)
最后,我们得到了预测函数FM(x),用来进行概率估计:
P(y=1|x)=p=e2F(x)1+e2F(x)=11+e−2F(x)
P(y=−1|x)=1−p=11+e2F(x)
有了概率之后,我们可以对样本进行分类。
多元分类
我们使用多分类log损失作为损失函数:
L(y,F)=−K∑k=1yklogpk(x)
对应的概率pk(x)为(就是softmax):
pk(x)=eFk(x)∑Kl=1eFl(x)
对于多分类问题,在构建基学习器时,我们要为每个类别k创建一棵回归树Fk(x),k=1,2,……,K
~yi,k=yi,k−pk,m−1(xi)
因此,每次迭代m,以概率角度来计算当前残差。
叶子节点值近似为:
γm,j=K−1K∑x∈Rm,j~yi∑x∈Rm,j|~yi|(2−|~y|)
面经
- GBDT为什么是在拟合前面几轮的残差?请公式推导。
- SVM为什么要比GBDT好?(这个问题有点奇怪,但是面试官真的是这么问的(微笑脸),因为我简历里写了用SVM做分类,面试官就问为什么不用GBDT,SVM比GBDT好在哪里?……)这个问题我至今不知道答案,请大神赐教。
- GBDT和LR的差别。(这个问题可以推广的,和AdaBoost、RF、XgBoost,etc的差别)
- 在你所知的算法中,哪个抗噪能力最强?哪个对采样不敏感?
作者 Scorpio.Lu
转载请注明出处!
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· 写一个简单的SQL生成工具
· AI 智能体引爆开源社区「GitHub 热点速览」
· C#/.NET/.NET Core技术前沿周刊 | 第 29 期(2025年3.1-3.9)