前言
这篇博客一部分内容转载了博客园上的一篇博客,那篇博客整理的比较好;另一部分内容整理自微信公众号;最后我还添加了一些内容,包括CatBoost、CART等。
1. 基本概念
- 集成学习的主要思路是先通过一定的规则生成多个学习器,再采用某种集成策略进行组合,最后综合判断输出最终结果。一般而言,通常所说的集成学习中的多个学习器都是同质的"弱学习器"。基于该弱学习器,通过样本集扰动、输入特征扰动、输出表示扰动、算法参数扰动等方式生成多个学习器,进行集成后获得一个精度较好的"强学习器"。
- 强分类器与弱分类器简单来说:一个分类器分类准确率在60%-80%,即:比随机预测略好,但准确率却不太高,我们可以称之为“弱分类器”,比如CART(classification and regression tree)。反之,如果分类精度90%以上,则是强分类器。
- 目前集成学习算法大多源于bagging、boosting、stacking三种思想。
2. bagging (装袋)
tip:对于数据集,每次放回取样叫做Bagging,不放回取样叫做Pasting。
-
一种提高分类模型的方法,具体步骤如下:
- (1) 从训练集S中有放回的随机选取数据集M(∣M∣<∣S∣)。
- (2) 生成一个分类模型C。
- (3) 重复以上步骤m次,得到m个分类模型。
- (4)对于分类问题,每一个模型投票决定,少数服从多数原则。
- (5)对于回归问题,取平均值。
-
注意:这种抽样的方式会导致有的样本取不到,大约有,即大约有36.8%的样本取不到,这部分可用来做测试集。
-
优点: 通过减少方差来提高预测结果。
-
缺点: 失去了模型的简单性。
2.1 Random Forest
-
是一种基于树模型的bagging算法改进的模型。假定数据集中有M个特征和 N个观测值。每一个树有放回的随机抽出个观测值(或者)个特征。把每一个单一决策树的结果综合起来。随机森林的随机就体现在这两点,一个是随机选择样例,另一个是随机选择属性。
-
优点:
- (1) 减少了模型方差,提高了预测准确性。
- (2) 不需要给树做剪枝。
- (3) 在大规模数据集,尤其是特征较多的情况下,依然可以保持高效率。
- (4) 不用做特征选择,并且可以给出特征变量重要性的排序估计。
-
缺点:
- (1) 随机森林已经被证明在某些噪音较大的分类或回归问题上会过拟合。
- (2) 对于有不同取值属性的数据,取值划分较多的属性会对随机森林产生更大的影响,所以随机森林在这种数据上产生的属性权值是不可信的。
3. boosting(提升)
每一轮根据上一轮的分类结果动态调整每个样本在分类器中的权重,训练得到个弱分类器,他们都有各自的权重,通过加权组合的方式得到最终的分类结果(综合所有的基模型预测结果)。主要算法有AdaBoost、GBDT、Xgboost、LightGBM。
3.1 Adboost(自适应提升学习)
- 给定数据集,它包含个样本,分别为,其中是数据对象的类标号。
- (1) 开始时,Adaboost对每个训练元组赋予相等的权重。组合分类器包含个基本分类器。
- (2) 针对第个分类器:
- 首先,从数据集中进行抽样,形成大小为的训练集子,此处抽样方式为有放回的抽样,抽样过程中,每个元组被选中的机会由它的权重决定。
- 然后,根据训练出的分类器,使用检验分类器的分类误差,并计算该分类器的“投票表决权”的权重;
- 最后,训练集的权重根据分类器的分类情况调整。
- 如果一个样本被错误分类,则它的权重增加。
- 如果一个样本被正确分类,则它的权重减少。
- 训练集中每个样例的权重反映该样例被分类的困难程度——权重越高,被错误分类的可能性越高。然后,使用这些权重,为下一轮分类器(下一个分类器)产生训练样本,权重高的样本更容易被选中。
分类器的错误率计算公式: = 分错样本的数量 / 样本的总数量.
分类器的被赋予的权重值:
这里有个证明,如下:(分类问题中常使用指数损失函数,回归问题常使用均方误差)
样本权重调整公式:
- 如果第个样本被正确分类,则该样本权重更改为:
- 如果第个样本被分错,则该样本权重更改为:
- 基本的思想是,当建立分类器时,希望它更关注上一轮分类器(上一个分类器)错误分类的元组。整个分类过程中,某些分类器对某些“困难”元组的分类效果可能比其他分类器好。这样,建立了一个互补的分类器系列。
- 多用于二分类或多分类的应用场景。
- 优点
- (1) 很好的利用了弱分类器进行级联。
- (2)可以将不同的分类算法作为弱分类器。
- (3)AdaBoost具有很高的精度。
- (4) 相对于bagging算法,AdaBoost充分考虑的每个分类器的权重。
- 缺点:
- (1) AdaBoost迭代次数也就是弱分类器数目不太好设定,可以使用交叉验证来进行确定。
- (2) 数据不平衡导致分类精度下降。
- (3) 训练比较耗时,每次重新选择当前分类器最好切分点。
3.2 CART
CART即可以做分类,还可以做回归;其中CART数做回归的思想如下:
3.3 BDT
简单来说:训练得到的第一个弱分类器,根据其预测结果可以得到残差,根据该残差又能训练得到下一个弱分类器。
3.4 GBDT
前面已经介绍过了CART树回归的做法,接下来改写我们的GBDT做回归的算法为:
GBDT做分类使用的弱分类器还是CART,具体流程如下:
总结:
- 采用决策树作为弱分类器的算法被称为GBDT(Gradient Boosting Decision Tree),有时又被称为MART(Multiple Additive Regression Tree)。GBDT中使用的决策树通常为CART,前面已经介绍,它不仅可以做分类还可以做回归。
- 用一个很简单的例子来解释一下GBDT训练的过程,如图下图所示。模型的任务是预测一个人的年龄,训练集只有A、B、C、D 4个人,他们的年龄分别是14、16、24、26,特征包括了 "月购物金额"、"上网时长"、"上网历史" 等。
- 下面开始训练第一棵树:
- 训练的过程跟传统决策树相同,简单起见,我们只进行一次分枝。训练好第一棵树后,求得每个样本预测值与真实值之间的残差。
- 可以看到A、B、C、D的残差分别是−1、1、−1、1。
- 这时我们就用每个样本的残差训练下一棵树,直到残差收敛到某个阈值以下,或者树的总数达到某个上限为止。
-
由于GBDT是利用残差训练的,在预测的过程中,我们也需要把所有树的预测值加起来,得到最终的预测结果。
-
优点:
- (1)预测阶段的计算速度快,树与树之间可并行化计算。
- (2)在分布稠密的数据集上,泛化能力和表达能力都很好,这使得GBDT在Kaggle的众多竞赛中,经常名列榜首。
- (3)采用决策树作为弱分类器使得GBDT模型具有较好的解释性和鲁棒性,能够自动发现特征间的高阶关系,并且也不需要对数据进行特殊的预处理如归一化等。
-
缺点:
- (1)GBDT在高维稀疏的数据集上,表现不如支持向量机或者神经网络。
- (2)GBDT在处理文本分类特征问题上,相对其他模型的优势不如它在处理数值特征时明显。
- (3)训练过程需要串行训练,只能在决策树内部采用一些局部并行的手段提高训练速度。
3.5 Xgboost
- XGBoost是陈天奇等人开发的一个开源机器学习项目,高效地实现了GBDT算法并进行了算法和工程上的许多改进。
- 目标函数:
- 优点:
- (1)计算效率高,使用了二阶导,而GBDT只使用了一阶导,按照个人理解更快的拟合残差。
- (2)有正则化,减少过拟合。
- (3)进行了特征抽样减少过拟合,同时有利于并行计算。
- 缺点:
- (1)每次迭代时都要遍历整个数据集。
- (2)内存占用大。
- 细节:
这部分内容比较多,Xgboost有一篇英文的论文,讲的比较详细;我直接看了贪心科技一位老师的视频,主要是公式的推导,有个哥们将课堂的笔记整理成博客了,链接。
3.6 GBDT与XGboost联系与区别
- (1) GBDT是机器学习算法,XGBoost是该算法的工程实现。
- (2) 在使用CART作为基分类器时,XGBoost显式地加入了正则项来控制模型的复杂度,有利于防止过拟合,从而提高模型的泛化能力。
- (3) GBDT在模型训练时只使用了代价函数的一阶导数信息,XGBoost对代价函数进行二阶泰勒展开,可以同时使用一阶和二阶导数。
- (4) 传统的GBDT采用CART作为基分类器,XGBoost支持多种类型的基分类器,比如线性分类器。
- (5) 传统的GBDT在每轮迭代时使用全部的数据,XGBoost则采用了与随机森林相似的策略,支持对数据进行采样。
- (6) 传统的GBDT没有设计对缺失值进行处理,XGBoost能够自动学习出缺失值的处理策略。
3.7 LightGBM
- LightGBM也是一种基于决策树的梯度提升算法,相比XGboost又做了许多改进。在树分裂计算分裂特征的增益时,xgboost 采用了预排序的方法来处理节点分裂,这样计算的分裂点比较精确。但是,也造成了很大的时间开销。为了解决这个问题,Lightgbm 选择了基于 histogram 的决策树算法。相比于pre-sorted算法,histogram在内存消耗和计算代价上都有不少优势。
- Histogram算法简单来说,就是先对特征值进行装箱处理,形成一个一个的bins。在Lightgbm中默认的bins为256(1个字节的能表示的长度,可以设置)。具体如下:
- (1) 把连续的浮点特征值离散化成N个整数,构造一个宽度为N的直方图;对于分类特征,则是每一种取值放入一个bin,且当取值的个数大于max_bin数时,会忽略那些很少出现的category值。
- (2) 遍历数据时,根据离散化后的值作为索引在直方图中累积统计量。
- (3) 一次遍历后,直方图累积了需要的统计量,然后根据直方图的离散值,遍历寻找最优的分割点。
- Level-wise 和 Leaf-wise
- 相对于xgboost的level—wise的生长策略,lightgbm使用了leaf-wise树生长策略。由于level-wise在分裂时,部分增益小的树也得到了增长,虽然容易控制误差,但是分裂有时是不合理的,而lightgbm使用level-wise,只在增益大的树上分裂生长,甚至对Feature f如果分裂无收益,那么后续也将不会对f计算。体现在参数上,xgboost使用max_depth,而lightgbm使用num_leaves控制过拟合。
- 相比XgBoost计算信息增益表达式不同。
- Level-wise过一次数据可以同时分裂同一层的叶子,容易进行多线程优化,也好控制模型复杂度,不容易过拟合。但实际上Level-wise是一种低效的算法,因为它不加区分的对待同一层的叶子,带来了很多没必要的开销,因为实际上很多叶子的分裂增益较低,没必要进行搜索和分裂。
- Leaf-wise则是一种更为高效的策略,每次从当前所有叶子中,找到分裂增益最大的一个叶子,然后分裂,如此循环。因此同Level-wise相比,在分裂次数相同的情况下,Leaf-wise可以降低更多的误差,得到更好的精度。Leaf-wise的缺点是可能会长出比较深的决策树,产生过拟合。因此LightGBM在Leaf-wise之上增加了一个最大深度的限制,在保证高效率的同时防止过拟合。
细节:
3.8 Xgboost与LightGBM对比
3.8.1 切分算法(切分点的选取)
- 占用的内存更低,只保存特征离散化后的值,而这个值一般用8位整型存储就足够了,内存消耗可以降低为原来的1/8。
- 降低了计算的代价:预排序算法每遍历一个特征值就需要计算一次分裂的增益,而直方图算法只需要计算k次(k可以认为是常数),时间复杂度从O(#data#feature)优化到O(k#features)。(相当于LightGBM牺牲了一部分切分的精确性来提高切分的效率,实际应用中效果还不错)
- 空间消耗大,需要保存数据的特征值以及特征排序的结果(比如排序后的索引,为了后续快速计算分割点),需要消耗两倍于训练数据的内存
- 时间上也有较大开销,遍历每个分割点时都需要进行分裂增益的计算,消耗代价大
- 对cache优化不友好,在预排序后,特征对梯度的访问是一种随机访问,并且不同的特征访问的顺序不一样,无法对cache进行优化。同时,在每一层长树的时候,需要随机访问一个行索引到叶子索引的数组,并且不同特征访问的顺序也不一样,也会造成较大的cache miss。
- XGBoost使用的是pre-sorted算法(对所有特征都按照特征的数值进行预排序,基本思想是对所有特征都按照特征的数值进行预排序;然后在遍历分割点的时候用O(#data)的代价找到一个特征上的最好分割点最后,找到一个特征的分割点后,将数据分裂成左右子节点。优点是能够更精确的找到数据分隔点;缺点为较高的时间复杂度。
- LightGBM使用的是histogram算法,基本思想是先把连续的浮点特征值离散化成k个整数,同时构造一个宽度为k的直方图。在遍历数据的时候,根据离散化后的值作为索引在直方图中累积统计量,当遍历一次数据后,直方图累积了需要的统计量,然后根据直方图的离散值,遍历寻找最优的分割点;优点在于
3.8.2 决策树生长策略
- XGBoost采用的是带深度限制的level-wise生长策略,Level-wise过一次数据可以能够同时分裂同一层的叶子,容易进行多线程优化,不容易过拟合;但不加区分的对待同一层的叶子,带来了很多没必要的开销(因为实际上很多叶子的分裂增益较低,没必要进行搜索和分裂)
- LightGBM采用leaf-wise生长策略,每次从当前所有叶子中找到分裂增益最大(一般也是数据量最大)的一个叶子,然后分裂,如此循环;但会生长出比较深的决策树,产生过拟合(因此 LightGBM 在leaf-wise之上增加了一个最大深度的限制,在保证高效率的同时防止过拟合)。
- Histogram做差加速。一个容易观察到的现象:一个叶子的直方图可以由它的父亲节点的直方图与它兄弟的直方图做差得到。通常构造直方图,需要遍历该叶子上的所有数据,但直方图做差仅需遍历直方图的k个桶。利用这个方法,LightGBM可以在构造一个叶子的直方图后,可以用非常微小的代价得到它兄弟叶子的直方图,在速度上可以提升一倍。
- 直接支持类别特征:LightGBM优化了对类别特征的支持,可以直接输入类别特征,不需要额外的0/1展开。并在决策树算法上增加了类别特征的决策规则。
3.8.3 分布式训练方法上(并行优化)
- 在特征并行算法中,通过在本地保存全部数据避免对数据切分结果的通信;
- 在数据并行中使用分散规约(Reducescatter)把直方图合并的任务分摊到不同的机器,降低通信和计算,并利用直方图做差,进一步减少了一半的通信量。基于投票的数据并行(ParallelVoting)则进一步优化数据并行中的通信代价,使通信代价变成常数级别。
- 特征并行的主要思想是在不同机器在不同的特征集合上分别寻找最优的分割点,然后在机器间同步最优的分割点。
- 数据并行则是让不同的机器先在本地构造直方图,然后进行全局的合并,最后在合并的直方图上面寻找最优分割点。
- Cache命中率优化
- 基于直方图的稀疏特征优化
- DART(Dropout + GBDT)
- GOSS(Gradient-based One-Side Sampling):一种新的Bagging(row subsample)方法,前若干轮(1.0f /gbdtconfig->learning_rate)不Bagging;之后Bagging时, 采样一定比例g(梯度)大的样本。
3.9 CatBoost
简介:
CatBoost是俄罗斯的搜索巨头Yandex在2017年开源的机器学习库,是Boosting族算法的一种。CatBoost和XGBoost、LightGBM并称为GBDT的三大主流神器,都是在GBDT算法框架下的一种改进实现。XGBoost被广泛的应用于工业界,LightGBM有效的提升了GBDT的计算效率,而Yandex的CatBoost号称是比XGBoost和LightGBM在算法准确率等方面表现更为优秀的算法。
CatBoost是一种基于对称决策树(oblivious trees)为基学习器实现的参数较少、支持类别型变量和高准确性的GBDT框架,主要解决的痛点是高效合理地处理类别型特征,这一点从它的名字中可以看出来,CatBoost是由Categorical和Boosting组成。此外,CatBoost还解决了梯度偏差(Gradient Bias)以及预测偏移(Prediction shift)的问题,从而减少过拟合的发生,进而提高算法的准确性和泛化能力。
CatBoost主要贡献:
- 它自动采用特殊的方式处理类别型特征(categorical features)。首先对categorical features做一些统计,计算某个类别特征(category)出现的频率,之后加上超参数,生成新的数值型特征(numerical features)。
- catboost还使用了组合类别特征,可以利用到特征之间的联系,这极大的丰富了特征维度。
- catboost的基模型采用的是对称树,同时计算leaf-value方式和传统的boosting算法也不一样,传统的boosting算法计算的是平均数,而catboost在这方面做了优化采用了其他的算法,这些改进都能防止模型过拟合。
- 无需调参即可获得较高的模型质量,采用默认参数就可以获得非常好的结果,减少在调参上面花的时间。
4. stacking
-
stacking的思想是将每个基模型的输出组合起来作为一个特征向量,重新进行训练。可以理解为:将训练好的所有基模型对整个训练集进行预测,第j个基模型对第 个训练样本的预测值将作为新的训练集中第 个样本的第 个特征值,最后基于新的训练集进行训练。同理,预测的过程也要先经过所有基模型的预测形成新的测试集,最后再对测试集进行预测。
-
具体算法如下(为方便理解我举例说明):
- (1) 训练集大小400×10,400个样本,每个样本10个特征,(如果算上target有11列)。测试集大小为120×10。
- (2) 首先对训练集4折划分:每个的大小都收是100×10。模型第一次用训练,用 预测得到预测结果100×1。重复训练步骤,直到每一个都有对应的预测结果100×1。合并所有预测结果得到400×1。用预测得到原始测试集的预测结果120×1。
- (3) 模型用4折交叉得到训练集的预测结果:400×1;得到测试集的预测结果:120×1。
- (4) 模型用4折叫交叉得到训练集的预测结果:400×1;得到测试集的预测结果:120×1。
- (5) 综合(2)(3)(4)底层模型得到的训练集的预测结果,得到上层模型的训练集400×3;得到上层模型的测试集120×3。
- (6) 用(5)得到的训练集和测试集进行上层模型的训练。
-
优点:学习了底层模型之间的关系。
-
缺点:对于数据量要求比较大,因为要平衡第一层和第二层。