LightGBM算法---介绍说明python代码

Posted 小葵花幼儿园园长

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了LightGBM算法---介绍说明python代码相关的知识,希望对你有一定的参考价值。

提示:这些是自己整理 可以借鉴 也可能存在错误 欢迎指正

LightGBM


细节技术

1. 直方图优化

XGBoost缺点

XGBoost是基于预排序方法的决策树算法。这种构建决策树的算法基本思想是:

1. 首先,对所有特征都按照特征的数值进行预排序。
2. 其次,在遍历分割点的时候用O(#data)的代价找到一个特征上的最好分割点。
3. 最后,在找到一个特征的最好分割点后,将数据分裂成左右子节点。

缺点:

  • 空间消耗大。这样的算法需要保存数据的特征值,还保存了特征排序的结果,这就需要消耗训练数据两倍的内存。
  • 时间上也有较大的开销,在遍历每一个分割点的时候,都需要进行分裂增益的计算,消耗的代价大。

LightGBM改进

基于Histogram的决策树算法;Histogram algorithm应该翻译为直方图算法

直方图算法的基本思想是:先把连续的浮点特征值离散化成K 个整数,同时构造一个宽度为K 的直方图。在遍历数据的时候,根据离散化后的值作为索引在直方图中累积统计量,当遍历一次数据后,直方图累积了需要的统计量,然后根据直方图的离散值,遍历寻找最优的分割点。

直方图算法简单理解为:

  1. 首先确定对于每一个特征需要多少个箱子(bin)并为每一个箱子分配一个整数;
  2. 然后将浮点数的范围均分成若干区间,区间个数与箱子个数相等,将属于该箱子的样本数据更新为箱子的值;
  3. 最后用直方图(#bins)表示。

征离散化具有很多优点,如存储方便、运算更快、鲁棒性强、模型更加稳定等。对于直方图算法来说最直接的有以下两个优点:

  • 内存占用更小:直方图算法不仅不需要额外存储预排序的结果,而且可以只保存特征离散化后的值,而这个值一般用8 位整型存储就足够了,内存消耗可以降低为原来的1 / 8 。也就是说XGBoost需要用32 位的浮点数去存储特征值,并用32 位的整形去存储索引,而 LightGBM只需要用32 位去存储直方图,内存相当于减少为1 / 8 ;

  • 计算代价更小:预排序算法XGBoost每遍历一个特征值就需要计算一次分裂的增益,而直方图 算法LightGBM只需要计算 k 次( k 可以认为是常数),直接将时间复杂度从 O ( #data ∗ # feature) 降低到 O ( k ∗ # feature ) , 而我们为道 # d a t a > > k

不足点:

  • 由于特征被离散化后,找到的并不是很精确的分割点,所以会对结果产生影响。
  • 但在不同的数据集上的结果表明,离散化的分割点对最终的精度影响并不是很大,甚至有时候会更好一点。
    • 原因是决策树本来就是弱模型,分割点是不是精确并不是太重要;
    • 较粗的分割点也有正则化的效果,可以有效地防止过拟合;
    • 即使单棵树的训练误差比精确分割的算法稍大,但在梯度提升(Gradient Boosting)的框架下没有太大的影响。

2. 深度限制的节点展开方法

LightGBM使用了带有深度限制的节点展开方法(Leaf-wise)来提高模型精度,这是比XGBoost中Level-wise更高效的方法。

XGBoost 采用 Level-wise 的增长策略,该策略遍历一次数据可以同时分裂同一层的叶子,容易进行多线程优化,也好控制模型复杂度,不容易过拟合。但实际上Level-wise是一种低效的算法,因为它不加区分的对待同一层的叶子,实际上很多叶子的分裂增益较低,没必要进行搜索和分裂,因此带来了很多没必要的计算开销。

LightGBM采用Leaf-wise的增长策略,该策略每次从当前所有叶子中,找到分裂增益最大的一个叶子,然后分裂,如此循环。因此同Level-wise相比,

Leaf-wise

  • 优点: 在分裂次数相同的情况下,Leaf-wise可以降低更多的误差,得到更好的精度;
  • 缺点:可能会长出比较深的决策树,产生过拟合。因此LightGBM会在Leaf-wise之上增加了一个最大深度的限制,在保证高效率的同时防止过拟合。

3. 直方图做差优化

LightGBM另一个优化是Histogram(直方图)做差加速。

一个叶子的直方图可以由它的父亲节点的直方图与它兄弟的直方图做差得到,在速度上可以提升一倍。

通常构造直方图时,需要遍历该叶子上的所有数据,但直方图做差仅需遍历直方图的k个桶。在实际构建树的过程中,LightGBM还可以先计算直方图小的叶子节点,然后利用直方图做差来获得直方图大的叶子节点,这样就可以用非常微小的代价得到它兄弟叶子的直方图。


注意:XGBoost 在进行预排序时只考虑非零值进行加速,而 LightGBM 也采用类似策略:只用非零特征构建直方图。

4. 支持类别特征

传统的机器学习一般不能支持直接输入类别特征,需要先转化成多维的0-1特征,这样无论在空间上还是时间上效率都不高。

对于决策树来说并不推荐使用 one-hot 编码,尤其当类别特征中类别个数很多的情况下,会存在以下问题:

  • 会产生样本切分不平衡问题,导致切分增益非常小(即浪费了这个特征)
  • 会影响决策树的学习。

LightGBM通过更改决策树算法的决策规则,直接原生支持类别特征,不需要转化,提高了近8倍的速度。

5. 支持并行学习

LightGBM原生支持并行学习,目前支持特征并行(Featrue Parallelization)和数据并行(Data Parallelization)两种,还有一种是基于投票的数据并行(Voting Parallelization)

  • 特征并行的主要思想是在不同机器、在不同的特征集合上分别寻找最优的分割点,然后在机器间同步最优的分割点。
  • 数据并行则是让不同的机器先在本地构造直方图,然后进行全局的合并,最后在合并的直方图上面寻找最优分割点。

LightGBM针对这两种并行方法都做了优化。

  1. 特征并行算法中,通过在本地保存全部数据避免对数据切分结果的通信。
  2. 数据并行中使用分散规约 (Reduce scatter) 把直方图合并的任务分摊到不同的机器,降低通信和计算,并利用直方图做差,进一步减少了一半的通信量。
  3. 基于投票的数据并行(Voting Parallelization)则进一步优化数据并行中的通信代价,使通信代价变成常数级别。在数据量很大的时候,使用投票并行可以得到非常好的加速效果。

特征并行

数据并行


投票并行

python 实现

# coding: utf-8
# pylint: disable = invalid-name, C0111
 
# 函数的更多使用方法参见LightGBM官方文档:http://lightgbm.readthedocs.io/en/latest/Python-Intro.html
 
import json
import lightgbm as lgb
import pandas as pd
from sklearn.metrics import mean_squared_error
from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split
from sklearn.datasets import  make_classification
 
iris = load_iris()   # 载入鸢尾花数据集
data=iris.data
target = iris.target
X_train,X_test,y_train,y_test =train_test_split(data,target,test_size=0.2)
 
 
# 加载你的数据
# print('Load data...')
# df_train = pd.read_csv('../regression/regression.train', header=None, sep='\\t')
# df_test = pd.read_csv('../regression/regression.test', header=None, sep='\\t')
#
# y_train = df_train[0].values
# y_test = df_test[0].values
# X_train = df_train.drop(0, axis=1).values
# X_test = df_test.drop(0, axis=1).values
 
# 创建成lgb特征的数据集格式
lgb_train = lgb.Dataset(X_train, y_train) # 将数据保存到LightGBM二进制文件将使加载更快
lgb_eval = lgb.Dataset(X_test, y_test, reference=lgb_train)  # 创建验证数据
 
# 将参数写成字典下形式
params = 
    'task': 'train',
    'boosting_type': 'gbdt',  # 设置提升类型
    'objective': 'regression', # 目标函数
    'metric': 'l2', 'auc',  # 评估函数
    'num_leaves': 31,   # 叶子节点数
    'learning_rate': 0.05,  # 学习速率
    'feature_fraction': 0.9, # 建树的特征选择比例
    'bagging_fraction': 0.8, # 建树的样本采样比例
    'bagging_freq': 5,  # k 意味着每 k 次迭代执行bagging
    'verbose': 1 # <0 显示致命的, =0 显示错误 (警告), >0 显示信息

 
print('Start training...')
# 训练 cv and train
gbm = lgb.train(params,lgb_train,num_boost_round=20,valid_sets=lgb_eval,early_stopping_rounds=5) # 训练数据需要参数列表和数据集
 
print('Save model...') 
 
gbm.save_model('model.txt')   # 训练后保存模型到文件
 
print('Start predicting...')
# 预测数据集
y_pred = gbm.predict(X_test, num_iteration=gbm.best_iteration) #如果在训练期间启用了早期停止,可以通过best_iteration方式从最佳迭代中获得预测
# 评估模型
print('The rmse of prediction is:', mean_squared_error(y_test, y_pred) ** 0.5) # 计算真实值和预测值之间的均方根误差

小结

以上是关于LightGBM算法---介绍说明python代码的主要内容,如果未能解决你的问题,请参考以下文章

LightGBM的算法介绍

比XGBOOST更快--LightGBM介绍

机器学习集成学习进阶LightGBM算法和案例

NGBoost美国斯坦福大学团队算法介绍-作者亲测性能对比LightGBM,XGBoost,catboost

LightGBM的并行优化

基于lightgbm的金融风控算法实践(Python版)