时隔两年,再次复盘之前写的lightgbm的这篇文章,发现当时主要是为了实践使用,并没有写很多的理论背景,这次在文章的前面部分,添加理论部分,后面依旧是简单的使用和参数的含义。希望迎接更好的2020年~
——————————————————————————
在第二部分原理中,结合了原始作者的论文,还有网络上比较好的几篇的讲解
lightGBM的论文
一、简介——机器学习竞赛的好工具
lightGBM是一个很好用的机器学习竞赛算法实现,他的本质是GDBT算法的一种优化实现,重点在于light这个单词上。作者在论文中提到,lightgbm可以比xgboost快6倍,同时使用更加小的内存,并且保持算法的高准确率。那么是如何实现light的呢?
主要是通过下面这些方式实现的:
GOSS(Gradient-based One-Side Sampling):减少样本数
EFB (Exclusive Feature Bundling ):减少特征数
直方图差加速
自动处理缺省值,包括是否将0视为缺省值。
处理类别特征
Leaf-wise生长策略
其中第一第二点,是在作者论文中就提到的,极大优化的时间和空间开销的方法,第三点是在分裂特征的时候使用的,第5点是最让人感动的,可以在拿到数据之后,快速的进行训练,不需要对离散特征进行one-hot encoding.第6点可以在相同的分裂次数时,获得更高的精度和更低的误差。下面将分别介绍这些优化方法。
二、lightgbm的优势们
0. 直方图算法
这个不是lightgbm首先提出的,但却是是light的一个基石。在训练树的时候,需要找到最佳划分节点,为此其中需要遍历特征下的每一个value,这里通常有两种做法:pre-sorted algorithm(预排序算法)和histogram-based algorithm(直方图算法)。
许多提升工具对于决策树的学习使用基于 pre-sorted 的算法。这是一个简单的解决方案,但是不易于优化。
LightGBM 利用基于 histogram 的算法 [3, 4, 5],通过将连续特征(属性)值分段为 discrete bins 来加快训练的速度并减少内存的使用。
1. GOSS
我们知道传统的Adaboost其实数据集都是有一个权值的,用来衡量其重要程度,没有被好好训练的样本其权值就大,以便下一个基学习器对其多加训练,于是就可以依据该权值对其采用,这样就做到采用利用部分数据集。
但是在GBDT中,数据没有权重这个概念,那我们应该怎么做呢?虽然我们没有权重,但是我们每次使用决策树训练的是之前所有模型的残差(平方损失的情况下),或者说是负梯度方向。那么我们可以将每个样本的一阶导数看做权重,一阶导数大的说明离最优解还远,这部分样本带来的增益大,或者说这部分样本还没有被好好训练,下一步我们应该重点训练他们。
我们计算所有样本的梯度,然后排序,取前top a%作为大梯度样本,然后对剩下的(1-a)x n的样本取b%作为小梯度样本训练。但是这样会导致数据的分布发生变化,所以还有给小样本一个补偿,那就是乘以一个常数即(1-a)/b,可以看到当a=0时就变成了随机采用啦,这样抽的结果还是能保持准确率的。
GOSS算法
这样训练的样本就只有原始样本的an + (1-a) x n x b了。在论文的实验中,a = 0.1, b=0.1(乃至更小)都没有影响最终的结果,还是和xgboost的结果那么精确。
2. EFB优化
通常,在GBDT和其最优的实现xgboost中,我们需要将类别型的特征预处理为onehot编码,否则就会认为是潜在有大小关系的。但是转为one hot之后,类别数大,gbdt这种树模型对高维稀疏特征的处理效果差。简直就是两难的问题啊。
我们先来理解一下为什么会效果差,GBDT是二叉树,使用one-hot编码的话,意味着在每一个决策节点上只能使用one vs rest(例如是不是狗,是不是猫等)的切分方式。当类别值很多时,每个类别上的数据可能会比较少,这时候切分会产生不平衡,这意味着切分增益也会很小(比较直观的理解是,不平衡的切分和不切分没有区别)。其次,可能因为训练数据的问题(噪声或者数据量太少)&#x