集成算法总结


集成算法是构建多个学习器,通过一定策略结合来完成学习任务。正所谓三个臭皮匠顶一个诸葛亮,当弱学习器被正确组合时,我们能得到更精确、鲁棒性更好的学习器。由于个体学习器在准确性和多样性存在冲突,追求多样性势必要牺牲准确性。这就需要将这些“好而不同”的个体学习器结合起来。而研究如何产生并结合个体学习器也是集成学习研究的核心。
集成学习的思想时将这些弱学习器的偏置或方差结合起来,从而创建一个强学习机,获得更好的性能
按照个体学习器之间的关系,集成算法分为Bagging、Boosting、Stacking三大类。

Bagging

基于自主采样法(bootstrap sampling)随即得到一些样本集训练,用来分别训练不同的基学习器,然后对不同的基学习器得到的结果投票得出最终的分类结果。自主采样法得到的样本大概会有63%的数据样本被使用(有些数据样本会被重复抽取,有些不会被抽取),剩下的可以用来做验证集。
在这里插入图片描述
Bagging中各个算法之间没有依赖,可以并行计算,他的结果参考了各种情况,实现的是在欠拟合和过拟合之间取折中。

Boosting

Boosting,提升算法,通过反复学习得到一系列弱分类器,然后组合这些弱分类器得到一个强分类器,吧弱学习器提升为强学习器的过程。主要分为两个部分,加法模型和向前分布。
加法模型就是把一系列弱学习器相加串联为强学习器,
F M ( x ; P ) = ∑ m = 1 n β m h ( x ; a m ) F_M(x;P) = \sum_{m=1}^n\beta_mh(x;a_m) FM(x;P)=m=1nβmh(x;am)
其中, h ( x ; a m ) h(x;a_m) h(x;am)是一些列的弱学习器, a m a_m am是该学习器训练得到的最优参数, β m \beta_m βm是对应弱学习器在强学习器中所占比例的系数。
向前分布是指本轮中的学习器是在上一轮学习器的基础上迭代训练得到的,
F m ( x ) = F m − 1 ( x ) + β m h m ( x ; a m ) F_m(x) = F_{m-1}(x) + \beta_mh_m(x;a_m) Fm(x)=Fm1(x)+βmhm(x;am)
在这里插入图片描述
训练过程为阶梯状,基模型按照次序一一进行训练,基模型的训练集按照某种策略每次都进行一定的转化,如果某一个数据在这次分错了,那么在下一次就会给他更大的权重。对所有基模型预测的结果进行线性综合产生最终的预测结果。
一般来说,他的效果会比Bagging好一些,由于新模型是在就模型的基本上建立的,因此不能使用并行方式训练,并且由于对错误样本的关注,也可能造成过拟合。

stacking

stacking训练一个模型用于组合其他各个基模型。具体方法是吧数据分成两部分,用其中一部分训练几个基模型1、2、3,用另一部分数据测试这几个基模型,把1、2、3的输出作为输入,训练组合模型。注意,他不是把模型的结果组织起来,而把模型组织起来。理论上,stacking可以组织任何模型,实际中常用单层logistic回归作为模型。
在这里插入图片描述
举个栗子:
在这里插入图片描述

  1. 首先我们会得到两组数据:训练集和测试集。将训练集分成5份:train1,train2,train3,train4,train5。
  2. 选定基模型。这里假定我们选择了xgboost, lightgbm 和 randomforest这三种作为基模型。比如xgboost模型部分:依次用train1,train2,train3,train4,train5作为验证集,其余4份作为训练集,进行5折交叉验证进行模型训练;再在测试集上进行预测。这样会得到在训练集上由xgboost模型训练出来的5份predictions,和在测试集上的1份预测值B1。将这五份纵向重叠合并起来得到A1。lightgbm和randomforest模型部分同理。
  3. 三个基模型训练完毕后,将三个模型在训练集上的预测值作为分别作为3个"特征"A1,A2,A3,使用LR模型进行训练,建立LR模型。
  4. 使用训练好的LR模型,在三个基模型之前在测试集上的预测值所构建的三个"特征"的值(B1,B2,B3)上,进行预测,得出最终的预测类别或概率。

stacking一般是两层就够了。

常用的集成算法

随机森林 Random Forest

概念:通过集成学习的思想将多棵树集成的一种算法。基本单元是决策树。随机森林中每颗决策树都是一个分类器,对于一个输入样本,N棵树会有N个分类结果。随机森林集成了所有的分类投票结果,将投票次数最多的类别指定为最终输出。

随机森林生成规则

  • 如果训练集大小为N,对于每棵树而言,随机且有放回的从训练集中的抽取N个训练样本,作为该树的训练集。(随机抽样保证每棵树的训练集不同,有放回抽样保证每棵树的训练样本有交集,避免树的结果有很大差异)
  • 特征随机。如果每个样本的特征维度是M。指定一个常数m<<M,随机从M个特征中选取m个特征子集,每次树进行分裂时,从m个特征中选择最优的
  • 每棵树尽最大程度生长,并没有剪枝过程
  • 将生成的多棵树组成随机森林,用随机森林对新的数据进行分类,分类结果按树分类多少而定

特点

  • 在当前所有算法中,具有极好的准确率
  • 能够处理具有高维特征的输入样本,而且不需要降维
  • 能够评估各个特征在分类问题上的重要性
  • 在生成过程中,能够获取到内部生成误差的一种无偏估计
  • 对于缺省值也能够获得很好的结果
  • 随机森林中的两个“随机性”是随机森林不容易陷入过拟合,并且具有很好的抗噪能力
  • 能够处理离散型/连续型数据,无需规范化
  • 随机森林不使用全样本,因为全样本忽视了局部样本的规律,不利于模型泛化能力

缺点

  • 随机森林在解决回归问题时,表现较差,这是因为它并不能给出一个连续的输出。
  • 随机森林已经被证明在某些噪音较大的分类或者回归问题上会过拟合
  • 随机森林就像黑盒子,无法控制模型内部运行(可控性差)
  • 对于小数据或者低维数据,可能不能产生很好的分类

Adaboost

adaboost将弱分类器迭代成强分类器的过程,每个迭代过程中改变样本权重和分类器权重,最终结果是每个分类器的权重和。
原理

  1. 初始化训练样本数据(每个样本)的权值分布:如果有N个样本,则每一个训练的样本点最开始时都被赋予相同的权重
  2. 训练弱分类器。具体训练过程中,如果某个样本已经被准确的分类,那么在构造下一个训练集中,他的权重就被降低;相反,如果某个样本点没有被准确分类,那么他的权重就得到提高。同时,得到弱分类器对应的话语权。然后,更新权值后的样本及被用于训练下一个分类器,整个训练过程如此迭代的进行下去。
  3. 将各个训练得到的弱分类器组合成强分类器。各个弱分类器的训练过程结束后,分类误差率小的弱分类器话语权较大,其在最终的分类函数中起着较大的决定作用,而分类误差率大的弱分类器的话语权小。

计算弱分类器的误差函数,即分错样本对应的权值之和,adaboost损失函数为指数损失
ϵ m = ∑ n = 1 N w n ( m ) I ( y m ( x n ) ≠ t n ) \epsilon_m = \sum_{n=1}{N}w_n^{(m)}I(y_m(x_n)\not=t_n) ϵm=n=1Nwn(m)I(ym(xn)=tn)
计算弱分类器 G m ( x ) G_m(x) Gm(x)的话语权 α m \alpha_m αm
α m = 1 2 l o g 1 − ϵ m ϵ m \alpha_m = \frac{1}{2}log\frac{1-\epsilon_m}{\epsilon_m} αm=21logϵm1ϵm
更新训练样本集的权值分布
D m + 1 = ( W m + 1 , 1 , W m + 1 , , 2 . . . . . . . W m + 1 , i . . . . . . . W m + 1 , N ) D_{m+1} = (W_{m+1,1},W_{m+1,,2}.......W_{m+1,i}.......W_{m+1,N}) Dm+1=(Wm+1,1,Wm+1,,2.......Wm+1,i.......Wm+1,N)
W m + 1 , i = W m i Z m e x p ( − α m y i G m x i ) ) , i = 1 , 2....... N W_{m+1,i} = \frac{W_{mi}}{Z_m} exp(-\alpha_my_iG_mx_i)),i=1,2.......N Wm+1,i=ZmWmiexp(αmyiGmxi)),i=1,2.......N
D m + 1 D_{m+1} Dm+1是用于下次迭代时样本的权值, W m + 1 , i W_{m+1,i} Wm+1,i是下一次迭代时,第i个样本的权值。其中, y i y_i yi代表第i个样本对应的类别(1或-1), G m ( x i ) G_m(x_i) Gm(xi)表示弱分类器对样本 x i x_i xi的分类(1或-1)。 Z m Z_m Zm是归一化因子,使得所有样本对应的权值之和为
Z M = ∑ i = 1 N w m i e x p ( − α m y i G m ( x i ) ) Z_M = \sum_{i=1}^{N}w_{mi}exp(-\alpha_my_iG_m(x_i)) ZM=i=1Nwmiexp(αmyiGm(xi))
迭代完成和,组合弱分类器
G ( x ) = s i g n ( f ( x ) ) = s i g n ( ∑ m = 1 M α m G m ( x ) ) G(x) = sign(f(x)) = sign(\sum_{m=1}^{M}\alpha_mG_m(x)) G(x)=sign(f(x))=sign(m=1MαmGm(x))

优点

  • 精度很高的分类器
  • 很好地利用了弱分类器进行级联
  • 可以将不同的分类算法作为弱分类器
  • 充分考虑每个分类器的权重
  • 提供的是框架,可以使用各种方法构建弱分类器
  • 简单,不需要做特征筛选
  • 不用担心过拟合

实际应用

  • 用于二分类或多分类
  • 特征选择
  • 分类任务的baseline

缺点

  • 迭代次数不太好设定
  • 数据不平衡导致分类精度下降
  • 训练比较耗时,每次重新选择当前分类器最好切分点
  • 对异常样本比较敏感,异常样本在迭代过程中会获得较高权值,影响最终学习器的性能表现

训练过程中,每轮训练一直存在分类错误的问题,整个Adaboost却能快速收敛
每轮训练结束后,AdaBoost 会对样本的权重进行调整,调整的结果是越到后面被错误分类的样本权重会越高。而后面的分类器为了达到较低的带权分类误差,会把样本权重高的样本分类正确。这样造成的结果是,虽然每个弱分类器可能都有分错的样本,然而整个 AdaBoost 却能保证对每个样本进行正确分类,从而实现快速收敛。

GBDT

gbdt,Gradient Boost Decision Tree,梯度下降树。是一种基于提升决策树的模型以分类回归决策树作为基本分类器的模型。

boosting tree
提升树就是把分类回归决策树CART直接进行线性组合的决策树模型。
f M ( x ) = = ∑ m = 1 M T ( x ; θ m ) f_M(x) = =\sum_{m=1}{M}T(x;\theta_m) fM(x)==m=1MT(x;θm)
T ( x ; θ m ) T(x;\theta_m) T(x;θm)表示决策树, θ m \theta_m θm是决策树的参数,M是树的个数
到第m步的模型是:
f m ( x ) = f m − 1 ( x ) + T ( x ; θ m ) f_m(x) = f_{m-1}(x) + T(x;\theta_m) fm(x)=fm1(x)+T(x;θm)
f m − 1 ( x ) f_{m-1}(x) fm1(x)当前模型,通过最小化损失函数的方法确定下一颗决策树的参数。一般对于回归问题采用的损失函数是平方误差损失函数,对于分类问题则使用指数损失函数。
f m ( x ) = f m − 1 ( x ) − T ( x ; θ m ) f_m(x) = f_{m-1}(x)-T(x;\theta_m) fm(x)=fm1(x)T(x;θm)
以回归问题为例:
L = [ y − f m ( x ) ] 2 = [ r − T ( x ; θ m ) ] 2 L = [y-f_m(x)]^2 = [r-T(x;\theta_m)]^2 L=[yfm(x)]2=[rT(x;θm)]2
r = y − f m − 1 ( x ) r = y-f_{m-1}(x) r=yfm1(x)是当前模型拟合的残差

gradient boosting
提升树算法利用加法模型与前向分布算法实现学习的优化过程,当损失函数是平方损失和指数损失的时候,每一步优化比较简单,但是对一般损失函数而言,往往每一步算法优化并不是那么容易,所以就有了梯度提升算法,主要是利用损失函数的负梯度在当前模型的值:
− [ ∂ L ( y , f ( x i ) ) ∂ f ( x i ) ] f ( x ) = f m − 1 ( x ) -[ \frac{\partial L(y,f(x_i))}{\partial f(x_i)}]_{f(x)=f_{m-1}(x)} [f(xi)L(y,f(xi))]f(x)=fm1(x)
算法流程:
在这里插入图片描述
gbdt的核心在于,每一颗树学的是之前所有树结论和的残差,这个残差就是一个加预测之后能得到真实值的累加量(所以gbdt中的树都是回归树)。gbdt的弱分类器默认选择CART TREE,也可以选择其他低方差高偏差的分类器。
比如A的真实年龄是18岁,但第一棵树的预测年龄是12岁,差了6岁,即残差为6岁。那么在第二棵树里我们把A的年龄设为6岁去学习,如果第二棵树真的能把A分到6岁的叶子节点,那累加两棵树的结论就是A的真实年龄;如果第二棵树的结论是5岁,则A仍然存在1岁的残差,第三棵树里A的年龄就变成1岁,继续学
在这里插入图片描述
在第一棵树分枝和图1一样,由于A,B年龄较为相近,C,D年龄较为相近,他们被分为两拨,每拨用平均年龄作为预测值。此时计算残差(残差的意思就是: A的预测值 + A的残差 = A的实际值),所以A的残差就是16-15=1(注意,A的预测值是指前面所有树累加的和,这里前面只有一棵树所以直接是15,如果还有树则需要都累加起来作为A的预测值)。进而得到A,B,C,D的残差分别为-1,1,-1,1。然后我们拿残差替代A,B,C,D的原值,到第二棵树去学习,如果我们的预测值和它们的残差相等,则只需把第二棵树的结论累加到第一棵树上就能得到真实年龄了。这里的数据显然是我可以做的,第二棵树只有两个值1和-1,直接分成两个节点。此时所有人的残差都是0,即每个人都得到了真实的预测值。

适用范围

  • 所有回归问题(线性/非线性)
  • 二分类问题

优点

  • 预测精度高
  • 适合低维数据
  • 能处理非线性数据

缺点

  • 并行麻烦
  • 数据维度高时会加大算法的计算复杂度

xgboost

xgboost,exterme gradient boosting,极限梯度提升。是基于决策树的集成机器学习算法,以梯度提升为框架。xgboost由gbdt发展而来,同样是利用加法模型与前向分布算法实现学习的优化过程,但与gbdt不同的地方在于:

  • 基分类器:XGBoost的基分类器不仅支持CART决策树,还支持线性分类器,此时XGBoost相当于带L1和L2正则化项的Logistic回归(分类问题)或者线性回归(回归问题)。
  • 目标函数:xgboost的损失函数添加了正则化项,使用正则用以控制模型的复杂度,正则项里包含了树的叶子节点个数、每个叶子节点权重(叶节点的score值)的平方和。
  • 优化方法:xgboost对损失函数做了二阶泰勒展开。并且支持自定义损失函数,只要损失函数一阶、二阶可导
  • xgboost对缺失值进行了处理。让缺失值分别被切分到左节点以及右节点,通过计算得分值比较两种切分方法哪一个更优,则会对每个特征的缺失值都会学习到一个最优的默认切分方向。
  • 防止过拟合:xgboost除了增加了正则项来防止过拟合,还支持列采样的方式来防止过拟合
  • 并行化,可以在最短时间内用更少的计算资源得到更好的结果。注意不是tree维度的并行,而是特征维度的并行。XGBoost预先将每个特征按特征值排好序,存储为块结构,分裂结点时可以采用多线程并行查找每个特征的最佳分割点,极大提升训练速度。

XGBoost的可以使用Regression Tree(CART)作为基学习器,也可以使用线性分类器作为基学习器。在这里插入图片描述
图中为两颗回归树(左右两个),其中树下方的输出值即为叶节点的权重(得分),当输出一个样本进行预测时,根据每个内部节点的决策条件进行划分节点,最终被划分到的叶节点的权重即为该样本的预测输出值

训练过程
目标函数:
在这里插入图片描述
公式(2)右边第一部分是度量预测值与真实值之间的损失函数,第二部分表示对模型复杂度的惩罚项(正则项),在惩罚项中 γ \gamma γ λ \lambda λ 表示惩罚系数, T T T表示给定一颗树的叶节点数, ∣ ∣ ω ∣ ∣ 2 ||\omega||^2 ω2 表示每颗树叶节点上的输出分数的平方(相当于L2正则)。从目标函数的定义可以看出XGBoost对模型复杂度考虑了每颗树的叶节点个数,以及每颗树叶节点输出得分值得平方和。

XGBoost为什么使用泰勒二阶展开

  • 精准性:相对于GBDT的一阶泰勒展开,XGBoost采用二阶泰勒展开,可以更为精准的逼近真实的损失函数
  • 可扩展性:损失函数支持自定义,只需要新的损失函数二阶可导。

XGBoost为什么快

  • 分块并行:训练前每个特征按特征值进行排序并存储为Block结构,后面查找特征分割点时重复使用,并且支持并行查找每个特征的分割点
  • 候选分位点:每个特征采用常数个分位点作为候选分割点
  • CPU cache 命中优化: 使用缓存预取的方法,对每个线程分配一个连续的buffer,读取每个block中样本的梯度信息并存入连续的Buffer中。
  • Block 处理优化:Block预先放入内存;Block按列进行解压缩;将Block划分到不同硬盘来提高吞吐

XGBoost防止过拟合的方法

  • 目标函数添加正则项:叶子节点个数+叶子节点权重的L2正则化
  • 列抽样:训练的时候只用一部分特征(不考虑剩余的block块即可)
  • 子采样:每轮计算可以不使用全部样本,使算法更加保守
  • shrinkage: 可以叫学习率或步长,为了给后面的训练留出更多的学习空间

XGBoost中叶子结点的权重如何计算出来
在这里插入图片描述
XGBoost如何处理不平衡数据

  • 使用AUC时,可以通过设置scale_pos_weight来平衡正样本和负样本的权重。例如,当正负样本比例为1:10时,scale_pos_weight可以取10;
  • 如果你在意概率(预测得分的合理性),你不能重新平衡数据集(会破坏数据的真实分布),应该设置max_delta_step为一个有限数字来帮助收敛(基模型为LR时有效)。
  • 通过上采样、下采样、SMOTE算法或者自定义代价函数的方式解决正负样本不平衡的问题。

XGBoost中如何对树进行剪枝

  • 在目标函数中增加了正则项:使用叶子结点的数目和叶子结点权重的L2模的平方,控制树的复杂度。
  • 在结点分裂时,定义了一个阈值,如果分裂后目标函数的增益小于该阈值,则不分裂。
  • 当引入一次分裂后,重新计算新生成的左、右两个叶子结点的样本权重和。如果任一个叶子结点的样本权重低于某一个阈值(最小样本权重和),也会放弃此次分裂。
  • XGBoost 先从顶到底建立树直到最大深度,再从底到顶反向检查是否有不满足分裂条件的结点,进行剪枝。(后剪枝)

XGBoost如何评价特征的重要性

  • weight :该特征在所有树中被用作分割样本的特征的总次数。
  • gain :该特征在其出现过的所有树中产生的平均增益。
  • cover :该特征在其出现过的所有树中的平均覆盖范围。

LightGBM比XGBoost的优点

  • 分割点查找算法:XGB使用特征预排序算法,LGB使用基于直方图的切分点算法,减少内存占用,提高计算效率
  • 支持离散变量:无法直接输入类别型变量,因此需要事先对类别型变量进行编码(例如独热编码),而LightGBM可以直接处理类别型变量。
  • 缓存命中率:XGB使用Block结构的一个缺点是取梯度的时候,是通过索引来获取的,而这些梯度的获取顺序是按照特征的大小顺序的,这将导致非连续的内存访问,可能使得CPU cache缓存命中率低,从而影响算法效率。而LGB是基于直方图分裂特征的,梯度信息都存储在一个个bin中,所以访问梯度是连续的,缓存命中率高。
  • LightGBM 与 XGboost 的并行策略不同

Lightgbm

LightGBM(Light Gradient Boosting Machine)是一个实现GBDT算法的框架,支持高效率的并行训练,并且具有更快的训练速度、更低的内存消耗、更好的准确率、支持分布式可以快速处理海量数据等优点。

基于Histogram的决策树算法
转自https://zhuanlan.zhihu.com/p/99069186
直方图算法
Histogram algorithm应该翻译为直方图算法,直方图算法的基本思想是:先把连续的浮点特征值离散化成 [公式] 个整数,同时构造一个宽度为 [公式] 的直方图。在遍历数据的时候,根据离散化后的值作为索引在直方图中累积统计量,当遍历一次数据后,直方图累积了需要的统计量,然后根据直方图的离散值,遍历寻找最优的分割点。
在这里插入图片描述
直方图算法简单理解为:首先确定对于每一个特征需要多少个箱子(bin)并为每一个箱子分配一个整数;然后将浮点数的范围均分成若干区间,区间个数与箱子个数相等,将属于该箱子的样本数据更新为箱子的值;最后用直方图(bins)表示。看起来很高大上,其实就是直方图统计,将大规模的数据放在了直方图中。
特征离散化具有很多优点,如存储方便、运算更快、鲁棒性强、模型更加稳定等。对于直方图算法来说最直接的有以下两个优点:

  • 内存占用更小:直方图算法不仅不需要额外存储预排序的结果,而且可以只保存特征离散化后的值,而这个值一般用8位整型存储就足够了,内存消耗可以降低为原来的1/8。也就是说XGBoost需要用32位的浮点数去存储特征值,并用[公式]位的整形去存储索引,而 LightGBM只需要用 32 位去存储直方图,内存相当于减少为1/8
  • 计算代价更小:预排序算法XGBoost每遍历一个特征值就需要计算一次分裂的增益,而直方图算法LightGBM只需要计算k次(k可以认为是常数),直接将时间复杂度从O(datafeature)降低到O(kfeature),而我们知道data>>k。
    当然,Histogram算法并不是完美的。由于特征被离散化后,找到的并不是很精确的分割点,所以会对结果产生影响。但在不同的数据集上的结果表明,离散化的分割点对最终的精度影响并不是很大,甚至有时候会更好一点。原因是决策树本来就是弱模型,分割点是不是精确并不是太重要;较粗的分割点也有正则化的效果,可以有效地防止过拟合;即使单棵树的训练误差比精确分割的算法稍大,但在梯度提升(Gradient Boosting)的框架下没有太大的影响。

直方图做差加速
LightGBM另一个优化是Histogram(直方图)做差加速。一个叶子的直方图可以由它的父亲节点的直方图与它兄弟的直方图做差得到,在速度上可以提升一倍。通常构造直方图时,需要遍历该叶子上的所有数据,但直方图做差仅需遍历直方图的k个桶。在实际构建树的过程中,LightGBM还可以先计算直方图小的叶子节点,然后利用直方图做差来获得直方图大的叶子节点,这样就可以用非常微小的代价得到它兄弟叶子的直方图。
在这里插入图片描述
注意:XGBoost 在进行预排序时只考虑非零值进行加速,而 LightGBM 也采用类似策略:只用非零特征构建直方图。

带深度限制的 Leaf-wise 算法
在Histogram算法之上,LightGBM进行进一步的优化。首先它抛弃了大多数GBDT工具使用的按层生长 (level-wise) 的决策树生长策略,而使用了带有深度限制的按叶子生长 (leaf-wise) 算法。
XGBoost 采用 Level-wise 的增长策略,该策略遍历一次数据可以同时分裂同一层的叶子,容易进行多线程优化,也好控制模型复杂度,不容易过拟合。但实际上Level-wise是一种低效的算法,因为它不加区分的对待同一层的叶子,实际上很多叶子的分裂增益较低,没必要进行搜索和分裂,因此带来了很多没必要的计算开销。
在这里插入图片描述
LightGBM采用Leaf-wise的增长策略,该策略每次从当前所有叶子中,找到分裂增益最大的一个叶子,然后分裂,如此循环。因此同Level-wise相比,Leaf-wise的优点是:在分裂次数相同的情况下,Leaf-wise可以降低更多的误差,得到更好的精度;Leaf-wise的缺点是:可能会长出比较深的决策树,产生过拟合。因此LightGBM会在Leaf-wise之上增加了一个最大深度的限制,在保证高效率的同时防止过拟合。
在这里插入图片描述
单边梯度采样算法
Gradient-based One-Side Sampling 应该被翻译为单边梯度采样(GOSS)。GOSS算法从减少样本的角度出发,排除大部分小梯度的样本,仅用剩下的样本计算信息增益,它是一种在减少数据量和保证精度上平衡的算法。
AdaBoost中,样本权重是数据重要性的指标。然而在GBDT中没有原始样本权重,不能应用权重采样。幸运的是,我们观察到GBDT中每个数据都有不同的梯度值,对采样十分有用。即梯度小的样本,训练误差也比较小,说明数据已经被模型学习得很好了,直接想法就是丢掉这部分梯度小的数据。然而这样做会改变数据的分布,将会影响训练模型的精确度,为了避免此问题,提出了GOSS算法。
GOSS是一个样本的采样算法,目的是丢弃一些对计算信息增益没有帮助的样本留下有帮助的。根据计算信息增益的定义,梯度大的样本对信息增益有更大的影响。因此,GOSS在进行数据采样的时候只保留了梯度较大的数据,但是如果直接将所有梯度较小的数据都丢弃掉势必会影响数据的总体分布。所以,GOSS首先将要进行分裂的特征的所有取值按照绝对值大小降序排序(XGBoost一样也进行了排序,但是LightGBM不用保存排序后的结果),选取绝对值最大的a100%个数据。然后在剩下的较小梯度数据中随机选择b100%个数据。接着将这b*100%个数据乘以一个常数(1-b)/a,这样算法就会更关注训练不足的样本,而不会过多改变原数据集的分布。最后使用这(a+b)*100%个数据来计算信息增益。

互斥特征捆绑算法
高维度的数据往往是稀疏的,这种稀疏性启发我们设计一种无损的方法来减少特征的维度。通常被捆绑的特征都是互斥的(即特征不会同时为非零值,像one-hot),这样两个特征捆绑起来才不会丢失信息。如果两个特征并不是完全互斥(部分情况下两个特征都是非零值),可以用一个指标对特征不互斥程度进行衡量,称之为冲突比率,当这个值较小时,我们可以选择把不完全互斥的两个特征捆绑,而不影响最后的精度。互斥特征捆绑算法(Exclusive Feature Bundling, EFB)指出如果将一些特征进行融合绑定,则可以降低特征数量。这样在构建直方图时的时间复杂度从O(datafeature) 变为O(databundle) ,这里 bundle 指特征融合绑定后特征包的个数,且 bundle远小于feature 。
针对这种想法,我们会遇到两个问题:

  • 怎么判定哪些特征应该绑在一起(build bundled)?
  • 怎么把特征绑为一个(merge feature)?
    (1)解决哪些特征应该绑在一起
    将相互独立的特征进行绑定是一个 NP-Hard 问题,LightGBM的EFB算法将这个问题转化为图着色的问题来求解,将所有的特征视为图的各个顶点,将不是相互独立的特征用一条边连接起来,边的权重就是两个相连接的特征的总冲突值,这样需要绑定的特征就是在图着色问题中要涂上同一种颜色的那些点(特征)。此外,我们注意到通常有很多特征,尽管不是100%相互排斥,但也很少同时取非零值。 如果我们的算法可以允许一小部分的冲突,我们可以得到更少的特征包,进一步提高计算效率。经过简单的计算,随机污染小部分特征值将影响精度最多 O ( [ 1 − γ ] n ) O([1-\gamma]n) O([1γ]n) γ \gamma γ是每个绑定中的最大冲突比率,当其相对较小时,能够完成精度和效率之间的平衡。具体步骤可以总结如下:
    构造一个加权无向图,顶点是特征,边有权重,其权重与两个特征间冲突相关;
    根据节点的度进行降序排序,度越大,与其它特征的冲突越大;
    遍历每个特征,将它分配给现有特征包,或者新建一个特征包,使得总体冲突最小。
    算法允许两两特征并不完全互斥来增加特征捆绑的数量,通过设置最大冲突比率 [公式] 来平衡算法的精度和效率。
    算法3的时间复杂度是 O ( f e a t u r e 2 ) O(feature^2) O(feature2),训练之前只处理一次,其时间复杂度在特征不是特别多的情况下是可以接受的,但难以应对百万维度的特征。为了继续提高效率,LightGBM提出了一种更加高效的无图的排序策略:将特征按照非零值个数排序,这和使用图节点的度排序相似,因为更多的非零值通常会导致冲突,新算法在算法3基础上改变了排序策略。
    (2)解决怎么把特征绑为一捆
    特征合并算法,其关键在于原始特征能从合并的特征中分离出来。绑定几个特征在同一个bundle里需要保证绑定前的原始特征的值可以在bundle中识别,考虑到histogram-based算法将连续的值保存为离散的bins,我们可以使得不同特征的值分到bundle中的不同bin(箱子)中,这可以通过在特征值中加一个偏置常量来解决。比如,我们在bundle中绑定了两个特征A和B,A特征的原始取值为区间[0,10),B特征的原始取值为区间[0,20),我们可以在B特征的取值上加一个偏置常量10,将其取值范围变为[10,30),绑定后的特征取值范围为 [0, 30),这样就可以放心的融合特征A和B了

优点
(1)速度更快

  • LightGBM 采用了直方图算法将遍历样本转变为遍历直方图,极大的降低了时间复杂度;
  • LightGBM 在训练过程中采用单边梯度算法过滤掉梯度小的样本,减少了大量的计算;
  • LightGBM 采用了基于 Leaf-wise 算法的增长策略构建树,减少了很多不必要的计算量;
  • LightGBM 采用优化后的特征并行、数据并行方法加速计算,当数据量非常大的时候还可以采用投票并行的策略;
  • LightGBM 对缓存也进行了优化,增加了缓存命中率;
    (2)内存更小
  • XGBoost使用预排序后需要记录特征值及其对应样本的统计值的索引,而 LightGBM 使用了直方图算法将特征值转变为 bin 值,且不需要记录特征到样本的索引,将空间复杂度从 O(2*data) 降低为 O(bin),极大的减少了内存消耗;
  • LightGBM 采用了直方图算法将存储特征值转变为存储 bin 值,降低了内存消耗;
  • LightGBM 在训练过程中采用互斥特征捆绑算法减少了特征数量,降低了内存消耗。

缺点

  • 可能会长出比较深的决策树,产生过拟合。因此LightGBM在Leaf-wise之上增加了一个最大深度限制,在保证高效率的同时防止过拟合;
  • Boosting族是迭代算法,每一次迭代都根据上一次迭代的预测结果对样本进行权重调整,所以随着迭代不断进行,误差会越来越小,模型的偏差(bias)会不断降低。由于LightGBM是基于偏差的算法,所以会对噪点较为敏感;
  • 在寻找最优解时,依据的是最优切分变量,没有将最优解是全部特征的综合这一理念考虑进去;

关于作者

在这里插入图片描述

  • 4
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值