当我们在谈论GBDT:从 AdaBoost 到 Gradient Boosting

本系列意在长期连载分享,内容上可能也会有所增删改减;

因此如果转载,请务必保留源地址,非常感谢!

知乎专栏:当我们在谈论数据挖掘

引言

GBDT 全称是 Gradient Boosting Decision Tree,是一种常用的 Ensemble Learning 算法。由于其出色的表现以及 XGBoost 的出现,近些年在 Kaggle 等竞赛中大放异彩。本系列旨在梳理 GBDT 相关的概念,并在 Kaggle 等竞赛中举例实践。

GBDT 作为一种 Ensemble Learning 算法,本质也就是融合多个弱分类器进行决策。从 GBDT 的名字可以看出,它包含两个概念:GB(Gradient Boosting) 和 DT(Decision Tree)。因此,GBDT 使用的弱分类器就是 Decision Tree,而融合的方法叫做 Gradient Boosting。但是在介绍 Gradient Boosting 前,我们先回顾一下相关的 Boosting 算法。

从 AdaBoost 到 Gradient Boosting

Boosting 是 Ensemble Learning 算法的一个类别。Boost 的意思为“提升”,这类算法的思想是“给定仅比随机猜测略好的弱学习算法 ,将其提升为强学习算法”。在2000年左右,Friedman 的几篇论文提出的几个 Boosting 算法,奠定了 Boosting 从一种思想走向实用的基础:

  • 1997年,Freund 在 A Decision-Theoretic Generalization of On-Line Learning and an Application to Boosting 中,提出了第一个实用的 Boosting 算法并扩展——AdaBoost(两类分类),AdaBoost.M1(多类分类),AdaBoost.M2(多类分类),AdaBoost.R(回归)
  • 2000年,Freund 在 Additive logistic regression: a statistical view of boosting 中,从加性模型的角度对 AdaBoost 的数学性质进行了研究,并扩展提出了Real AdaBoost、LogitBoost、Gentle AdaBoost 等两类分类 Boosting 算法
  • 2001年,Freund 在 Greedy function approximation: A gradient boosting machine 中,将梯度下降的思想引入 Boosting 算法,提出了Gradient Boosting 思想。Gradient Boosting 是一个 Boosting 框架,能处理不同的损失函数,较为实用

本文主要对其中部分算法进行理论上的介绍。

AdaBoost

AdaBoost(Adaptive Boosting)针对的是两类分类问题。其弱学习算法L也是一个两类分类器,可以根据需要选择。AdaBoost 的伪代码如下:

可以看出:AdaBoost 本质就是,每次迭代更新样本分布,然后对新的分布下的样本学习一个弱分类器,和它对应的权重。更新样本分布的规则是:减小之前弱分类器分类效果较好的数据的概率,增大之前弱分类器分类效果较差的数据的概率。最终的分类器是弱分类器线性组合。


以下,我们以指数损失函数为例,对 AdaBoost 的原理进行说明。对理论不感兴趣的同学可以跳过。

需要注意的是,按照作者的说法,“最小化指数分布损失函数”这并不是 AdaBoost 被设计的初衷。但是这提供了一个深入理解 AdaBoost,以及扩展 AdaBoost 的机会。

首先,

我们有训练样本(x_1, y_1),...,(x_m,y_m) ,其中y\in\{-1,1\}。目标是训练出一个两类分类器H(x),使损失函数最小,损失函数表达如下。(感谢@haijin jiang 提醒,这里需要说明下,下式中的f(x)表示的是样本x对应的真实类别;同时,h(x)应该理解为H(x),会与下文更连贯):

同时,H(x)由若干个弱分类器线性组合而成

随后,我们需要证明如果求出H,它是否是有效的分类器

为了求出令损失函数\iota_{exp}最小的H,我们对其求导

可以求得

而将H(x)二值化,则能得到最终的二类分类器

从上式能够看出,通过最小化损失函数\iota_{exp},我们求出的H(x)能够最小化分类误差,所以H(x)是有效的

随后,由于弱分类器h_t(x)是可以自己选择的,训练过程无需描述;但是需要求它对应的权值\alpha_t

H(x)是弱分类器h_t(x)的线性组合,当第t次迭代中,h_t(x)已经训练完毕(步骤3),接下来就要求h_t(x)对应的系数\alpha_t,使\alpha_th_t(x)能最小化本轮的损失函数\iota_{exp}

其中,\epsilon_t

为了求\alpha_t,对\iota_{exp}求导

可以求得h_t(x)的权值\alpha_t

之后,需要明确如何通过前几轮的学习效果,确定下一个弱分类器

假设在第t-1轮迭代后,我们得到了t-1个弱分类器,此时将它们组合成强分类器H_{t-1}。接下来,我们希望下一个弱分类器h_t能够纠正H_{t-1}中的所有错误。即,由于h_t纠正了所有的错误,此时的损失函数\iota_{exp}应该最小

e^{-f(x)h_t(x)}泰勒展开,且由于f(x)^2=1h_t(x)^2=1

因此,理想的h_t(x)应该能够有如下性质

需要注意的是,上式最后两行,只是单纯除以了一个常数而已。有了这个常数,我们可以定义一个分布D_t

于是,h_t(x)可以被写成

由于又有下式(其中I(x)=1x为真;I(x)=0x为假)

h_t(x)最终可以写成

此时,h_t(x)只与定义出的分布D_t相关,因此我们只需要求出D_t的表达即可

上式最后一项是个常数,可以理解为将D_t归一化为分布的系数,即得到了步骤7中的公式

AdaBoost.SAMME(AdaBoost.M1改进版)

Freund 在1997年提出的 AdaBoost.M1 算法,本质上就是将 AdaBoost 的弱分类器从两类分类器,换成了多类分类器。此时 AdaBoost.M1 有个重要限制,就是每次迭代的弱分类器错误率小于0.5。这个限制对于二类分类是合适的,但是对于多类分类器是比较严格的。

Hastie, Trevor, et al. "Multi-class AdaBoost." 2006 中,Hastie 提出了AdaBoost.SAMME 。该算法通过最小化多类指数损失函数求得,并且作者也证明了此结果满足多类贝叶斯分类准则。即

AdaBoost.SAMME 的步骤与 AdaBoost 差不多,只是将步骤6中的系数公式变为了

AdaBoost.SAMME 详细步骤如下,其中,K表示类别个数

在 AdaBoost.SAMME 中,为了使\alpha^{(m)}>0,需要1-err^{(m)}>1/K,即弱分类器的效果大于随机猜测即可。这比 AdaBoost.M1 的约束宽松很多。

Real AdaBoost

AdaBoost 中,弱分类器输出是类别,属于集合\{-1,1\}。在 Real AdaBoost 中,弱分类器输出的是属于每一类的概率。

AdaBoost.MH

还有一种处理多类分类的方法,是将多类分类转换为两类分类问题,有 one-versus-rest 和 one-versus-one 两种方式:

一对多(one-versus-rest)即将K类分类问题,转换为K个两类分类问题,每个问题是“样本是否属于第K类”

一对一(one-versus-one)即将K类分类问题,转换为K(K-1)/2个两类分类问题,每个问题是“样本属于第i类还是第j类”

AdaBoost.MH 就是一对多的思想,伪代码如下

Gradient Boosting

Gradient Boosting 是一种 Boosting 的思想,它本质是,每一次建立模型是在之前建立模型损失函数的梯度下降方向。其步骤如下

接下来,我们从理论上推演上面的步骤

首先

我们有样本\{x,y\}_1^N,其中x=\{x_1,...,x_n\}。目的是训练出F^*,使损失函数\psi(y,F(x))最小,即

然后,我们先推导如何在参数空间求最优解

假设这里的F(x)是由参数能确定的函数,即它其实是F(x;P),这里P表示F(x;P)中的参数序列。并且,我们只考虑加性模型,即

其中

因此,F(x;P)的求解从寻找最佳的函数F^*,变成了寻找最佳的参数P^*

为了能迭代求出P^*,我们将它写成

其中,P_0表示初始设置的参数,P_m表示后续第m次迭代,求出的参数。

接下来求解P^*使损失函数\psi(y,F(x))最小,就是一个典型的梯度下降过程了。先求P^*的梯度

其中

随后,求出步长

其中

迭代以上两步,直到收敛,既可求出P^*


随后,我们将上述推导推广到函数空间

损失函数\Phi(F(x))

F^*为多个f(x)的线性组合

其中,f_0(x)为初始函数,f_m(x)为第m次迭代求出的函数。使用梯度下降法求解F^*,使损失函数最小

其中

随后,求出步长

其中,g_m(x)如下(交换了期望与求导)

但是,上述推导需要知道(x,y)的联合分布,而用训练样本估计出来的分布肯定是不准确的

最后,我们参考上面求解最优“参数/函数空间”的思想,得到在“有限样本集”的情况下的 Gradient Descent 模型

理论上,我们只需要在第m次迭代的时候,求出最优的(\beta_m,\alpha_m)

并代入递推式即可,如下

但是,并不是所有的\Psi(y,F)都能够直接求解出上式。同时,我们可以看到在加性模型下,\beta h(x_i;\alpha)本身就可以看成是参数前进的方向。又根据梯度下降法,使参数前进方向为负梯度方向-g_m(x_i)。于是,可以通过最小二乘法求\alpha_m,如下

接下来,将\alpha_m代入,并将h(x_i;\alpha)作为梯度下降的方向,求解\rho_m

最终的迭代式为

完整的 Gradient Descent 模型流程于是为

本系列其他文章:


  • 当我们在谈论GBDT:从 AdaBoost 到 Gradient Boosting
  • 当我们在谈论GBDT:Gradient Boosting 用于分类与回归
  • 当我们在谈论GBDT:其他 Ensemble Learning 算法
  • 当我们在谈论GBDT:在 Kaggle 等竞赛中实践
  • 编辑于 2017-03-09

    文章被以下专栏收录