1.1 集成学习
1.1.1 boosting
boosting是一族可将弱学习器提升为强学习器的算法。它先从初始训练集训练出一个基学习器,再根据基学习器的表现对训练样本分布进行调整,使得先前基学习器做错的训练样本在后续受到更多的关注,然后基于调整后的样本分布来训练下一个基学习器;如此重复进行,知道基学习器数目达到实现指定的值T,最终将这T个基学习器进行加权融合。
1.1.2 bagging
bagging是并行式集成学习的最著名代表。它基于自助采样法,采用有放回式取样,经过m次采样可得到含m个样本的数据集,注意初始训练集中有的样本在采样集中会多次出现,有的则从未出现。
1.1.3 boosting与bagging的区别
①样本选择上:
Boosting:每一轮训练集不变,只是训练集中每个样本在分类器的权重发生变化。权值是根据上一轮的结果进行调整
Bagging:训练集是在原始集上有放回取的,从原始集选出的各轮训练集独立
②样本权重:
Boosting:根据错误率不断调整样本权重,错误率越大则权重越大
Bagging:使用均匀取样,每个样本的权重相等
③预测函数:
Boosting:每个弱分类器都有相应的权重,分类误差小的会有更大的权重
Bagging:所有分类器权重相等
④并行计算:
Boosting:各个分类器只能顺序生成
Bagging:各个分类器可以并行生成
1.2 XGB模型
(1)论文:XGBoost: AScalable Tree Boosting System[1603.02754] XGBoost: A Scalable Tree Boosting System
(2)《深入理解XGBoost》
论文为14年陈天奇最早提出的XGBoost模型,这本书详细介绍了XGB模型。论文中提出了4条主要贡献:
①构建了高可扩展的端到端的boosting系统
②提出了具有合理理论支撑的分布分位调整框架
③提出了一种新的并行树稀疏感知算法
④提出一种有效的块缓存结构便于外存树的学习
1.2.1 高可扩展的端到端的boosting系统
XGB的构成:XGB可以说是高配版的GBDT,它以CART树作为子模型,通过Gradient Tree Boosting实现多棵CART树的集成学习。
子树的训练算法:XGB训练时树的生成算法与CART一致,即通过计算节点分裂后是否产生“增益”来确定是否进行分裂。当一棵树生成完毕后再对其进行剪枝,CART树采用的是后剪枝算法,即生成决策树后再对其剪枝,防止过拟合,而XGB在实现时并未完全按照这个剪枝过程,而是采用了简单、高效的剪枝方法,即判断当前节点的收益是否小于定义的最小收益,若比最小收益小,则进行剪枝。
损失函数:在每一轮的训练中,XGB将损失函数梯度下降方向作为优化目标,即第m轮生成的树会学习真实值和m-1轮模型的预测值的“残差”,使得模型预测结果逐步逼近真实值。
目标函数:XGB的目标函数有两项组成:损失函数和正则化项。损失函数即为上述“残差”,正则化项用来控制模型的复杂度,倾向于选择简单的模型,正则化项又包含两项,其中第一项为通过叶子结点数及其系数控制树的复杂度,第二项为L2正则项,用于控制叶子结点的权重分数。
目标函数的优化:XGB引入了泰勒公式来近似和简化目标函数,其中损失函数进行了二阶泰勒展开,这样同时用到了一阶、二阶导数,可以加快优化速度。而GBDT只展开到一阶梯度。
为什么进行二阶泰勒展开:XGB为什么二阶展开效果更好的官方解释:展开形式好,能很好的复用MSE的推导流程,同时对自定义损失函数的拓展支持也比较好。网上学者的总结大概为如下两点:1)当目标函数是MSE时,展开是一阶项(残差)+二阶项的形式(官网说这是一个nice form),而其他目标函数,如logloss的展开式就没有这样的形式。为了能有个统一的形式,所以采用泰勒展开来得到二阶项,这样就能把MSE推导的那套直接复用到其他自定义损失函数上。简短来说,就是为了统一损失函数求导的形式以支持自定义损失函数。这是从为什么会想到引入泰勒二阶的角度来说的。2)二阶信息本身就能让梯度收敛更快更准确。这一点在优化算法里的牛顿法里已经证实了。可以简单认为一阶导指引梯度方向,二阶导指引梯度方向如何变化。这是从二阶导本身的性质,也就是为什么要用泰勒二阶展开的角度来说的。
缩减:XGB引入了缩减的思想,即在每一轮训练前,为新的子模型前加一个参数(类似于学习率),可以限制每棵树对模型的影响,使得在模型优化过程中每次只前进一小步,逐步达到最优,有效避免过拟合。
列采样:XGB同时支持行采样和列采样。行采样是对样本有放回采样;列采样时每次从所有特征中选一部分特征采样而非所有特征(列采样最初被应用到随机森林算法中,XGB借鉴了该方法,既能避免模型过拟合,也减少了计算量)。根据实践经验,列采样比行采样更能有效避免过拟合。
1.2.2 分布分位调整框架(切分点查找算法)
精确贪心算法:是一种启发式算法,每次在节点分裂时,选择当前最优的分裂策略,而非全局最优的分裂策略。
基于直方图的近似算法:对某一特征寻找最优切分点时,首先对该特征的所有切分点按分位数分桶,得到一个候选的切分点集,然后计算每个桶的特征统计G和H(一、二阶梯度),最后将受益最大的桶的候选切分点作为最优切分点。(近似算法中还包含全局策略与本地策略两种构建策略)
加权分位数概要算法:上述算法的关键在于怎么得到候选切分点集,分位数的方法经常会被用作选择的依据,XGB提出了一种带权值数据求分位数的近似算法。
1.2.3 并行树稀疏感知算法
稀疏感知算法:XGB处理稀疏数据的方法是给每棵树指定一个默认方向,即当特征值缺失时,该样本会被划分到默认方向的节点上。默认方向的选取原则为:选取受益最大的方向为默认方向。该算法需要从左到右和从右到左两次扫描来完成默认方向的学习,XGB采用了一种替代方法,即先求缺失值梯度对总和,然后通过一次扫描完成上述操作,实现并行树计算。
1.2.4 块缓存结构
此部分为XGB在系统设计方面的实现和优化,包括基于列存储数据块的并行学习、缓存感知访问、外存块计算。
1.3 LightGBM模型
论文:LightGBM: A Highly Efficient GradientBoosting Decision TreeLightGBM: A Highly Efficient Gradient Boosting Decision Tree
LGB也是一种GBDT算法,相比XGB算法,LGB的速度快了很多,这篇文献主要提出了两种新的技术:
①基于梯度的单边采样(GOSS)
②互斥特征的捆绑(EFB)
GOSS可以用更小的数据量对信息增益进行相当准确的估计。EFB可以用来降低特征的个数。这两种算法都对传统的GBDT算法进行了加速。
1.3.1 基于梯度的单边采样(GOSS)
样本权重是一个很好的描述数据重要性的指标,但是在GBDT中没有这种权重,幸运的是,注意到每个样本的梯度可以提供给我们有用的关于数据采样的信息。对于具有小梯度的样本,它的训练误差很小并且此时它就已经学习的很好了,一个直接的想法是丢弃它,但是这会改变数据的分布,影响模型精度,于是提出了GOSS解决这一问题。
GOSS保留所有具有大梯度的样本,在梯度小的样本上进行随机采样,为了抵消数据分布的影响,计算信息增益时对小梯度样本乘上一个系数,从而不会改变过多原数据集的分布。
1.3.2 互斥特征的捆绑(EFB)
高维的数据通常是稀疏的,特别地,在稀疏特征空间中,许多特征是互斥的,即它们不同时为非零值。我们可以绑定互斥的特征为单一特征,这种方式的构建直方图时间复杂度从O(#data * #feature)降到O(#data * #bundle),由于#bundle << # feature,可以极大地加速GBDT的训练过程而且不损失精度。(构造直方图的时候,遍历一个“捆绑的大特征”可以得到一组互斥特征的直方图。这样只需要遍历这些“大特征”就可以获取到所有特征的直方图,降低了需要遍历的特征量)
1.4 Catboost模型
论文:CatBoost: unbiased boosting withcategorical feature[1810.11363] CatBoost: gradient boosting with categorical features support
特别适合处理类别特征的算法,且速度比LGB还要快。Catboost是基于对称树的GBDT算法,论文中主要提出:
①一种排列驱动的替代分类算法
②一种处理类别特征的算法
1.4.1 一种排列驱动的替代分类算法(计算TBS)
类别特征:如果类别特征种类少,则可以用one-hot编码的方式处理;当类别特征种类很多时,使用one-hot会造成维度灾难,catboost采用了计算“基于标签的统计量(TBS)”来处理这种情况,即统计每个特征的频率,再加上超参数(先验系数),形成新的数值特征。
基于标签的统计量(TBS):catboost提供几种计算TBS的方法,包括Gready TBS、Holdout TBS、Leave-one-out TBS但这些方法都有缺陷,最后采取了最推荐的方法_——Ordered TBS。它使用次序原则(ordering principle),这是受到在线学习的启发(在线学习按照时序获取训练数据),简单地说就是它的TBS是依靠目前以观察到的样本值计算,可以理解成滑动窗口TBS,而之前的TBS都是基于固定系数K计算得出的。
1.4.2 一种处理类别特征的算法:(旨在解决预测偏移,普遍存在于梯度提升算法中)
预测偏移:catboost提出一种ordered boosting方法来解决这个问题,简单地说就是每一轮训练时都会使用一组新的训练集,这个新的训练集相比上一次的训练集,它的特征分布会有变化,如果用上一个训练集训练得到的模型来对新的训练集预测,就会产生预测偏移问题。ordeted boosting采用了这样一种方法:每次训练时,不使用此时新得到的训练集计算“残差”,而是通过用新的训练集的label减去上一个模型对新的训练集的预测值来计算来计算“残差”,从而解决这一问题。
特征结合:是catboost的另一个细节,它能捕捉高阶的依赖信息。但是特征结合数目呈指数级增长,catboost采用贪心的算法,即第一次分裂时不进行结合,从第二次开始对当先分裂特征和其余所有数据集中的分类特征进行结合,选取最优的进行分裂。