当前位置: 代码迷 >> 综合 >> LightGBM(LGB)
  详细解决方案

LightGBM(LGB)

热度:36   发布时间:2023-11-26 15:24:15.0

转载自littlemichelle

LightGBM(Light Gradient Boosting Machine)是一个实现GBDT算法的框架,支持高效率的并行训练,并且具有更快的训练速度、更低的内存消耗、更好的准确率、支持分布式可以快速处理海量数据等优点。

背景

常用的机器学习算法,例如神经网络等算法,都可以以mini-batch的方式训练,训练数据的大小不会受到内存限制。而GBDT在每一次迭代的时候,都需要遍历整个训练数据多次。如果把整个训练数据装进内存则会限制训练数据的大小;如果不装进内存,反复地读写训练数据又会消耗非常大的时间。尤其面对工业级海量的数据,普通的GBDT算法是不能满足其需求的。

LightGBM提出的主要原因就是为了解决GBDT在海量数据遇到的问题,让GBDT可以更好更快地用于工业实践。

原生形式使用lightgbm(import lightgbm as lgb)

import lightgbm as lgb
from sklearn.metrics import mean_squared_error
from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split# 加载数据
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("Train data length:", len(X_train))
print("Test data length:", len(X_test))# 转换为Dataset数据格式
lgb_train = lgb.Dataset(X_train, y_train)
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 显示信息
}# 模型训练
gbm = lgb.train(params, lgb_train, num_boost_round=20, valid_sets=lgb_eval, early_stopping_rounds=5)# 模型保存
gbm.save_model('model.txt')# 模型加载
gbm = lgb.Booster(model_file='model.txt')# 模型预测
y_pred = gbm.predict(X_test, num_iteration=gbm.best_iteration)# 模型评估
print('The rmse of prediction is:', mean_squared_error(y_test, y_pred) ** 0.5)

Sklearn接口形式使用lightgbm(from lightgbm import LGBMRegressor)


from lightgbm import LGBMRegressor
from sklearn.metrics import mean_squared_error
from sklearn.model_selection import GridSearchCV
from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split
import joblib# 加载数据
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)# 模型训练
gbm = LGBMRegressor(objective='regression', num_leaves=31, learning_rate=0.05, n_estimators=20)
gbm.fit(X_train, y_train, eval_set=[(X_test, y_test)], eval_metric='l1', early_stopping_rounds=5)# 模型存储
joblib.dump(gbm, 'loan_model.pkl')
# 模型加载
gbm = joblib.load('loan_model.pkl')# 模型预测
y_pred = gbm.predict(X_test, num_iteration=gbm.best_iteration_)# 模型评估
print('The rmse of prediction is:', mean_squared_error(y_test, y_pred) ** 0.5)# 特征重要度
print('Feature importances:', list(gbm.feature_importances_))# 网格搜索,参数优化
estimator = LGBMRegressor(num_leaves=31)
param_grid = {
    'learning_rate': [0.01, 0.1, 1],'n_estimators': [20, 40]
}
gbm = GridSearchCV(estimator, param_grid)
gbm.fit(X_train, y_train)
print('Best parameters found by grid search are:', gbm.best_params_)

第二种接口实现,个人感觉比第一种好记

import datetime
import numpy as np
import pandas as pd
import lightgbm as lgb
from sklearn.datasets import load_breast_cancer#加载经典的乳腺癌数据
from sklearn.model_selection import train_test_split
from sklearn.metrics import accuracy_score
import matplotlib.pyplot as plt#加载数据集
breast=load_breast_cancer()
#获取特征值和目标值
X,y=breast.data,breast.target
#获取目标名称
feature_name=breast.feature_names#数据集划分
X_train,X_test,y_train,y_test=train_test_split(X,y,test_size=0.2,random_state=0)#数据格式转换
lgb_train=lgb.Dataset(X_train,y_train)
lgb_eval=lgb.Dataset(X_test,y_test,reference=lgb_train)#参数设置
boost_round=50#迭代次数
early_stop_rounds=10#验证数据如果在early_stop_rounds轮中未提高,则提前停止params={
    'boost_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 显示信息}
result={
    }
gbm=lgb.train(params,lgb_train,num_boost_round=boost_round,valid_sets=(lgb_train,lgb_eval),valid_names=('validata','train'),early_stopping_rounds=early_stop_rounds,evals_result=result
)

> **参数:**
> 
> boosting_type (string__, optional (default="gbdt")) – ‘gbdt’,
> traditional Gradient Boosting Decision Tree. ‘dart’, Dropouts meet
> Multiple Additive Regression Trees. ‘goss’, Gradient-based One-Side
> Sampling. ‘rf’, Random Forest. 默认的就挺好
> 
> num_leaves (int__, optional (default=31)) – Maximum tree leaves for
> base learners. 每个基学习器的最大叶子节点。LightGBM 使用的是 leaf-wise
> 的算法,因此在调节树的复杂程度时使用的是 num_leaves,它的值的设置应该小于 2^(max_depth)
> 
> max_depth (int__, optional (default=-1)) – Maximum tree depth for base
> learners, -1 means no limit. 每个基学习器的最大深度。当模型过拟合,首先降低max_depth 
> 
> learning_rate (float__, optional (default=0.1)) – Boosting learning
> rate. 梯度下降的步长。常用 0.1, 0.001, 0.003
> 
> n_estimators (int__, optional (default=10)) – Number of boosted trees
> to fit. 基学习器的数量 
> 
> max_bin (int__, optional (default=255)) – Number of bucketed bins for
> feature values. 存储feature的bin的最大数量,对应的是直方图的组数k  
> 
> subsample_for_bin (int__, optional (default=50000)) – Number of
> samples for constructing bins. 用来构建直方图的数据的样本数量
> 
> objective (string__, callable or None__, optional (default=None)) –
> Specify the learning task and the corresponding learning objective or
> a custom objective function to be used (see note below). default:
> ‘regression’ for LGBMRegressor, ‘binary’ or ‘multiclass’ for
> LGBMClassifier, ‘lambdarank’ for LGBMRanker.
> 
> min_split_gain(= min_gain_to_split) (float__, optional (default=0.)) –
> Minimum loss reduction required to make a further partition on a leaf
> node of the tree. 最小切分的信息增益值
> 
> min_child_weight(= min_sum_hessian_in_leaf) (float__, optional
> (default=1e-3)) – Minimum sum of instance weight(hessian) needed in a
> child(leaf).
> 决定最小叶子节点样本权重和(hessian)的最小阈值,若是基学习器切分后得到的叶节点中样本权重和低于该阈值则不会进一步切分,在线性模型中该阈值就对应每个节点的最小样本数。当它的值较大时,可以避免模型学习到局部的特殊样本,防止模型过拟合。但如果这个值过高,又会导致欠拟合
> 
> min_child_samples(= min_data_in_leaf) (int__, optional (default=20)) –
> Minimum number of data need in a child(leaf). 一个叶子节点中最小的数据量,调大可以防止过拟合
> 
> subsample (= bagging_fraction)(float__, optional (default=1.)) –
> Subsample ratio of the training instance.
> 这个参数控制对于每棵树,在非重复采样的情况下随机采样的比例。减小这个参数的值算法会更加保守,避免过拟合,加快运算速度。但是这个值设置的过小,它可能会导致欠拟合
> 
> subsample_freq(= bagging_freq) (int__, optional (default=1)) –
> Frequence of subsample, <=0 means no enable. bagging 的频率, 0 意味着禁用
> bagging. k 意味着每 k 次迭代执行bagging
> 
> colsample_bytree(= feature_fraction) (float__, optional (default=1.))
> – Subsample ratio of columns when constructing each tree.
> 用来控制每棵随机采样的列数的占比(每一列是一个特征)。 调小可以防止过拟合,加快运算速度。典型值:0.5-1范围:
> (0,1]。一般设置成0.8左右。
> 
> reg_alpha(= lambda_l1)(float__, optional (default=0.)) – L1
> regularization term on weights. L1 正则化项的权重系数,越大模型越保守。防止过拟合,提高泛化能力
> 
> reg_lambda(= lambda_l2) (float__, optional (default=0.)) – L2
> regularization term on weights. L2 正则化项的权重系数,越大模型越保守。防止过拟合,提高泛化能力
> 
> random_state (int or None__, optional (default=None)) – Random number
> seed. Will use default seeds in c++ code if set to None.
> 计算机不能产生绝对的随机数,只能产生伪随机数。伪就是有规律的意思。如果每次使用一样的 随机种子,生成的随机数列就是一样的了
> 
> n_jobs (int__, optional (default=-1)) – Number of parallel threads.
> 多线程,表示可以在机器的多个核上并行的构造树以及计算预测值。不过受限于通信成本,可能效率并不会说分为k个线程就得到k倍的提升,不过整体而言相对需要构造大量的树或者构建一棵复杂的树而言还是高效的
> 
> silent (bool__, optional (default=True)) – Whether to print messages
> while running boosting. 在运行过程中是否打印流程
> 
>  
> 
> 官方参数优化建议 针对 Leaf-wise (最佳优先) 树的参数优化
> 
> num_leaves. 这是控制树模型复杂度的主要参数. 理论上, 借鉴 depth-wise 树, 我们可以设置 num_leaves =
> 2^(max_depth) 但是, 这种简单的转化在实际应用中表现不佳. 这是因为, 当叶子数目相同时, leaf-wise 树要比
> depth-wise 树深得多, 这就有可能导致过拟合. 因此, 当我们试着调整 num_leaves 的取值时, 应该让其小于
> 2^(max_depth). 举个例子, 当 max_depth=6 时(这里译者认为例子中, 树的最大深度应为7), depth-wise
> 树可以达到较高的准确率.但是如果设置 num_leaves 为 127 时, 有可能会导致过拟合, 而将其设置为 70 或 80
> 时可能会得到比 depth-wise 树更高的准确率. 其实, depth 的概念在 leaf-wise 树中并没有多大作用,
> 因为并不存在一个从 leaves 到 depth 的合理映射. min_child_samples(min_data_in_leaf).
> 这是处理 leaf-wise 树的过拟合问题中一个非常重要的参数. 它的值取决于训练数据的样本个树和 num_leaves.
> 将其设置的较大可以避免生成一个过深的树, 但有可能导致欠拟合. 实际应用中, 对于大数据集, 设置其为几百或几千就足够了.
> max_depth. 你也可以利用 max_depth 来显式地限制树的深度 针对更快的训练速度
> 
> 通过设置 subsample(bagging_fraction) 和 subsample_freq(= bagging_freq)
> 参数来使用 bagging 方法进行采样提升训练速度(减小了数据集) 通过设置 colsample_bytree(=
> feature_fraction)参数来使用特征的子抽样 使用较小的 max_bin,较少的直方图数目 使用 save_binary
> 将数据集被保存为二进制文件,下次加载数据时速度会变快 通过并行训练来提速 针对更好的准确率
> 
> 使用较大的直方图数目 max_bin,这样会牺牲训练速度 使用较小的学习率 learning_rate,这样会增加迭代次数 使用较大的
> num_leaves,可能导致过拟合 使用更大的训练数据 尝试 dart 模型(Dropouts meet Multiple
> Additive Regression Trees) 处理过拟合
> 
> 设置较少的直方图数目 max_bin 设置较小的叶节点数 num_leaves 使用
> min_child_samples(min_data_in_leaf) 和  min_child_weight(=
> min_sum_hessian_in_leaf) 通过设置  subsample(bagging_fraction) 和 
> subsample_freq(= bagging_freq)来使用 bagging 通过设置
> colsample_bytree(feature_fraction) 来使用特征子抽样 使用更大的训练数据 使用
> reg_alpha(lambda_l1), reg_lambda(lambda_l2) 和
> min_split_gain(min_gain_to_split) 来使用正则 尝试 max_depth 来避免生成过深的树

一个上午的个人学习笔记,用了一些草稿纸,害怕丢,就放到博客上了,我这字迹和作图.。。。。。。哈哈,看不懂就别看了,这里面我自己不会的也有好多,等我完全搞明白了再好好整理一份。
在这里插入图片描述在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述