赞
踩
2、leaf wise tree growth叶子节点优先生长决策
2、互斥特征捆绑(Exclusive Feature Bunding,EFB)
3、基于梯度的单边采样 (Grandient-based One-Side Sampling ,GOSS )
LightGBM的数据压缩策略LightGBM建模过程总共会进行三方面的数据压缩,根据实际建模顺序,会现在全样本上连续变量分箱(连续变量离散化),然后同时带入离散特征和离散后的连续变量进行离散特征捆绑(合并)降维,最终在每次构建一颗树之前进行样本下采样。其中连续变量的分箱就是非常简单的等宽分箱,并且具体箱体的数量可以通过超参数进行人工调节;而离散特征的降维,则是采用了一种所谓的互斥特征捆绑(Exclusive Feature Bundling, EFB)算法,该算法也是由LGBM首次提出,该方法的灵感来源于独热编码的逆向过程,通过把互斥的特征捆绑到一起来实现降维,这种方法能够很好的克服传统降维方法带来的信息大量损耗的问题,并且需要注意的是,输入EFB进行降维的特征,即包括原始离散特征,也包括第一阶段连续变量离散化之后的特征;在这一系列数据压缩之后,LGBM在每次迭代(也就是每次训练一颗决策树模型)的时候,还会围绕训练数据集进行下采样,此时的下采样不是简单的随机抽样,而是一种名为基于梯度的单边采样(Gradient-based One-Side Sampling, GOSs)的方法,和EFB类似,这种方法能够大幅压缩数据,但同时又不会导致信息的大量损失。不难发现,最终输入到每颗决策树进行训练的数据,实际上是经过大幅压缩后的数据,这也是LGBM计算高效的根本原因之一。
高效表示分裂前后的节点的核心数据,且父子节点可以通过直方图减法直接计算,从而加速数据集分裂的计算过程:
XGboost是一次生长一层也就是Level-wise tree growth,生长过程如下:
但是针对叶子节点优先分裂,可以理解为深度优先的“有偏”决策 生长。
优点:大幅提升每颗树的收敛速度,提升迭代速率。
劣势:每棵树计算更加复杂,且数据压缩后易出现过拟合的,但是可以通过设置树的深度来优化。
lightGBM连续变量分箱实现简单的等宽分箱,通过设置max_bin值来确定分箱数,例如连续变量取值范围是[0,10],设置max_bin=2,则bin0=[0,5]和bin1=[5,10],XGboost是通过分位数分箱,不是等宽分箱。
- import pandas as pd
- import numpy as np
- from sklearn.preprocessing import KBinsDiscretizer
-
- # 创建数据集
- data = {
- 'x1': [1.2, 3.0, 2.6, 3.3, 2.2, 2.5, 1.3, 2.0, 1.9, 2.9],
- 'x2': [4.6, 5.4, 3.8, 6.1, 3.4, 4.4, 5.0, 2.6, 4.0, 3.7],
- 'x3': [1, 1, 0, 1, 1, 1, 1, 0, 1, 1],
- 'x4': [0, 0, 1, 0, 0, 1, 0, 1, 0, 1],
- 'y': [1, 0, 1, 0, 1, 1, 0, 0, 1, 1]
- }
-
- df = pd.DataFrame(data)
-
- # 提取连续变量列
- continuous_cols = ['x1', 'x2']
-
- # 定义等宽分箱器
- max_bin = 3
- kbins = KBinsDiscretizer(n_bins=max_bin, encode='ordinal', strategy='uniform')
-
- # 对连续变量进行分箱
- binned_cols = ['x1_binned', 'x2_binned']
- df_binned = pd.DataFrame(kbins.fit_transform(df[continuous_cols]), columns=binned_cols)
-
- # 将分箱结果合并到原数据集
- df_final = pd.concat([df, df_binned], axis=1)
-
- print(df_final)
如示例所示的等宽分箱区间划分实际情况,如x1值域区间[1.2,3.3]若设置max_bin=3,则分箱深度为(3.3-1.2)/3=0.7,分箱区间则为{ [1.2,1.9) , [1.9,2.6) , [2.6,3.3] }。binned值为{ 0 , 1 , 2 }。至此,第一阶段对数据的连续变量采用的分箱处理完成。
离散特征降维,LGBM采用互斥特征捆绑的降维方法,本节研究背景、原理、及示例代码。
根据论文《A Highly Efficient Gradient Boosting Decision Tree (2017) 》中说明,原始GBDT树训练时,需要使用到全量的数据计算信息增益,从而找到决策树节点最佳分支节点,但缺点是耗费算力和时间,在传统基础上提出的欠采样会使得模型训练不稳定和PCA降维会由冗余信息导致信息丢失。因此,LightGBM日出单边采样的GOSS对样本数量进行压缩,EFB来进行特征捆绑,这两者的结合能够同时兼顾精度和效率。后续还提出了直方图的数据压缩优化。
EFB在真实数据中的计算十分复杂,互斥并非压缩完全互斥,是冲突比例超过设定阈值则进行压缩。LightGBM中设置一个max_confilict_rate超参数空值冲突比例最大阈值,冲突比例越大说明互斥程度越低。很明显,max_conflict_rate设置的越小,对互斥的要求就越高,特征就越不容易被捆绑,模型计算量就越大、精度也越高,而如果max_conflict_rate设置的很大,则更多的特征会被捆绑,模型计算速度会更快,但精度也会降低。
可以将互斥捆绑问题理解为图论的着色问题,组合优化问题,给定一个无向图,特征即为标记节点。在EFB计算过程中,若特征之间存在冲突,则用一条无向边进行连接,边的权重就是冲突比例,而如果两个特征互斥,则彼此没有边进行相连。而在将特征及其冲突情况用图进行展示后,即可进一步进行图着色——即在相邻的点颜色不同的前提条件下,用尽可能少的颜色对图上的点进行着色,既然相互冲突的特征都有边进行相连,那么相同颜色的点其实就是互斥的特征,接下来我们仅需把相同颜色的特征进行合并即可。
- data
- data[['x1_binned','x2_binnned','x3','x4']]
- def conflict_ratio_matrix(data):
- """
- 冲突比例计算函数
-
- :param data: 计算冲突比例的dataframe
- :return:冲突比例矩阵
- """
- if isinstance(data, pd.DataFrame):
- data = data.values
-
- num_features = data.shape[1]
- # 创建空特征比例矩阵
- conflict_matrix = np.zeros((num_features, num_features))
-
- # 两层循环挑选两个特征
- for i in range(num_features):
- for j in range(i+1, num_features):
- # 计算特征冲突特征总数
- conflict_count = np.sum((data[:, i] != 0) & (data[:, j] != 0))
- # 计算不为0的特征总数
- total_count = np.sum((data[:, i] != 0) | (data[:, j] != 0))
- # 计算冲突比例
- conflict_ratio = conflict_count / total_count
- conflict_matrix[i, j] = conflict_ratio
- conflict_matrix[j, i] = conflict_ratio
-
- return conflict_matrix
-
- conflict_ratio_matrix(data[['x1_binned', 'x2_binned', 'x3', 'x4']])
然后设置max_conflict_rate=0.3后进行着色
x4为什么和x2_binned都是绿色,因为相较于x4和x3,x4和x2_binned的冲突比例小,互斥程度大,所以将它们标记为相同颜色。
最后,我们把相同着色的点(特征)进行捆绑。捆绑过程并不复杂,核心是需要对特征取值进行合理转化。而具体的转化过程中,LGBM会根据主特征的最大取值设置一个offset值,然后对合并进来特征的非零值加上这个offset值,然后再让这两个特征取值相加。例如data数据集中,我们将x4并入x2_binned中,则offset=1
- data['x2_binned']
- #然后对x4的非零值+offset,并构成新的特征x2_binned&x4
- arr=np.array(data['x4'])
- arr[arr!=0]+=1
- arr
-
- data['x2_binned&x4']= arr+data['x2_binned']
- data
- #至此,我们就在data这个简化的数据集上完成了EFB特征捆绑过程,经过连续变量分箱和特征捆绑,实际上接下来带入进行模型训练的特征就只有x1_binned、x2_binned&x4和x3这三个特征:
- data[['x1_binned','x2_binned&x4','x3']]
GOSS是一种非常特殊的基于梯度分布的抽样方法。我们知道在执行优化算法的过程中,每个样本都有一个对应的梯度计算结果,如果某条样本梯度绝对值较小,则说明这条样本已经被正确的分类或者预测结果和真实结果非常接近,在后续的参数更新过程中,这些梯度绝对值较小的样本对参数的改进贡献较小,因此每次迭代计算时再把这些小梯度的样本再算一遍梯度,会一定程度造成资源浪费。而反观那些梯度绝对值较大的样本,这些样本具有更高的误差,因此对模型的训练有更大的贡献。
因此,GOSS的思路是将全部样本按照梯度绝对值大小进行降序排序,然后抽取梯度绝对值最大的前
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。