集成学习主要有两个思想,分别是bagging和boosting。树模型的集成模型都是使用树作为基模型,最常用的cart树,常见的集成模型有RandomForest、GBDT、Xgboost、Lightgbm、Catboost。
随机森林(Random Forest,RF)是Bagging的一个扩展变体。RF在以决策树为基学习器构建Bagging集成的基础上,进一步在决策树的训练过程中引入了随机属性选择。既然模型叫做随机森林,森林我们可以理解为是多棵树的集合就是森林,随机主要有两个点进行有放回的采样,
- 每次建树特征个数随机选择
- 每次建树样本个数随机选择
随机森林中基学习器的多样性不仅来自样本扰动,还来自属性扰动,这就使得最终集成得泛化性能可通过个体学习器之间差异度得增加而进一步提升。使得模型更加鲁棒。
GBDT使用的是加法模型和前向分布算法,而AdaBoost算法是前向分布加法算法的特例,前向分布算法学习的是加法模型,当基函数为基本分类器时,该加法模型等价于Adaboost的最终分类器。
GBDT也是迭代,使用了前向分布算法,但是弱学习器限定了只能使用CART回归树模型,同时迭代思路和Adaboost也有所不同。在GBDT的迭代中,假设我们前一轮迭代得到的强学习器是, 损失函数是, 我们本轮迭代的目标是找到一个CART回归树模型的弱学习器,让本轮的损失函数最小。也就是说,本轮迭代找到决策树,要让样本的损失尽量变得更小。GBDT本轮迭代只需拟合当前模型的残差。
Xgboost是gbdt的改进或者说是梯度提升树的一种,Xgb可以说是工程上的最佳实践模型,简单的说xgb=gbdt+二阶梯度信息+随机特征和样本选择+特征百分位值加速+空值特征自动划分。还有必要的正则项和最优特征选择时的并行计算等。
首先,GBDT是一个非常流行的机器学习算法,另外基于GBDT实现的XGBoost也被广泛使用。但是当面对高纬度和大数据量时,其效率和可扩展性很难满足要求。主要的原因是对于每个特征,我们需要浏览所有的数据去计算每个可能分裂点的信息增益,真是非常耗时的。基于此,提出了两大技术:Gradient-based One-Side Sampling (GOSS) and Exclusive Feature Bundling (EFB).
CatBoost = Category + Boosting.
2017年7月21日,俄罗斯Yandex开源CatBoost,亮点是在模型中可直接使用Categorical特征并减少了tuning的参数。
1.随机森林为什么能够更鲁棒?
由于随机森林使用了使用了行采样和列采样技术,是的每棵树不容易过拟合;并且是基于树的集成算法,由于使用了采用数据是的每棵树的差别较大,在进行embedding的时候可以更好的降低模型的方差,整体而言是的RF是一个鲁棒的模型。
2.RF分类和回归问题如何预测y值?
RF是一个加权平均的模型,是进行分类问题的时候,使用的个k个树的投票策略,多数服从少数。在回归的使用是使用的k个树的平均。可以看出来rf的训练和预测过程都可以进行并行处理。
3.相同数据量,训练RF和gbdt谁可以更快?谁对异常值不敏感?
gbdt是前向加法模型,由于第i棵树需要用到前i-1树的残差,所有在再整个建立过程是串行处理的,RF整体是bagging算法的一种,是k个树的加权平均,k棵树可以并行处理,因此可能得到更快的速度。需要指出在gbdt的原始算法中没有使用行列的随机采样,相反rf使用了随机采样。由于gbdt当前的误差会延续给下一棵树,而RF每次都是独立的随机采样,随机森林对异常值不敏感,GBDT对异常值非常敏感。
4.解释一个什么是gb,什么是dt,即为什么叫做gbdt?
gbdt(Gradient Boosting Decision Tree),dt是指Decision Tree表示使用决策树作为基学习器,使用的cart树,gb表示梯度提升,因为在传统的gbdt中在第i轮的迭代中,使用前i-1的梯度作为当前残差进行拟合。
5.gbdt为什么用负梯度代表残差?
上文公式(3)是gbdt的损失函数,对公式(3)进行在$f_{m-1}(x)处进行
泰勒的一阶展开:
L ( y , f m ( x ) ) = L ( y , f m − 1 ( x ) + β m b ( x ; γ m ) ) L(y,f_m(x))=L(y,f_{m-1}(x)+\beta_m b(x;\gamma_m)) L(y,fm(x))=L(y,fm−1(x)+βmb(x;γm))
= L ( y , f m − 1 ( x ) ) + ∂ L ( y , f m − 1 ( x ) ) ∂ f m − 1 ( x ) ( f m ( x ) − f m − 1 ( x ) ) =L(y,f_{m-1}(x))+\frac{\partial L(y, f_{m-1}(x))}{\partial f_{m-1}(x)}(f_{m}(x)-f_{m-1}(x)) =L(y,fm−1(x))+∂fm−1(x)∂L(y,fm−1(x))(fm(x)−fm−1(x))
(19) = L ( y , f m − 1 ( x ) ) + ∂ L ( y , f m − 1 ( x ) ) ∂ f m − 1 ( x ) ( β m b ( x ; γ m ) ) =L(y,f_{m-1}(x))+\frac{\partial L(y, f_{m-1}(x))}{\partial f_{m-1}(x)}(\beta_m b(x;\gamma_m)) \tag{19} =L(y,fm−1(x))+∂fm−1(x)∂L(y,fm−1(x))(βmb(x;γm))(19)
从我们的目标是损失函数最小化,使公式(19)最小化,由于是个常数,所以我们的损失函数最小化可以转化为:
(20) a r g m i n ( β m , γ m ) = m i n ∂ L ( y , f m − 1 ( x ) ) ∂ f m − 1 ( x ) ( β m b ( x ; γ m ) ) argmin_{(\beta_m,\gamma_m)}=min \frac{\partial L(y, f_{m-1}(x))}{\partial f_{m-1}(x)}(\beta_m b(x;\gamma_m)) \tag{20} argmin(βm,γm)=min∂fm−1(x)∂L(y,fm−1(x))(βmb(x;γm))(20)
将上述式子的两项都看做是向量,为了是相乘之后最小,一定是向量之间的异号,因此得到:
(21) ( β m b ( x ; γ m ) ) = − ∂ L ( y , f m − 1 ( x ) ) ∂ f m − 1 ( x ) (\beta_m b(x;\gamma_m)) = - \frac{\partial L(y, f_{m-1}(x))}{\partial f_{m-1}(x)} \tag{21} (βmb(x;γm))=−∂fm−1(x)∂L(y,fm−1(x))(21)
从公式(20)可以看出第m棵树使用前m-1的负梯度作为残差,所有每次都是拟合的负梯度.
6.gbdt是训练过程如何选择特征?
gbdt使用基学习器是CART树,CART树是二叉树,每次使用yes or no进行特征选择,数值连续特征使用的最小均方误差,离散值使用的gini指数。在每次划分特征的时候会遍历所有可能的划分点找到最有的特征分裂点,这是用为什么gbdt会比rf慢的主要原因之一。
7.gbdt应用在多分类问题?
8.RF和GBDT的区别?
GBDT是采用boosing方法,降低偏差;RF采用的是baggging方法,降低方差。其中GBDT中的核心是通过用分类器(如CART、RF)拟合损失函数梯度,而损失函数的定义就决定了在子区域内各个步长,其中就是期望输出与分类器预测输出的查,即bias;而RF的核心就是自采样(样本随机)和属性随机(所有样本中随机选择K个子样本选择最优属性来划分),样本数相同下的不同训练集产生的各个分类器,即数据的扰动导致模型学习性能的变化,即variance。
9.Xgboost相对gbdt做了哪些改进?
- 传统GBDT以CART作为基分类器,xgboost还支持线性分类器,这个时候xgboost相当于带L1和L2正则化项的逻辑斯蒂回归(分类问题)或者线性回归(回归问题)。
- 传统GBDT在优化时只用到一阶导数信息,xgboost则对代价函数进行了二阶泰勒展开,同时用到了一阶和二阶导数。顺便提一下,xgboost工具支持自定义代价函数,只要函数可一阶和二阶求导。
- xgboost在代价函数里加入了正则项,用于控制模型的复杂度。正则项里包含了树的叶子节点个数、每个叶子节点上输出的score的L2模的平方和。从Bias-variance tradeoff角度来讲,正则项降低了模型的variance,使学习出来的模型更加简单,防止过拟合,这也是xgboost优于传统GBDT的一个特性。
- 列抽样(column subsampling)。xgboost借鉴了随机森林的做法,支持列抽样,不仅能降低过拟合,还能减少计算,这也是xgboost异于传统gbdt的一个特性。
对缺失值的处理。对于特征的值有缺失的样本,xgboost可以自动学习出它的分裂方向。- xgboost工具支持并行。boosting不是一种串行的结构吗?怎么并行的?注意xgboost的并行不是tree粒度的并行,xgboost也是一次迭代完才能进行下一次迭代的(第t次迭代的代价函数里包含了前面t-1次迭代的预测值)。xgboost的并行是在特征粒度上的。我们知道,决策树的学习最耗时的一个步骤就是对特征的值进行排序(因为要确定最佳分割点),xgboost在训练之前,预先对数据进行了排序,然后保存为block结构,后面的迭代中重复地使用这个结构,大大减小计算量。这个block结构也使得并行成为了可能,在进行节点的分裂时,需要计算每个特征的增益,最终选增益最大的那个特征去做分裂,那么各个特征的增益计算就可以开多线程进行。
- 可并行的近似直方图算法。树节点在进行分裂时,我们需要计算每个特征的每个分割点对应的增益,即用贪心法枚举所有可能的分割点。当数据无法一次载入内存或者在分布式情况下,贪心算法效率就会变得很低,所以xgboost还提出了一种可并行的近似直方图算法,用于高效地生成候选的分割点。
10.xgb如何在计算特征时加速的?
- xgboost工具支持并行。boosting不是一种串行的结构吗?怎么并行的?注意xgboost的并行不是tree粒度的并行,xgboost也是一次迭代完才能进行下一次迭代的(第t次迭代的代价函数里包含了前面t-1次迭代的预测值)。xgboost的并行是在特征粒度上的。我们知道,决策树的学习最耗时的一个步骤就是对特征的值进行排序(因为要确定最佳分割点),xgboost在训练之前,预先对数据进行了排序,然后保存为block结构,后面的迭代中重复地使用这个结构,大大减小计算量。这个block结构也使得并行成为了可能,在进行节点的分裂时,需要计算每个特征的增益,最终选增益最大的那个特征去做分裂,那么各个特征的增益计算就可以开多线程进行。
- 可并行的近似直方图算法。树节点在进行分裂时,我们需要计算每个特征的每个分割点对应的增益,即用贪心法枚举所有可能的分割点。当数据无法一次载入内存或者在分布式情况下,贪心算法效率就会变得很低,所以xgboost还提出了一种可并行的近似直方图算法,用于高效地生成候选的分割点。
11.xgb为什么使用二阶梯度信息,为什么不使用三阶或者更高梯度信息?
- xgb之所以使用二阶梯度信息,是因为从泰勒展开式来看,gbdt使用的一阶梯度的泰勒展开式,丢失了很多的信息,使用二阶可以使损失函数更加准确。从泰勒展开的角度来看展开的次数越多越能更精准的表示损失函数的值,但是如果我们使用二阶梯度就要要求损失函数二阶可导,如果使用n阶展开就要求损失函数n阶可导,但是有很多损失函数不是n阶可导的,比如均方误差,因此使用二阶梯度信息是一个泰勒展开和损失函数选择的折中。
12.lgb相对xgb做了哪些改进?
- 直方图算法,LightGBM提供一种数据类型的封装相对Numpy,Pandas,Array等数据对象而言节省了内存的使用,原因在于他只需要保存离散的直方图,LightGBM里默认的训练决策树时使用直方图算法,XGBoost里现在也提供了这一选项,不过默认的方法是对特征预排序,直方图算法是一种牺牲了一定的切分准确性而换取训练速度以及节省内存空间消耗的算法.
- 在训练决策树计算切分点的增益时,预排序需要对每个样本的切分位置计算,所以时间复杂度是O(#data)而LightGBM则是计算将样本离散化为直方图后的直方图切割位置的增益即可,时间复杂度为O(#bins),时间效率上大大提高了(初始构造直方图是需要一次O(#data)的时间复杂度,不过这里只涉及到加和操作).
- 直方图做差进一步提高效率,计算某一节点的叶节点的直方图可以通过将该节点的直方图与另一子节点的直方图做差得到,所以每次分裂只需计算分裂后样本数较少的子节点的直方图然后通过做差的方式获得另一个子节点的直方图,进一步提高效率
- 节省内存,将连续数据离散化为直方图的形式,对于数据量较小的情形可以使用小型的数据类型来保存训练数据
不必像预排序一样保留额外的对特征值进行预排序的信息
减少了并行训练的通信代价.- 稀疏特征优化、直接支持类别特征、网络通信优化
13.比较一下catboost、lgb和xgb?
- catboost自动采用特殊的方式处理类别型特征(categorical features)。首先对categorical features做一些统计,计算某个类别特征(category)出现的频率,之后加上超参数,生成新的数值型特征(numerical features)。这也是我在这里介绍这个算法最大的motivtion,有了catboost,再也不用手动处理类别型特征了。
- catboost还使用了组合类别特征,可以利用到特征之间的联系,这极大的丰富了特征维度。
- catboost的基模型采用的是对称树,同时计算leaf-value方式和传统的boosting算法也不一样,传统的boosting算法计算的是平均数,而catboost在这方面做了优化采用了其他的算法,这些改进都能防止模型过拟合。
14.如果将所有数据复制一倍放入训练数据集,RF和GBDT分别有什么表现?
RF可能出现过拟合? GBDT没有任何改变?(请思考)
15.gbdt如何防止过拟合?由于gbdt是前向加法模型,前面的树往往起到决定性的作用,如何改进这个问题?
一般使用缩减因子对每棵树进行降权,可以使用带有dropout的gbdt算法,dart树,随机丢弃生成的决策树,然后再从剩下的决策树集中迭代优化提升树。