LightGBM 整理

1、Lightgbm如何处理类别特征

one-hot的弊端:

参考:https://www.zhihu.com/people/insulator/answers
one-hot编码是处理类别特征的一个通用方法,然而在树模型中,这可能并不一定是一个好的方法,尤其当类别特征中类别个数很多的情况下。主要的问题是:

  1. 可能无法在这个类别特征上进行切分(即浪费了这个特征)。使用one-hot编码的话,意味着在每一个决策节点上只能使用one vs rest(例如是不是狗,是不是猫等)的切分方式。当类别值很多时,每个类别上的数据可能会比较少,这时候切分会产生不平衡,这意味着切分增益也会很小(比较直观的理解是,不平衡的切分和不切分没有区别)。

  2. 会影响决策树的学习。因为就算可以在这个类别特征进行切分,也会把数据切分到很多零碎的小空间上,如图1左边所示。而决策树学习时利用的是统计信息,在这些数据量小的空间上,统计信息不准确,学习会变差。但如果使用如图1右边的分裂方式,数据会被切分到两个比较大的空间,进一步的学习也会更好。这样才能充分的挖掘该维特征所包含的信息,找到最优的分割策略。

在决策树上怎么用类别特征

LGBM采用了Many vs many的切分方式,实现了类别特征的最优切分。用Lightgbm可以直接输入类别特征,并产生如图1右边的效果。在1个k维的类别特征中寻找最优切分,朴素的枚举算法的复杂度是O(2^k),而LGBM实现了O(klogk)的算法。

二、 算法流程:

1. 建立直方图

对于连续值:先把特征取值从连续值转化成了离散值,也就是对每个特征的取值做个分段函数;对于离散化后的连续值特征 & 其他本来就是离散值的特征:统计该特征下每一种离散值出现的次数,并从高到低排序,并过滤掉出现次数较少的特征值, 然后为每一个特征值,建立一个bin容器。

对于该过程:算法图为下图1,case为下图2,左边#features(红框)、#data(绿框)即为表格中的数据,所以对应右侧的#features = 4,#bins(每个feature都有其对应的bin)中的每个#bin分别为:对于性别特征:#bin = 2(两个离散值);对于年龄特征:#bin = 离散化后的特征个数;对于手机特征:#bin = 3,对于身高特征(已经进行了预处理离散化)#bin = 3
直方图的构建在这里插入图片描述直方图算法有几个需要注意的地方:

  • 使用bin替代原始数据相当于增加了正则化;
  • 使用bin意味着很多数据的细节特征被放弃了,相似的数据可能被划分到相同的桶中,这样的数据之间的差异就消失了;
  • bin数量选择决定了正则化的程度,bin越少惩罚越严重,欠拟合风险越高。
2. 枚举分割点

在枚举分割点之前,先把直方图按每个类别的均值进行排序;然后按照均值的结果依次枚举最优分割点。从下图1可以看到,Sum(y) / Count(y)为类别的均值。当然,这个方法很容易过拟合,所以LightGBM里面还增加了很多对于这个方法的约束和正则化
在这里插入图片描述如身高特征(高、中、低三个枚举值):分别计算 Sum(y) / Count(y),按照均值的结果依次枚举最优分割点;为什么这样的顺序枚举呢?直观的理解是:sum / count 越低,则代表该特征对应的Y值种类数越多,也就是越杂乱,越需要分割,比如高特征两个data样本,两种Y,中特征三个data样本,两种Y,低特征一个data样本,一种Y(不需要分割),这样分割得到的信息增益最大,效率最高
在这里插入图片描述
在这里插入图片描述

3. 计算分类阈值

在这里插入图片描述

  1. 首先(最外面的for循环),对于当前模型的每个叶子节点,需要遍历所有的特征(# features),来找到增益最大的特征及其划分值,以此来分裂该叶子节点。gbdt会训练多个树模型,这个举例可能是其中任何一个模型吧。
  2. 然后(在第二个for循环中)对于每个特征(feature),首先为其创建一个直方图,这个直方图存储了两类信息,分别是每个bin中样本的梯度之和( 等同于sum(Y) ),还有就是每个bin中样本数量( 等同于 count(Y)
  3. 插入一个解释:( S_L)是当前分裂bin左边所有bin的集合,对比理解(S_R),那么(S_P)其中的P就是parent的意思,就是父节点
  4. 遍历所有样本,累积上述的两类统计值到样本所属的 bin 中;接着遍历所有bin,分别以当前 bin 作为分割点,累加其左边的 bin 至当前 bin 的梯度和(SL)以及样本数量(nL),并与父节点上的总梯度和(Sp)以及总样本数量(np)相减,得到右边所有bin的梯度和(SR)以及样本数量(nR),带入公式计算出增益,一句话解释就是(右=父-左)。在遍历过程中取最大的增益,以此时的特征和bin的特征值作为分裂节点的特征和分裂特征取值。(直方图做差加速)
    在这里插入图片描述
4. 带深度限制的 Leaf-wise 算法

LightGBM采用Leaf-wise的增长策略,该策略每次从当前所有叶子中,找到分裂增益最大的一个叶子,然后分裂,如此循环。因此同Level-wise相比,Leaf-wise的优点是:在分裂次数相同的情况下,Leaf-wise可以降低更多的误差,得到更好的精度;Leaf-wise的缺点是:可能会长出比较深的决策树,产生过拟合。因此LightGBM会在Leaf-wise之上增加了一个最大深度的限制,在保证高效率的同时防止过拟合
在这里插入图片描述

三、优缺点

优点:

  1. 首先,最明显就是内存消耗的降低,直方图算法不仅不需要额外存储预排序的结果,而且可以只保存特征离散化后的值,而这个值一般用 8 位整型存储就足够了,内存消耗可以降低为原来的1/8。
  2. 然后在计算上的代价也大幅降低,预排序算法每遍历一个特征值就需要计算一次分裂的增益,而直方图算法只需要计算 k 次(#bins)(k 可以认为是常数),时间复杂度从O(#样本数*#特征数)优化到O(k*#特征数)

缺点:

  1. 预处理能够忽略零值特征,减少训练代价;而直方图不能对稀疏进行优化,只是计算累加值(累加梯度和样本数)。但是,LightGBM对稀疏进行了优化:只用非零特征构建直方图。
LightGBM为何使用直方图这种比较粗的分割节点方法,还能达到比较好的效果
  1. 虽然分割的精度变差了,但是对最后结果的影响不是很大,主要由于决策树是弱模型, 分割点是不是精确并不是太重要 ;较粗的分割点也有正则化的效果,可以有效地防止过拟合;即使单棵树的训练误差比精确分割的算法稍大,但在梯度提升(Gradient Boosting)的框架下没有太大的影响。