梯度提升是构建预测模型最强大的技术之一。
在这篇文章中,您将了解梯度提升机器学习算法,并对其起源和工作原理有一个初步的认识。
阅读本文后,你将了解:
- 提升(Boosting)在学习理论和 AdaBoost 中的起源。
- 梯度提升如何工作,包括损失函数、弱学习器和加性模型。
- 如何通过各种正则化方案改进基础算法的性能。
通过我的新书《XGBoost With Python》启动您的项目,其中包括所有示例的分步教程和 Python 源代码文件。
让我们开始吧。

机器学习梯度提升算法简明介绍
图片由 brando.n 拍摄,保留部分权利。
在 Python 中使用 XGBoost 需要帮助吗?
参加我的免费 7 天电子邮件课程,探索 xgboost(含示例代码)。
立即点击注册,还将免费获得本课程的 PDF 电子书版本。
提升的起源
提升的思想源于一个问题:弱学习器是否可以被修改以变得更好。
Michael Kearns 将目标阐述为“假设提升问题”,从实践角度将其目标描述为
……一种将相对较差的假设转化为非常好的假设的有效算法
— 关于假设提升的思考 [PDF],1988
弱假设或弱学习器被定义为性能至少略优于随机猜测的假设或学习器。
这些想法建立在 Leslie Valiant 关于独立于分布的或可能近似正确(PAC)学习的工作之上,这是一个用于研究机器学习问题复杂性的框架。
假设提升的思想是过滤观测值,保留弱学习器可以处理的观测值,并专注于开发新的弱学习器来处理剩余的困难观测值。
其思想是多次使用弱学习方法,以获得一系列假设,每个假设都重新聚焦于那些前一个假设发现困难且错误分类的例子。……然而,请注意,如何做到这一点并不明显。
— 可能近似正确:自然界在复杂世界中学习和繁荣的算法,第 152 页,2013
AdaBoost:第一个提升算法
第一个在应用中取得巨大成功的提升实现是自适应提升,简称 AdaBoost。
提升指的是通过结合粗糙且中等不准确的经验法则,生成一个非常准确的预测规则的通用问题。
— 在线学习的决策论泛化及其在提升中的应用 [PDF],1995
AdaBoost 中的弱学习器是只有一次分割的决策树,因其短小而被称作决策树桩。
AdaBoost 的工作原理是对观测值进行加权,对难以分类的实例赋予更大的权重,而对那些已经处理得很好的实例赋予较小的权重。新的弱学习器会按顺序添加,它们将训练重点放在更困难的模式上。
这意味着难以分类的样本会获得越来越大的权重,直到算法识别出一个能正确分类这些样本的模型。
— 应用预测建模,2013
预测是通过弱学习器预测的多数投票来完成的,并根据它们各自的准确性进行加权。AdaBoost 算法最成功的形式是用于二元分类问题,被称为 AdaBoost.M1。
您可以在这篇文章中了解更多关于 AdaBoost 算法的信息。
AdaBoost 作为梯度提升的泛化
AdaBoost 及相关算法首先由 Breiman 重新置于统计框架中,并将其称为 ARCing 算法。
Arcing 是 Adaptive Reweighting and Combining(自适应重加权和组合)的首字母缩写。弧形算法中的每一步都包括加权最小化,然后重新计算 [分类器] 和 [加权输入]。
— 预测博弈和弧形算法 [PDF],1997
这个框架由 Friedman 进一步发展,并被称为梯度提升机。后来又简称为梯度提升或梯度树提升。
统计框架将提升(boosting)视为一个数值优化问题,目标是通过使用类似梯度下降的过程添加弱学习器来最小化模型的损失。
这类算法被描述为阶段性加性模型。这是因为每次只添加一个新的弱学习器,而模型中现有的弱学习器则被冻结并保持不变。
请注意,这种阶段性策略与分步方法不同,分步方法在添加新项时会重新调整先前输入的项。
— 贪婪函数逼近:梯度提升机 [PDF],1999
这种泛化允许使用任意可微分的损失函数,将该技术扩展到二元分类问题之外,支持回归、多分类等。
梯度提升的工作原理
梯度提升包含三个要素
- 要优化的损失函数。
- 用于进行预测的弱学习器。
- 用于添加弱学习器以最小化损失函数的加性模型。
1. 损失函数
所使用的损失函数取决于所解决的问题类型。
它必须是可微分的,但支持许多标准损失函数,您也可以自定义。
例如,回归可以使用平方误差,分类可以使用对数损失。
梯度提升框架的一个好处是,对于每种可能想要使用的损失函数,不必派生出一种新的提升算法;相反,它是一个足够通用的框架,可以使用任何可微分的损失函数。
2. 弱学习器
在梯度提升中,决策树被用作弱学习器。
具体来说,使用的是回归树,它们为分割输出实数值,并且它们的输出可以相加,从而允许后续模型的输出相加并“纠正”预测中的残差。
树以贪婪的方式构建,根据基尼(Gini)等纯度得分或最小化损失来选择最佳分割点。
最初,例如在 AdaBoost 的情况下,使用了非常短的决策树,只有一次分割,称为决策树桩。通常可以使用 4 到 8 层深的更大树。
通常以特定方式限制弱学习器,例如最大层数、节点数、分割数或叶节点数。
这是为了确保学习器保持弱,但仍能以贪婪的方式构建。
3. 加性模型
树一次添加一个,模型中已有的树不会改变。
在添加树时,使用梯度下降过程来最小化损失。
传统上,梯度下降用于最小化一组参数,例如回归方程中的系数或神经网络中的权重。在计算误差或损失后,更新权重以最小化该误差。
我们不是参数,而是弱学习器子模型,更具体地说是决策树。在计算损失后,为了执行梯度下降过程,我们必须向模型添加一棵树以减少损失(即,跟随梯度)。我们通过参数化树,然后修改树的参数并朝着正确的方向移动(通过减少残差损失)来做到这一点。
通常这种方法被称为函数梯度下降或带函数的梯度下降。
产生优化 [成本] 的分类器加权组合的一种方法是函数空间中的梯度下降。
— 函数空间中的梯度下降作为提升算法 [PDF],1999
然后,新树的输出将添加到现有树序列的输出中,以期纠正或改进模型的最终输出。
添加固定数量的树,或者一旦损失达到可接受的水平,或者在外部验证数据集上不再改善,就停止训练。
基本梯度提升的改进
梯度提升是一种贪婪算法,它会很快使训练数据集过拟合。
它可以通过惩罚算法各个部分的正则化方法来受益,并通常通过减少过拟合来提高算法的性能。
在本节中,我们将探讨基本梯度提升的 4 项增强功能
- 树约束
- 收缩
- 随机抽样
- 惩罚学习
1. 树约束
重要的是弱学习器要有技能但保持弱。
有多种方法可以约束树。
一个很好的通用启发式是,树创建的约束越多,模型中需要的树就越多;反之,单个树的约束越少,需要的树就越少。
以下是对决策树构建施加的一些约束:
- 树的数量,通常向模型添加更多树会非常缓慢地导致过拟合。建议是持续添加树,直到不再观察到改进为止。
- 树的深度,更深的树是更复杂的树,更短的树更受青睐。通常,4-8 层的树会产生更好的结果。
- 节点数或叶节点数,与深度类似,这可以约束树的大小,但如果使用其他约束,则不限于对称结构。
- 每次分割的观测值数量 对训练节点上的训练数据量施加了一个最小约束,在此之前才能考虑分割。
- 损失的最小改进 是对添加到树中的任何分割的改进的约束。
2. 加权更新
每棵树的预测值按顺序相加。
每棵树对这个和的贡献可以加权,以减缓算法的学习速度。这种加权称为收缩或学习率。
每次更新都简单地按“学习率参数 v”的值进行缩放。
— 贪婪函数逼近:梯度提升机 [PDF],1999
其效果是学习速度减慢,从而需要向模型中添加更多的树,从而需要更长的训练时间,从而在树的数量和学习率之间提供了配置权衡。
减小 v [学习率] 的值会增加 M [树的数量] 的最佳值。
— 贪婪函数逼近:梯度提升机 [PDF],1999
通常取 0.1 到 0.3 范围内的较小值,以及小于 0.1 的值。
类似于随机优化中的学习率,收缩减少了每棵树的独立影响,并为未来的树改进模型留下了空间。
— 随机梯度提升 [PDF],1999
3. 随机梯度提升
对 Bagging 集成和随机森林的一个重要见解是允许从训练数据集的子样本中贪婪地创建树。
同样的优势可以用来减少梯度提升模型中序列中树之间的相关性。
这种提升的变体称为随机梯度提升。
在每次迭代中,从完整的训练数据集中随机(不放回)抽取一个训练数据的子样本。然后使用随机选择的子样本,而不是完整的样本,来拟合基本学习器。
— 随机梯度提升 [PDF],1999
随机提升的一些变体可以使用:
- 在创建每棵树之前对行进行子采样。
- 在创建每棵树之前对列进行子采样。
- 在考虑每次分割之前对列进行子采样。
一般来说,激进的子采样,例如只选择 50% 的数据,已被证明是有益的。
根据用户反馈,使用列子采样比传统的行子采样更能防止过拟合。
— XGBoost: 一种可扩展的树提升系统,2016
4. 惩罚梯度提升
除了它们的结构之外,还可以对参数化树施加额外的约束。
经典的决策树(如 CART)不被用作弱学习器,而是使用一种称为回归树的修改形式,其叶节点(也称为终端节点)中具有数值。在某些文献中,树的叶子中的值可以被称为权重。
因此,可以使用流行的正则化函数对树的叶权重值进行正则化,例如
- 权重的 L1 正则化。
- 权重的 L2 正则化。
额外的正则化项有助于平滑最终学习到的权重,以避免过拟合。直观地说,正则化目标倾向于选择一个使用简单且预测性函数的模型。
— XGBoost: 一种可扩展的树提升系统,2016
梯度提升资源
梯度提升是一个迷人的算法,我相信您一定想深入了解。
本节列出了可用于了解更多梯度提升算法的各种资源。
梯度提升视频
- 梯度提升机器学习,Trevor Hastie,2014
- 梯度提升,Alexander Ihler,2012
- GBM,John Mount,2015
- 学习:提升,MIT 6.034 人工智能,2010
- xgboost:一个用于快速准确梯度提升的 R 包, 2016
- XGBoost:一个可扩展的树提升系统,Tianqi Chen,2016
教材中的梯度提升
- 第 8.2.3 节 提升,第 321 页,统计学习导论:R 中的应用。
- 第 8.6 节 提升,第 203 页,应用预测建模。
- 第 14.5 节 随机梯度提升,第 390 页,应用预测建模。
- 第 16.4 节 提升,第 556 页,机器学习:概率视角
- 第 10 章 提升和加性树,第 337 页,统计学习的要素:数据挖掘、推理和预测
梯度提升论文
- 关于假设提升的思考 [PDF],Michael Kearns,1988
- 在线学习的决策论泛化及其在提升中的应用 [PDF],1995
- Arcing the edge [PDF],1998
- 随机梯度提升 [PDF],1999
- 函数空间中的梯度下降作为提升算法 [PDF],1999
梯度提升幻灯片
梯度提升网页
总结
在这篇文章中,您了解了用于机器学习中预测建模的梯度提升算法。
具体来说,你学到了:
- 提升在学习理论和 AdaBoost 中的历史。
- 梯度提升算法如何与损失函数、弱学习器和加性模型协同工作。
- 如何通过正则化提高梯度提升的性能。
您对梯度提升算法或这篇文章有什么疑问吗?请在评论中提出您的问题,我将尽力回答。
精彩的评论!!
谢谢。
对梯度提升的极其直观的介绍。
谢谢 Rishabh。
杰森,非常全面细致的概述!
谢谢!很高兴你喜欢。
简直太棒了。
谢谢 Sasikanth。
谢谢 Jason!
不客气。
嗨,Jason,
非常感谢这篇文章,学到了很多。但我仍然有一个地方没有完全理解。梯度树提升只对原始数据进行一次决策树拟合吗?然后将新树添加到第一棵树的残差中?
还是两者都做,既对原始数据拟合多棵树(像随机森林那样),然后又为每棵树拟合新树到其残差中?
很好的问题。
两者兼有。树利用残差误差对数据进行加权,然后新树再拟合这些加权数据。
嗨,Jason,感谢您关于提升的详细文章。
我的问题主要延续了 Rob 提出的问题。每棵树(弱学习器)都是基于我们考虑的学习数据的子样本生成的吗?如果不是,它是否仅基于残差误差或对数损失函数(在分类问题中)?我想了解生成这么多弱学习器背后的机制。
在这方面,一个稍微详细的答案将非常有帮助。
每个后续的弱学习器都是在相同的数据上开发的,通过前一个弱学习器产生的错误进行重新缩放。
嘿,Jason,我有个问题,为了写一篇关于梯度提升的论文,我需要知道
——资源消耗和
-速度/快慢
但我没有找到它。我甚至不太明白。你能帮帮我吗?
您可以设计一个实验来评估这些因素。
非常感谢这篇出色的评论
很高兴它有帮助。
杰森,这真是一篇很棒的文章!
我有点困惑一件事——
您在梯度提升的 3 个组成部分第 1 点中提到的损失函数,是每个弱学习器自身的损失函数吗?比如 AdaBoost 中的误差 = sum(w(i) * terror(i)) / sum(w)?
还是整个集成的损失函数?
每个弱学习器的损失函数。
你好,
我为我的数据拟合了一个线性模型。
我想提取残差,并用这些残差初始化用于回归的梯度提升。理论上和代码中如何实现?
谢谢
有趣的想法。
恐怕您需要从头开始自己编写代码。或者请人为您编写代码。
嗨,Jason,对于惩罚梯度提升,L1 或 L2 正则化,我们该怎么做?需要指定哪个参数?
您可以将 alpha 和 lambda 作为参数传递给 xgboost。
https://docs.xgboost.com.cn/en/latest/parameter.html
嗨,Jason,
我很好奇您是否有在运行梯度提升算法之前进行特征选择的经验。我读到过,预先进行特征选择可以提高预测能力,但我不太明白原因。想知道您是否能对此主题有所启发?不能也没关系。
通常,提升树和 Bagging 树擅长挑选所需的特征。
精力最好花在特征工程上。例如,将所有能想到的东西都扔给模型,让它自己选择哪些是预测性的。
感谢 Jason 的快速回复!我完全同意!为什么要限制算法可以选择的预测器数量,这对我来说没有多大意义!
嗨,Mitchell,Jason。
我认为不应该把所有东西都扔给算法(尽管我是一个经验不足的用户)。如果您有大量的特征,并且它们之间可能存在共线性,那么通过(例如)方差膨胀因子分析来过滤它们不是更好吗?
或者你会把这称为特征工程吗?
祝好,
安德鲁。
在 Python 中,调用 fit 过程时有一个 'sample_weight' 函数。您知道这是模型惩罚某个类别的地方,还是它正在改变输入到树中的数据样本?
谢谢
抱歉,我不了解这个函数。
这太棒了。我一直在寻找一篇不错的梯度提升算法评论,这是迄今为止我发现的最简洁、最易懂的概述。
谢谢,很高兴它有所帮助。
解释得很好
谢谢。
极其有帮助!
很高兴听到这个消息。
引用中有一个错别字:“The idea is to used the weak learning method several times to get a succession of hypotheses, each one refocused on the examples that the previous ones found difficult and misclassified. … Note, however, it is not obvious at all how this can be done”
我认为应该是 "use" 而不是 "used"
谢谢,已修正。
梯度提升在分类设置中究竟是如何工作的?
该算法创建了一个由提升分类树组成的集成。
太棒了。继续努力!
谢谢。
嗨,Jason,
非常感谢这篇评论。
它真的很有帮助。
尽管我读完了所有的文字、您的问题和答案,但我仍然对 GBM 中决策树的生长感到困惑。
我的理解是,GBM 中的决策树使用相同的自变量集,但使用不同的训练数据集(所有训练数据的随机子集)。
我想知道新添加的树与已存在的树之间有什么关系?停止添加决策树的标准是什么?
谢谢!
朱莉娅
不完全是,树是按顺序添加的,以纠正先前树的预测。它们在相同的数据上进行拟合,只是被修改以将注意力集中在先前树所犯的错误上。
添加固定数量的树,我们将这个数量指定为一个超参数。
Jason,
非常感谢!
我仍然有一个关于“固定数量的树”的问题。如果已经添加了固定数量的树,但预测残差仍然不令人满意,我们该怎么办?添加更多的树吗?
朱莉娅
也许,或者也许尝试调整模型的超参数。我有很多关于如何做到这一点的文章和一本书,也许可以从这里开始
https://machinelearning.org.cn/start-here/#xgboost
嗨,Jason,
我读完了整篇文章,但我不太确定我是否完全理解 GB 和 SGB(梯度提升与随机梯度提升)之间的区别。
我的理解是,对于 GB,我们使用整个训练集来训练一棵树;对于 SGB,我们有 3 种选项来对其进行子采样并训练树。
基本上,GB 训练树,而 SGB 训练随机森林吗?
此致,
弗拉德
两种情况下都是树林,只是 SGB 中我们使用采样来增加树的方差。
嗨,Jason,
非常棒的文章。我试着理解 GB 的森林是如何创建的。既然 GB 森林中的每棵树都是在整个数据集上构建/使用相同数据的,那么这些树难道不是都一样吗?
祝好
马丁
谢谢。
不,它们试图纠正它们在序列中之前的树的预测。
啊哈,谢谢。我原以为是森林中的森林被构建。现在清楚了。
谢谢 Jason
不客气。
明白了,Jason,现在说得通了。
非常感谢。
此致,
弗拉德
很高兴听到弗拉德。
你好,
我有一个小疑问。在梯度提升算法中,用于估计区间目标时,为什么第一个预测值会用 mean(y) 初始化?
请帮助
抱歉,我没有梯度提升预测区间的例子。
嗨 Jason。很棒的文章,你能解释一下这种算法,即梯度提升,在处理分类数据方面的可用性吗?
非常感谢 🙂
一个好的起点是将分类变量进行整数编码或独热编码。
非常感谢,这正是我理解 GBM 概念所需要的。
我很高兴它能帮到你。
非常感谢!
有没有办法预测每个特征的方向,尤其是在 GBM 分类中?
变量重要性并不能说明方向,是正向还是负向。
您说的方向具体指什么?
Jason,多么精彩的文章。解释得清晰透彻。非常感谢。
谢谢,很高兴您觉得它有用。
3. 随机梯度提升
对 Bagging 集成和随机森林的一个重要见解是允许从训练数据集的子样本中贪婪地创建树。
同样的优势可以用来减少梯度提升模型中序列中树之间的相关性。
这种提升的变体称为随机梯度提升。
在每次迭代中,从完整的训练数据集中随机(不放回)抽取一个训练数据的子样本。然后使用随机选择的子样本,而不是完整的样本,来拟合基本学习器。
— 随机梯度提升 [PDF],1999
随机提升的一些变体可以使用:
在创建每棵树之前对行进行子采样。
在创建每棵树之前对列进行子采样。
在考虑每次分割之前对列进行子采样。
一般来说,激进的子采样,例如只选择 50% 的数据,已被证明是有益的。
根据用户反馈,使用列子采样比传统的行子采样更能防止过拟合。
这一部分也可以称为 Bagging 吗?
如果错了请指正。
在数据的行子集上拟合贪婪树就是 Bagging。
介绍得很好,有没有计划从头开始用 python 编写 gbdt 代码?
目前还没有。
你好,Jason。
我想您能澄清一下 XGBoost 是可微模型还是不可微模型。它们是端到端可训练的吗?因此,当它们与深度学习模型(如深度学习分类器)结合时,可以对它们应用反向传播吗?
是的,损失函数是可微分的——这是梯度提升方法的一大优势——它可以使用任何可微分的损失函数进行拟合。
该模型是端到端可训练的。
不确定将其与神经网络结合是否有意义。
嗨,Jason,
感谢这篇文章
这句话让我困惑
“梯度下降用于最小化一组参数,例如回归方程中的系数或神经网络中的权重”
这句话表明:“梯度下降……最小化……回归中的系数”;我以为梯度下降试图最小化成本/损失函数。具体来说,梯度下降是为了找到*最小化损失函数值*的系数吗?换句话说,系数的值可能会增加,即使它降低了损失函数。
也许我没理解错
再次感谢,
抱歉。是的,梯度下降可以通过最小化损失来找到线性回归中的系数或神经网络中的权重。
为什么当我们在进行多元回归时,梯度提升和 XGBoost 不起作用?也就是说,我有 2 个值需要从给定值中预测
也许可以尝试使用 sklearn 的实现——我认为它支持多输出回归。
如何知道 GBR 模型会预测多少天的数据?请解释一下
您可以将模型配置为根据需要预测任意天数。
这与您如何选择构建预测问题有关,例如模型的输入数量和输出数量。模型本身并不关心这些。
也许这会有帮助。
https://machinelearning.org.cn/multi-step-time-series-forecasting/
写得很好。有一个错别字。“Probably Approximately Correct”写成了“Probability Approximately Correct”。
谢谢。已修复。
这是一个很棒的解释,非常有帮助。
谢谢。
谢谢!
你好,杰森,
您能以同样的方式解释 Light GBM 算法吗?
谢谢。
是的,我有一个教程计划详细解释 LightGBM。
在此之前,也许这会有所帮助
https://machinelearning.org.cn/gradient-boosting-with-scikit-learn-xgboost-lightgbm-and-catboost/
解释得真好。谢谢!
谢谢!
嘿 Jason,文章写得很好。
我有一个关于早期停止的测试集和验证集的疑问。我们可以在不使用早期停止的情况下使用交叉验证进行超参数优化,然后使用测试集进行早期停止,并使用已知的最佳超参数吗?这是否会因为测试集在训练过程中某种程度上参与而影响模型的泛化能力?
早期停止和交叉验证配合得不好,这可能会给您一些启发。
https://machinelearning.org.cn/faq/single-faq/how-do-i-use-early-stopping-with-k-fold-cross-validation-or-grid-search
对于初学者理解梯度提升来说,这是一篇很棒的文章,谢谢!
谢谢!