参考:https://www.zhihu.com/people/insulator/answers
one-hot编码是处理类别特征的一个通用方法,然而在树模型中,这可能并不一定是一个好的方法,尤其当类别特征中类别个数很多的情况下。主要的问题是:
可能无法在这个类别特征上进行切分(即浪费了这个特征)。使用one-hot编码的话,意味着在每一个决策节点上只能使用one vs rest(例如是不是狗,是不是猫等)的切分方式。当类别值很多时,每个类别上的数据可能会比较少,这时候切分会产生不平衡,这意味着切分增益也会很小(比较直观的理解是,不平衡的切分和不切分没有区别)。
会影响决策树的学习。因为就算可以在这个类别特征进行切分,也会把数据切分到很多零碎的小空间上,如图1左边所示。而决策树学习时利用的是统计信息,在这些数据量小的空间上,统计信息不准确,学习会变差。但如果使用如图1右边的分裂方式,数据会被切分到两个比较大的空间,进一步的学习也会更好。这样才能充分的挖掘该维特征所包含的信息,找到最优的分割策略。
LGBM采用了Many vs many的切分方式,实现了类别特征的最优切分。用Lightgbm可以直接输入类别特征,并产生如图1右边的效果。在1个k维的类别特征中寻找最优切分,朴素的枚举算法的复杂度是O(2^k),而LGBM实现了O(klogk)的算法。
对于连续值:先把特征取值从连续值转化成了离散值,也就是对每个特征的取值做个分段函数;对于离散化后的连续值特征 & 其他本来就是离散值的特征:统计该特征下每一种离散值出现的次数,并从高到低排序,并过滤掉出现次数较少的特征值, 然后为每一个特征值,建立一个bin容器。
对于该过程:算法图为下图1,case为下图2,左边#features(红框)、#data(绿框)即为表格中的数据,所以对应右侧的#features = 4,#bins(每个feature都有其对应的bin)中的每个#bin分别为:对于性别特征:#bin = 2(两个离散值);对于年龄特征:#bin = 离散化后的特征个数;对于手机特征:#bin = 3,对于身高特征(已经进行了预处理离散化)#bin = 3
直方图算法有几个需要注意的地方:
在枚举分割点之前,先把直方图按每个类别的均值进行排序;然后按照均值的结果依次枚举最优分割点。从下图1可以看到,Sum(y) / Count(y)为类别的均值。当然,这个方法很容易过拟合,所以LightGBM里面还增加了很多对于这个方法的约束和正则化
如身高特征(高、中、低三个枚举值):分别计算 Sum(y) / Count(y),按照均值的结果依次枚举最优分割点;为什么这样的顺序枚举呢?直观的理解是:sum / count 越低,则代表该特征对应的Y值种类数越多,也就是越杂乱,越需要分割,比如高特征两个data样本,两种Y,中特征三个data样本,两种Y,低特征一个data样本,一种Y(不需要分割),这样分割得到的信息增益最大,效率最高
LightGBM采用Leaf-wise的增长策略,该策略每次从当前所有叶子中,找到分裂增益最大的一个叶子,然后分裂,如此循环。因此同Level-wise相比,Leaf-wise的优点是:在分裂次数相同的情况下,Leaf-wise可以降低更多的误差,得到更好的精度;Leaf-wise的缺点是:可能会长出比较深的决策树,产生过拟合。因此LightGBM会在Leaf-wise之上增加了一个最大深度的限制,在保证高效率的同时防止过拟合
优点:
缺点: