Kaggle老手领你入门梯度提升——梯度提升两三事

更多深度文章,请关注: https://yq.aliyun.com/cloud

作者简介:Ben Gorman,痴迷于数据,数据科学爱好者,现居住于新奥尔良。在我加入GormAnalysis之前,我曾在Strategic Comp工作了五年时间,担任高级数据分析师的职位。我热衷于讨论数据科学,因此,如果你有任何疑问,不要犹豫,欢迎随时给我发邮件:bgorman@gormanalysis.com。在2016年9月份,我在Kaggle社区中的全球排名到达了前1%。

本篇文章最初发表在作者的个人博客当中。


如果我们把线性回归比作丰田凯美瑞,那么梯度提升就好比UH-60黑鹰直升机。XGBoost,一个梯度提升的具体实现,在Kaggle社区中被广泛应用于各类机器学习竞赛。然而不幸的是,许多使用者(包括从前的我)把梯度提升当做一个黑盒来使用。在一些数据科学家的博客当中,也提出了很多对梯度提升的批评。因此,本篇文章的目的在于直观且全面地介绍经典的梯度提升方法。

前期准备

本文将从一个简单的示例开始。我们希望根据一个人是否玩视频游戏、是否喜欢园艺以及戴帽子时的特点来判断这个人的年龄。我们的目标是最小化均方误差。我们总共有九个训练样本来构建模型。


d8790a7276868190c2f71be68e3324f38500311b

直观地说,我们可能希望

  • 喜欢园艺的人年纪可能比较大
  • 喜欢视频游戏的人可能比较年轻
  • 对帽子的喜好可能对年龄的预测没有帮助

我们可以快速粗略地检测训练数据,看看这些假设是否成立:


2a2d588d6521015f425db4fd53bef2f2f85a0065

现在,让我们使用回归树对数据进行建模。首先,我们要求回归树的叶子节点至少有三个样本数据。考虑到这一点,回归树只会根据"LikesGardening"这个特征进行一次划分。


b7020ca359f1c178395c60a1a5e96517471a4402

这样做很好,但是这种做法忽略了"PlaysVideoGames"特征中包含的宝贵信息。我们可以尝试让回归树的叶子节点保留两个样本数据。


3d27adbdac353e37ad8107a93976e5b7eb9a43c6

在这里,我们综合考虑"PlaysVideoGames"以及"LikesHats"特征中蕴含的信息,这些信息表明我们的模型陷入了过拟合,回归树的属性划分受到了随机噪声的影响。

此时,使用单一决策/回归树的缺点就暴露出来了——在整个特征空间中,我们无法对多个彼此重叠的区域进行预测。假设我们计算第一棵回归树的训练误差。


7da24e7cfee539b1e2ca68a9d0e56dca9cf277ce

现在,我们可以根据第一棵回归树的残差构建另一棵回归树。


afe78d4c0a0db9fc68036e76e0ddd0f084ee7d4b

注意,尽管前面过拟合的回归树考虑了"LikesHats"特征,但是这个模型并没有考虑这个特征。这是因为,与过拟合的回归树不同,第二棵回归树能够结合所有训练样本,综合考虑"LikesHats"特征与"PlaysVideoGames"特征的信息。而过拟合回归树仅考虑了输入空间中小范围内的特征信息,进而允许随机噪声选择"LikesHats"作为划分特征。

现在,我们可以通过增加"误差校正"预测来改进第一棵回归树的预测效果。


09776098fffc9b8bb6a530e17d8415454afe51a8

梯度提升——思路1

受到前面想法的启发,我们可以构建一个简单的梯度提升方法。伪码如下:

  1. 根据数据拟合一个模型,F1(x) = y
  2. 根据残差拟合一个模型,h1(x) = y - F1(x)
  3. 构建一个新模型,使得F2(x) = F1(x) + h1(x)

不难看出,我们可以通过引入更多的模型来纠正前一个模型的错误,从而扩展这个模型。特别地


811d396a4c407ab35106fca7f19d5f220a07fbad

其中,F1(x)表示拟合至y的初始模型

由于我们通过拟合F1(x)来初始化模型,在之后每一步,我们的任务是找到hm(x) = y - Fm(x)。

这里需要注意一点。hm只是一个"模型"。在我们的定义中,并没有要求hm是一个基于树形结构的模型。这正是梯度提升更宽泛的概念以及优势之一。这仅仅只是一个通过迭代改善弱学习器效果的计算框架。所以,从理论上讲,一个良好编码的梯度提升模块能够根据需要随意"插入"各种各样的弱分类器。然而,在实践中,hm几乎总是一个基于树的学习器,因此,在此我们可以将hm理解为示例中的那种回归树。

梯度提升——思路2

现在,我们将调整我们的模型以符合大多数梯度提升方法的实现 — 我们将使用单一的预测值初始化模型。由于我们(目前)的任务是最小化均方误差,我们将使用训练目标值的期望来初始化F()函数。


0363d948de8311b69ddf81680483fce40164519c

随后,我们就可以像前面一样,递归地定义后续的各个F()函数。


1d895dc607e1c60854e31d14e5cdc1fd8f5ca83f

其中hm表示一个基本学习器(比如回归树)。

到这里,你可能想知道如何选择最优的模型超参数m。换句话说,我们需要迭代多少次残差校正程序,才能确定最终的模型F?我们可以通过交叉验证)测试不同的数值来寻找参数m的最优取值。

梯度提升——思路3

直到现在,我们一直都在构建一个最小化均方误差的模型,如果我们想要最小化绝对误差该怎么办?我们可以调整我们的基本模型(回归树)以最小化绝对误差,但这样做有一些缺点。

  1. 考虑到数据的规模,这样做的代价可能非常昂贵。(每一次划分都需要计算当前数据的均值。)
  2. 这种做法也破坏了我们的"插件"系统。我们只能在当前模型中加入那些支持我们目标函数的弱分类器。

与这种做法相反,我们打算采取一些更灵活的方式。回顾我们的示例问题。为了确定F0,我们从绝对误差最小的分类器开始。此时年龄数据y的中位数为35。然后,我们可以计算残差,y-F0。


486c7cd4bbba2bec2be35fba0b82d505311907d9

观察第一个和第四个训练样本。它们的F0残差分别为-22和-10。此时,假设我们可以使预测结果接近目标值1个单位。那么均方误差的减少量分别为43和19,它们的绝对误差都分别减少了1。因此,对于一个在默认情况下最小化平方误差的回归树而言,它将在很大程度上侧重于减少第一个训练样本的残差。但是,如果我们希望最小化绝对误差,将预测结果向目标值靠近一个单位,那么根据代价函数的定义,我们将得到相同的减少量。考虑到这一点,假设我们不使用F0残差来更新h0,相反,我们根据F0(x)产生的预测值计算损失函数L(y, F0(x)) 的梯度来训练h0。本质上讲,我们通过计算每一个样本与观测值更接近时模型代价的减少量来训练h0。在绝对误差的情况下,hm只需要考虑每一个Fm函数的残差符号( 不同于考虑每一个残差大小的均方误差)。hm中的样本数据被划分至叶子节点后,我们可以计算出梯度均值,然后根据一些因子γ对结果进行缩放,使得Fm+γhm能够最小化每个叶子节点处样本的损失函数。(注意,在实际操作的过程中,每个叶子节点会选择不同的γ因子。)

梯度下降

接下来,让我们使用梯度下降的概念把这个想法形式化。假设我们有一个希望最小化的可微函数。例如


a171a9b131e4bb25dac59af208b55eb899ff909a

我们的目标是找到一组能够最小化L的(x1, x2)。注意,这个函数可以理解为给定两个预测值x1和x2,计算其与两个数据点15和25的均方误差(使用1/2乘子更有利于梯度的计算)。尽管我们可以直接最小化这个函数,但是在面对更复杂的损失函数时,我们往往无法直接最小化损失函数,而梯度下降则为我们提供了一种可行的方式。

初始阶段:

  • 迭代次数M=100
  • 迭代起始点s0=(0,0)
  • 迭代步长γ=0.1

在第m次迭代过程中(m取值从1到M):

  1. 计算函数L在数据点s(m-1)处的梯度
  2. 沿梯度最大方向(梯度的反方向)前进步长γ的距离。公式如下:


4008bd5e0e8d2f6c2b8504545de8856cb0414b74

如果γ很小且M足够大,那么sM将落在函数L的最小值处

以下几种方法可以改进这个计算框架:

  1. 除了使用固定的模型迭代次数,我们也可以在迭代结果带来的改进足够小时停止模型迭代过程
  2. 我们可以使用一些更加智能的方式选择迭代步长,比如线性搜索,而不是在每次迭代中都采用相同大小的步长

如果你对这部分内容不是很理解,google一下梯度下降。有很多研究者从不同的角度对梯度下降的过程进行了诠释。

应用梯度下降

现在,我们可以在前面的梯度提升模型中使用梯度下降了。我们需要最小化的目标函数是L。我们的起始点是F0(x)。在模型第一次迭代m=1时,我们计算L关于F0(x)的梯度。然后,我们将一个弱分类器调整为梯度分量。在回归树的例子中,叶子节点会在具有相似特征的样本间计算梯度均值。对于每一个叶子节点,我们沿梯度均值的方向更新参数(使用线性搜索来确定步长的大小)。更新后的结果记为F1。随后,我们反复重复这个过程,直到得到FM

我们修改了前面提到的梯度提升算法,使其适用于任何可微损失函数。 现在,让我们忘记前面的想法,从另外一个角度重新考虑我们的梯度提升模型。

使用常量来初始化模型:


cd58177f1aed6d62c8b61ec28b41619caf264857

m从1到M:

  1. 计算伪残差
  2. 根据伪残差拟合基本学习器hm(x)
  3. 计算步长乘子γm(在树形模型的情况下,需要为每一个叶子节点计算不同的γm
  4. 更新Fm(x)=Fm-1(x)+γmhm(x)

如果你想要检测自己对梯度提升的理解是否正确,我们目前的梯度提升方法应用于示例问题的均方误差和绝对误差结果如下:

均方误差


aa2a2449b35545366e34b8ca5b5859a6c3530baf


d3c2ce5fec64b9376c6f8745c2ce5a1cab9eaf9f

绝对误差


b79cdba1762c6a41649415a9b69a38cc5c1ef586


43f13dd6494fd100cf776ce4a501631b5bfa490c

梯度提升——思路4

在这里,我们要介绍一下收缩量的概念。这个概念很简单。对于每个梯度步长,步长幅度都会乘以一个0到1之间的学习率因子。换句话说,每个梯度步长都被一些因子缩放了。维基百科目前关于收缩量的摘录并没有提到为什么收缩是有效的——它只是说根据经验,收缩似乎是有效的。我个人的看法是,收缩导致样本预测值逐渐收敛到观察值。随着这种缓慢收敛的进行,更接近目标值的样本最终被组合成一个更大的叶子节点(由于树大小参数固定),并产生较好的正则化效果。

梯度提升——思路5

最后,让我们谈谈行采样与列采样。大多数的梯度提升算法提供了在单次迭代前对行数据和列数据进行采样的能力。这种技术通常是有效的,因为它能够产生更多不同的树划分,这意味着我们能够得到更多关于模型的总体信息。为了更好地理解为什么这样做有效,请阅读我关于随机森林的博客,随机森林也采用相同的随机采样技术。

梯度提升实践

梯度提升在实践中具有令人难以置信的效果。XGBoost,可能是目前梯度提升最流行的算法实现,在一些获胜的Kaggle解决方案中得到了广泛的应用。XGBoost在实现上采用了一些技巧,使它比传统的梯度提升(特别是二阶梯度下降)更快更准确,我建议你尝试一下XGBoost,阅读Tianqi Chen关于XGBoost算法的论文。据说,微软的LightGBM是XGBoost的一个新的竞争对手,正在逐渐得到关注。

我们还能做什么呢?虽然本篇文章将梯度提升用于回归模型,但它也同样在分类和排名模型中非常有效。对于一个需要最小化的给定算法,只要我们能够为其找到一个可微的损失函数,那么我们就可以高效地求解。逻辑函数通常用于二分类问题,而softmax函数则经常用于多分类问题。


数十款阿里云产品限时折扣中,赶紧点击领劵开始云上实践吧!

以上为译文

本文由北邮@爱可可-爱生活 老师推荐,阿里云云栖社区组织翻译。

文章原标题《A Kaggle Master Explains Gradient Boosting》,作者:Felipe Hoffa,译者:6816816151,校对:爱小乖

文章为简译,更为详细的内容,请查看原文

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值