当前位置:首页 » 《休闲阅读》 » 正文

【集成学习系列教程3】LightGBM_Juicy B的博客

24 人参与  2022年02月14日 15:58  分类 : 《休闲阅读》  评论

点击全文阅读


1.7 LightGBM

1.7.1 概述

前面我们介绍了AdaBoost和GBDT这两种Boosting方法,它们已经在很多问题上发挥了强大的威力,也已经具有较好效率。但是,如今的数据集正在朝着样本数越来越巨大,特征维度也越来越高的方向发展,此时这两种传统的Boosting方法在效率和可扩展性上已经不能满足现在的需求了。主要原因是:传统的Boosting算法中的基学习器需要通过对所有样本点的每一个特征都进行扫描来计算信息增益,进而找到最佳的分割点,这在样本数和特征数巨大的情况下会相当耗时。为了解决传统Boosting方法在大样本、高纬度数据的环境下的耗时问题,微软团队提出了两种新的技术:基于梯度的单边采样(Gradient-based One-Side Sampling, GOSS)和互斥特征捆绑(Exclusive Feature Bundling, EFB)。下面简单介绍下这两种方法的原理。

  • GOSS:不再对所有的样本都计算信息增益,而是采取“保留所有大梯度样本,而对小梯度样本进行随机采样”的方式,减少了计算信息增益的样本数,降低了运算的复杂度,又不会对数据集的总体分布造成太大的破坏。这就是基于梯度的单边采样方法的基本思想。

  • EFB:将某些互斥性较大的特征捆绑成一个新的特征来降低特征的维度,使得找到最佳分割点的时间大大减少。互斥特征一般是针对高维度特征而言的,指的是几乎不会同时取非零值的一组(两个或两个以上)特征。具体示例如下表所示:

    样本 x 1 \boldsymbol x_1 x1样本 x 2 \boldsymbol x_2 x2样本 x 3 \boldsymbol x_3 x3样本 x 4 \boldsymbol x_4 x4样本 x 5 \boldsymbol x_5 x5样本 x m − 1 \boldsymbol x_{ m-1} xm1样本 x m \boldsymbol x_m xm
    特征 f 1 f_1 f11300805
    特征 f 2 f_2 f20059020

上表模拟了在大样本、高维度数据集中两个特征的分布情况,这两个特征就组成了一组互斥特征。在大样本、高维度数据集中,特征的分布一般都比较稀疏,也就是说会出现很多样本在某些特征上取0值的情况。我们通过一定的策略找到在所有的样本中都不会同时取非0值,或者同时取非0值的样本很少的多个特征,将它们捆绑成一个特征,这样可以在降低特征维度的同时又不会对数据集的分布造成太大的破坏。这就是互斥特征捆绑方法的思想。

​回顾前面介绍的GBDT算法,可以发现,GBDT算法在训练每棵提升树的时候有两种提供样本方式:第一种是为每棵树都提供所有的样本进行训练,第二种是采用子采样方式,按照固定比例无放回地取出一部分样本依次给每棵提升树训练。使用第一种方法会导致如下问题:当数据集样本数很多、特征维数很高的时候,为每棵树都提供所有数据集中的样本进行训练会非常耗时。为了解决这一问题,我们可以在GBDT算法的基础上使用GOSS和EFB这两种方法。通过GOSS方法对基决策树的训练样本进行灵活限制,再通过EFB方法对高维的特征空间进行降维,双管齐下,这样就能在很大程度上减少模型拟合数据集的时间,同时又不会降低准确率。我们将结合了GOSS方法和EFB方法的GBDT算法称为LightGBM算法。可以用如下公式通俗地表示:
L i g h t G B M = G B D T + G O S S + E F B LightGBM=GBDT+GOSS+EFB LightGBM=GBDT+GOSS+EFB
这就是LightGBM算法的由来。

1.7.2 LightGBM优化算法详解

上一小节我们简要介绍了GOSS和EFB这两种算法的思路,并通过一条通俗的公式说明了LightGBM算法的来源 。本小节我们将对LightGBM中涉及的优化算法的细节进行阐述。

1.7.2.1 GOSS算法

前面我们介绍了AdaBoost算法,该算法的大体思想是:在每次迭代时更加注重上一次错分的样本点,增大上一次分错的样本的权重。虽然GBDT算法中并没有这种为分错样本增大权重的机制,但是由于GBDT是以样本的残差(即模型对样本的训练结果与标签值之间的差距)作为训练提升树的依据,所以GBDT算法可以根据每个样本的残差来判断模型对样本的拟合程度。在这里我们将残差称为梯度,那么按照梯度大小,数据集中的样本就分为大梯度样本和小梯度样本两种。

  • 大梯度样本一般是未经模型拟合或者模型欠拟合的样本,模型对这些样本训练偏差较大,所以这些样本是要在后续模型训练中重点关注的样本,应全部保留;
  • 小梯度样本一般是已经被模型拟合过、并且拟合得比较好的样本,模型对这些样本的训练误差较小,因此可以弱化对这些样本的训练,一个简单粗暴的办法就是直接抛弃掉这部分梯度较小的样本,但这样会对数据集的总体分布造成较大的破坏,所以还是不能完全忽略这部分样本,而是对这部分样本采取随机采样的方式。

GOSS算法对上面这两点进行了实现。具体如下:

设当前模型为 m o d e l model model,训练数据集为 I I I,迭代次数为 d d d,大梯度样本的采样率为 a a a,小梯度样本的采样率为 b b b,损失函数为 l o s s loss loss,弱学习器的类型为 L L L(一般为决策树)。

循环进行 d d d轮迭代,循环体中的各个步骤如下:

  1. 获取 m o d e l model model I I I 中各个样本的训练梯度的绝对值,按照降序的顺序对所有样本进行排序;
  2. 在上述排序结果的基础上,选取前 a × 100 % a×100\% a×100%的样本,组成一个大梯度样本子集;
  3. 在剩下 ( 1 − a ) × 100 % (1-a)×100\% (1a)×100%的样本中随机的选取 b × ( 1 − a ) × 100 % b×(1-a)×100\% b×(1a)×100%个样本,生成一个小梯度样本子集;
  4. 为小梯度样本子集中的每一个样本乘上一个权重系数 1 − a b \frac{1-a}{b} b1a
  5. 将上面得到的大梯度样本子集和小梯度样本子集进行合并;
  6. 使用上一步得到的样本集对一个新的弱学习器 L L L进行训练;

不断重复循环体中的步骤,直到达到规定的迭代次数 d d d或者 l o s s loss loss收敛为止。

​ 从上面的步骤中可以看到,当 a = 0 a=0 a=0时,GOSS算法退化为随机采样算法;当 a = 1 a=1 a=1时,GOSS算法退化为传统的取所有训练样本对弱学习器进行训练的方法。训练出的模型精确度要高于随机采样算法。

GOSS算法具有如下优点:

  • 对样本进行采样增加了弱学习器的多样性,从而提升了模型的泛化能力;
  • 该算法几乎不会对数据集的分布造成破坏,同时又大幅度减少了每一轮迭代的训练样本数,所以该算法在保证了GBDT模型的精度不受损失的同时,又大大减少了GBDT模型对数据集的拟合时间。
1.7.2.2 EFB算法

前面我们已经简单介绍了EFB算法的原理,即将多个不同的特征按照互斥的程度划分为了更小的互斥捆绑数,从而实现了特征降维。但由于现实中的数据集很多是大样本、高维度的数据集,遍历所有特征在各个样本上的值尚且非常耗时了,更不用说为了匹配互斥特征还要进行重复遍历,所以找到各组互斥的特征并进行捆绑是一个NP-hard问题,即在多项式时间内不可能找到确切的解。为了解决这一问题,EFB算法在原有特征互斥判定方法的基础上进行了如下改进:用一个称为最大冲突数的参数来量化并限制同一个特征捆中总的互斥程度,我们允许特征之间存在少数样本不互斥,即允许存在某些特征对应的样本之间不同时取非零值。这样做放宽了特征互斥的条件,减少了特征捆绑数,从而进一步的提高了计算的有效性。理论上,使用该方法对模型准确率的影响程度为 O ( [ ( 1 − γ ) n ] − 2 3 ) O([(1-\gamma)n]^{-\frac{2}{3}}) O([(1γ)n]32),参数 γ \gamma γ称为每个绑定的最大冲突率,用来量化不同特征之间的互斥程度。当 γ \gamma γ取值较小时,可以在精确度和模型训练效率上获得很好的权衡。EFB算法实现该功能的具体步骤如下:

初始化各变量:构造一个带权图 G G G,图中结点代表各个不同的特征,边的权值代表对应特征之间的互斥程度(冲突数),通过各个特征节点在图 G G G中的度(即与特征节点相连的边数)降序排序所有特征,并按顺序加入到列表 F e a t u r e s Features Features中。设特征数为 F F F,特征捆中的最大冲突数为 K K K,特征捆列表为 b u n d l e s bundles bundles(如 b u n d l e s [ i ] bundles[i] bundles[i]表示构建出的第 i i i捆特征,初始化状态下所有 b u n d l e s [ i ] bundles[i] bundles[i]均为空), b u n d l e s C o n f l i c t s bundlesConflicts bundlesConflicts列表记录 b u n d l e s bundles bundles中各个特征捆的当前总冲突数(如 b u n d l e s C o n f l i c t s [ i ] bundlesConflicts[i] bundlesConflicts[i]表示第 i i i捆特征的总冲突数)。

接下来进行 F F F次循环。循环体中的步骤如下:

  1. 遍历有序列表 F e a t u r e s Features Features中的每个特征;
  2. 遍历 b u n d l e s bundles bundles列表中的所有特征捆 b u n d l e s [ j ] bundles[j] bundles[j],如果特征捆为空,则将当前特征 F e a t u r e s [ i ] Features[i] Features[i]加入 b u n d l e s [ j ] bundles[j] bundles[j]中;若特征捆不为空,则进行如下判断:
    • 如果加入新特征 F e a t u r e s [ i ] Features[i] Features[i] b u n d l e s [ j ] bundles[j] bundles[j]的总冲突数小于 K K K,则将该特征加入 b u n d l e s [ j ] bundles[j] bundles[j]
    • 如果加入之后大于 K K K,则将新特征 F e a t u r e s [ i ] Features[i] Features[i]加入下一个空的特征捆 b u n d l e s [ j + 1 ] bundles[j+1] bundles[j+1]中。

不断重复上述步骤,直至遍历完所有特征,最终输出 b u n d l e s bundles bundles

上述算法的时间复杂度为 O ( n _ f e a t u r e s 2 ) O(n\_features^2) O(n_features2) n _ f e a t u r e s n\_features n_features为总的特征数),在特征维度不是很大时,这样的复杂度是可以接受的,但当样本维度较高时,这种方法就显得非常低效。对此,微软团队又提出的另外一种更加高效的算法:不再按照特征节点度的大小的降序来对特征进行排序,而是按特征中非零值数量的降序来对特征进行排序,因为非零值更多的特征通常会导致更高的冲突概率。通过这一点小小的改变,EFB算法的复杂度得到了进一步下降。

1.7.2.3 Histogram算法

我们通过EFB算法成功将所有特征拆分成了多个互斥的特征捆,但要怎么将同一特征捆中的所有特征合并起来呢?Lightgbm中使用直方图(Histogram)算法来合并互斥特征。直方图算法的直观示意图如下:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Zc9MR1xt-1632986330980)(his.png)]

如图,该算法的基本思想为:

  1. 把连续的特征值离散化成 k k k个整数,同时构造一个具有 k k k个bins的直方图;
  2. 遍历所有特征的各个特征值数据,根据离散化后的值,在直方图中对应的bins部分进行累加求出统计量,这样的话,当遍历一次数据后,直方图累积了所有的特征统计量;
  3. 根据直方图的离散值,遍历寻找最优的分割点。

由于直方图算法的思想是存储离散的bins而不是连续的特征值,所以我们可以通过让互斥特征驻留在不同的bins中来构造特征捆。这可以通过在原始特征值的基础上增加适当的偏移量来实现。比如,假设我们有两个特征A和B,A的取值范围是[0,10),而B的取值范围是[0,20),我们可以通过给B增加偏移量10,使得B的取值范围变成[10, 30),这样就可以合并特征A和B的范围区间,形成取值范围为[0,30)的新特征来取代原来的A和B。使用直方图算法在规避了对特征进行排序、从而减小了损耗时间的同时,又实现了对互斥特征进行合并、从而实现了特征降维的目的,一举两得。

1.7.2.4 Leaf-Wise策略

在LightGBM算法之前,大部分以决策树为基学习器的集成学习方法(包括原始GBDT算法、XGBoost算法等)都是通过一种称为Level-Wise的策略来生成基决策树。这种生成策略的缺点是:对于同一深度的的所有节点都不加区分地进行分裂,使得很多分裂增益较低的节点也进行了分裂,从而带来了没必要的开销。示意图如下:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-EC1yYsvC-1632986330983)(level_wise.png)]

为了避免带来不必要的开销,LightGBM使用了一种称为Leaf-Wise的树生成策略。该策略的思路为:每次只从同一深度的所有节点中找到分裂增益最大的那一个节点进行分裂而不对其他节点进行分裂,如此循环,直到到达所设定的最大深度为止。示意图如下:

在这里插入图片描述

在分裂次数相同的情况下,相比使用Level-Wise策略,使用Leaf-Wise策略可以得到更好的精度。但是,当样本量较小的时候,Leaf-Wise很容易造成过拟合。 所以,可以通过调整LightGBM中的参数 max_depth 来限制树的最大深度,避免过拟合。

1.7.2.5 直接支持类别型特征

所谓类别型特征(Categorical features)是指其值是离散的集合且相互比较并无意义的变量,比如用户的ID、产品ID、颜色等。 这些变量无法在二叉决策树当中直接使用。 常规的做法是将这些类别变量通过预处理的方式转化成数值型变量再喂给模型,比如用一个或者若干个数值来代表一个类别型特征。目前广泛用于类别特征的处理方法是One-Hot编码:将原来的特征删除,然后对于每一个类别加一个0/1的用来指示是否含有该类别的数值型特征。使用这种处理方式有一个致命的缺点:在高势特征(也叫高数量类别特征,即对于某个类别型特征,不同值的数量非常多)当中,比如用户的ID,用这种编码方式生成的特征维数会非常巨大,造成维度灾难。

​ 在实际应用中,大多数机器学习算法模型都无法直接支持对类别特征的使用,一般需要把类别特征通过One-Hot编码的方式转化到高维的0/1 特征空间,这样做降低了机器学习模型拟合数据集的空间和时间的效率。而如果能直接使用类别特征,避开类别特征编码,那么就可以提升机器学习算法的整体效率。基于这个考虑,LightGBM实现了对类别特征的支持,也就是说,LightGBM模型支持对类别特征的直接读取,而不需要读取类别特征的One-Hot编码形式。这使得LightGBM模型的效率有了进一步的提升。

1.7.2.6 并行优化方法

LightGBM中还采用了并行优化方法,进一步提升了模型拟合的效率。它的并行优化方法是基于特征并行和数据并行这两种普通的并行方法进行改进的。这两种方法的主要思想如下:

  • 特征并行:使用多个不同的机器,分别在不同特征集合上寻找最优的分割点,然后再对所有机器结果进行同步,输出最优分割点;
  • 数据并行:让不同的机器先在本地各自构造特征直方图,然后进行全局合并,最后在合并的直方图上寻找最优分割点。

LightGBM针对这两种并行方法都做了优化:

  • 在特征并行方法中,各个机器均保存数据集中的全部数据,“各取所需”,避免因数据量不足造成不同机器数据分割结果的相互干扰;
  • 在数据并行方法中,使用一种称为分散规约 (Reduce scatter)的方法把直方图合并的任务分摊到不同的机器,减少了单个机器的计算负担,并利用直方图做差的方式减少了一半的通信量。
1.7.2.7 小结

1.7.2小节中我们介绍了LightGBM中所用到的优化算法,这些方法在原始GBDT算法的基础上大幅提升运算速度,同时保持了和原始GBDT算法几乎一致的准确率,从而解决了原始GBDT算法在大样本、高维度数据集上效率过慢的问题,这使得LightGBM算法在近两年来得到了广泛的应用。

1.7.3 LightGBM的使用

令人感到可惜的是,sklearn中并没有为用户提供调用LightGBM算法模型的接口,因为LightGBM是微软团队的研究成果,它们自己编写了一个独立的库供用户使用LightGBM算法。尽管如此,sklearn还是巧妙借鉴了LightGBM算法的思想,在GBDT算法的基础上进行了改进,设计出了基于直方图算法进行改进的GBDT算法,并提供了HistGradientBoostingClassifier和HistGradientBoostingRegressor这两个接口供用户使用,大大提升了GBDT模型在大样本数据集上的训练速度,使得用户可以轻松地将GBDT模型用于样本数10000个以上的数据集的训练。而完整的LightGBM算法过于复杂,导致其参数、属性、方法等有很多,故本书不再进行赘述,读者可以移步LightGBM的官方文档进行详细了解,下面仅列举出LightGBM中的常用参数,以及每个参数的所对应的调参场景。

1.7.3.1 常用参数
参数含义用法
max_depth基决策树树的最大深度当模型过拟合时,可以考虑降低 max_depth的值以限制最大深度
min_data_in_leaf基决策树叶子节点所需要的最小样本数默认值为20,模型过拟合时用
feature_fraction使用bagging方法时特征子集的采样比例指定boosting 方法为 random forest 时使用
bagging_fractions使用bagging方法时样本的采样比例用于加快训练速度,减小过拟合的风险
early_stopping_round指定使用提前停止方法的迭代次数上限。如果在一次验证中模型对数据集的度量(如验证错误率、验证准确率等)在early_stopping_round轮迭代中中没有得到提高,模型将终止训练减少因迭代次数过多造成计算资源的浪费
lambda指定正则化系数指定为0~1之间的实数,缓解过拟合
min_gain_to_split指定基决策树分裂时所要求的最小gain(信息增益)缓解过拟合
Task模型对数据集的操作指定为train表示对数据集进行拟合,指定为predict表示对数据进行预测
application模型的用途指定为regression表示完成回归任务,指定为binary表示完成二分类任务, 指定为multiclass表示完成多分类任务
num_boost_round迭代次数通常设置成100以上
learning_rate学习率常用 0.1, 0.001等较小值
num_leaves基决策树节点数量默认值为31(对应深度为5),取值应不大于 2 m a x _ d e p t h 2 ^{max\_depth} 2max_depth, 超过此值会导致过拟合
save_binary是否将数据集存储为二进制文件这个参数为 true 时,则数据集被保存为二进制文件,下次读数据时速度会变快
max_bin表示特征存入的最大bin数量不得超过255
device训练模型所用的设备cpu | gpu
metric损失函数
1.7.3.4 常用调参方法

1 针对 Leaf-Wise策略

  • 通过调整num_leaves参数来控制基决策树中节点的数量,进而控制树模型的复杂程度。一般情况下,若使用Level-Wise策略来生成基决策树,则可以设置该参数的值为 2 m a x _ d e p t h 2^{max\_depth} 2max_depth。但如果要使用Leaf_Wise策略来优化模型的拟合效果,则num_leaves 的取值应小于 2 m a x _ d e p t h 2^{max\_depth} 2max_depth

  • 通过调整min_data_in_leaf参数来控制基决策树中每个节点所要求的最小样本数。该参数是处理Leaf-Wise 树过拟合问题中一个非常重要的参数。将该值设置得较大可避免基决策树的深度过深,,但设置得较大又有可能导致欠拟合,并且其取值不得超过训练数据集的总样本数 num_leaves。在实际应用中,应对该参数进行小心调整,调整的范围一般在几百到几千之间;

  • 通过调整max_depth参数显式地限制基决策树的的深度,以降低过拟合的风险。一般设置为5—10之间的整数。

2 针对更快的训练速度

  • 设置 bagging_fractionbagging_freq 参数以使用 bagging 方法;
  • 设置合适的feature_fraction 参数(表示特征子采样的比例);
  • 使用较小的 max_bin
  • 使用 save_binary ,用以在后续学习过程中加速对数据集的加载。

3 针对更好的准确率

  • 使用较大的 max_bin (学习速度可能变慢);

  • 使用较小的 learning_rate 和较大的 num_iterations

  • 使用较大的 num_leaves (可能导致过拟合);

  • 使用更大的训练数据集合。

4 缓解过拟合

  • 使用较小的 max_bin(默认值为255);

  • 使用较小的 num_leaves(默认为31);

  • 调整 min_data_in_leaf(默认为20)和 min_sum_hessian_in_leaf(默认为 e − 3 e^{-3} e3)的值;

  • 调整bagging_fraction (默认为1.0)和 bagging_freq (默认值为0,表示禁用bagging;将该值设置为 k k k,表示每 k k k次迭代执行一次bagging操作)的值以使用 bagging;

  • 调整 feature_fraction(默认为1.0)的值以调整特征子采样的比例;

  • 使用更大的训练数据;

  • 使用 lambda_l1(默认为0), lambda_l2 (默认为0)和 min_split_gain(默认为0,表示执行切分的最小增益)以执行正则化操作;

  • 尝试调低 max_depth 的值,以避免生成过深的树。


点击全文阅读


本文链接:http://m.zhangshiyu.com/post/34749.html

特征  样本  算法  
<< 上一篇 下一篇 >>

  • 评论(0)
  • 赞助本站

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。

关于我们 | 我要投稿 | 免责申明

Copyright © 2020-2022 ZhangShiYu.com Rights Reserved.豫ICP备2022013469号-1