[ML]LightGBM论文理解
lightGBM和XGBoost都是对GBDT模型的进化版本,原理上它和GBDT类似,也是采用损失函数的负梯度作为当前决策树的残差近似值,去拟合新的决策树。
GBDT既可以基于预排序特征值进行特征选取(可以忽略特征零值降低训练成本),也可以基于直方图进行特征选取。但是GBDT在使用直方图进行特征提取时并没有有效的稀疏优化方式,一方面是因为基于直方图的算法需要对每一个数据检索直方图的特征箱值,不管特征值是不是零。而基于直方图的GBDT算法能够有效地利用特征值稀疏性。
GBDT与lightGBM的区别主要如下表所示:
LightGBM
提出的动机
gbdt在处理海量数据时会遇到内存或者时间上的问题,因为gbdt在每轮迭代的时候都需要遍历整个训练数据多次,如果把所有的训练数据都放进内存会限制训练数据的大小;如果不放进内存又会遇到反复读写数据导致的时间消耗过大问题。LightGBM针对于此提出了解决方法。按照论文中所述,LightGBM提出了GOSS和EFB思想,GOSS的目的是为了剔除具有小梯度的数据实例,而使用具有较大梯度的数据来计算信息增益,由于具有较大梯度的数据在信息增益的计算中有更重要的作用,因此GOSS可以在较小的数据量下获得相当精确的信息增益估计。EFB使用互斥特征(多个特征很少同时取非零值),以减少特征数量。
Gradient-based One-Side Sampling(GOSS)
这是lightGBM提出的一种针对于GBDT的新的采样方法,该方法能够平衡训练数据数量和学习到的决策树的准确性之间的问题。
在Adaboost中,我们利用样本权重进行采样,但是在GBDT中,我们使用梯度来进行采样(因为梯度中包含足够有用的采样信息)。具体地说,如果一个样本有小梯度,则对该样本的训练错误较小,该样本为已训练好的样本。因此,直观的想法是将小梯度的样本分割出来,但是这样的话会更改样本分布,这对于已学习好的模型来说不是个好消息。为了避免样本分布被更改这个问题,提出了GOSS方法。
该方法主要是保留具有大梯度的数据,并随机采样小梯度的数据。为了弥补因此造成的对数据分布的影响,在计算信息增益时,GOSS会对小梯度样本引入一个常数乘法器。
GOSS算法描述:
输入:训练数据,迭代步数d,大梯度数据的采样率a,小梯度数据的采样率b,损失函数和弱学习器的类型(一般为决策树)
输出:训练好的强学习器
①GOSS首先根据样本梯度的绝对值,对数据进行降序排序操作。
②选取前a*100%的样本生成一个大梯度样本集的子集。
③从剩下的样本集合(1-a)x100%中随机选取bx(1-a)x100%的样本,生成一个小梯度样本点的集合。
④将大梯度样本集合小梯度样本集合并。
⑤计算信息增益时,为了放大采样出的小梯度样本,会给小梯度样本乘以一个常数
⑥使用上述的采样的样本,学习一个新的弱学习器。
⑦重复上述6个步骤,知道达到规定的迭代次数或者收敛为止。
通过这个方法,我们能够更多的关注训练不足的数据上,却不会改变原始数据的分布。
从上面的描述可知,a=0时,GOSS算法退化为随机采样算法;a=1时,GOSS算法变为采取整个样本的算法。在许多情况下,GOSS算法训练处的模型精确度要高于随机采样算法。另一方面,采样也将会增加弱学习器的多样性,从而潜在的提升了训练出的模型泛化能力。
上面为GOSS伪代码。
Exclusive Feature Bundling(EFB)
该方法主要是为了减少特征数量,进行特征抽样,使得模型的训练速度进一步的减少。
高维数据通常都很稀疏,而特征空间的稀疏性为几乎无损的减少特征数量提供了可能。因为在稀疏的特征空间,很多特征彼此排斥,不会同时获取0值。因此我们可以安全的将互斥特征捆绑到单个特征上。通过精心设计特征扫描算法(feature scanning algorithm),我们可以从特征束中构建与单个特征相同的特征直方图。这样一来,直方图构建的复杂度就从降低为,而特征束(feature bundle)的数量远远小于特征的数量。
在这个方法中,我们需要解决两个问题:①决定哪些特征可以绑定为特征束②怎样建立一个特征束。
事实上,问题①是一个NP-hard问题,即在多项式时间内不可能去找到准确的解决办法。所以这里使用的是一种近似的解决办法,即特征之间允许存在少数的样本点并不是互斥的,允许小部分的冲突可以得到更小的特征绑定数量,更进一步的提高了计算的有效性。
以下是解决问题①和②的伪代码。
1、EFB算法描述:
输入:特征F,最大冲突数K,图G(顶点是特征,边是权重,权重与两个特征间的冲突相关)
输出:特征捆绑集合bundles
①构造一个加权无向图,其权值对应于特征之间的总冲突;
②通过特征在图中的度来降序排序特征
③检查有序列表中的每个特征,并将其分配给具有小冲突的现有bundling(由控制),或者创建新的bundling。
上述算法的时间复杂度为并且在模型训练之前只被处理一次即可。在特征维度不是很大时,这种复杂度可以接受,但是当样本维度较高时,这种方法就会很低效。所以针对于此,作者又提出另一种更高效的算法:按非零值计数排序,这类似于按度数排序,因为更多的非零值通常会导致更高的冲突概率。
2、合并互斥特征
合并互斥特征使用直方图算法。直方图算法的基本思想是先把连续的特征值离散化成k个整数,同时构造一个宽度为k的直方图。在遍历数据的时候,根据离散化后的值作为索引在直方图中累积统计量,当遍历一次数据后,直方图累积了需要的统计量,然后根据直方图的离散值,遍历寻找最优的分割点。
当然,Histogram算法并不是完美的。由于特征被离散化后,找到的并不是很精确的分割点,所以会对结果产生影响。但在不同的数据集上的结果表明,离散化的分割点对最终的精度影响并不是很大,甚至有时候会更好一点。原因是决策树本来就是弱模型,分割点是不是精确并不是太重要;差一点的切分点也有正则化的效果,可以有效地防止过拟合;即使单棵树的训练误差比精确分割的算法稍大,但在Gradient Boosting的框架下没有太大的影响。
直方图算法的优点:
①减少分割增益的计算量:XGBoost中默认的是pre-sorted算法,需要的是|data|次计算,而直方图算法只需要|bins|次计算,|bins|大小远小于|data|大小
②通过直方图相减来进一步的加速模型的训练
③减少内存的使用:将连续的值替换为离散的bins。
④减少并行学习的通信代价。
LightGBM=使用GOSS算法和EFB算法的GBDT(梯度提升树)
LightGBM的优势
1、LightGBM是垂直增长的,指它的增长是基于叶子节点增长的,而其他的boosting算法是基于层进行增长的,如下图所示。
2、lightGBM能够更快速、更低内存的处理海量数据,并且准确度更高。
3、LightGBM适用于大规模数据,不适用于小数据,会导致过拟合问题
4、支持并行化
5、支持直接使用category特征
Lightgbm中的并行学习
1、 特征并行 (1)传统算法的的特征并行
传统的特征并行算法旨在于在并行化决策树中的寻找最佳切分点,主要流程如下:
①垂直切分数据(不同的Worker有不同的特征集);
②在本地特征集寻找最佳切分点 {特征, 阈值};
③在各个机器之间进行通信,拿出自己的最佳切分点,然后从所有的最佳切分点中推举出一个最好的切分点,作为全局的切分点;
④以最佳划分方法对数据进行划分,并将数据划分结果传递给其他Worker;
⑤其他Worker对接受到的数据进一步划分。
(2)传统的特征并行方法主要不足:
①存在计算上的局限,传统特征并行无法加速特征切分(时间复杂度为 )。 因此,当数据量很大的时候,难以加速。
②需要对划分的结果进行通信整合,其额外的时间复杂度约为。(一个数据一个字节)
(3)LightGBM 中的特征并行
在数据量很大时,传统并行方法无法有效地对特征进行并行,LightGBM 做了一些改变:不再垂直划分数据,即每个Worker都持有全部数据。 因此,LighetGBM中没有数据划分结果之间通信的开销,各个Worker都知道如何划分数据。 而且,样本量也不会变得更大,所以,使每个机器都持有全部数据是合理的。
LightGBM 中特征并行的流程如下:
①每个Worker都在本地特征集上寻找最佳划分点{特征, 阈值};
②本地进行各个划分的通信整合并得到最佳划分;
③执行最佳划分。
然而,该特征并行算法在数据量很大时仍然存在计算上的局限。因此,建议在数据量很大时使用数据并行。
2、 数据并行 (1)传统的数据并行算法
数据并行目的是并行化整个决策学习过程。数据并行的主要流程如下:
①水平划分数据;
②Worker以本地数据构建本地直方图;
③将所有Worker的本地直方图整合成全局整合图;
④在全局直方图中寻找最佳切分,然后执行此切分。
(2)传统数据并行的不足:
高通讯开销。 如果使用点对点的通讯算法,一个Worker的通讯开销大约为。 如果使用集体通讯算法(例如, “All Reduce”等),通讯开销大约为。
(3)LightGBM中的数据并行
LightGBM 中通过减少数据并行过程中的通讯开销,来减少数据并行的开销:
①不同于传统数据并行算法中的,整合所有本地直方图以形成全局直方图的方式,LightGBM 使用Reduce scatter的方式对不同Worker的不同特征(不重叠的)进行整合。 然后Worker从本地整合直方图中寻找最佳划分并同步到全局的最佳划分中。
②如上面提到的,LightGBM 通过直方图做差法加速训练。 基于此,我们可以进行单叶子的直方图通讯,并且在相邻直方图上使用做差法。
通过上述方法,LightGBM 将数据并行中的通讯开销减少到O(0.5x|data|x|feature|)。
3、投票并行 投票并行进一步的减少数据并行的的通信消耗为常数级别。它使用两阶段的投票来减少特征直方图的通信消耗。
LightGBM中的主要调节的参数
1、 针对 Leaf-wise(Best-first)树的参数优化 (1)num_leaves这是控制树模型复杂度的主要参数。理论上, 借鉴 depth-wise 树, 我们可以设置 num_leaves= 但是, 这种简单的转化在实际应用中表现不佳. 这是因为, 当叶子数目相同时, leaf-wise 树要比 depth-wise 树深得多, 这就有可能导致过拟合. 因此, 当我们试着调整 num_leaves 的取值时, 应该让其小于 . 举个例子, 当 max_depth=7时,depth-wise 树可以达到较高的准确率.但是如果设置 num_leaves 为 128 时, 有可能会导致过拟合, 而将其设置为 70 或 80 时可能会得到比 depth-wise 树更高的准确率. 其实, depth 的概念在 leaf-wise 树中并没有多大作用, 因为并不存在一个从 leaves 到 depth 的合理映射。
(2)min_data_in_leaf. 这是处理 leaf-wise 树的过拟合问题中一个非常重要的参数. 它的值取决于训练数据的样本个树和 num_leaves. 将其设置的较大可以避免生成一个过深的树, 但有可能导致欠拟合. 实际应用中, 对于大数据集, 设置其为几百或几千就足够了。
(3)max_depth(默认不限制,一般设置该值为5—10即可) 你也可以利用 max_depth 来显式地限制树的深度。
2、 针对更快的训练速度 (1)通过设置 bagging_fraction 和 bagging_freq 参数来使用 bagging 方法;
(2)通过设置 feature_fraction 参数来使用特征的子抽样;
(3)使用较小的 max_bin;
(4)使用 save_binary 在以后的学习过程对数据进行加速加载。
3、针对更好的准确率 (1)使用较大的 max_bin (学习速度可能变慢);
(2)使用较小的 learning_rate 和较大的 num_iterations;
(3)使用较大的 num_leaves (可能导致过拟合);
(4)使用更大的训练数据;
(5)尝试 dart(一种在多元Additive回归树种使用dropouts的算法).
4、处理过拟合 (1)使用较小的 max_bin(默认为255)
(2)使用较小的 num_leaves(默认为31)
(3)使用 min_data_in_leaf(默认为20) 和 min_sum_hessian_in_leaf(默认为)
(4)通过设置 bagging_fraction (默认为1.0)和 bagging_freq (默认为0,意味着禁用bagging,k表示每k次迭代执行一个bagging)来使用 bagging
(5)通过设置 feature_fraction(默认为1.0) 来使用特征子抽样
(6)使用更大的训练数据
(7)使用 lambda_l1(默认为0), lambda_l2 (默认为0)和 min_split_gain(默认为0,表示执行切分的最小增益) 来使用正则
(8)尝试 max_depth 来避免生成过深的树
关于类别特征的详细内容,待补充。
参考资料
[1]https://www.biaodianfu.com/lightgbm.html
[3]https://blog.csdn.net/qq_24519677/article/details/82811215