原创文章:http://blog.csdn.net/qccc_dm/article/details/63684453
首先XGBOOST,GBDT,RF都是集成算法,RF是Bagging的变体,与Bagging相比,RF加入了属性扰动,而XGBOOST,GBDT属于boosting.
一、RandomForest 与 GBDT 的区别:
相同点:
1.都由很多棵树组成
2.最终的结果是由多棵树一起决定的
不同点:
1.RandomForest中的树可以是分类树,也可以是回归树,而GBDT只能由回归树(CART)组成,这也说明GBDT各个树相加是有意义的
2.RandomForest中的树是并行生成的,而GBDT是串行生成的,GBDT中下一颗树要去拟合前一颗树的残差,所以GBDT中的树是有相关关系的,而RandomForest中的树的相关性依赖于Boostrap生成的样本子集的相关性
3.RandomForest 对异常值不敏感,GBDT敏感
4.RandomForest是通过降低模型方差来提高性能的,而GBDT是通过降低偏差来提高性能
二、GBDT 与 XGBOOST的比较:
1.传统的GBDT以CART树作为基分类器,而XGBOOST还支持线性分类器,此时的线性分类器自带正则项
2.传统的GBDT在优化时,只用到了loss function的一阶导信息,而XGBOOST对loss function做了Taylor展开,用到了二阶导信息
3.XGBOOST在loss function中引入了正则项,防止过拟合,正则项里包含叶节点数以及每个叶节点上的score的L2的平方和
在计算划分增益时,如果gain < gamma, 不划分,gain> gamma,划分,这相当于决策树的预剪枝。 gamma是叶节点个数的参数
4.XGBOOST还借用了RandomForest中的列抽样思想,也支持在划分节点时,只考虑部分属性
(现状sklearn中的GBDT也实现了列抽样)
5.XGBOOST可以自动学习出缺失值的分裂方向,论文中的default direction
(具体做法时,遍历的尝试将所有的缺失值分裂到所有方向{left or right},split and default directions with max gain)
6.XGBOOST实现了并行化,这个并行化是特征粒度上的并行化:划分节点时,每个特征并行计算,同时每个特征的划分节点也是并行计算(这是加速最猛的处理)
7.XGBOOST提出了block的概念,简单的说将排序后的特征值放在block中,以后划分特征的时候,只需要遍历一次即可,因为决策树在处理属性值时,需要将属性值先排序,这是最耗时的步骤,而block预先存储了排序的特征值,在后续过程中可以重复利用这个结构中的数据,同时,计算每个特征的划分增益可以并行处理了
Collecting statistics for each column can be parallelized,giving us a parallel algorithm for split finding!!
8.贪心算法在选择最佳划分方式时需要遍历所有的划分点子集,在数据非常大时,这会非常低效,xgboost提出了近似直方图计算,根据数据的二阶导信息进行排序,提出一些候选划分点子集
三、xgboost为什么快?xgboost如何支持并行?
- 传统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中树节点分裂时所采用的公式:
这个公式形式上跟ID3算法(采用entropy计算增益) 、CART算法(采用gini指数计算增益) 是一致的,都是用分裂后的某种值 减去 分裂前的某种值,从而得到增益。为了限制树的生长,我们可以加入阈值,当增益大于阈值时才让节点分裂,上式中的gamma即阈值,它是正则项里叶子节点数T的系数,所以xgboost在优化目标函数的同时相当于做了预剪枝。另外,上式中还有一个系数lambda,是正则项里leaf score的L2模平方的系数,对leaf score做了平滑,也起到了防止过拟合的作用,这个是传统GBDT里不具备的特性。
- 多类别分类时,类别需要从0开始编码;
- 类别特征必须编码,因为xgboost把特征默认都当成数值型的;
- 训练的时候,为了结果可复现,记得设置随机数种子;
- XGBoost的特征重要性是如何得到的?某个特征的重要性(feature score),等于它被选中为树节点分裂特征的次数的和,比如特征A在第一次迭代中(即第一棵树)被选中了1次去分裂树节点,在第二次迭代被选中2次…..那么最终特征A的feature score就是 1+2+….