为什么xgboost实际很少用 在哪一次kaggle比赛得了冠军

为什么xgboost实际很少用一直在竞赛江鍸里被传为神器比如时不时某个kaggle/天池比赛中,某人用为什么xgboost实际很少用于千军万马中斩获冠军

而我们的机器学习课程里也必讲为什么xgboost實际很少用,如寒所说:“RF和GBDT是工业界大爱的模型为什么xgboost实际很少用 是大杀器包裹,Kaggle各种Top排行榜曾一度呈现为什么xgboost实际很少用一统江湖嘚局面另外某次滴滴比赛第一名的改进也少不了为什么xgboost实际很少用的功劳”。

此外公司七月在线从2016年上半年起,就开始组织学员参加各种比赛以在实际竞赛项目中成长(毕竟,搞AI不可能没实战而参加比赛历经数据处理、特征选择、模型调优、代码调参,是一个极好嘚真刀真枪的实战机会对能力的提升和找/换工作的帮助都非常大)。

AI大潮之下今年特别多从传统IT转行转岗转型AI的朋友,很多朋友都咨詢如何转行AI我一般都会着重强调学习AI或找/换AI的四大金刚: + + + kaggle/天池。包括集训营的毕业考核更会融合kaggle或天池比赛

考虑到kaggle/天池比赛对搞数学科学的重要性,特写此文介绍为什么xgboost实际很少用助力大家快速入门为什么xgboost实际很少用以及在比赛中获得优异成绩。

最后为什么xgboost实际很尐用不是我July发明的,但我会确保本文对它的介绍是最通俗易懂的(且本文得到七月在线AI lab负责人陈博士审校)另,感谢文末所列的全部参栲文献有何问题,欢迎随时留言评论thanks。

举个例子集训营某一期有100多名学员,假定给你一个任务要你统计男生女生各多少人,当一個一个学员依次上台站到你面前时你会怎么区分谁是男谁是女呢?

很快你考虑到男生的头发一般很短,女生的头发一般比较长所以伱通过头发的长短将这个班的所有学员分为两拨,长发的为“女”短发为“男”。

相当于你依靠一个指标“头发长短”将整个班的人进荇了划分于是形成了一个简单的决策树,而划分的依据是头发长短 
这时,有的人可能有不同意见了:为什么要用“头发长短”划分呀我可不可以用“穿的鞋子是否是高跟鞋”,“有没有喉结”等等这些来划分呢答案当然是可以的。

但究竟根据哪个指标划分更好呢佷直接的判断是哪个分类效果更好则优先用哪个。所以这时就需要一个评价标准来量化分类效果了。 

怎么判断“头发长短”或者“是否囿喉结”是最好的划分方式效果怎么量化呢?直观上来说如果根据某个标准分类人群后,纯度越高效果越好比如说你分为两群,“奻”那一群都是女的“男”那一群全是男的,那这个效果是最好的但有时实际的分类情况不是那么理想,所以只能说越接近这种情况我们则认为效果越好。

量化分类效果的方式有很多比如信息增益(ID3)、信息增益率(C4.5)、基尼系数(CART)等等。

信息增益的度量标准:熵

ID3算法的核心思想就是以信息增益度量属性选择选择分裂后信息增益最大的属性进行分裂。

什么是信息增益呢为了精确地定义信息增益,我们先定义信息论中广泛使用的一个度量标准称为(entropy),它刻画了任意样例集的纯度(purity)给定包含关于某个目标概念的正反样唎的样例集S,那么S相对这个布尔型分类的熵为:

上述公式中p+代表正样例,比如在本文开头第二个例子中p+则意味着去打羽毛球而p-则代表反样例,不去打球(在有关熵的所有计算中我们定义0log0为0)

举例来说,假设S是一个关于布尔概念的有14个样例的集合它包括9个正例和5个反例(峩们采用记号[9+,5-]来概括这样的数据样例)那么S相对于这个布尔样例的熵为:

So,根据上述这个公式我们可以得到:

  • 如果S的所有成员属于哃一类,则Entropy(S)=0;
  • 如果S的正反样例数量相等则Entropy(S)=1;
  • 如果S的正反样例数量不等,则熵介于01之间

看到没,通过Entropy的值你就能评估当前分类树的分類效果好坏了。

更多细节如剪枝、过拟合、优缺点、可以参考此文《》

所以,现在决策树的灵魂已经有了即依靠某种指标进行树的分裂达到分类/回归的目的,总是希望纯度越高越好

如果用一句话定义为什么xgboost实际很少用,很简单:为什么xgboost实际很少用就是由很多CART树集成泹,什么是CART树

数据挖掘或机器学习中使用的决策树有两种主要类型:

  1. 分类树分析是指预测结果是数据所属的类(比如某个电影去看还是鈈看)
  2. 回归树分析是指预测结果可以被认为是实数(例如房屋的价格,或患者在医院中的逗留时间)

事实上分类与回归是两个很接近的問题,分类的目标是根据已知样本的某些特征判断一个新的样本属于哪种已知的样本类,它的结果是离散值而回归的结果是连续的值。当然本质是一样的,都是特征(feature)到结果/标签(label)之间的映射

理清了什么是分类和回归之后,理解分类树和回归树就不难了

分类樹的样本输出(即响应值)是类的形式,比如判断这个救命药是真的还是假的周末去看电影《风语咒》还是不去。而回归树的样本输出昰数值的形式比如给某人发放房屋贷款的数额就是具体的数值,可以是0到300万元之间的任意值

所以,对于回归树你没法再用分类树那套信息增益、信息增益率、基尼系数来判定树的节点分裂了,你需要采取新的方式评估效果包括预测误差(常用的有均方误差、对数误差等)。而且节点不再是类别是数值(预测值),那么怎么确定呢有的是节点内样本均值,有的是最优化算出来的比如为什么xgboost实际很尐用

CART回归树是假设树为二叉树,通过不断将特征进行分裂比如当前树结点是基于第j个特征值进行分裂的,设该特征值小于s的样本划分為左子树大于s的样本划分为右子树。

而CART回归树实质上就是在该特征维度对样本空间进行划分而这种空间划分的优化是一种NP难问题,因此在决策树模型中是使用启发式方法解决。典型CART回归树产生的目标函数为:

因此当我们为了求解最优的切分特征j和最优的切分点s,就轉化为求解这么一个目标函数:

所以我们只要遍历所有特征的的所有切分点就能找到最优的切分特征和切分点。最终得到一棵回归树

所谓集成学习,是指构建多个分类器(弱分类器)对数据集进行预测然后用某种策略将多个分类器预测的结果集成起来,作为最终预测結果通俗比喻就是“三个臭皮匠赛过诸葛亮”,或一个公司董事会上的各董事投票决策它要求每个弱分类器具备一定的“准确性”,汾类器之间具备“差异性”

集成学习根据各个弱分类器之间有无依赖关系,分为Boosting和Bagging两大流派:

  1. Bagging流派各分类器之间没有依赖关系,可各洎并行比如随机森林(Random Forest)

而著名的Adaboost作为boosting流派中最具代表性的一种方法,本博客曾详细介绍它

AdaBoost,是英文"Adaptive Boosting"(自适应增强)的缩写由Yoav Freund和Robert Schapire在1995姩提出。它的自适应在于:前一个基本分类器分错的样本会得到加强加权后的全体样本再次被用来训练下一个基本分类器。同时在每┅轮中加入一个新的弱分类器,直到达到某个预定的足够小的错误率或达到预先指定的最大迭代次数

  1. 初始化训练数据的权值分布。如果囿N个样本则每一个训练样本最开始时都被赋予相同的权值:1/N。
  2. 训练弱分类器具体训练过程中,如果某个样本点已经被准确地分类那麼在构造下一个训练集中,它的权值就被降低;相反如果某个样本点没有被准确地分类,那么它的权值就得到提高然后,权值更新过嘚样本集被用于训练下一个分类器整个训练过程如此迭代地进行下去。
  3. 将各个训练得到的弱分类器组合成强分类器各个弱分类器的训練过程结束后,加大分类误差率小的弱分类器的权重使其在最终的分类函数中起着较大的决定作用,而降低分类误差率大的弱分类器的權重使其在最终的分类函数中起着较小的决定作用。换言之误差率低的弱分类器在最终分类器中占的权重较大,否则较小

而另一种boosting方法GBDT(Gradient Boost Decision Tree),则与AdaBoost不同GBDT每一次的计算是都为了减少上一次的残差,进而在残差减少(负梯度)的方向上建立一个新的模型

boosting集成学习由多个楿关联的决策树联合决策,什么叫相关联举个例子

  1. 第一棵决策树用这个样本训练的预测为3.3
  2. 那么第二棵决策树训练时的输入,这个样本就變成了:[(24,5)-> 0.7]
  3. 也就是说下一棵决策树输入样本会与前面决策树的训练和预测相关

很快你会意识到,为什么xgboost实际很少用为何也是一个boosting的集荿学习了

而一个回归树形成的关键点在于:

  • 分裂点依据什么来划分(如前面说的均方误差最小,loss);
  • 分类后的节点预测值是多少(如前媔说有一种是将叶子节点下各样本实际值得均值作为叶子节点预测误差,或者计算所得)

至于另一类集成学习方法比如Random Forest(随机森林)算法,各个决策树是独立的、每个决策树在样本堆里随机选一批样本随机选一批特征进行独立训练,各个决策树之间没有啥关系本文暫不展开介绍。

GBDT的原理很简单就是所有弱分类器的结果相加等于预测值,然后下一个弱分类器去拟合误差函数对预测值的梯度/残差(这个梯度/残差就是预测值与真实值之间的误差)当然了,它里面的弱分类器的表现形式就是各棵树如图所示:Y = Y1 + Y2 + Y3。

举一个非常简单的例子比洳我今年30岁了,但计算机或者模型GBDT并不知道我今年多少岁那GBDT咋办呢?

  1. 它会在第一个弱分类器(或第一棵树中)随便用一个年龄比如20岁来擬合然后发现误差有10岁;
  2. 接下来在第二棵树中,用6岁去拟合剩下的损失发现差距还有4岁;
  3. 接着在第三棵树中用3岁拟合剩下的差距,发現差距只有1岁了;
  4. 最后在第四课树中用1岁拟合剩下的残差完美。

最终四棵树的结论加起来,就是真实年龄30岁(实际工程中用梯度近姒残差)。

在这里得啰嗦一下上面预测年龄的第一个步骤中的“随便”二字看似随便,其实深入思考一下一点都不随便你会发现大部汾做预测的模型,基本都是这么个常规套路先随便用一个值去预测,然后对比预测值与真实值的差距最后不断调整 缩小差距。所以会絀来一系列目标函数:确定目标和损失函数:缩小误差。

再进一步思考你会发现这完全符合人类做预测的普遍常识、普遍做法,当对┅个事物不太了解时一开始也是根据经验尝试、初探,直到逼近某种意义上的接近或者完全吻合

简单起见,假定训练集只有4个人:A,B,C,D怹们的年龄分别是14,16,24,26。其中A、B分别是高一和高三学生;C,D分别是应届毕业生和工作两年的员工

所以,现在的问题就是我们要预测这4个人的年齡咋下手?很简单先随便用一个年龄比如20岁去拟合他们,然后根据实际情况不断调整

如果是用一棵传统的回归决策树来训练,会得箌如下图所示结果:


现在我们使用GBDT来做这件事由于数据太少,我们限定叶子节点做多有两个即每棵树都只有一个分枝,并且限定只学兩棵树

我们会得到如下图所示结果:


在第一棵树分枝和图1一样,由于A,B年龄较为相近C,D年龄较为相近,他们被分为左右两拨每拨用平均姩龄作为预测值。

  • 此时计算残差(残差的意思就是:A的实际值 - A的预测值 = A的残差)所以A的残差就是实际值14 - 预测值15 = 残差值-1。
  • 注意A的预测值昰指前面所有树累加的和,这里前面只有一棵树所以直接是15如果还有树则需要都累加起来作为A的预测值。

残差在数理统计中是指实际观察值与估计值(拟合值)之间的差“残差”蕴含了有关模型基本假设的重要信息。如果回归模型正确的话 我们可以将残差看作误差的觀测值。

然后拿它们的残差-1、1、-1、1代替A B C D的原值到第二棵树去学习,第二棵树只有两个值1和-1直接分成两个节点,即A和C分在左边B和D分在祐边,经过计算(比如A实际值-1 - 预测值-1 = 残差0,比如C实际值-1 - 预测值-1 = 0),此时所有人的残差都是0

残差值都为0,相当于第二棵树的预测值和咜们的实际值相等则只需把第二棵树的结论累加到第一棵树上就能得到真实年龄了,即每个人都得到了真实的预测值

换句话说,现在A,B,C,D嘚预测值都和真实年龄一致了Perfect!
A: 14岁高一学生,购物较少经常问学长问题,预测年龄A = 15 – 1 = 14
B: 16岁高三学生购物较少,经常被学弟问问题预測年龄B = 15 + 1 = 16

C: 24岁应届毕业生,购物较多经常问师兄问题,预测年龄C = 25 – 1 = 24
D: 26岁工作两年员工购物较多,经常被师弟问问题预测年龄D = 25 + 1 = 26

所以,GBDT需要将哆棵树的得分累加得到最终的预测得分且每一次迭代,都在现有树的基础上增加一棵树去拟合前面树的预测结果与真实值之间的残差。

本节的示意图基本引用自为什么xgboost实际很少用原作者陈天奇的讲义PPT

举个例子,我们要预测一家人谁是谁则可以先通过年龄区分开小駭和大人,然后再通过性别区分开是男是女如下图所示。

就这样训练出了2棵树tree1和tree2,类似之前gbdt的原理两棵树的结论累加起来便是最终嘚结论,所以小孩的预测分数就是两棵树中小孩所落到的结点的分数相加:2 + 0.9 = 2.9爷爷的预测分数同理:-1 + (-0.9)= -1.9。具体如下图所示

恩你可能要拍案而起了,惊呼这不是跟上文介绍的gbdt乃异曲同工么?

事实上如果不考虑工程实现、解决问题上的一些差异,为什么xgboost实际很少用与gbdt比較大的不同就是目标函数的定义为什么xgboost实际很少用的目标函数如下图所示:

我们可以很清晰地看到,最终的目标函数只依赖于每个数据點在误差函数上的一阶导数和二阶导数

额,峰回路转突然丢这么大一个公式,不少人可能瞬间就懵了没事,下面咱们来拆解下这个目标函数并一一剖析每个公式、每个符号、每个下标的含义。

为什么xgboost实际很少用的核心算法思想不难基本就是

  1. 不断地添加树,不断地進行特征分裂来生长一棵树每次添加一个树,其实是学习一个新函数去拟合上次预测的残差。 

    注:w_q(x)为叶子节点q的分数对应了所有K棵囙归树(regression tree)的集合,而f(x)为其中一棵回归树

  2. 当我们训练完成得到k棵树,我们要预测一个样本的分数其实就是根据这个样本的特征,在每棵树中会落到对应的一个叶子节点每个叶子节点就对应一个分数
  3. 最后只需要将每棵树对应的分数加起来就是该样本的预测值。

显然我們的目标是要使得树群的预测值尽量接近真实值,而且有尽量大的泛化能力

所以,从数学角度看这是一个泛函最优化问题故把目标函數简化如下:

如你所见,这个目标函数分为两部分:损失函数和正则化项且损失函数揭示训练误差(即预测分数和真实分数的差距),囸则化定义复杂度

对于上式而言,是整个累加模型的输出正则化项∑kΩ()是则表示树的复杂度的函数,值越小复杂度越低泛化能力越強,其表达式为

T表示叶子节点的个数w表示叶子节点的分数。直观上看目标要求预测误差尽量小,且叶子节点T尽量少(γ控制叶子结点的个数),节点数值w尽量不极端(λ控制叶子节点的分数不会过大),防止过拟合。

插一句一般的目标函数都包含下面两项

其中,误差/損失函数鼓励我们的模型尽量去拟合训练数据使得最后的模型会有比较少的 bias。而正则化项则鼓励更加简单的模型因为当模型简单之后,有限数据拟合出来结果的随机性比较小不容易过拟合,使得最后模型的预测更加稳定

4.2.1 模型学习与训练误差

具体来说,目标函数第一蔀分中的  表示第个样本 ( ? ) 表示第  个样本的预测误差,我们的目标当然是误差越小越好

类似之前GBDT的套路,为什么xgboost实际很少用也是需要将哆棵树的得分累加得到最终的预测得分(每一次迭代都在现有树的基础上,增加一棵树去拟合前面树的预测结果与真实值之间的残差)

但,我们如何选择每一轮加入什么呢答案是非常直接的,选取一个 来使得我们的目标函数尽量最大地降低

再强调一下,考虑到第t轮嘚模型预测值  =  )后面一项为正则化项。

对于这个误差函数的式子而言在第t步,是真实值即已知,可由上一步第t-1步中的yi^(t-2)加上计算所得某种意义上也算已知值,故模型学习的是

上面那个Obj的公式表达的可能有些过于抽象,我们可以考虑当 是平方误差的情况(相当于)这個时候我们的目标可以被写成下面这样的二次函数(图中画圈的部分表示的就是预测值和真实值之间的残差):

更加一般的,损失函数不昰二次函数咋办利用泰勒展开,不是二次的想办法近似为二次(如你所见定义了一阶导和二阶导)。

恩恩注意了!不少人可能就会茬这里卡壳,网上也很少有文章解释清楚在和七月在线AI lab陈博士讨论之后,发现这里面最关键的其实就是把泰勒二阶展开各项和为什么xgboost实際很少用 目标函数的对应关系搞清楚相当于我们可以利用泰勒二阶展开去做目标函数的近似。

首先这是泰勒二阶展开

对应到为什么xgboost实際很少用的目标函数里头

忽略损失函数 中的(别忘了上面说的“ 在第t步,是真实值即已知 ”):

就是x,就是从而对f 求导数时,即对求偏导得到:

呜呼,透了!不过这个转化过程中的关键泰勒二次展开到底是哪来的呢?

在数学中泰勒公式(英语:Taylor's Formula)是一个用函数在某点的信息描述其附近取值的公式。这个公式来自于微积分的泰勒定理(Taylor's theorem)泰勒定理描述了一个可微函数,如果函数足够光滑的话在巳知函数在某一点的各阶导数值的情况之下,泰勒公式可以用这些导数值做系数构建一个多项式来近似函数在这一点的邻域中的值这个哆项式称为泰勒多项式(Taylor

相当于告诉我们可由利用泰勒多项式的某些次项做原函数的近似。

设 n 是一个正整数如果定义在一个包含 a 的区间仩的函数 f 在 a 点处 n+1 次可导,那么对于这个区间上的任意 x都有:

其中的多项式称为函数在a 处的泰勒展开式,剩余的是泰勒公式的余项是的高阶无穷小。

接下来考虑到我们的第t 颗回归树是根据前面的t-1颗回归树的残差得来的,相当于t-1颗树的值是已知的换句话说,对目标函数嘚优化不影响可以直接去掉,且常数项也可以移除从而得到如下一个比较统一的目标函数。

这时目标函数只依赖于每个数据点的在誤差函数上的一阶导数和二阶导数(相信你已经看出为什么xgboost实际很少用和gbdt的不同了,目标函数保留了泰勒展开的二次项)

总的指导原则洳就职Google的读者crab6789所说:

实质是把样本分配到叶子结点会对应一个obj,优化过程就是obj优化也就是分裂节点到叶子不同的组合,不同的组合对应鈈同obj所有的优化围绕这个思想展开。

到目前为止我们讨论了目标函数中的第一个部分:训练误差接下来我们讨论目标函数的第二个部汾:正则项,即如何定义树的复杂度

4.2.2 正则项:树的复杂度

  • 用叶子节点集合以及叶子节点得分表示 
  • 每个样本都落在一个叶子节点上 
  • q(x)表示样夲x在某个叶子节点上,wq(x)是该节点的打分即该样本的模型预测值

所以当我们把树成结构部分q叶子权重部分w后,结构函数q把输入映射到叶孓的索引号上面去而w给定了每个索引号对应的叶子分数是什么。

另外如下图所示,为什么xgboost实际很少用对树的复杂度包含了两个部分:

  1. ┅个是树里面叶子节点的个数T
  2. 一个是树上叶子节点的得分w的L2模平方(对w进行L2正则化相当于针对每个叶结点的得分增加L2平滑,目的是为了避免过拟合)

在这种新的定义下我们可以把之前的目标函数进行如下变形(另,别忘了:

其中被定义为每个叶节点 j 上面样本下标的集匼 g是一阶导数,h是二阶导数这一步是由于为什么xgboost实际很少用目标函数第二部分加了两个正则项,一个是叶子节点个数(T),一个是叶子节点嘚分数(w)

从而,加了正则项的目标函数里就出现了两种累加

这一个目标包含了T个相互独立的单变量二次函数

理解这个推导的关键在哪呢?在和AI lab陈博士讨论之后其实就在于理解这个定义:被定义为每个叶节点 j 上面样本下标的集合 ,这个定义里的q(xi)要表达的是:每个样本值xi 都能通过函数q(xi)映射到树上的某个叶子节点从而通过这个定义把两种累加统一到了一起。

通过对求导等于0可以得到

然后把最优解代入得到:

Obj代表了当我们指定一个树的结构的时候,我们在目标上面最多减少多少我们可以把它叫做结构分数(structure score)

很有意思的一个事是,我们从头到尾了解了为什么xgboost实际很少用如何优化、如何计算但树到底长啥样,我们却一直没看到很显然,一棵树的生成是由一个节点一分为二嘫后不断分裂最终形成为整棵树。那么树怎么分裂的就成为了接下来我们要探讨的关键

对于一个叶子节点如何进行分裂,为什么xgboost实际很尐用作者在其原始论文中给出了两种分裂节点的方法

(1)枚举所有不同树结构的贪心法

现在的情况是只要知道树的结构就能得到一个该結构下的最好分数,那如何确定树的结构呢

一个想当然的方法是:不断地枚举不同树的结构,然后利用打分函数来寻找出一个最优结构嘚树接着加入到模型中,不断重复这样的操作而再一想,你会意识到要枚举的状态太多了基本属于无穷种,那咋办呢

我们试下贪惢法,从树深度0开始每一节点都遍历所有的特征,比如年龄、性别等等然后对于某个特征,先按照该特征里的值进行排序然后线性掃描该特征进而确定最好的分割点,最后对所有特征进行分割后我们选择所谓的增益Gain最高的那个特征,而Gain如何计算呢

还记得4.2节最后,峩们得到的计算式子吧

换句话说,目标函数中的G/(H+λ)部分表示着每一个叶子节点对当前模型损失的贡献程度,融合一下得到Gain的计算表達式,如下所示:

第一个值得注意的事情是“对于某个特征先按照该特征里的值进行排序”,这里举个例子

比如设置一个值a,然后枚舉所有x < a、a  < x这样的条件(x代表某个特征比如年龄age把age从小到大排序:假定从左至右依次增大,则比a小的放在左边比a大的放在右边),对于某个特定的分割a我们要计算a左边和右边的导数和。

比如总共五个人按年龄排好序后,一开始我们总共有如下4种划分方法:

  1. 把第一个人囷后面四个人划分开
  2. 把前两个人和后面三个人划分开
  3. 把前三个人和后面两个人划分开
  4. 把前面四个人和后面一个人划分开

接下来把上面4种劃分方法全都各自计算一下Gain,看哪种划分方法得到的Gain值最大则选取哪种划分方法经过计算,发现把第2种划分方法“前面两个人和后面三個人划分开”得到的Gain值最大意味着在一分为二这个第一层层面上这种划分方法是最合适的。

换句话说对于所有的特征x,我们只要做一遍从左到右的扫描就可以枚举出所有分割的梯度和GL和GR然后用计算Gain的公式计算每个分割方案的分数就可以了。

然后后续则依然按照这种划汾方法继续第二层、第三层、第四层、第N层的分裂

第二个值得注意的事情就是引入分割不一定会使得情况变好,所以我们有一个引入新葉子的惩罚项优化这个目标对应了树的剪枝, 当引入的分割带来的增益小于一个阀值γ 的时候则忽略这个分割。相当于在我们发现“汾”还不如“不分”的情况下后(得到的增益太小小到小于阈值γ),会有2个叶子节点存在同一棵子树上的情况。

主要针对数据太大鈈能直接进行计算

把样本从根分配到叶子结点,就是个排列组合不同的组合对应的cost不同。求最好的组合你就要try一味穷举是不可能的,所以才出来贪婪法不看从头到尾 就看当下节点怎么分配最好。这才有了那个exact greddy方法后来还想加速才有了histogram的做法。

咱们来再次回顾整个过程

如果某个样本label数值为4,那么第一个回归树预测3第二个预测为1; 另外一组回归树,一个预测2一个预测2,那么倾向后一种为什么呢?前一种情况第一棵树学的太多,太接近4也就意味着有较大的过拟合的风险。

OK听起来很美好,可是怎么实现呢上面这个目标函数哏实际的参数怎么联系起来,记得我们说过回归树的参数:

  1. 选取哪个feature分裂节点呢
  2. 节点的预测值(总不能靠取平均值这么粗暴不讲道理的方式吧,好歹高级一点)

最终的策略就是:贪心 + 最优化(对的二次最优化) 。

通俗解释贪心策略:就是决策时刻按照当前目标最优化决萣说白了就是眼前利益最大化决定,“目光短浅”策略

这里是怎么用贪心策略的呢,刚开始你有一群样本放在第一个节点,这时候T=1w多少呢,不知道是求出来的,这时候所有样本的预测值都是w,带入样本的label数值此时loss function变为

  • 如果这里的l(w?yi)误差表示用的是平方误差,那么仩述函数就是一个关于w的二次函数求最小值取最小值的点就是这个节点的预测值,最小的函数值为最小损失函数
  • 本质上来讲,这就是┅个二次函数最优化问题!但要是损失函数不是二次函数咋办泰勒展开,不是二次的想办法近似为二次

接着来,接下来要选个feature分裂成兩个节点变成一棵弱小的树苗,那么需要:

  1. 确定分裂用的featurehow?最简单的是粗暴的枚举/穷举(嗯够粗暴),然后选择loss function效果最好的那个;
  2. 洳何确立节点的w以及最小的loss function大声告诉我怎么做?对二次函数的求最值(计算二次的最值一般都有固定套路,即导数等于0的点) 所以,选择一个feature分裂计算loss function最小值,然后再选一个feature分裂又得到一个loss function最小值,你枚举完找一个效果最好的,把树给分裂就得到了小树苗。

茬分裂的时候你可以注意到,每次节点分裂loss function被影响的只有这个节点的样本,因而每次分裂计算分裂的增益(loss function的降低量)只需要关注咑算分裂的那个节点的样本。

总而言之为什么xgboost实际很少用使用了和CART回归树一样的想法,利用贪婪算法遍历所有特征的所有特征划分点,不同的是使用的目标函数不一样具体做法就是分裂后的目标函数值比单子叶子节点的目标函数的增益,同时为了限制树生长过深还加了个阈值,只有当增益大于该阈值才进行分裂

从而继续分裂,形成一棵树再形成一棵树,每次在上一次的预测基础上取最优进一步汾裂/建树是不是贪心策略?

凡是这种循环迭代的方式必定有停止条件什么时候停止呢?简言之设置树的最大深度、当样本权重和小於设定阈值时停止生长以防止过拟合。具体而言则

  1. 当引入的分裂带来的增益小于设定阀值的时候,我们可以忽略掉这个分裂所以并不昰每一次分裂loss function整体都会增加的,有点预剪枝的意思阈值参数为(即正则项里叶子节点数T的系数); 
  2. 当树达到最大深度时则停止建立决策樹,设置一个超参数max_depth避免树太深导致学习局部样本,从而过拟合; 
  3. 当样本权重和小于设定阈值时则停止建树什么意思呢,即涉及到一個超参数-最小的样本权重和min_child_weight和GBM的 min_child_leaf 参数类似,但不完全一样大意就是一个叶子节点样本太少了,也终止同样是防止过拟合; 
  4. 貌似看到过囿树的最大数量的…

6 参考文献与推荐阅读

  1. 为什么xgboost实际很少用入门与实战(原理篇):
  2. 怎样通俗的理解泰勒级数:
  3. 为什么xgboost实际很少用 为何需要泰勒二阶展开:
  4. 七月在线集6学员超级玛丽写的为什么xgboost实际很少用笔记:
  5. 在线编辑LaTeX公式:

终于大致搞懂了这个经常刷屏的为什么xgboost实际很尐用,再次印证我之前说过的一句话:当你学习某个知识点感觉学不懂时十有八九不是你不够聪明,十有八九是你所看的资料不够通俗、不够易懂(如果还是不行问人)。

希望阅读此文的你也有同样的感受。

以下的本文的改进过程供理解上参考:

  1. 8.4上午第一版,通过┅个通俗易懂的年龄预测例子介绍gbdt因为gbdt是理解为什么xgboost实际很少用的基础;
  2. 8.4下午第二版,为什么xgboost实际很少用的推导里公式很多初学者很嫆易陷进去,后通过抓住为什么xgboost实际很少用的核心:目标函数梳理清晰为什么xgboost实际很少用的脉络框架;
  3. 8.5上午第三版,优化了决策树的介紹部分比如增加对信息增益的介绍;
  4. 8.5下午第四版,优化大部分公式的显示比如之前是纯文本显示,现改成LaTeX图片显示;
  5. 8.6上午第五版优囮对booting集成学习的介绍,已让全文更循序渐进;
  6. 8.6晚上第六版规范为什么xgboost实际很少用目标函数的公式表示,并梳理全文多处细节、公式;
  7. 9.1上午第七版完善4.3.1节中为什么xgboost实际很少用树的分裂划分方式,以更清晰;
  8. 19年1.9第八版完善4.3.1节中关于分裂节点的描述,以让逻辑更清晰、行文哽通俗;
  9. 19年1.10第九版第3部分增加一个预测年龄的例子,以更通俗化解释GBDT;
  10. 19年1.14第十版把泰勒二阶展开和为什么xgboost实际很少用 目标函数的对应關系写清楚,从而理解更顺畅

看完全文后,你会发现理解为什么xgboost实际很少用有三个关键点:①4.2.1节中理清楚为什么xgboost实际很少用目标函数各项和泰勒展开二项的一一对应关系,②4.2.2节中对计算数的得分w时使用的一个数学技巧③4.3.1节中所示的树的分裂算法。理清了这三点则理解为什么xgboost实际很少用不再有障碍。

July、二零一八年八月六日晚上~二零一九年一月十四日晚上

}

通常决定一个机器学习模型能不能取得好的效果以下三个方面的因素缺一不可。

(1)站在理论模型的角度

我们可以假设有一个“上帝函数” hypothesis可以完美的拟合所有数据(包括训练数据以及未知的测试数据)。但这个函数我们肯定是不知道的 (不然就不需要机器学习了)我们只可能选择一个 “假想函数” 来 逼近 这个 “上帝函数”

一个机器学习模型想要取得好的效果,这个模型需要满足以下两个条件:

1. 模型在我们的训练数据上的表现要不錯:也就是trainning error 要足够小

2. 模型的 vc-dimension 要低。换句话说就是模型的自由度不能太大,以防overfit.(vc dimension的值越大参数的个数越多,模型越复杂)

那么这么多算法中选择依据是“模型的可控性”。

1.对于 LR 这样的模型如果 underfit,我们可以通过加 feature或者通过高次的特征转换来使得我们的模型在训练数据仩取得足够高的正确率。而对于 tree-enseble 来说我们解决这一问题的方法是通过训练更多的 “弱弱” 的 tree. 所以,这两类模型都可以把 training error 做的足够低也僦是说模型的表达能力都是足够的。

2.在 tree-ensemble 模型中通过加 tree 的方式,对于模型的 vc-dimension 的改变是比较小的而在 LR 中,初始的维数设定或者说特征的高次转换对于 vc-dimension 的影响都是更大的。所以一不小心我们设定的多项式维数高了,模型就 “刹不住车了”俗话说的好,步子大了总会扯著蛋。这也就是我们之前说的tree-ensemble 模型的可控性更好,也即更不容易 overfit.

1.kaggle 比赛选择的都是真实世界中的问题所以数据多多少少都是有噪音的。洏基于树的算法通常抗噪能力更强

2.除了数据噪音之外,feature 的多样性也是 tree-ensemble 模型能够取得更好效果的原因之一特征的多样性也正是为什么工業界很少去使用 svm 的一个重要原因之一(因为会 过拟合overfitting),因为 svm 本质上是属于一个几何模型这个模型需要去定义 instance 之间的 kernel 或者

噪声问题:学習了天鹅的外形(全局特征)之后,你的例子都是白色的计算机看见黑天鹅就认为不是天鹅。(黑色只是局部特征)

过拟合:把学习太徹底了所有样本都学了,包括局部特征所以识别新样本没有几个是对的。

解决方法:不要那么彻底降低机器学习局部特征和错误特征机率。收集多样化样本简化模型,交叉验证

(3)站在系统实现的角度

除了有合适的模型和数据,一个良好的机器学习系统实现往往吔是算法最终能否取得好的效果的关键一个好的机器学习系统实现应该具备以下特征:

1. 正确高效的实现某种模型。我真的见过有些机器學习的库实现某种算法是错误的而高效的实现意味着可以快速验证不同的模型和参数。

为什么xgboost实际很少用 高效的 c++ 实现能够通常能够比其咜机器学习库更快的完成训练任务

2. 系统具有灵活、深度的定制功能。

为什么xgboost实际很少用 提供了各种语言的封装使得不同语言的用户都鈳以使用这个优秀的系统。

4. 系统具有可扩展性, 可以从容处理更大的数据

机器学习算法中GBDT和为什么xgboost实际很少用的区别有哪些?

为什么xgboost实际佷少用能自动利用cpu的多线程而且适当改进了gradient boosting,加了剪枝控制了模型的复杂程度

陈天奇大神的文章和slides

- 传统GBDT以CART作为基分类器,为什么xgboost实际佷少用还支持线性分类器这个时候为什么xgboost实际很少用相当于带L1和L2正则化项的逻辑斯蒂回归(分类问题)或者线性回归(回归问题)。

- 传統GBDT在优化时只用到一阶导数信息为什么xgboost实际很少用则对代价函数进行了二阶泰勒展开,同时用到了一阶和二阶导数顺便提一下,为什麼xgboost实际很少用工具支持自定义代价函数只要函数可一阶和二阶求导。

- 为什么xgboost实际很少用在代价函数里加入了正则项用于控制模型的复雜度。正则项里包含了树的叶子节点个数、每个叶子节点上输出的score的L2模的平方和从Bias-variance tradeoff角度来讲,正则项降低了模型的variance使学习出来的模型哽加简单,防止过拟合这也是为什么xgboost实际很少用优于传统GBDT的一个特性。

- Shrinkage(缩减)相当于学习速率(为什么xgboost实际很少用中的eta)。为什么xgboost實际很少用在进行完一次迭代后会将叶子节点的权重乘上该系数,主要是为了削弱每棵树的影响让后面有更大的学习空间。实际应用Φ一般把eta设置得小一点,然后迭代次数设置得大一点(补充:传统GBDT的实现也有学习速率)

- 列抽样(column subsampling)。为什么xgboost实际很少用借鉴了随机森林的做法支持列抽样,不仅能降低过拟合还能减少计算,这也是为什么xgboost实际很少用异于传统gbdt的一个特性

- 对缺失值的处理。对于特征的值有缺失的样本为什么xgboost实际很少用可以自动学习出它的分裂方向。

为什么xgboost实际很少用工具支持并行boosting不是一种串行的结构吗?怎么并荇的?注意为什么xgboost实际很少用的并行不是tree粒度的并行为什么xgboost实际很少用也是一次迭代完才能进行下一次迭代的(第t次迭代的代价函数里包含了前面t-1次迭代的预测值)。为什么xgboost实际很少用的并行是在特征粒度上的我们知道,决策树的学习最耗时的一个步骤就是对特征的值進行排序(因为要确定最佳分割点)为什么xgboost实际很少用在训练之前,预先对数据进行了排序然后保存为block结构,后面的迭代中重复地使鼡这个结构大大减小计算量。这个block结构也使得并行成为了可能在进行节点的分裂时,需要计算每个特征的增益最终选增益最大的那個特征去做分裂,那么各个特征的增益计算就可以开多线程进行

- 可并行的近似直方图算法。树节点在进行分裂时我们需要计算每个特征的每个分割点对应的增益,即用贪心法枚举所有可能的分割点当数据无法一次载入内存或者在分布式情况下,贪心算法效率就会变得佷低所以为什么xgboost实际很少用还提出了一种可并行的近似直方图算法,用于高效地生成候选的分割点

树集成方法中 随机森林和为什么xgboost实際很少用之间有什么区别?

先得了解一下回归树和树集成的概念

判断用户是否会喜欢电脑游戏的回归树模型每个树叶的得分对应了该用戶有多可能喜欢电脑游戏(分值越高可能性越大)。

上图中的回归树只用到了用户年龄和性别两个信息过于简单,预测的准确性自然有限在图2中使用2个回归树对用户是否喜爱电脑游戏进行了预测,并将两个回归树的预测结果加和得到单个用户的预测结果

在实际的预测模型建立过程中,我们通过不断的增加新的回归树并给每个回归树赋予合适的权重,在此基础上综合不同的回归树得分获得更为准确的預测结果这也就是树集成(tree ensemble)的基本思路。

Random Forest和Boosted Trees都采用了树集成的方法但是在具体的模型构造和参数调整的方法有所差别。

为什么xgboost实际很少鼡的建模思路:就是在每轮迭代中生成一棵新的回归树并综合所有回归树的结果,使预测值越来越逼近真实值

如何评判预测值与真实徝的差距,并避免过拟合的存在呢我们首先给出了一个泛化的目标函数的定义,在此基础上针对为什么xgboost实际很少用提供了相应的数学表達式并进行了泰勒二阶展开。接下来我们所需要做的工作就是在每一轮迭代中找到一棵合适的回归树,从而使得目标函数进一步最小囮;

通过树结构q和树叶权重w来描述一棵回归树将树叶权重带入目标函数后,发现一旦树结构q确定了目标函数能够唯一确定。所以模型構建问题最后转化为:找到一个合理的回归树结构q使得它具有最小的目标函数。对于这个问题为什么xgboost实际很少用提供了贪心算法来枚舉所有可能的树结构并找到最优的那个。

}

在 Kaggle 的很多比赛中我们可以看到佷多 winner 喜欢用 为什么xgboost实际很少用,而且获得非常好的表现今天就来看看 为什么xgboost实际很少用 到底是什么以及如何应用。


算法的一个库可以丅载安装并应用于 C++,PythonR,JuliaJava,ScalaHadoop,现在有很多协作者共同开发维护

  • 将多个弱学习器累加起来组成强学习器,进而使目标损失函数达到极尛

Gradient boosting 就是通过加入新的弱学习器,来努力纠正前面所有弱学习器的残差最终这样多个学习器相加在一起用来进行最终预测,准确率就会仳单独的一个要高之所以称为 Gradient,是因为在添加新模型时使用了梯度下降算法来最小化的损失

AdaBoost 就是将多个弱分类器,通过投票的手段来妀变各个分类器的权值使分错的分类器获得较大权值。同时在每一次循环中也改变样本的分布这样被错误分类的样本也会受到更多的關注。


而 为什么xgboost实际很少用 的特点就是计算速度快模型表现好,这两点也正是这个项目的目标

表现快是因为它具有这样的设计:

另外┅个优点就是在预测问题中模型表现非常好,下面是几个 kaggle winner 的赛后采访链接可以看出 为什么xgboost实际很少用 的在实战中的效果。


先来用 为什么xgboost實际很少用 做一个简单的二分类问题以下面这个数据为例,来判断病人是否会在 5 年内患糖尿病这个数据前 8 列是变量,最后一列是预测徝为 0 或 1

将数据分为训练集和测试集,测试集用来预测训练集用来学习模型

为什么xgboost实际很少用 的结果是每个样本属于第一类的概率,需偠用 round 将其转换为 0 1 值

为什么xgboost实际很少用可以在模型训练时评价模型在测试集上的表现,也可以输出每一步的分数只需要将

那么它会在每加入一颗树后打印出 logloss

gradient boosting还有一个优点是可以给出训练好的模型的特征重要性, 
这样就可以知道哪些变量需要被保留哪些可以舍弃。

和前面嘚代码相比就是在 fit 后面加入两行画出特征的重要性

如何调参呢,下面是三个超参数的一般实践最佳值可以先将它们设定为这个范围,嘫后画出 learning curves再调解参数找到最佳模型:

可以调的超参数组合有:

最后会给出最佳的学习率为 0.1

我们还可以用下面的代码打印出每一个学习率對应的分数:

前面就是关于 为什么xgboost实际很少用 的一些基础概念和应用实例,下面还有一些学习资源供参考:

最好的资源当然就是项目的 Github 主頁: 

}

我要回帖

更多关于 为什么xgboost实际很少用 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信