一、梯度提升决策树GBDT
GBDT(Gradient Boosting Decision Tree)是Boosting算法的一种,每轮迭代是在上一轮弱学习器的损失函数梯度下降的方向上,训练产生新的弱学习器,所有弱学习器加权组合得到最终的强学习器。GBDT对弱学习器的要求是要足够简单,即低方差&高偏差,一般深度不会超过5,叶子节点的数量也不会超过10,默认选择CART回归树。注意GBDT中的树都是回归树,通过改变损失函数(使用指数、对数损失函数)后也可以用于解决分类问题,但不是基学习器变成分类树。
GBDT有三部分构成:DT(Regression Decision Tree)、GB(Gradient Boosting)和衰减(Shrinkage)。Shrinkage思想认为,每次走一小步逐渐逼近结果,要比每次迈一大步很快逼近结果的方式更容易避免过拟合。即它不完全信任每一个棵残差树,认为每棵树只学到了真理的一部分,所以累加的时候只累加一部分,通过多学几棵树弥补不足。
回归树总体流程类似于分类树,区别在于损失函数不同,回归树节点的划分标准不再和熵有关,而是要最小化损失函数,一般为均方误差或者绝对值误差;而在分类算法中的损失函数一般选择对数函数。
1、GBDT算法原理
训练集样本为{(x(1),y(1)),(x(2),y(2)),...,(x(m),y(m))},迭代次数t=1,2,...,T,目标是找到近似函数F(x),使得损失函数L(y,F(x))的值最小。
损失函数一般采用最小二乘或绝对值的形式表示:
最优解为:
假定F(X)是一组最优基函数fi(X)的和:
以贪心算法的思想扩展得到FT(X),求解最优F:
贪心算法在每次选择最优基函数f时仍然困难,因此使用梯度下降的方法近似计算
初始化弱学习器,c为初始拟合估计:
根据梯度下降计算学习率:
使用数据(xi,αti)(i=1,2,...,m)计算拟合残差找到一个CART回归树,得到第t棵树,对应叶子节点区域为leaftj,j=1,2,...,J,其中J为回归树t的叶子结点总的个数。
对每一个叶子节点中的样本,求出使损失函数最小,计算最佳拟合值:
得到本轮的决策树拟合函数
更新学习器,得到最终的强学习器
2、GBDT的正则化
GBDT避免过拟合的方法主要有三种:
(1)early stopping(预剪枝)策略,保留一个验证集,每增添一棵树通过验证集测试误差是否下降,当增添一定数目的树时验证误差不再下降的时候,就可以终止迭代了,得到T*棵回归树。
(2)Shrinkage添加缩放系数v(0
(3)sub-sampling子采样比例 (0,1],即在拟合一棵新的回归树时,不使用完全的样本集,而仅是无放回的抽样其中的部分(和RF的有放回抽样不同),如果取1,则采用全部样本;如果小于1,则采用一部分样本,从而防止出现过拟合。采样比例一般选在[0.5~0.8]之间。
由于使用子采样技术,程序可以通过将采样分发到不同的任务进行boosting的迭代训练的过程,从而减少弱学习器难以并行训练的弱点。
3、GBDT总结
(1)GBDT的优点:
解释性强、可扩展性强
可处理连续值和离散值,以及混合类型特征
具有伸缩不变性(不用归一化特征值)
在相对少的调参情况下,也能得到不错的模型预测效果
模型的健壮性较强,对特征缺失值不敏感
可以用来进行特征选择
(2)GBDT的缺点:
由于弱学习器之间存在关联关系,难以并行训练模型
缺乏平滑性,回归预测时输出值只能输出有限的若干种数值
不适合处理高维稀疏数据
(3)GBDT和AdaBoost、RF的区别如下:
AdaBoost算法是利用前一轮的弱学习器的误差来更新样本的权重值,然后不断迭代;GBDT要求弱学习器一般是CART回归树,而且GBDT在模型训练的时候,要求模型预测的样本损失尽可能小,所有树的结果累加起来就是最终结果。
RF使用抽取不同的样本构建不同的子树,也就是说第m棵树的构建和前面m-1棵树没有关系;GBDT在构建子树的时候,使用之前子树构建结果后形成残差作为输入数据构建下一棵子树,最终预测时按照子树构建的顺序进行预测,并将预测结果相加。
4、GBDT scikit-learn相关参数
二、XGBoost
XGBoost(eXtreme Gradient Boosting)是GBDT算法的一种变种,基学习器既可以是CART(gbtree),也可以是线性分类器(gblinear),对传统的GBDT算法做了很多细节改进,包括使用损失函数二阶导数、用模型复杂度作为正则项、分裂点查找近似算法、稀疏感知算法、并行化训练设计等。XGBoost是伸缩性强、便捷的可以并行构建模型的一种梯度提升算法。
XGBoost官网:http://xgboost.readthedocs.io
XGBoost中文版介绍:http://www.52cs.org/?p=429
XGBoost GitHub源码位置:https://github.com/dmlc/xgboost
1、XGBoost模型学习
第t次迭代后,模型的预测为前t-1次的模型加上第t棵树的预测:
每一次迭代保留原模型不变,加入一个新的函数f到模型中,这个f是目标函数尽可能的降低。将树拆分成结构部分q和权重部分w,结构函数q把输入映射到叶子的索引号,wj给定了每个索引号对应的叶子的权重值。T为叶子节点总数。
一棵树的复杂度可以定义为:叶子节点的总数,加上每个叶子节点权重的平方。
根据Taylor公式
将目标函数在处进行二阶泰勒展开,则XGBoost的目标函数可写为:
其中
定义每个叶子节点j上的样本集合为Ij:
将函数中的所有t-1求和的常数项全部去掉,带入函数f和正则项,并将样本累加转换为根据叶子节点重新组合目标函数,可得公式:
为了书写简便令
如果树的结构q确定,为了使目标函数最小,可以令其导数为零,求出最优的w*,将带入目标函数可得最终的损失函数为:
2、XGBoost的节点分割策略
当树的结构确定的时候,可以得到最优的叶子节点分数以及对应的最小损失值,问题在于如何确定树结构?
暴力法枚举不同树的结构,选择损失函数值最小的一个最优结构树,加入到模型中,重复这样的操作(很难求解);
贪心法,每次尝试对已有的叶子加入一个分割,计算操作前后的增益,选择增益最大的方式进行分裂。
对一个叶子节点的分裂,分裂前后的信息增益可定义为:不分裂时的损失,减去分裂后的损失(左子树加上右子树)。
Gain的值越大,分裂后减少的损失值越大。有两种计算方法:
(1)精确算法:遍历所有特征的所有可能的分割点,计算所有候选的(feature,value)对应的Gain,选择Gain最大的特征进行分割。
(2)近似算法:对于每个特征,只考虑分位点,减少计算复杂度。
3、XGBoost的特性总结
(1)XGBoost算法中加入正则项,用于控制模型的复杂度,从而使最终得到的模型更加不容易过拟合。
(2)XGBoost对损失函数进行了二阶泰勒展开,支持自定义损失函数,只要损失函数二阶可导即可(高灵活性)。
(3)XGBoost的基学习器支持CART、线性回归、逻辑回归。
(4)XGBoost可以用列采样(column sub-sampling)的方法防止过拟合、减少计算量,借鉴了RF的思想。
(5)支持对缺失值的自动处理,可以自动学习分裂方向。稀疏感知算法 Sparsity-aware Split Finding。
(6)内置交叉验证(Built-in Cross Validation),XGBoost allows user to run a cross-validation at each iteration of the boosting process and thus it is easy to get the exact optimum number of boosting iterations in a single run.
This is unlike GBM where we have to run a grid-search and only a limited values can be tested.
(7)近似算法选择适合的划分点,先通过直方图算法获得候选分割点的分布情况,根据候选分割点将连续的特征信息映射到不同的buckets中,并统计汇总信息。
(8)continue on existing model
User can start training an XGBoost model from its last iteration of previous run. This can be of significant advantage in certain specific applications.
GBM implementation of sklearn also has this feature so they are even on this point.
(7)XGBoost支持特征粒度上的并行计算。由于构建决策树最耗时的一个步骤是对特征值进行排序(确定最佳分割点),XGBoost在训练之前预先对数据进行排序并保存为block结构,迭代时重复使用这个结构,在计算特征的Gain值的时候,可以在多个线程并行计算。但是在每轮迭代时,还是串行构建树的,第t轮迭代的损失函数包含了前面t-1轮迭代的预测值。
(8)XGBoost的最初设计目标就是高性能,高性能不仅仅意味着速度上的提升,而且在资源有限情况下仍能对大型数据集使用该算法。
内存优化,大部分的内存分配在第一次加载中就完成了,之后便不再涉及动态内存分配的问题;
缓存线优化,训练模式尽可能善用缓存机制;
以最大限度地利用计算资源,在一个节点上能运行多个实例;
使用扩展内存的版本,允许数据存在硬盘上,不必把所有数据导入内存;
分布式版本对XGBoost的每一个节点都进行过优化,可以有效地在更少节点上处理更大的数据集。
4、XGBoost 相关参数
参考链接:http://xgboost.readthedocs.io/en/latest/python/python_api.html#module-xgboost.sklean
三、DART
DART(Dropouts meet Multiple Additive Regression Trees):通过删除已经构建好的树,来降低模型过拟合的情况。