GBDT(Gradient Boosting Decision Tree) 又叫 MART(Multiple Additive Regression Tree),是一种迭代的决策树算法,该算法由多棵决策树组成,全部树的结论累加起来作最终答案。它在被提出之初就和SVM一块儿被认为是泛化能力较强的算法。
GBDT中的树是回归树(不是分类树),GBDT用来作回归预测,调整后也能够用于分类。c++
集成学习(ensemble learning)经过构建并结合多个学习器来完成学习任务。如何产生“好而不一样”的个体学习器,是集成学习研究的核心。算法
根据个体学习器的生成方式,能够将集成学习方法大体分为两大类:网络
对于adaboost,bagging和随机森林能够参考集成学习方法多线程
Boosting是一族可将弱学习器提高为强学习器的算法。boosting方法经过分步迭代(stage-wise)的方式来构建模型,在迭代的每一步构建的弱学习器都是为了弥补已有模型的不足。(个体学习器之间存在强依赖关系。)dom
boosting族算法的著名表明:AdaBoost。
AdaBoost算法经过给已有模型预测错误的样本更高的权重,使得先前的学习器作错的训练样本在后续受到更多的关注的方式来弥补已有模型的不足。机器学习
GBDT主要由三个概念组成:函数
Regression Decistion Tree(即DT),Gradient Boosting(即GB),Shrinkage (算法的一个重要演进分枝,目前大部分源码都按该版本实现)。搞定这三个概念后就能明白GBDT是如何工做的。性能
提起决策树(DT, Decision Tree) 绝大部分人首先想到的就是C4.5分类决策树。但若是一开始就把GBDT中的树想成分类树,那就错了。千万不要觉得GBDT是不少棵分类树。决策树分为两大类,回归树和分类树。前者用于预测实数值,如明天的温度、用户的年龄、网页的相关程度;后者用于分类标签值,如晴天/阴天/雾/雨、用户性别、网页是不是垃圾页面。这里要强调的是,前者的结果加减是有意义的,如10岁+5岁-3岁=12岁,后者则无心义,如男+男+女=究竟是男是女?GBDT的核心在于累加全部树的结果做为最终结果,就像前面对年龄的累加(-3是加负3),而分类树的结果显然是没办法累加的,因此GBDT中的树都是回归树,不是分类树,这点对理解GBDT至关重要(尽管GBDT调整后也可用于分类但不表明GBDT的树是分类树)。学习
回归树整体流程相似于分类树,区别在于,回归树的每个节点都会得一个预测值,以年龄为例,该预测值等于属于这个节点的全部人年龄的平均值。分枝时穷举每个feature的每一个阈值找最好的分割点,但衡量最好的标准再也不是最大熵,而是最小化平方偏差。也就是被预测出错的人数越多,错的越离谱,平方偏差就越大,经过最小化平方偏差可以找到最可靠的分枝依据。分枝直到每一个叶子节点上人的年龄都惟一或者达到预设的终止条件(如叶子个数上限),若最终叶子节点上人的年龄不惟一,则以该节点上全部人的平均年龄作为该叶子节点的预测年龄。
测试
回归树算法以下图(截图来自《统计学习方法》5.5.1 CART生成):
梯度提高(Gradient boosting)是一种用于回归、分类和排序任务的机器学习技术[1],属于Boosting算法族的一部分。Boosting是一族可将弱学习器提高为强学习器的算法,属于集成学习(ensemble learning)的范畴。Boosting方法基于这样一种思想:对于一个复杂任务来讲,将多个专家的判断进行适当的综合所得出的判断,要比其中任何一个专家单独的判断要好。通俗地说,就是“三个臭皮匠顶个诸葛亮”的道理。梯度提高同其余boosting方法同样,经过集成(ensemble)多个弱学习器,一般是决策树,来构建最终的预测模型。
Boosting、bagging和stacking是集成学习的三种主要方法。
不一样于bagging方法,boosting方法经过分步迭代(stage-wise)的方式来构建模型,在迭代的每一步构建的弱学习器都是为了弥补已有模型的不足。Boosting族算法的著名表明是AdaBoost。AdaBoost算法经过给已有模型预测错误的样本更高的权重,使得先前的学习器作错的训练样本在后续受到更多的关注的方式来弥补已有模型的不足。
相比于AdaBoost,梯度提高方法的优势:
虽然同属于Boosting族,可是梯度提高方法的优势比较多。
提高树是迭代多棵回归树来共同决策。当采用平方偏差损失函数时,每一棵回归树学习的是以前全部树的结论和残差,拟合获得一个当前的残差回归树,残差的意义如公式:残差 = 真实值 - 预测值 。提高树便是整个迭代过程生成的回归树的累加。GBDT的核心就在于,每一棵树学的是以前全部树结论和的残差,这个残差就是一个加预测值后能得真实值的累加量。
这与决策树算法自身的优势有很大的关系:
一、 决策树能够认为是if-then规则的集合,易于理解,可解释性强,预测速度快;
二、决策树算法相比于其余的算法须要更少的特征工程,好比能够不用作特征标准化,能够很好的处理字段缺失的数据,也能够不用关心特征间是否相互依赖等
三、决策树可以自动组合多个特征,它能够毫无压力地处理特征间的交互关系而且是非参数化的,所以你没必要担忧异常值或者数据是否线性可分。
举个例子,西瓜a(乌黑色、纹路清晰)多是好瓜,西瓜b(青绿色,纹路清晰)的也多是好瓜。决策树同样能够处理。
单独使用决策树算法时,有容易过拟合缺点。怎么解决呢?
因而可知,梯度提高方法和决策树学习算法能够互相取长补短,是一对完美的搭档。
抑制单颗决策树的复杂度的方法有不少:
如今主流的GBDT算法实现中这些方法基本上都有实现,所以GBDT算法的超参数仍是比较多的,应用过程当中须要精心调参,并用交叉验证的方法选择最佳参数。
提高树利用加法模型和前向分步算法实现学习的优化过程。当损失函数时平方损失和指数损失函数时,每一步的优化很简单,如平方损失函数学习残差回归树。
提高方法实际上是一个比adaboost概念更大的算法,由于adaboost能够表示为boosting的前向分布算法(Forward stagewise additive modeling)的一个特例,boosting最终能够表示为:
其中的w是权重,Φ是弱分类器(回归器)的集合,其实就是一个加法模型(即基函数的线性组合)
前向分布算法其实是一个贪心的算法,也就是在每一步求解弱分类器Φ(m)和其参数w(m)的时候不去修改以前已经求好的分类器和参数:
OK,这也就是提高方法(以前向分布算法)的大体结构了,能够看到其中存在变数的部分其实就是极小化损失函数 这关键的一步了,如何选择损失函数决定了算法的最终效果(名字)……这一步你能够看出算法的“趋势”,之后再单独把“趋势”拿出来讲吧,由于我感受理解算法的关键之一就是理解算法公式的“趋势”
不一样的损失函数和极小化损失函数方法决定了boosting的最终效果,咱们如今来讲几个常见的boosting:
广义上来说,所谓的Gradient Boosting 其实就是在更新的时候选择梯度降低的方向来保证最后的结果最好,一些书上讲的“残差” 方法其实就是L2Boosting吧,由于它所定义的残差其实就是L2Boosting的Derivative,接下来咱们着重讲一下弱回归器是决策树的状况,也就是GBDT。
GBDT算法能够当作是由K棵树组成的加法模型:
解这一优化问题,能够用前向分布算法(forward stagewise algorithm)。由于学习的是加法模型,若是可以从前日后,每一步只学习一个基函数及其系数(结构),逐步逼近优化目标函数,那么就能够简化复杂度。这一学习过程称之为Boosting。具体地,咱们从一个常量预测开始,每次学习一个新的函数,过程以下:
举个例子,参考自一篇博客, 该博客举出的例子较直观地展示出多棵决策树线性求和过程以及残差的意义。
仍是年龄预测,简单起见训练集只有4我的,A,B,C,D,他们的年龄分别是14,16,24,26。其中A、B分别是高一和高三学生;C,D分别是应届毕业生和工做两年的员工。若是是用一棵传统的回归决策树来训练,会获得以下图1所示结果:
如今咱们使用GBDT来作这件事,因为数据太少,咱们限定叶子节点作多有两个,即每棵树都只有一个分枝,而且限定只学两棵树。咱们会获得以下图2所示结果:
在第一棵树分枝和图1同样,因为A,B年龄较为相近,C,D年龄较为相近,他们被分为两拨,每拨用平均年龄做为预测值。此时计算残差(残差的意思就是: A的预测值 + A的残差 = A的实际值),因此A的残差就是15-16=-1(注意,A的预测值是指前面全部树累加的和,这里前面只有一棵树因此直接是15,若是还有树则须要都累加起来做为A的预测值)。进而获得A,B,C,D的残差分别为-1,1,-1,1。而后咱们拿残差替代A,B,C,D的原值,到第二棵树去学习,若是咱们的预测值和它们的残差相等,则只需把第二棵树的结论累加到第一棵树上就能获得真实年龄了。这里的数据显然是我能够作的,第二棵树只有两个值1和-1,直接分红两个节点。此时全部人的残差都是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
那么哪里体现了Gradient呢?其实回到第一棵树结束时想想,不管此时的cost function是什么,是均方差仍是均差,只要它以偏差做为衡量标准,残差向量(-1, 1, -1, 1)都是它的全局最优方向,这就是Gradient。
讲到这里咱们已经把GBDT最核心的概念、运算过程讲完了!没错就是这么简单。
该例子很直观的能看到,预测值等于全部树值得累加,如A的预测值 = 树1左节点 值 15 + 树2左节点 -1 = 14。
所以,给定当前模型 fm-1(x),只须要简单的拟合当前模型的残差。现将回归问题的提高树算法叙述以下:
答案是过拟合。过拟合是指为了让训练集精度更高,学到了不少”仅在训练集上成立的规律“,致使换一个数据集当前规律就不适用了。其实只要容许一棵树的叶子节点足够多,训练集老是能训练到100%准确率的(大不了最后一个叶子上只有一个instance)。在训练精度和实际精度(或测试精度)之间,后者才是咱们想要真正获得的。
咱们发现图1为了达到100%精度使用了3个feature(上网时长、时段、网购金额),其中分枝“上网时长>1.1h” 很显然已通过拟合了,这个数据集上A,B也许刚好A天天上网1.09h, B上网1.05小时,但用上网时间是否是>1.1小时来判断全部人的年龄很显然是有悖常识的;
相对来讲图2的boosting虽然用了两棵树 ,但其实只用了2个feature就搞定了,后一个feature是问答比例,显然图2的依据更靠谱。(固然,这里是LZ故意作的数据,因此才能靠谱得如此狗血。实际中靠谱不靠谱老是相对的) Boosting的最大好处在于,每一步的残差计算其实变相地增大了分错instance的权重,而已经分对的instance则都趋向于0。这样后面的树就能愈来愈专一那些前面被分错的instance。就像咱们作互联网,老是先解决60%用户的需求凑合着,再解决35%用户的需求,最后才关注那5%人的需求,这样就能逐渐把产品作好,由于不一样类型用户需求可能彻底不一样,须要分别独立分析。若是反过来作,或者刚上来就必定要作到尽善尽美,每每最终会竹篮打水一场空。
Shrinkage(缩减)的思想认为,每次走一小步逐渐逼近结果的效果,要比每次迈一大步很快逼近结果的方式更容易避免过拟合。即它不彻底信任每个棵残差树,它认为每棵树只学到了真理的一小部分,累加的时候只累加一小部分,经过多学几棵树弥补不足。用方程来看更清晰,即
没用Shrinkage时:(yi表示第i棵树上y的预测值, y(1~i)表示前i棵树y的综合预测值)
y(i+1) = 残差(y1~yi), 其中: 残差(y1~yi) = y真实值 - y(1 ~ i)
y(1 ~ i) = SUM(y1, ..., yi)
Shrinkage不改变第一个方程,只把第二个方程改成:
y(1 ~ i) = y(1 ~ i-1) + step * yi
即Shrinkage仍然以残差做为学习目标,但对于残差学习出来的结果,只累加一小部分(step残差)逐步逼近目标,step通常都比较小,如0.01~0.001(注意该step非gradient的step),致使各个树的残差是渐变的而不是陡变的。直觉上这也很好理解,不像直接用残差一步修复偏差,而是只修复一点点,其实就是把大步切成了不少小步。本质上,Shrinkage为每棵树设置了一个weight,累加时要乘以这个weight,但和Gradient并无关系*。 这个weight就是step。就像Adaboost同样,Shrinkage能减小过拟合发生也是经验证实的,目前尚未看到从理论的证实。
该版本GBDT几乎可用于全部回归问题(线性/非线性),相对logistic regression仅能用于线性回归,GBDT的适用面很是广。亦可用于二分类问题(设定阈值,大于阈值为正例,反之为负例)。
如下摘自知乎上的一个问答(详见参考文献8),问题和回复都很好的阐述了这个参数设置的数学原理。
【问】xgboost/gbdt在调参时为何树的深度不多就能达到很高的精度?
用xgboost/gbdt在在调参的时候把树的最大深度调成6就有很高的精度了。可是用DecisionTree/RandomForest的时候须要把树的深度调到15或更高。用RandomForest所须要的树的深度和DecisionTree同样我能理解,由于它是用bagging的方法把DecisionTree组合在一块儿,至关于作了屡次DecisionTree同样。可是xgboost/gbdt仅仅用梯度上升法就能用6个节点的深度达到很高的预测精度,使我惊讶到怀疑它是黑科技了。请问下xgboost/gbdt是怎么作到的?它的节点和通常的DecisionTree不一样吗?
【答】
这是一个很是好的问题,题主对各算法的学习很是细致透彻,问的问题也关系到这两个算法的本质。这个问题其实并非一个很简单的问题,我尝试用我浅薄的机器学习知识对这个问题进行回答。
一句话的解释,来自周志华老师的机器学习教科书( 机器学习-周志华):Boosting主要关注下降误差,所以Boosting能基于泛化性能至关弱的学习器构建出很强的集成;Bagging主要关注下降方差,所以它在不剪枝的决策树、神经网络等学习器上效用更为明显。
随机森林(random forest)和GBDT都是属于集成学习(ensemble learning)的范畴。集成学习下有两个重要的策略Bagging和Boosting。
Bagging算法是这样作的:每一个分类器都随机从原样本中作有放回的采样,而后分别在这些采样后的样本上训练分类器,而后再把这些分类器组合起来。简单的多数投票通常就能够。其表明算法是随机森林。Boosting的意思是这样,他经过迭代地训练一系列的分类器,每一个分类器采用的样本分布都和上一轮的学习结果有关。其表明算法是AdaBoost, GBDT。
其实就机器学习算法来讲,其泛化偏差能够分解为两部分,误差(bias)和方差(variance)。这个可由下图的式子导出(这里用到了几率论公式D(X)=E(X2)-[E(X)]2)。误差指的是算法的指望预测与真实预测之间的误差程度,反应了模型自己的拟合能力;方差度量了同等大小的训练集的变更致使学习性能的变化,刻画了数据扰动所致使的影响。这个有点儿绕,不过你必定知道过拟合。
以下图所示,当模型越复杂时,拟合的程度就越高,模型的训练误差就越小。但此时若是换一组数据可能模型的变化就会很大,即模型的方差很大。因此模型过于复杂的时候会致使过拟合。
当模型越简单时,即便咱们再换一组数据,最后得出的学习器和以前的学习器的差异就不那么大,模型的方差很小。仍是由于模型简单,因此误差会很大。
也就是说,当咱们训练一个模型时,误差和方差都得照顾到,漏掉一个都不行。
对于Bagging算法来讲,因为咱们会并行地训练不少不一样的分类器的目的就是下降这个方差(variance) ,由于采用了相互独立的基分类器多了之后,h的值天然就会靠近.因此对于每一个基分类器来讲,目标就是如何下降这个误差(bias),因此咱们会采用深度很深甚至不剪枝的决策树。
对于Boosting来讲,每一步咱们都会在上一轮的基础上更加拟合原数据,因此能够保证误差(bias),因此对于每一个基分类器来讲,问题就在于如何选择variance更小的分类器,即更简单的分类器,因此咱们选择了深度很浅的决策树。
Gradient Boosting算法:xgboost,在计算速度和准确率上,较GBDT有明显的提高。xgboost 的全称是eXtreme Gradient Boosting,它是Gradient Boosting Machine的一个c++实现,做者为正在华盛顿大学研究机器学习的大牛陈天奇 。xgboost最大的特色在于,它可以自动利用CPU的多线程进行并行,同时在算法上加以改进提升了精度。它的处女秀是Kaggle的 希格斯子信号识别竞赛,由于出众的效率与较高的预测准确度在比赛论坛中引发了参赛选手的普遍关注。值得咱们在GBDT的基础上对其进一步探索学习。
参考: