集成学习
集成学习中对个体学习器的要求应该是**“好而不同”,即既满足准确性,又满足多样性**(diversity),也即是说,学习器既不能太坏,而且学习器与学习器之间也要有差异
Bagging Boosting
Bagging的主要作用是降低方差,而Boosting的主要作用是降低偏差。
Boosting能降低偏差很好理解,因为其原理就是将多个弱学习器组合成强学习器
bagging,多个模型平均起来,降低方差
结合加权**多数投票(分类)或加权求和(回归)**以产生最终预测。
Boosting 与 bagging 等方法的主要区别是基础学习器通过加权的数据进行顺序训练。
Boosting
- 步骤1:所有分布下的基础学习器对于每个观测值都应该有相同的权重
- 步骤2:如果第一个基础的学习算法预测错误,则该点在下一次的基础学习算法中有更高的权重
- 步骤3:迭代第2步,直到到达预定的学习器数量或预定的预测精度。
XGBoost
优点:速度快、效果好、能处理大规模数据、支持多种语言、支持自定义损失函数等等。
缺点:算法参数过多,调参负责,对原理不清楚的很难使用好XGBoost。不适合处理超高维特征数据
所以 Boosting 有三个要素:
- A loss function to be optimized:例如分类问题中用 cross entropy,回归问题用 mean squared error。
- A weak learner to make predictions:例如决策树。
- An additive model:将多个弱学习器累加起来组成强学习器,进而使目标损失函数达到极小。
1、正则化。XGBoost在代价函数里加入了正则项,用于控制模型的复杂度。正则项里包含了树的叶子节点个数、每个叶子节点上输出的score的L2模的平方和。从Bias-variance tradeoff角度来讲,正则项降低了模型的variance方差,使学习出来的模型更加简单,防止过拟合,这也是xgboost优于传统GBDT的一个特性。
2、XGBoost工具支持并行。Boosting不是一种串行的结构吗?怎么并行的?注意XGBoost的并行不是tree粒度的并行,XGBoost也是一次迭代完才能进行下一次迭代的(第t次迭代的代价函数里包含了前面t-1次迭代的预测值)。XGBoost的并行是在特征粒度上的。我们知道,决策树的学习最耗时的一个步骤就是对特征的值进行排序(因为要确定最佳分割点),XGBoost在训练之前,**预先对数据进行了排序,然后保存为block结构,**后面的迭代中重复地使用这个结构,大大减小计算量。这个block结构也使得并行成为了可能,在进行节点的分裂时,需要计算每个特征的增益,最终选增益最大的那个特征去做分裂,那么各个特征的增益计算就可以开多线程进行
3、高度的灵活性。XGBoost支持用户自定义目标函数和评估函数,只要目标函数二阶可导就行。
4、缺失值处理。XGBoost内置处理缺失值的规则。用户需要提供一个和其它样本不同的值,然后把它作为一个参数传进去,以此来作为缺失值的取值。XGBoost在不同节点遇到缺失值时采用不同的处理方法,并且会学习未来遇到缺失值时的处理方法。
5、剪枝。当分裂时遇到一个负损失时,GBM会停止分裂。因此GBM实际上是一个贪心算法。 XGBoost会一直分裂到指定的最大深度(max_depth),然后回过头来剪枝。如果某个节点之后不再有正值,它会去除这个分裂。 这种做法的优点,当一个负损失(如-2)后面有个正损失(如+10)的时候,就显现出来了。GBM会在-2处停下来,因为它遇到了一个负值。但是XGBoost会继续分裂,然后发现这两个分裂综合起来会得到+8,因此会保留这两个分裂。比起GBM,这样不容易陷入局部最优解。
6、内置交叉验证。XGBoost允许在每一轮boosting迭代中使用交叉验证。因此,可以方便地获得最优boosting迭代次数。而GBM使用网格搜索,只能检测有限个值。
7、在已有的模型基础上继续。XGBoost可以在上一轮的结果上继续训练。
最终的目标函数只依赖于每个数据点的在误差函数上的一阶导数和二阶导数,通过二阶泰勒展开式的变换,这样求解其他损失函数变得可行
决策树算法
XGBoost使用的是pre-sorted算法,能够更精确的找到数据分隔点。
- 首先,对所有特征按数值进行预排序。
- 其次,在每次的样本分割时,用O(# data)的代价找到每个特征的最优分割点。
- 最后,找到最后的特征以及分割点,将数据分裂成左右两个子节点。
这种pre-sorting算法能够准确找到分裂点,但是在空间和时间上有很大的开销。
LightGBM使用的是histogram算法,占用的内存更低,数据分隔的复杂度更低。其思想是将连续的浮点特征离散成k个离散值,并构造宽度为k的Histogram。然后遍历训练数据,统计每个离散值在直方图中的累计统计量。在进行特征选择时,只需要根据直方图的离散值,遍历寻找最优的分割点。
内存消耗可以降低为原来的1/8
计算上的代价也大幅降低,预排序算法每遍历一个特征值就需要计算一次分裂的增益,而直方图算法只需要计算k次(k可以认为是常数),时间复杂度从O(#data*#feature)优化到O(k*#features)
主要由于决策树是弱模型, 分割点是不是精确并不是太重要;较粗的分割点也有正则化的效果,可以有效地防止过拟合;即使单棵树的训练误差比精确分割的算法稍大,但在梯度提升(Gradient Boosting)的框架下没有太大的影响
直方图做差算法
一个叶子的直方图可以由它的父亲节点的直方图与它兄弟的直方图做差得到。通常构造直方图,需要遍历该叶子上的所有数据,但直方图做差仅需遍历直方图的k个桶
决策树生长算法
-
XGBoost采用的是按层生长level(depth)-wise生长策略,能够同时分裂同一层的叶子,从而进行多线程优化,不容易过拟合;但不加区分的对待同一层的叶子,带来了很多没必要的开销。因为实际上很多叶子的分裂增益较低,没必要进行搜索和分裂。
-
LightGBM采用leaf-wise生长策略,每次从当前所有叶子中找到分裂增益最大(一般也是数据量最大)的一个叶子,然后分裂,如此循环。因此同Level-wise相比,在分裂次数相同的情况下,Leaf-wise可以降低更多的误差,得到更好的精度。Leaf-wise的缺点是可能会长出比较深的决策树,产生过拟合。因此LightGBM在Leaf-wise之上增加了一个最大深度的限制,在保证高效率的同时防止过拟合
Adaboost
AdaBoost针对第一个问题的做法是提高那些被前一轮弱分类器错误分类样本的权值,并降低那些被正确分类的样本的权值。经过一轮的权值加大后,后一轮的弱分类器就会更关注那些没有被正确分类的样本。持续下去,分类问题便会被一系列弱分类器“分而治之”。
而对于第二个问题,即弱分类器的组合,AdaBoost采取加权多数表决法,具体的,就是加大误差率小的弱分类器的权值,使其在表决中起更大的作用,另一方面,减小分类误差率大的弱分类器的权值,使其在表决中起较小的作用。
GBDT
Gradient Boosting是非常经典而又重要的提升方法,他与AdaBoost一样都是讲弱分类器合成强分类,但是其大致区别有:
Gradient Boosting通过残差来变量的改变错误分类的权重,而AdaBoost就真的直接去修改分类错误的训练权重了
Gradient Boosting接入的分类器一般完整的决策树居多,但是AdaBoost一般使用二层决策树
Gradient Boosting中最有代表性的就是GBDT
GBDT的一般步骤
- Step 1: 初始化。初始化y_hat在第0时刻的值。
- Step 2:求残差。通过类似梯度下降法的思路,每次y都向梯度下降的方向挪一小步。只是在GBDT,y挪的一小步并不是一个variable,而是一个function。
- Step 3:构建决策树。使用决策树逼近这个残差 –g,得到第t个决策树:f_t。
- Step 4:求叶节点权重。
- Step 5:更新输出y。y(t) = y(t – 1) + learning_rate * f_t
LightGBM
优点:
- 更快的训练效率
- 低内存使用
- 更高的准确率
- 支持并行化学习
- 可处理大规模数据
- 支持直接使用category特征
GBDT在每一次迭代的时候,都需要遍历整个训练数据多次;
XGBoost采用精确贪心算法:每轮迭代时,都需要遍历整个训练数据多次。如果把整个训练数据装进内存则会限制训练数据的大小;如果不装进内存,反复地读写训练数据又会消耗非常大的时间。计算量巨大、内存占用巨大、易产生过拟合
lightGBM主要有以下特点:
- 基于Histogram的决策树算法
- 直方图做差加速
- 直接支持类别特征(Categorical Feature)
- 基于直方图的稀疏特征优化
- 多线程优化
GBDT、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还提出了一种可并行的近似直方图算法,用于高效地生成候选的分割点。
- 节点分裂算法能自动利用特征的稀疏性。
- 样本数据事先排好序并以block的形式存储,利于并行计算
LightGBM 与 XGBoost
-
由于在决策树在每一次选择节点特征的过程中,要遍历所有的属性的所有取值并选择一个较好的。
XGBoost 使用的是近似算法,先对特征值进行预排序 Pre-sort,然后根据二阶梯度进行分桶,能够更精确的找到数据分隔点;但是复杂度较高。
LightGBM 使用的是 histogram 算法,这种只需要将数据分割成不同的段即可,不需要进行预先的排序。占用的内存更低,数据分割的复杂度更低。 -
决策树生长策略,XGBoost 采用的是 按层生长Level-wise 的树生长策略,LightGBM 采用的是 leaf-wise 的生长策略,以最大信息增益为导向。后者精度度更高,容易过拟合,所以要控制最大深度。
-
并行策略对比,XGBoost 的并行主要集中在特征并行上,而 LightGBM 的并行策略分特征并行,数据并行以及投票并行。