机器学习分类算法(九)-LightGBM

之前在讲xgboost的时候,详细介绍了陈天奇等人于2014年发布的XGBoost的内在原理,同时阐述了其特有的几大优点。然而时代变化之迅速,新技术如春笋般应运而生,与日俱进。继xgboost之后,2016年微软进一步发布了GBST的另一个实现:lightgbm。据悉,与xgboost相比,在相同的运行时间下能够得到更好的预测性能。同时,在multi-class、classification、click prediction和排序(lerning to rank)都有很好的效果。本文将基于lightgbm的原始paper,对其原理进行归纳总结。

前言

为了确保文章的连续性,读者需对Boosting系列有一定的理解,在阅读本文核心内容之前,还读者预先在心里回答下下面几个问题:

  • XGBoost的目标函数表达式?
    O b j ( t ) = ∑ i = 1 n l ( y i , y ^ i ( t ) ) + ∑ i = 1 t Ω ( f i ) O b j^{(t)}=\sum_{i=1}^{n} l\left(y_{i}, \hat{y}_{i}^{(t)}\right)+\sum_{i=1}^{t} \Omega\left(f_{i}\right) Obj(t)=i=1nl(yi,y^i(t))+i=1tΩ(fi)

  • XGBoost在GBDT的基础上做了哪些优化?

    • 对应上文的XGBoost算法的优点
  • XGBoost的exact greedy Algorithm for split finding是什么?

  • XGBoost寻找分裂点的增益计算方法?

  • XGBoost的近似算法原理?

  • 解释下Weighted Quantile Sketch原理?

如果对上面的问题模棱两可的,可前往上一篇文章,回顾一下。接下来将会针对XGBoost的不足进一步探讨lightGBM模型,相对于GBDTlightGBM的精度与它相差不大,但是速度可以提升20倍。By the way,在学习lightGBM的时候,可以思考下下面几个问题(本文不会直接给出结论,读完之后,读者自然就明白了):

  • 1.Adaboost、GBDT、XGBoost的样本梯度都是什么?
  • 2.XGBoost的不足之处在哪里(lightGBM因何诞生,解决了什么问题)?
  • 3.XGBoost的近似算法与lightGBM的histogram-based方法的区别?
  • 4.什么是lightGBM?
  • 5.lightGBM与XGBoost的结构有什么区别?

不管是XGBoost还是lightGBM,模型的优化方向上必不可少的就是决策树的分裂上。下面,将重点介绍lightGBM算法在寻找最佳切分点上所做出的努力。

LightGBM

LigthGBM是一款常用的GBDT工具包,速度比XGBoost快,精度也还可以。它的设计理念是:

  • 单个机器在不牺牲速度的情况下,尽可能使用上更多的数据
  • 多机并行的时候,通信的代价尽可能地低,并且在计算上可以做到线性加速。

所以其使用分布式的GBDT,选择了基于直方图的决策树算法。

寻找最佳分裂点

lightGBM引入的核心思想包括两个方面:

  • 1.Histogram: 基于特征的数值进行分bin,然后基于bin的值寻找最佳分裂的bin值。
  • 2.GOSS(Gradient based One Side Sampling): 移除小梯度样本,使用余留的样本做增益计算;
  • 3.EFB(exclusive Feature Bundling):bundle不会同时为零的特征(互斥),达到减少特征数量的目的。

Histogram分桶策略

GBDT是以决策树为基学习器的ensemble模型,在每次迭代中,GBDT都通过拟合负梯度来学习决策树,其中代价最大最耗时的就是寻找最佳切分点过程。

一种方法是采用了预排序的算法,然后枚举所有可能的切分点,再寻找到增益最大的分裂点。比如Xgboost。

XGBoost中的Exact greedy算法:

  • 对每个特征都按照特征值进行排序
  • 在每个排好序的特征都寻找最优切分点
  • 用最优切分点进行切分

优点是比较精确,缺点是空间消耗比较大,时间开销大和对内存不友好,使用直方图算法进行划分点的查找可以克服这些缺点。

另一中方法是基于histogram的算法。

直方图算法(Histogram algorithm)把连续的浮点特征值离散化为k个整数(也就是分桶bins的思想),比如[0,0.1)—> 0,[0.1,0.3)—>1.并根据特征所在的bin对其进行梯度累加和个数统计,然后根据直方图,寻找最优的切分点。
机器学习分类算法(九)-LightGBM_第1张图片

histogram算法并不是在预排序的特征值当中寻找最佳切分点,而是将连续的特征值进行离散化bin并放入不同的bucket,在训练的时候基于这些bin来构建特征histogram。这种做法效率更高,速度更快。

如Algorithm 1所示,构建histogram的时间复杂度为O(#data × #feature),寻找最佳分裂点的时间复杂度O(#bin × #feature)
机器学习分类算法(九)-LightGBM_第2张图片

直方图算法-如何分桶

如何分桶bins?数值型特征和类别特征采用的方法是不同

  • 数值型特征
    • 对特征值去重后进行排序(从大到小),并统计每个值的counts
    • max_bin(设置的超参数,最大有几个分桶)和distinct_value.size()(数据去重后值的类别)中的较小值作为bins_num(分桶个数)
    • 计算bins中的平均样本个数mean_bin_size,若某个distinct_valuecount大于mean_bin_size,则该特征值作为bins的上界,小于该特征值的第一个distinct value作为下界;若某个distinct_valuecount小于mean_bin_size,则要进行累计后再分组。
  • 类别性特征
    • 首先对特征取值按出现的次数排序(从大到小)
    • 取前min(max_bin,distinct_values_int.size())中的每个特征做第3步(忽略一些出现次数很少的特征取值)
    • bin_2_categorical_bin_2_categorical_(vector类型)categorical_2_bin_categorical_2_bin_(unordered_map类型)将特征取值和bin一一对应起来,这样就可以方便进行两者之间的转换了。
直方图算法

如何构建直方图

给定一个特征值,我们可以转化为对应的bin了,就要构建直方图了,直方图中累加了一阶梯度和二阶梯度,并统计了取值的个数。
机器学习分类算法(九)-LightGBM_第3张图片

直方图作差:

一个叶子节点的直方图可以由它的父亲节点的直方图与其兄弟的直方图做差得到。使用这个方法,构建完一个叶子节点的直方图后,就可以用较小的代价得到兄弟节点的直方图,相当于速度提升了一倍。
机器学习分类算法(九)-LightGBM_第4张图片

寻找最优的切分点:
  • 遍历所有bin
  • 以当前的bin作为分割点,累加左边的bins至当前bin的梯度和 S L S_{L} SL及样本数量 n L n_L nL,并利用直方图作差求得右边的梯度和样本数量。
  • 带入公式计算增益loss
  • 在遍历过程中取得最大的增益,以此时的特征和bin的特征值作为分裂的特征及取值。
    机器学习分类算法(九)-LightGBM_第5张图片
    其中 S R S_{R} SR表示右节点, S L S_{L} SL表示左节点, S P S_{P} SP表示父亲节点
直方图算法的优点
  • 减少内存占用
  • 缓存命中率提高,直方图中梯度存放是连续的
  • 计算效率提高,相对于XGBoost中预排许每个特征都要遍历数据,复杂度为O(#feature * #data),而直方图算法只需遍历每个特征的直方图即可,复杂度为O(#feature * #bins)
  • 在进行数据并行时,可大幅降低通信代价

直方图算法改进

直方图算法仍有优化的空间,建立直方图的复杂度为O(#feature * #data),如果能降低特征数或者降低样本数,训练的时间会大大减少。假如特征存在冗余时,可以使用PCA 等算法进行降维,但特征通常是精心设计的,去除它们中的任何一个可能会影响训练精度。因此LightGbm提出了GOSS算法和EFB算法。

GOSS算法

样本的梯度越小,则样本的训练误差越小,表示样本已经训练的很好了。最直接的做法就是丢掉这部分样本,然而直接扔掉会影响数据的分布,因此lightGBM采用了one-side 采样的方式来适配:GOSS(Gradient-based One-Side Sampleing)采样策略,它保留了所有的大梯度样本,对小梯度样本进行随机采样,来划分最优节点。

同时为了保证分布的一致性,在计算信息增益的时候,将采样的小梯度样本乘以一个常量: 1 − a b \frac{1-a}{b} b1a a a a表示Top a×100%的大梯度样本比例值, b b b表示小梯度样本的采样比值(很多文章里面理解成从省下的小梯度样本中采样b%的比例,其实是有误解的,这里的百分比是相对于全部样本而言的,即b%×N)。

例如:100个样本中,大梯度样本有20个,小梯度样本80个,小梯度样本量是大梯度样本数据量的4倍,则大样本采样比率 a a a等于0.2,假设小梯度样本的采样率为30%,则 b b b=0.3,那么小梯度样本的采样数目等于 b b b×100=30个,为了保证采样前后样本的分布保持一致,最后小梯度样本采样得到的数据在计算梯度时需要乘以 1 − a b = 1 − 0.2 0.3 = 8 3 \frac{1-a}{b}=\frac{1-0.2}{0.3}=\frac{8}{3} b1a=0.310.2=38(解释一下,乘以1− a a a是因为大梯度样本采样的整体是整个样本集N,小梯度样本采样的候选样本集为 ( 1 − a ) N (1−a)N (1a)N,除以 b b b是因为采样导致小梯度样本的整体分布减少,为此需要将权重放大1/b倍)。整个过程如下图Algorithm 2所示。
机器学习分类算法(九)-LightGBM_第6张图片
通过这个过程,减少了我们在寻找最优分割点时候的计算量。

原始直方图算法下,在第 j j j个特征,值为 d d d处进行分裂带来的增益可以定义为:

V j ∣ O ( d ) = 1 n O ( ( ∑ x i ∈ O x i , S d g i ) 2 n l ∣ 0 j ( d ) + ( ∑ x i ∈ O x i > d g i ) 2 n r ∣ O j ( d ) ) V_{j \mid O}(d)=\frac{1}{n_{O}}\left(\frac{\left(\sum_{x_{i} \in O_{x_{i}, S d}} g_{i}\right)^{2}}{n_{l \mid 0}^{j}(d)}+\frac{\left(\sum_{x_{i} \in O_{x_{i}>d}} g_{i}\right)^{2}}{n_{r \mid O}^{j}(d)}\right) VjO(d)=nO1nl0j(d)(xiOxi,Sdgi)2+nrOj(d)(xiOxi>dgi)2 (1)

原始计算是拿梯度的平方/子节点的个数

其中 O O O为在决策树待分裂节点的训练集, n o = ∑ I ( x i ∈ O ) , n l ∣ O j ( d ) = ∑ I [ x i ∈ O : x i j ≤ d ] n_{o}=\sum I\left(x_{i} \in O\right), n_{l \mid O}^{j}(d)=\sum I\left[x_{i} \in O: x_{i j} \leq d\right] no=I(xiO),nlOj(d)=I[xiO:xijd] 并且 n r ∣ O j ( d ) = ∑ I [ x i ∈ O : x i j > d ] n_{r \mid O}^{j}(d)=\sum I\left[x_{i} \in O: x_{i j}>d\right] nrOj(d)=I[xiO:xij>d].

采用GOSS之后,在第 j j j个特征,值为 d d d处进行分裂带来的增益可以定义为:

V j ∣ O ( d ) = 1 n O ( ( ∑ x i ∈ A l g i + 1 − a b ∑ x i ∈ B l g i ) 2 n l j ( d ) + ( ∑ x i ∈ A r g i + 1 − a b ∑ x i ∈ B l g r ) 2 n r j ( d ) ) V_{j \mid O}(d)=\frac{1}{n_{O}}\left(\frac{\left(\sum_{x_{i} \in A_{l}} g_{i}+\frac{1-a}{b} \sum_{x_{i} \in B_{l}} g_{i}\right)^{2}}{n_{l}^{j}(d)}+\frac{\left(\sum_{x_{i} \in A_{r}} g_{i}+\frac{1-a}{b} \sum_{x_{i} \in B_{l}} g_{r}\right)^{2}}{n_{r}^{j}(d)}\right) VjO(d)=nO1(nlj(d)(xiAlgi+b1axiBlgi)2+nrj(d)(xiArgi+b1axiBlgr)2) (2)

其中, A l = x i ∈ A : x i j ≤ d , A r = x i ∈ A : x i j > d , B l = x i ∈ B : x i j ≤ d , B r = x i ∈ B : x i j > d A_{l}=x_{i} \in A: x_{i j} \leq d, A_{r}=x_{i} \in A: x_{i j}>d, B_{l}=x_{i} \in B: x_{i j} \leq d, B_{r}=x_{i} \in B: x_{i j}>d Al=xiA:xijd,Ar=xiA:xij>d,Bl=xiB:xijd,Br=xiB:xij>d

计算量大大减少,本来是全部样本,现在只需要
A l A_{l} Al+ B l B_{l} Bl的计算量

其中,A表示大梯度样本集,而B表示小梯度样本中随机采样的结果。

接下来我们来看;另一种算法

EFB算法

高维数据通常是非常稀疏的,而且很多特征是互斥的(即两个或多个特征列不会同时为0),lightGBM对这类数据采用了名为EFB(exclusive feature bundling)的优化策略,将这些互斥特征进行合并,能够合并的特征为一个#bundle。通过这种方式,可以将特征的维度降下来,相应的,构建histogram所耗费的时间复杂度也从O(#data × #feature)变为O(#data × #bundle),其中#feature << #bundle。方法说起来虽然简单,但是实现起来将面临两大难点:

  • 哪些特征可以bundle在一起—Greedy bundle
  • 如何构建bundle,实现特征降维—Merge Exclusive Features

针对这两个问题,paper里面提到了两种算法:Greedy BundlingMerge Exclusive feature

对于第一个问题,将特征划分为最少数量的Bundle本质上属于NP-hard problem(非确定性多项式)。

Greedy bundled的原理与图着色相同,给定一个图G,定点为V,表示特征,边为E,表示特征之间的互斥关系,接着采用贪心算法对图进行着色,以此来生成bundle。

不过论文中指出,对于特征值的互斥在一定程度上是可以容忍的,具体的算法流程如Algorithm 3所示。

  • 1.首先构建一张带权重的图,权重为特征间的总冲突数;
  • 2.对特征按照在图内的度进行降序排序;
  • 3.检查排好序的特征,并将其划分到一个冲突较小的bundle里,如果没有就创建一个bundle。

该算法复杂度为O(#feature^2),采用这种方法对于特征数目不大的数据,还算OK,但是对于超大规模的特征,效率不高,这时可以不建立图,采用特征中非零值的个数作为排序的值,因为非零值越多通常冲突就越大。
机器学习分类算法(九)-LightGBM_第7张图片其中 F F F表示特征的个数, k k k表示互斥的个数

对于第二个问题:应该如何如何构建bundle。

MEF(Merge Exclusive Features)将bundle中的特征合并为新的特征,合并的关键在于构建前的特征的值在构建后的bundle中能够识别。由于基于histogram的方法存储的是离散bin而不是连续的数值,因此可以通过添加偏移的方法将不同特征的bin值设定为不同的区间。

例如,特征A的bin值为[0,10),特征B的bin值为[0,20),要想将两个特征bin合并,我们可以将特征B的特征bin的值加上10,其取值区间将变为[0,30)。整个方法描述如下图所示。
机器学习分类算法(九)-LightGBM_第8张图片

leaf-wises 树的生长策略

另外,在树的生成方式上,lightGBMXGBoost也是有区别的。

XGBoost中决策树的生长策略是level-wise,按层生长,同一层的所有节点都做分裂,最后剪枝,它不加区分的对待同一层的叶子,带来了很多没必要的开销,因为实际上很多叶子的分裂增益较低,没必要进行搜索和分裂。
机器学习分类算法(九)-LightGBM_第9张图片
对比之下,lightGBM的生长策略是leaf-wise,维持的是一颗平衡树,leaf-wise策略以降低模型损失最大化为目的,对当前所有叶子节点中切分增益最大的leaf节点进行切分。优点是生长出来的树一定是最优的。不过leaf-wise存在一个弊端,就是最后会得到一颗非常深的决策树,为了防止过拟合,可以在模型参数中设置决策树的深度
机器学习分类算法(九)-LightGBM_第10张图片

系统设计

这里我们主要介绍下LightGBM中的并行计算优化方法,在本小节中,工作的节点称为worker,LightGBM具有支持高效并行的特点,原生支持并行学习,目前支持:

  • 特征并行
  • 数据并行
  • Voting并行(数据并行的一种)

特征并行是并行化决策树中寻找最优划分点的过程。特征并行是将对特征进行划分,每个worker找到局部的最佳切分点,使用点对点通信找到全局的最佳切分点。
机器学习分类算法(九)-LightGBM_第11张图片

  • 传统算法:
    不同worker存储不同的特征集,在找到全局的最佳划分点后,具有该划分点的worker进行节点分裂,然后广播切分后的左右子树数据结果,其他worker收到结果后也进行划分。
  • LightGBM中算法
    每个worker中保存了所有的特征集,在找到全局的最佳划分点后每个worker可自行进行划分,不再进行广播划分结果,减少了网络的通信量。但存储代价变高。

数据并行的目标是并行化整个决策学习的过程。每个worker中拥有部分数据,独立的构建局部直方图,合并后得到全局直方图,在全局直方图中寻找最优切分点进行分裂。
机器学习分类算法(九)-LightGBM_第12张图片
LightGBM采用一种称为PV-Tree的算法进行投票并行(Voting Parallel),其实这本质上也是一种数据并行,PV-Tree和普通的决策树差不多,只是在寻找最优切分点上有所不同。
机器学习分类算法(九)-LightGBM_第13张图片
每个worker拥有部分数据,独自构建直方图并找到top-K最优的划分特征,中心worker聚合得到最优的2K个全局划分特征,再向每个worker手机top-2k特征的直方图,并进行合并得到最优划分,广播给所有worker进行本地划分。
机器学习分类算法(九)-LightGBM_第14张图片

结束语

lightGBM主要提出了两个新颖的方法:GOSSEFB。两者都对算法性能的提升有着重要的贡献,其中GOSS是针对分裂时样本的数目进行采样优化(行优化),EFB是针对特征进行合并,达到特征减少的目的(列优化)。

实际上,XGBoostlightGBM都属于GBDT的一种实现,旨在优化算法的性能,提升算法的训练速度,与XGBoost相比,lightGBM更适应于数据量更大的场景。

GBDT->XGBoost->lightGBM,在模型训练阶段,是不能百分百地断定lightGBM就比GBDTXGBoost好,因为数据量的大小也决定了模型的可行性。所以实际场景中,还是建议一一尝试之后再做抉择,因为训练一个XGBoostlightGBM,都是非常简单的事情。

参考文献

  • Boosting模型:lightGBM 算法原理
  • 集成学习:XGBoost, lightGBM
  • https://baike.baidu.com/item/NP-hard

你可能感兴趣的:(机器学习)