一、GBDT
GDBT(Gradient Boosting Decision Tree)是一种迭代的决策树算法,该算法由多棵决策树组成,所有树的结论累加起来做最终结果。它在被提出之初就和SVM一起被认为是泛化能力(generalization)较强的算法。近些年更因为被用于搜索排序的机器学习模型而引起广泛关注。
GBDT是一个应用很广泛的算法,可以用来做分类、回归。在很多的数据上都有很不错的效果
1.1 决策树
决策树分为俩大类,分类树和回归树。分类树是我们比较熟悉的决策树,比如C4.5分类决策树。分类树用于分类标签值,如晴天/阴天、用户性别、网页是否是垃圾页面。而回 归树用于预测实数值,如明天的温度、用户的年龄、网页的相关程度。也就是分类树的输出是定性的,而回归树的输出是定量的。
GBDT的核心在于累加所有树的结果作为最终结果,比如对年龄的累加来预测年龄,而分类树的结果显然是没办法累加的,所以GBDT中的树都是回归树,不是分类树。
1.1.1 分类树
以C4.5分类树为例,C4.5分类树在每次分枝时,是穷举每一个feature的每一个阈值,找到使得按照feature<=阈值,和feature>阈值分成的两个分枝的熵最大的阈值(熵最大的概念可理解成尽可能每个分枝的男女比例都远离1:1),按照该标准分枝得到两个新节点,用同样方法继续分枝直到所有人都被分入性别唯一的叶子节点,或达到预设的终止条件,若最终叶子节点中的性别不唯一,则以多数人的性别作为该叶子节点的性别。
1.1.2 回归树
回归树总体流程也是类似,区别在于,回归树的每个节点(不一定是叶子节点)都会得一个预测值,以年龄为例,该预测值等于属于这个节点的所有人年龄的平均值。分枝时穷举每一个feature的每个阈值找最好的分割点,但衡量最好的标准不再是最大熵,而是最小化均方差即(每个人的年龄-预测年龄)^2 的总和 / N。也就是被预测出错的人数越多,错的越离谱,均方差就越大,通过最小化均方差能够找到最可靠的分枝依据。分枝直到每个叶子节点上人的年龄都唯一或者达到预设的终止条件(如叶子个数上限),若最终叶子节点上人的年龄不唯一,则以该节点上所有人的平均年龄做为该叶子节点的预测年龄。
1.2 梯度迭代(Gradient Boosting)
Boosting,迭代,即通过迭代多棵树来共同决策。GBDT的核心就在于,每一棵树学的是之前所有树结论和的残差,这个残差就是一个加预测值后能得真实值的累加量。比如A的真实年龄是18岁,但第一棵树的预测年龄是12岁,差了6岁,即残差为6岁。那么在第二棵树里我们把A的年龄设为6岁去学习,如果第二棵树真的能把A分到6岁的叶子节点,那累加两棵树的结论就是A的真实年龄;如果第二棵树的结论是5岁,则A仍然存在1岁的残差,第三棵树里A的年龄就变成1岁,继续学习。
1.3 Shrinkage
Shrikage(缩减)的思想认为:每次走一小步逐渐逼近结果,要比每次迈一大步很快逼近结果的方式更容易避免过拟合。即它不完全信任每一个棵残差树,它认为每棵树只学到了结果的一小部分,累加的时候只累加一小部分,通过多学几棵树弥补不足。假设yi表示第i棵树上y的预测值,y(1~i)表示前i棵树y的综合预测值。
y(i+1)= f(残差(y(1~i))) 其中,残差(y(1~i))=y真实值 - y(1~i)
y_(1~i)= SUM(y_1,…, y_i)
引入Shrinkage后,y(1~i) = y(1~i-1)+step *yi
step可以认为是学习速度,越小表示学习越慢,越大表示学习越快。step一般都比较小,导致各个树的残差是渐变的而不是陡变的。
1.4 GBDT适用范围
机器学习可以解决很多问题,其中最为重要的两个是 回归与分类。GBDT可用于回归问题,相对logistic regression仅能用于线性回归,GBDT能用于线性回归和非线性回归,GBDT的适用面非常广。GBDT也可用于二分类问题(设定阈值,大于阈值为正例,反之为负例)。
1.5 GBDT示例
由于输出样本是连续值,因此我们通过迭代多棵回归树来共同决策。
我们利用平方误差来表示损失函数,其中每一棵回归树学习的是之前所有树的结论和残差,拟合得到一个当前的残差回归树。其中残差=真实值-预测值,提升树即是整个迭代过程生成的回归树的累加。
我们通过以下例子来详解算法过程,希望通过训练提升树来预测年龄。训练集是4个人,A、B、C、D年龄分别是14、16、24、26。样本中有购物金额、上网时长、经常到百度知道提问等特征。提升树的过程如下:
二、XGBoost
XGBoost(eXtreme Gradient Boosting)是基于Boosting框架的一个算法工具包(包括工程实现),在并行计算效率、缺失值处理、预测性能上都非常强大。
三、GBDT和XGBoost对比
Gradient Boosting (GDBT)通过负梯度来识别问题,通过计算负梯度来改进模型。
XGBoost 可以看做是 GBDT 的升级版算法的实现(进行二阶泰勒展开,用到了二阶梯度信息)
其中需要明确的一个概念是,XGBoost 是 Boosting 框架的一种实现结构, lightgbm 也是一种框架实现结构,而 GBDT 则是一种算法实现。
GBDT 和 XGBOOST 的区别有以下几点:
- 传统 GBDT 以 CART (采用 gini 指数计算增益的回归树)作为基分类器,xgboost还支持线性分类器,这个时候xgboost相当于带L1和L2正则化项的逻辑斯蒂回归(分类问题)或者线性回归(回归问题)。
- 传统 GBDT 在优化时只用到一阶导数信息,xgboost则对代价函数进行了二阶泰勒展开,同时用到了一阶和二阶导数。顺便提一下,xgboost工具支持自定义代价函数,只要函数可一阶和二阶求导。
- xgboost 在代价函数里加入了正则项,用于控制模型的复杂度。正则项里包含了树的叶子节点个数等,正则项降低了模型的 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还提出了一种可并行的近似直方图算法,用于高效地生成候选的分割点。