详见https://www.cnblogs.com/ModifyRong/p/7744987.html
详见https://www.jianshu.com/p/005a4e6ac775
详见https://www.cnblogs.com/pinard/p/6140514.html
首先gbdt 是通过采用加法模型(即基函数的线性组合),以及不断减小训练过程产生的残差来达到将数据分类或者回归的算法。
gbdt的训练过程
我们通过一张图片来说明gbdt的训练过程:
图1 GBDT 的训练过程
gbdt通过多轮迭代,每轮迭代产生一个弱分类器,每个分类器在上一轮分类器的残差基础上进行训练。对弱分类器的要求一般是足够简单,并且是低方差和高偏差的。因为训练的过程是通过降低偏差来不断提高最终分类器的精度。
弱分类器一般会选择为CART TREE(也就是分类回归树)。由于上述高偏差和简单的要求每个分类回归树的深度不会很深。最终的总分类器是将每轮训练得到的弱分类器加权求和得到的(也就是加法模型)。
模型最终可以描述为:
模型一共训练M轮,每轮产生一个弱分类器T(x;θm)。弱分类器的损失函数为
Fm-1(x)当前的模型,gbdt 通过经验风险极小化来确定下一个弱分类器的参数。具体到损失函数本身的选择也就是L的选择,有平方损失函数,0-1损失函数,对数损失函数等等。如果我们选择平方损失函数,那么这个差值其实就是我们平常所说的残差。
但是其实我们真正关注的,1.是希望损失函数能够不断的减小,2.是希望损失函数能够尽可能快的减小。所以如何尽可能快的减小呢?
让损失函数沿着梯度方向下降。这个就是gbdt的gb的核心了。利用损失函数的负梯度在当前模型的值作为回归问题提升树算法中的残差的近似值去拟合一个回归树。gbdt每轮迭代的时候,都去拟合损失函数在当前模型下的负梯度。
这样每轮训练的时候都能够让损失函数尽可能快的减小,尽快的收敛达到局部最优解或者全局最优解。
gbdt如何选择特征?
gbdt选择特征的细节其实是想问你CART Tree生成的过程。这里有一个前提,gbdt的弱分类器默认选择的是CART TREE。其实也可以选择其他弱分类器的,选择的前提是低方差和高偏差。框架服从boosting 框架即可。
GBDT 如何用于分类?
首先明确一点,gbdt无论用于分类还是回归一直都是使用的CART回归树。不会因为我们所选择的任务是分类任务就选用分类树,这里面的核心是因为gbdt每轮的训练是在上一轮的训练的残差基础之上进行训练的。这里的残差就是当前模型的负梯度值 。这个要求每轮迭代的时候,弱分类器的输出的结果相减是有意义的。残差相减是有意义的。
如果选用的弱分类器是分类树,类别相减是没有意义的。上一轮输出的是样本x属于 A类,本一轮训练输出的是样本x属于 B类。 A和B很多时候甚至都没有比较的意义,A类-B类是没有意义的。
我们具体到分类这个任务上面来,我们假设样本X总共有K类。来了一个样本x,我们需要使用gbdt来判断x属于样本的哪一类。
图2 gbdt 多分类算法流程
第一步:我们在训练的时候,是针对样本X每个可能的类都训练一个分类回归树。举例说明,目前样本有三类,也就是K=3。样本x属于第二类。那么针对该样本 x 的分类结果,其实我们可以用一个三维向量[0,1,0]来表示。0表示样本不属于该类,1表示样本属于该类。由于样本已经属于第二类了,所以第二类对应的向量维度为1,其他位置为0。
针对样本有三类的情况,我们实质上是在每轮的训练的时候是同时训练三颗树。第一颗树针对样本x的第一类,输入为(x,0)。第二颗树输入针对样本x的第二类,输入为(x,1)。第三颗树针对样本x的第三类,输入为(x,0)。
在这里每颗树的训练过程其实就是我们之前已经提到过的CATR TREE 的生成过程。在此处我们参照之前的生成树的程序即可以就解出三颗树,以及三颗树对x类别的预测值f1(x),f2(x),f3(x)。那么在此类训练中,我们仿照多分类的逻辑回归,使用softmax来产生概率,则属于类别1的概率
并且我们我们可以针对类别1 求出残差f11(x)=0-f1(x); 类别2求出残差f22(x)=1-f2(x); 类别3 求出残差f33(x)=0-f3(x).
然后开始第二轮训练针对第一类输入为(x,f11(x)), 针对第二类输入为(x,f22(x)), 针对第三类输入为(x,f33(x))。继续训练出三颗树,一直迭代M轮。每轮构建3颗树。
所以当K=3,我们其实应该有三个式子
当训练完毕以后,新来一个样本x1,我们需要预测该样本的类别的时候,便可以有这三个式子产生三个值,f1(x),f2(x),f3(x)。样本属于某个类别c的概率为
- GBDT 多分类举例说明
上面的理论阐述可能仍旧过于难懂,我们下面将拿Iris 数据集中的六个数据作为例子,来展示gbdt 多分类的过程。
-
-
样本编号 花萼长度(cm) 花萼宽度(cm) 花瓣长度(cm) 花瓣宽度 花的种类 1 5.1 3.5 1.4 0.2 山鸢尾 2 4.9 3.0 1.4 0.2 山鸢尾 3 7.0 3.2 4.7 1.4 杂色鸢尾 4 6.4 3.2 4.5 1.5 杂色鸢尾 5 6.3 3.3 6.0 2.5 维吉尼亚鸢尾 6 5.8 2.7 5.1 1.9 维吉尼亚鸢尾 图3 Iris 数据集
-
这是一个有6个样本的三分类问题。我们需要根据这个花的花萼长度,花萼宽度,花瓣长度,花瓣宽度来判断这个花属于山鸢尾,杂色鸢尾,还是维吉尼亚鸢尾。具体应用到gbdt多分类算法上面。我们用一个三维向量来标志样本的label。[1,0,0] 表示样本属于山鸢尾,[0,1,0] 表示样本属于杂色鸢尾,[0,0,1] 表示属于维吉尼亚鸢尾。
gbdt的多分类是针对每个类都独立训练一个 CART Tree。所以这里,我们将针对山鸢尾类别训练一个CART Tree 1。杂色鸢尾训练一个CART Tree 2 。维吉尼亚鸢尾训练一个CART Tree 3,这三个树相互独立。
我们以样本 1 为例。针对 CART Tree1 的训练样本是【5.1,3.5,1.4,0.2】,label 是 1,最终输入到模型当中的为【5.1,3.5,1.4,0.2,1】。针对 CART Tree2 的训练样本也是【5.1,3.5,1.4,0.2】,但label是0,最终输入模型的为【5.1,3.5,1.4,0.2,1】。对 CART Tree 3的训练样本也是【5.1,3.5,1.4,0.2】,label是0,最终输入模型当中的是【5.1,3.5,1.4,0.2,0】
下面我们来看 CART Tree1 是如何生成的,其他树 CART Tree2 , CART Tree 3的生成方式是一样的。CART Tree的生成过程是从这四个特征中找一个特征做为CART Tree1 的节点。比如花萼长度做为节点。6个样本当中花萼长度大于5.1 cm的就是A类,小于等于 5.1 cm 的是B类。生成的过程其实非常简单,问题 1.是哪个特征最合适? 2.是这个特征的什么特征值作为切分点? 即使我们已经确定了花萼长度做为节点。花萼长度本身也有很多值。在这里我们的方式是遍历所有的可能性,找到一个最好的特征和它对应的最优特征值可以让当前式子的值最小。
我们以第一个特征的第一个特征值为例。R1为所有样本中花萼长度小于5.1cm的样本集合,R2为所有样本当中花萼长度大于等于5.1cm的样本集合。所以 R1={2},R2={1,3,4,5,6}。所以y1为R1所有样本的label的均值1/1=1。y2为R2所有样本的label的均值 (1+0+0+0+0)/5=0.2。
图4 节点分裂示意图
下面便开始针对所有的样本计算这个式子的值。样本1属于R2,计算的值为(1-0.2)2,样本2属于R1,计算的值为(1-1)2,样本3,4,5,6同理都是属于R2的,所以值是(0-0.2)2。 把这六个值加起来,便是山鸢尾类型在特征1的第一个特征值的损失值。这里(1-0.2)^2+(1-1)^2+(0-0.2)^2+(0-0.2)^2+(0-0.2)^2+(0-0.2)^2=0.8。
接着我们计算第一个特征的第二个特征值,计算方式同上,R1为所有样本中花萼长度小于4.9 cm的样本集合,R2 为所有样本当中花萼长度大于等于 4.9cm的样本集合。所以R1={},R2={1,2,3,4,5,6}。y1为R1所有样本的label的均值=0。y2为R2 所有样本的label的均值(1+1+0+0+0+0)/6=0.3333。
图5 第一个特征的第二个特侦值的节点分裂情况 (图中数据有误)
我们需要针对所有的样本,样本1属于R2,计算的值为(1-0.333)2,样本2属于R2,计算的值为(1-0.333)2,样本 3,4,5,6同理都是属于R2的,所以值是(0-0.333)2。把这六个值加起来山鸢尾类型在特征1 的第二个特征值的损失值。这里算出来 (1-0.333)^2+ (1-0.333)^2 + (0-0.333)^2+(0-0.333)^2+(0-0.333)^2 +(0-0.333)^2= 1.333. 这里的损失值大于特征一的第一个特征值的损失值,所以我们不取这个特征的特征值。
图6 所有情况说明 (图中数据有误)
这样我们可以遍历所有特征的所有特征值,找到让这个式子最小的特征以及其对应的特征值,一共有24种情况,4个特征*每个特征有6个特征值。在这里我们算出来让这个式子最小的特征花萼长度,特征值为5.1 cm。这个时候损失函数最小为 0.8。
于是我们的预测函数此时也可以得到:
此处 R1 = {2},R2 = {1,3,4,5,6},y1 = 1,y2 = 0.2。训练完以后的最终式子为
借由这个式子,我们得到对样本属于类别1 的预测值f1(x)=1+0.2*5=2。同理我们可以得到对样本属于类别2,3的预测值f2(x),f3(x)。样本属于类别1的概率即为
图7 模型复杂度与方差偏差的关系
当模型越简单时,即使我们再换一组数据,最后得出的学习器和之前的学习器的差别就不那么大,模型的方差很小。还是因为模型简单,所以偏差会很大。
也就是说,当我们训练一个模型时,偏差和方差都得照顾到,漏掉一个都不行。对于Bagging算法来说,我们会并行地训练很多不同的分类器的目的就是降低这个方差(variance),因为采用了相互独立的基分类器多了以后,h的值自然就会靠近.所以对于每个基分类器来说,目标就是如何降低这个偏差(bias),所以我们会采用深度很深甚至不剪枝的决策树。对于Boosting来说,每一步我们都会在上一轮的基础上更加拟合原数据,所以可以保证偏差(bias),所以对于每个基分类器来说,问题就在于如何选择variance更小的分类器,即更简单的分类器,所以我们选择了深度很浅的决策树。
拓展最近引起关注的一个Gradient Boosting算法:xgboost,在计算速度和准确率上,较GBDT有明显的提升。xgboost 的全称是eXtreme Gradient Boosting,它是Gradient Boosting Machine的一个c++实现,作者为正在华盛顿大学研究机器学习的大牛陈天奇 。xgboost最大的特点在于,它能够自动利用CPU的多线程进行并行,同时在算法上加以改进提高了精度。它的处女秀是Kaggle的 希格斯子信号识别竞赛,因为出众的效率与较高的预测准确度在比赛论坛中引起了参赛选手的广泛关注。值得我们在GBDT的基础上对其进一步探索学习。