机器学习——梯度提升(GBDT)算法

机器学习——梯度提升(GBDT)算法

1、集成学习中的两种方式

1.1 Bagging和Boosting

在之前的文章中,我们介绍了集成学习的两种方式,一种是弱分类器之间是并行的,彼此之间不存在关系,第二种是弱分类器是串行的,彼此之间存在着一定的联系。我们将第一种思想称为Bagging,第二种思想称为Boosting。

1.2 Bagging简述

所谓的Bagging,就是指通过对大小为N的原始数据进行又放回的重复采样,采样K次,每次采样N个样本,由于数据是有放回的,那么也就说对于每一次的采样,原始数据中的某个样本可以在该次采样形成的样本集合中存在多次,也可能一次都没有出现,对于多次采样而言,某一个样本可以在多个样本集合中出现,也可能所有的样本集合中都没有出现,这种抽样的方式称为Bootstrap simpling,在形成K个不同的样本集合之后,通过这个K个样本集合构建K个弱学习器,然后形成一个学习器系统。对于输入的数据,如果是分类问题,在每个弱学习器获得结果之后,进行投票法的方式进行投票获取最后的结果。其中Bagging最典型的例子就是随机森林,具体可以参考另外一篇文章机器学习——随机森林算法

1.3 Boosting简述

与Bagging方式不同,Boosting的核心思想是通过迭代构建K个学习器,每次迭代构建的学习器都重点去关注之前的前一个学习器没有解决的问题。为了能够去更加关注上一个学习器预测失败的样本,我们将不同的样本之间在每一轮赋予不用的权重,给那些上一次预测错误的样本更高的权重。我们在这里给一个图示:
在这里插入图片描述
对于Boosting方法最为常见的就是AdaBoost方法与GBDT算法,在之前的文章机器学习——AdaBoost算法中,我们已经提到了AdaBoost的训练方法。这篇文章中,我们主要介绍Boosting的另外一种代表算法GBDT算法。

2、梯度提升树(GBDT)算法

2.1 GBDT算法的引入

首先,我们先回顾一下AdaBoost算法,在AdaBoost算法中,我们主要是利用前一轮的迭代弱学习器的误差率来更新当前轮次的训练集的误差权重,这样一轮一轮的迭代下去,在AdaBoost的算法中,我们每一轮的目标是为了最小化当前轮次的学习误差函数 L ( Y , G i ( X ) ) L(Y,G_i(X)) L(Y,Gi(X)),其中i表示的是当前迭代的轮次。我们下面换一种思想来看待这个问题,在AdaBoost算法中,每一轮都变换样本的权重,这样使得当前轮的学习器对前一轮预测失败的样本更多的关注,那么我们是不是可以在进一步,在变换权重的同时,也关注前一轮所产生的误差,通过这种方式,不断的去缩小当前样本产生的误差和前一轮留下的误差,当两者之和最小的时候,说明我们既降低了当前学习产生的误差,有降低了前些轮迭代产生的累积误差。这也就是GBDT算法的基本思想。

在GBDT的迭代中,假设每一轮迭代得到的学习器 G t − 1 ( X ) G_{t-1}(X) Gt1(X),产生的误差采用 L ( Y , G t − 1 ( X ) ) L(Y,G_{t-1}(X)) L(Y,Gt1(X))来进行表示,我们本轮迭代的目标是找到一个弱学习器 G t ( x ) G_t(x) Gt(x),使得损失函数 L ( Y , G t − 1 ( X ) ) + Y , G t ( X ) ) L(Y,G_{t-1}(X))+Y,G_t(X)) L(Y,Gt1(X))+Y,Gt(X))

2.2 GBDT拟合负梯度

GBDT算法是对于提升树的(Boosting Tree)的一种改进算法,首先简单的介绍一下提升树算法:

  1. 初始化一个 G 0 ( x ) G_0(x) G0(x)=0
  2. 开始迭代过程,一共迭代K次,当迭代到第i次的时候,计算上一轮迭代的残差:
    r i j = y j − G i − 1 ( x j ) r_{ij}=y_j-G_{i-1}(x_j) rij=yjGi1(xj)
    其中,i表示当前迭代的轮数,j表示训练集合中的第j个样本。
  3. 拟合残差,生成一个新的学习器树 H i ( x ) H_i(x) Hi(x)
  4. 生成当前轮的学习器 G i ( x ) = G i − 1 ( x ) + H i ( x ) G_i(x)=G_{i-1}(x)+H_i(x) Gi(x)=Gi1(x)+Hi(x)
  5. 重复2,3,4直到迭代结束。
  6. 生成最终的学习器:
    G K ( x ) = ∑ i = 1 K H i ( x ) G_K(x)=∑_{i=1}^KH_i(x) GK(x)=i=1KHi(x)

在上面的算法描述中,我们提到了拟合残差的概念,那么我们应该如何去理解残差呢?
首先,我们假设前一轮的得到的学习器为:
G i − 1 ( x ) G_{i-1}(x) Gi1(x)
对应的损失函数为:
L ( y , G i − 1 ( x ) ) L(y,G_{i-1}(x)) L(y,Gi1(x))
我们本轮的目标是找到一个CART学习器 H i ( x ) H_i(x) Hi(x),使其最小化本轮的损失:
L ( y , G i ( x ) ) = L ( y , G i − 1 ( x ) + H i ( x ) ) L(y,G_{i}(x))=L(y,G_{i-1}(x)+H_i(x)) L(y,Gi(x))=L(y,Gi1(x)+Hi(x))
当损失采用的是平方函数的时候:
L ( y , G i ( x ) ) = L ( y , G i − 1 ( x ) + H i ( x ) ) = 1 2 ( y − G i − 1 ( x ) − H i ( x ) ) 2 = 1 2 ( r − H i ( x ) ) 2 L(y,G_{i}(x))=L(y,G_{i-1}(x)+H_i(x))=\frac{1}{2}(y-G_{i-1}(x)-H_i(x))^2=\frac{1}{2}(r-H_i(x))^2 L(y,Gi(x))=L(y,Gi1(x)+Hi(x))=21(yGi1(x)Hi(x))2=21(rHi(x))2
其中r为
r = y − G i − 1 ( x ) = ∑ j = 1 N y j − G i − 1 ( x j ) r=y-G_{i-1}(x)=∑_{j=1}^Ny_j-G_{i-1}(x_j) r=yGi1(x)=j=1NyjGi1(xj)
N表示样本的个数,r表示上一轮的误差总和,也称为残差。根据 ( r − H i ( x ) ) 2 (r-H_i(x))^2 (rHi(x))2我们可以确定,当前构建的CART树,只需要最小化上一轮的残差即可。

当损失函数为平方函数或者指数函数的时候,GBDT算法的优化是很容易的,但是当损失损失函数的过于复杂的时候,优化起来不是很容易,Friedman提出了梯度提升算法GBDT,这个算法的核心是使用损失函数的负梯度作为残差的近似值,来替代残差

我们简单的计算一下负梯度:对于第j个样本而言:
− [ ∂ L ( y j , G ( x j ) ) ∂ G ( x j ) ] G ( x ) = G i − 1 ( x ) -\bigg[\frac{\partial L(y_j, G(x_j))}{\partial G(x_j)}\bigg]_{G(x)=G_{i-1}(x)} [G(xj)L(yj,G(xj))]G(x)=Gi1(x)

2.3 GBDT算法

我们上面介绍了提升树,也强调了在GBDT算法中弱学习器只使用CART树,下面我们将两者结合,描述一下GBDT算法:

  1. 初始化一个弱学习器:
    G 0 ( x ) = a r g m i n G 0 ∑ j = 1 N L ( y j , G 0 ( x j ) ) G_0(x)=argmin_{G_0}∑_{j=1}^NL(y_j,G_0(x_j)) G0(x)=argminG0j=1NL(yj,G0(xj))
  2. 开始迭代过程,一共迭代K次,当迭代到第i次的时候,计算上一轮迭代的负梯度:
    r i j = − [ ∂ L ( y j , G ( x j ) ) ∂ G ( x j ) ] G ( x ) = G i − 1 ( x ) r_{ij}=-\bigg[\frac{\partial L(y_j, G(x_j))}{\partial G(x_j)}\bigg]_{G(x)=G_{i-1}(x)} rij=[G(xj)L(yj,G(xj))]G(x)=Gi1(x)
    其中,i表示当前迭代的轮数,j表示训练集合中的第j个样本。
  3. 将上一轮产生的负梯度作为样本的新的真实值,并且将数据 ( x i , r i j ) , j ∈ [ 1 , N ] (x_i,r_{ij}),j∈[1,N] (xi,rij),j[1,N]作为下一个学习器的训练数据,生成一个新的学习器CART树 H i ( x ) H_i(x) Hi(x),该树结构将训练数据分为M个子集,也就是CART树有M个叶子节点。表示为 R i 1 , R i 2 , . . . R i M R_{i1},R_{i2},...R_{iM} Ri1,Ri2,...RiM
    H i ( x ) = ∑ m = 1 M C i m I ( x ∈ R i m ) H_i(x)=∑_{m=1}^MC_{im}I(x∈R_{im}) Hi(x)=m=1MCimI(xRim)
    其中 C i m C_{im} Cim为当前i轮迭代某一个叶节点m的拟合值,I表示示性函数。
    其中 C i m C_{im} Cim的计算为:
    C i m = a r g m i n β ∑ x j ∈ R i m L ( y j , G i − 1 ( x j ) + β ) C_{im}=argmin_β∑_{x_j∈R_{im}}L(y_j,G_{i-1}(x_j)+β) Cim=argminβxjRimL(yj,Gi1(xj)+β)
    这里需要注意的是, y j y_j yj不是原始样本的y,而是上一轮的负梯度值 r i − 1 , j r_{i-1,j} ri1,j
  4. 生成当前轮的学习器
    G i ( x ) = G i − 1 ( x ) + H i ( x ) = G i − 1 ( x ) + ∑ m = 1 M C i m I ( x ∈ R i m ) G_i(x)=G_{i-1}(x)+H_i(x)=G_{i-1}(x)+∑_{m=1}^MC_{im}I(x∈R_{im}) Gi(x)=Gi1(x)+Hi(x)=Gi1(x)+m=1MCimI(xRim)
  5. 重复2,3,4直到迭代结束。
  6. 生成最终的学习器:
    G K ( x ) = G 0 ( x ) + ∑ i = 1 K H i ( x ) = G 0 ( x ) + ∑ i = 1 K ∑ m = 1 M C i m I ( x ∈ R i m ) G_K(x)=G_0(x)+∑_{i=1}^KH_i(x)=G_0(x)+∑_{i=1}^K∑_{m=1}^MC_{im}I(x∈R_{im}) GK(x)=G0(x)+i=1KHi(x)=G0(x)+i=1Km=1MCimI(xRim)

3 XGBoost和GBDT的区别

1)将树模型的复杂度加入到正则项中,来避免过拟合,因此泛化性能会由于GBDT。

2)损失函数是用泰勒展开式展开的,同时用到了一阶导和二阶导,可以加快优化速度。

3)和GBDT只支持CART作为基分类器之外,还支持线性分类器,在使用线性分类器的时候可以使用L1,L2正则化。

4)引进了特征子采样,像RandomForest那样,这种方法既能降低过拟合,还能减少计算。

5)在寻找最佳分割点时,考虑到传统的贪心算法效率较低,实现了一种近似贪心算法,用来加速和减小内存消耗,除此之外还考虑了稀疏数据集和缺失值的处理,对于特征的值有缺失的样本,XGBoost依然能自动找到其要分裂的方向。

6)XGBoost支持并行处理,XGBoost的并行不是在模型上的并行,而是在特征上的并行,将特征列排序后以block的形式存储在内存中,在后面的迭代中重复使用这个结构。这个block也使得并行化成为了可能,其次在进行节点分裂时,计算每个特征的增益,最终选择增益最大的那个特征去做分割,那么各个特征的增益计算就可以开多线程进行。

4、参考

  1. GBDT算法原理以及实例理解
  2. 机器学习算法总结(四)——GBDT与XGBOOST
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值