天天看点

GBDT梯度提升树

前言

GBDT的全称是Gradient Boosting Decision Tree,Gradient Boosting和Decision Tree是两个独立的概念。

GBDT算法

Boosting讲解

Boosting的概念很好理解,意思是用一些弱分类器的组合来构造一个强分类器。因此,它不是某个具体的算法,它说的是一种理念。和这个理念相对应的是一次性构造一个强分类器。像支持向量机,逻辑回归等都属于后者。通常,我们通过相加来组合分类器,形式如下:

F m ( x ) = f 0 + a 1 f 1 ( x ) + a 2 f 2 ( x ) + . . . + a m f m ( x ) F_m(x)=f_0+a_1f_1(x)+a_2f_2(x)+...+a_mf_m(x) Fm​(x)=f0​+a1​f1​(x)+a2​f2​(x)+...+am​fm​(x)

其中每一个 f i ( x ) f_i(x) fi​(x)就是一个分类器,强分类器是由多个弱分类器线性相加而成,具体如何做呢?

Boosting,迭代,即通过迭代多棵树来共同决策。这怎么实现呢?难道是每棵树独立训练一遍,比如年龄预测,训练三棵树,针对A这个样本,第一棵树认为是10岁,第二棵树认为是0岁,第三棵树认为是20岁,我们就取平均值10岁做最终结论?–当然不是!且不说这是投票方法并不是GBDT,只要训练集不变,独立训练三次的三棵树必定完全相同,这样做完全没有意义。之前说过,GBDT是把所有树的结论累加起来做最终结论的,所以可以想到每棵树的结论并不是年龄本身,而是年龄的一个累加量。GBDT的核心就在于,每一棵树学的是之前所有树结论和的残差,这个残差加上一棵树的预测值后能得真实值。比如A的真实年龄是18岁:

  • 第一棵树的预测年龄是12岁,差了6岁,即残差为6岁。
  • 那么在第二棵树里我们把A的年龄设为6岁去学习,如果第二棵树真的能把A分到6岁的叶子节点,那累加两棵树的结论就是A的真实年龄;如果第二棵树的结论是5岁,则A仍然存在1岁的残差,第三棵树里A的年龄就变成1岁,继续学。

这就是Gradient Boosting在GBDT中的意义。

Decision Tree

Decision Tree是决策树算法,一种强分类器,决策树分为两大类,回归树和分类树。前者用于预测实数值,如明天的温度、用户的年龄、网页的相关程度;后者用于分类标签值,如晴天/阴天/雾/雨、用户性别、网页是否是垃圾页面。这里要强调的是,前者的结果加减是有意义的,如10岁+5岁-3岁=12岁,后者则无意义,如男+男+女=到底是男是女? GBDT的核心在于累加所有树的结果作为最终结果,就像前面对年龄的累加(-3是加负3),GBDT中一般使用回归树,回归树不同于分类树,它原理在下一节会突出。

多模块累加算法的目标函数

由上述两个部分我们可以知道梯度提升树是一个多个提升树模型混合后的一个模型,形式化如下所示:

y i ^ = ∑ k = 1 K f k ( x i ) \widehat{y_i}=\sum_{k=1}^{K}{f_k(x_i)} yi​

​=k=1∑K​fk​(xi​)

我们定义一个误差函数 l ( y i , y i ^ ) l(y_i,\widehat{y_i}) l(yi​,yi​

​),来表示误差情况,如下所示:

O b j = ∑ i = 1 n l ( y i , y i ^ ) + ∑ k = 1 K Ω ( f k ) Obj = \sum_{i=1}^{n}{l(y_i,\widehat{y_i})}+\sum_{k=1}^{K}{\Omega(f_k)} Obj=i=1∑n​l(yi​,yi​

​)+k=1∑K​Ω(fk​)

  • l ( y i , y i ^ ) l(y_i,\widehat{y_i}) l(yi​,yi​

    ​) 表示误差函数,一般可以为平方损失函数 ( y − y i ^ ) 2 (y-\widehat{y_i})^2 (y−yi​

    ​)2或者Huber loss 损失函数。

  • ∑ k = 1 K Ω ( f k ) \sum_{k=1}^{K}{\Omega(f_k)} ∑k=1K​Ω(fk​)代表了基模型的复杂度,用来抑制模型复杂度的正则项,若基模型是树模型,则树的深度、叶子节点数等指标可以反应树的复杂程度。

我们接下来分析 y i ^ \widehat{y_{i}} yi​

​,因为它是有多个模型结果累加起来的,所以我们用另一种方式表示为:

y i t ^ = y i t − 1 ^ + f t ( x i ) \widehat{y_{i}^{t}} = \widehat{y_{i}^{t-1}}+f_t(x_i) yit​

​=yit−1​

​+ft​(xi​)

其中 y ^ i t − 1 \widehat{y}_{i}^{t-1} y

​it−1​为前 t − 1 t-1 t−1次模型结果累加的值,于是在t个模型的时候,他的目标函数为:

O b j t = ∑ i = 1 n l ( y i , y ^ i t − 1 + f t ( x i ) ) + Ω ( f t ) + C Obj^t= \sum_{i=1}^{n}{l(y_i, \widehat{y}_{i}^{t-1}+f_t(x_i))}+\Omega(f_t)+C Objt=i=1∑n​l(yi​,y

​it−1​+ft​(xi​))+Ω(ft​)+C

  • 因为是第t个模型,则 ∑ k = 1 K Ω ( f k ) = Ω ( f t ) + C \sum_{k=1}^{K}{\Omega(f_k)} =\Omega(f_t)+C ∑k=1K​Ω(fk​)=Ω(ft​)+C,前t-1个模型都是常量
  • 即此时最优化目标函数,就相当于求 f t ( x i ) f_t(x_i) ft​(xi​),其他都是已知的。

利用二阶泰勒展开式来表述该问题:

f ( x + Δ x ) ≈ f ( x ) + f ′ ( x ) Δ x + 1 2 f ′ ′ ( x ) Δ x 2 f(x+\Delta{x}) \approx f(x)+f^{'}(x)\Delta{x}+\frac{1}{2}f^{''}(x)\Delta{x}^2 f(x+Δx)≈f(x)+f′(x)Δx+21​f′′(x)Δx2

我们令 y ^ i t − 1 \widehat{y}_{i}^{t-1} y

​it−1​表示上述公式中的 x x x, f t ( x i ) ) f_t(x_i)) ft​(xi​))表示为公式中的 Δ x \Delta{x} Δx,于是等式就改写为:

O b j t = ∑ i = 1 n l ( y i , y ^ i t − 1 + f t ( x i ) ) + Ω ( f t ) + C = ∑ i = 1 n [ l ( y i , y ^ i t − 1 ) + g i f t ( x ) + 1 2 h i f t 2 ( x i ) ] + Ω ( f t ) + C \begin{aligned} Obj^t &= \sum_{i=1}^{n}{l(y_i, \widehat{y}_{i}^{t-1}+f_t(x_i))}+\Omega(f_t)+C \\ &=\sum_{i=1}^{n} \bigg[l(y_i,\widehat{y}_{i}^{t-1})+g_if_t(x)+\frac{1}{2}h_if_t^2(x_i) \bigg] +\Omega(f_t)+C \end{aligned} Objt​=i=1∑n​l(yi​,y

​it−1​+ft​(xi​))+Ω(ft​)+C=i=1∑n​[l(yi​,y

​it−1​)+gi​ft​(x)+21​hi​ft2​(xi​)]+Ω(ft​)+C​

  • g i g_i gi​表示误差函数的一阶导,也就是 l 函 数 l函数 l函数的一阶导数
  • h i h_i hi​表示误差函数的二阶导,也就是 l 函 数 l函数 l函数的二阶导数

公式是怎么得来的呢 ?把 y i y_i yi​作为一个常量,不过它本身也是常量,然后对另一个变量使用泰勒展开式,

其实这里我还有一个疑问,为什么令 y ^ i t − 1 \widehat{y}_{i}^{t-1} y

​it−1​表示上述公式中的 x x x, f t ( x i ) ) f_t(x_i)) ft​(xi​))表示为公式中的 Δ x \Delta{x} Δx?这个疑惑还不清楚,

但是我们针对第t个模型,我可以可以知道 y ^ i t − 1 \widehat{y}_{i}^{t-1} y

​it−1​是前t-1个模型的输出累加, y i y_i yi​是样本的标签值,都是常量,去掉这些常量,得到如下形式:

O b j t ≈ ∑ i = 1 n [ g i f t ( x ) + 1 2 h i f t 2 ( x i ) ] + Ω ( f t ) Obj^t \approx \sum_{i=1}^{n} \bigg[g_if_t(x)+\frac{1}{2}h_if_t^2(x_i) \bigg] +\Omega(f_t) Objt≈i=1∑n​[gi​ft​(x)+21​hi​ft2​(xi​)]+Ω(ft​)

这就是多个模型累加的目标函数,如果应用在决策树中,我们来看看会有什么结果。

应用在回归树

一颗生成好的决策树,其叶子节点个数为T,将所有叶子节点对应值组成的向量 w ∈ R T w∈R^T w∈RT,还有一个把输入特征向量映射到叶子节点索引(Index)的函数 q : R d → 1 , 2 , ⋯ , T q:R^d→{1,2,⋯,T} q:Rd→1,2,⋯,T组成的。因此,决策树可以定义为 f t ( x ) = w q ( x ) f_t(x)=w_{q(x)} ft​(x)=wq(x)​。还有一个,决策树的复杂度如何定义?

Ω ( f t ) = γ T + 1 2 λ ∑ i = 1 T w i 2 \Omega(f_t)=\gamma T+\frac{1}{2}\lambda \sum_{i=1}^{T}{w_{i}^{2}} Ω(ft​)=γT+21​λi=1∑T​wi2​

  • 一部分是叶子结点数量
  • 另一部分是叶子节点对应的值向量的L2范式

同时假设第 j j jg个样本上有多个样本,集合为 I j = { i ∣ q ( x i ) = j } I_j=\{i|q(x_i)=j\} Ij​={i∣q(xi​)=j},上述公式变为:

O b j t ≈ ∑ i = 1 n [ g i f t ( x ) + 1 2 h i f t 2 ( x i ) ] + Ω ( f t ) = ∑ i = 1 n [ g i w q ( x ) + 1 2 h i w q ( x i ) 2 ] + γ T + 1 2 λ ∑ i = 1 T w i 2 = ∑ j = 1 T [ ( ∑ i ∈ I j g i ) w j + 1 2 ( ∑ i ∈ I j h i + λ ) w q ( x j ) 2 ] + γ T \begin{aligned} Obj^t &\approx \sum_{i=1}^{n} \bigg[g_if_t(x)+\frac{1}{2}h_if_t^2(x_i) \bigg] +\Omega(f_t) \\ &= \sum_{i=1}^{n} \bigg[g_iw_{q(x)}+\frac{1}{2}h_iw_{q(x_i)}^2 \bigg] +\gamma T+\frac{1}{2}\lambda \sum_{i=1}^{T}{w_{i}^{2}} \\ &= \sum_{j=1}^{T} \bigg[ (\sum_{i\in I_j}{g_i})w_j + \frac{1}{2}(\sum_{i\in I_j}{h_i}+\lambda)w_{q(x_j)}^2 \bigg]+\gamma T \end{aligned} Objt​≈i=1∑n​[gi​ft​(x)+21​hi​ft2​(xi​)]+Ω(ft​)=i=1∑n​[gi​wq(x)​+21​hi​wq(xi​)2​]+γT+21​λi=1∑T​wi2​=j=1∑T​[(i∈Ij​∑​gi​)wj​+21​(i∈Ij​∑​hi​+λ)wq(xj​)2​]+γT​

G j = ∑ i ∈ I j g i , H j = ∑ i ∈ I j h i + λ G_j=\sum_{i\in I_j}{g_i}, H_j=\sum_{i\in I_j}{h_i}+\lambda Gj​=∑i∈Ij​​gi​,Hj​=∑i∈Ij​​hi​+λ,等式改写为:

O b j t = ∑ j = 1 T [ G j w j + 1 2 H i w q ( x j ) 2 ] + γ T Obj^t = \sum_{j=1}^{T} \bigg[ G_jw_j + \frac{1}{2}H_{i}w_{q(x_j)}^2 \bigg]+\gamma T Objt=j=1∑T​[Gj​wj​+21​Hi​wq(xj​)2​]+γT

假设树的结构是固定的,即函数 q ( x ) q(x) q(x)确定,令函数 O b j ( t ) Obj(t) Obj(t)的一阶导数等于0,即可求得叶子节点 j j j对应的值为:

w j = − G j H j + λ w_j=-\frac{G_j}{H_j+\lambda} wj​=−Hj​+λGj​​

此时目标函数变为:

O b j = − 1 2 ∑ j = 1 T G j 2 H j + λ + γ T Obj = -\frac{1}{2}\sum_{j=1}^{T}{\frac{G_j^2}{H_j+\lambda}}+\gamma T Obj=−21​j=1∑T​Hj​+λGj2​​+γT

综上,为了便于理解,单颗决策树的学习过程可以大致描述为:

  • 枚举所有可能的树结构q
  • 用最终的目标函数为每个q计算其对应的分数Obj,分数越小说明对应的树结构越好
  • 根据上一步的结果,找到最佳的树结构,为树的每个叶子节点计算预测值 w j w_j wj​

然而,可能的树结构数量是无穷的,所以实际上我们不可能枚举所有可能的树结构。通常情况下,我们采用贪心策略来生成决策树的每个节点。

  • 从深度为0的树开始,对每个叶节点枚举所有的可用特征
  • 针对每个特征,把属于该节点的训练样本根据该特征值升序排列,通过线性扫描的方式来决定该特征的最佳分裂点,并记录该特征的最大收益(采用最佳分裂点时的收益)
  • 选择收益最大的特征作为分裂特征,用该特征的最佳分裂点作为分裂位置,把该节点生长出左右两个新的叶节点,并为每个新节点关联对应的样本集
  • 回到第1步,递归执行到满足特定条件为止

在上述算法的第二步,样本排序的时间复杂度为 O ( n l o g n ) O(n logn) O(nlogn),假设一共有K个特征,那么生成一颗深度为K的树的时间复杂度为 O ( d K ∗ n ∗ l o g n ) O(d_K*n*logn) O(dK​∗n∗logn)。具体实现可以进一步优化计算复杂度,比如可以缓存每个特征的排序结果等。

这里的问题是怎么求得最大收益?

  • 假设树要分裂成左子树( L L L)和右子树( R R R)
  • 分裂前的目标函数是:

    O b j a = − 1 2 ( G L + G R ) 2 H L + H R + λ + γ T Obj_a = -\frac{1}{2}{\frac{(G_L+G_R)^2}{H_L+H_R+\lambda}}+\gamma T Obja​=−21​HL​+HR​+λ(GL​+GR​)2​+γT

  • 分裂后的目标函数则是:

    O b j b = − 1 2 [ ( G L ) 2 H L + λ + ( G R ) 2 H R + λ ] + 2 γ T Obj_b = -\frac{1}{2}\bigg[ {\frac{(G_L)^2}{H_L+\lambda}}+\frac{(G_R)^2}{H_R+\lambda}\bigg]+2\gamma T Objb​=−21​[HL​+λ(GL​)2​+HR​+λ(GR​)2​]+2γT

  • 两个损失相减 O b j b − O b j a Obj_b-Obj_a Objb​−Obja​这个就是选择某一个特征之后的收益:

    G a i n = O b j b − O b j a = − 1 2 [ ( G L ) 2 H L + λ + ( G R ) 2 H R + λ − ( G L + G R ) 2 H L + H R + λ ] + γ T \begin{aligned} Gain &=Obj_b-Obj_a \\ &= -\frac{1}{2}\bigg[ {\frac{(G_L)^2}{H_L+\lambda}}+\frac{(G_R)^2}{H_R+\lambda} - \frac{(G_L+G_R)^2}{H_L+H_R+\lambda} \bigg]+\gamma T \end{aligned} Gain​=Objb​−Obja​=−21​[HL​+λ(GL​)2​+HR​+λ(GR​)2​−HL​+HR​+λ(GL​+GR​)2​]+γT​

    当然这里很多博文里选择 O b j a − O b j b Obj_a - Obj_b Obja​−Objb​,利用分裂前的目标函数减去分裂后的目标函数:

    G a i n = O b j a − O b j b = 1 2 [ ( G L ) 2 H L + λ + ( G R ) 2 H R + λ − ( G L + G R ) 2 H L + H R + λ ] − γ T \begin{aligned} Gain &=Obj_a-Obj_b \\ &= \frac{1}{2}\bigg[ {\frac{(G_L)^2}{H_L+\lambda}}+\frac{(G_R)^2}{H_R+\lambda} - \frac{(G_L+G_R)^2}{H_L+H_R+\lambda} \bigg]-\gamma T \end{aligned} Gain​=Obja​−Objb​=21​[HL​+λ(GL​)2​+HR​+λ(GR​)2​−HL​+HR​+λ(GL​+GR​)2​]−γT​

    其实不管那种计算方式,只需要这两个差值的绝对值最大就是收益的最大。

  • 针对每个特征计算最大收益之后,比较每个特征的最大收益,选择收益最大值的特征作为下一个节点,但是这里好像并没有说特征的最佳分裂点是如何计算的?

最后,总结一下GBDT的学习算法:

  1. 算法每次迭代生成一颗新的决策树
  2. 在每次迭代开始之前,计算损失函数在每个训练样本点的一阶导数 g i g_i gi​和二阶导数 h i h_i hi​
  3. 通过贪心策略生成新的决策树,通过等式(7)计算每个叶节点对应的预测值 f t ( x ) f_t(x) ft​(x)

    f t ( x ) = w j = − G j H j + λ f_t(x)=w_j=-\frac{G_j}{H_j+\lambda} ft​(x)=wj​=−Hj​+λGj​​

  4. 把新生成的决策树 f t ( x ) f_t(x) ft​(x)添加到模型中: y i t = y i t − 1 + f t ( x i ) y^t_i=y^{t−1}_i+f_t(x_i) yit​=yit−1​+ft​(xi​)

通常在第四步,我们把模型更新公式替换为: y i t = y i t − 1 + ϵ f t ( x i ) y^t_i=y^{t−1}_i+\epsilon f_t(x_i) yit​=yit−1​+ϵft​(xi​),其中 ϵ \epsilon ϵ称之为步长或者学习率。增加 ϵ \epsilon ϵ因子的目的是为了避免模型过拟合。虽然大家这样似乎没有什么问题,但是依旧有一些问题:

  • 模型的个数问题?似乎从上述看,每一个特征就对应一个模型,因为分裂是通过特征值分裂得来的
  • 如果前两个特征就确定了所有样本,也就终止了,那么终止条件到底是什么?

作用范围

该版本GBDT几乎可用于所有回归问题(线性/非线性),相对logistic regression仅能用于线性回归,GBDT的适用面非常广。亦可用于二分类问题(设定阈值,大于阈值为正例,反之为负例)。

参考博客

GBDT(MART) 迭代决策树入门教程 | 简介

机器学习-一文理解GBDT的原理-20171001

继续阅读