作者:韩信子@ShowMeAI
教程地址:http://www.showmeai.tech/tutorials/41
本文地址:http://www.showmeai.tech/article-detail/205
申明:版权所有,转载请分割平台与作者并注明出处
珍藏ShowMeAI查看更多精彩内容

引言

LightGBM是微软开发的boosting集成模型,和XGBoost一样是对GBDT的优化和高效实现,原理有一些相似之处,但它很多方面比XGBoost有着更为优良的体现。

本篇内容ShowMeAI开展给大家解说LightGBM的工程利用办法,对于LightGBM原理常识感兴趣的同学,欢送参考ShowMeAI的另外一篇文章 图解机器学习 | LightGBM模型详解

1.LightGBM装置

LightGBM作为常见的弱小Python机器学习工具库,装置也比较简单。

1.1 Python与IDE环境设置

python环境与IDE设置能够参考ShowMeAI文章 图解python | 装置与环境设置 进行设置。

1.2 工具库装置

(1) Linux/Mac等零碎

这些零碎下的XGBoost装置,大家只有基于pip就能够轻松实现了,在命令行端输出命令如下命令即可期待装置实现。

pip install lightgbm

大家也能够抉择国内的pip源,以取得更好的装置速度:

pip install -i https://pypi.tuna.tsinghua.edu.cn/simple lightgbm

(2) Windows零碎

对于windows零碎而言,比拟高效便捷的装置形式是:在网址http://www.lfd.uci.edu/~gohlke/pythonlibs/ 中去下载对应版本的的LightGBM安装包,再通过如下命令装置。
pip install lightgbm‑3.3.2‑cp310‑cp310‑win_amd64.whl

2.LightGBM参数手册

在ShowMeAI的前一篇内容 XGBoost工具库建模利用详解 中,咱们解说到了Xgboost的三类参数通用参数,学习指标参数,Booster参数。而LightGBM可调参数更加丰盛,蕴含外围参数,学习控制参数,IO参数,指标参数,度量参数,网络参数,GPU参数,模型参数,这里我常批改的便是外围参数,学习控制参数,度量参数等。上面咱们对这些模型参数做开展解说,更多的细节能够参考LightGBM中文文档。

2.1 参数介绍

(1) 外围参数

  • config或者config_file:一个字符串,给出了配置文件的门路。默认为空字符串。
  • task:一个字符串,给出了要执行的工作。能够为:

    • train或者training:示意是训练任务。默认为train
    • predict或者prediction或者test:示意是预测工作。
    • convert_model:示意是模型转换工作。将模型文件转换成if-else格局。
  • application或者objective或者app:一个字符串,示意问题类型。能够为:

    • regressionregression_l2mean_squared_errormsel2_rootroot_mean_squred_errorrmse:示意回归工作,然而应用L2损失函数。默认为regression
    • regression_l1或者mae或者mean_absolute_error:示意回归工作,然而应用L1损失函数。
    • huber:示意回归工作,然而应用huber损失函数。
    • fair:示意回归工作,然而应用fair损失函数。
    • poisson:示意Poisson回归工作。
    • quantile:示意quantile回归工作。
    • quantile_l2:示意quantile回归工作,然而应用了L2损失函数。
    • mape或者mean_absolute_precentage_error:示意回归工作,然而应用MAPE损失函数
    • gamma:示意gamma回归工作。
    • tweedie:示意tweedie回归工作。
    • binary:示意二分类工作,应用对数损失函数作为指标函数。
    • multiclass:示意多分类工作,应用softmax函数作为指标函数。必须设置num_class参数
    • multiclassova或者multiclass_ova或者ova或者ovr:示意多分类工作,应用one-vs-all的二分类指标函数。必须设置num_class参数。
    • xentropy或者cross_entropy:指标函数为穿插熵(同时具备可抉择的线性权重)。要求标签是[0,1]之间的数值。
    • xentlambda或者cross_entropy_lambda:代替了参数化的cross_entropy。要求标签是[0,1]之间的数值。
    • lambdarank:示意排序工作。在lambdarank工作中,标签应该为整数类型,数值越大示意相关性越高。label_gain参数能够用于设置整数标签的增益(权重)。
  • boosting或者boost或者boosting_type:一个字符串,给出了基学习器模型算法。能够为:

    • gbdt:示意传统的梯度晋升决策树。默认值为gbdt
    • rf:示意随机森林。
    • dart:示意带dropout的gbdt。
    • goss:示意Gradient-based One-Side Sampling 的gbdt。
  • data或者train或者train_data:一个字符串,给出了训练数据所在的文件的文件名。默认为空字符串。LightGBM将应用它来训练模型。
  • valid或者test或者valid_data或者test_data:一个字符串,示意验证集所在的文件的文件名。默认为空字符串。LightGBM将输入该数据集的度量。如果有多个验证集,则用逗号分隔。
  • num_iterations或者num_iteration或者num_tree或者num_trees或者num_round或者num_rounds或者num_boost_round一个整数,给出了boosting的迭代次数。默认为100。

    • 对于Python/R包,该参数是被疏忽的。对于Python,应用train()/cv()的输出参数num_boost_round来代替。
    • 在外部,LightGBM对于multiclass问题设置了num_class*num_iterations棵树。
  • learning_rate或者shrinkage_rate:个浮点数,给出了学习率。默认为1。在dart中,它还会影响dropped trees的归一化权重。
  • num_leaves或者num_leaf:一个整数,给出了一棵树上的叶子数。默认为31。
  • tree_learner或者tree:一个字符串,给出了tree learner,次要用于并行学习。默认为serial。能够为:

    • serial:单台机器的tree learner
    • feature:特色并行的tree learner
    • data:数据并行的tree learner
    • voting:投票并行的tree learner
  • num_threads或者num_thread或者nthread:一个整数,给出了LightGBM的线程数。默认为OpenMP_default

    • 为了更快的速度,应该将它设置为真正的CPU内核数,而不是线程的数量(大多数CPU应用超线程来使每个CPU内核生成2个线程)。
    • 当数据集较小的时候,不要将它设置的过大。
    • 对于并行学习,不应该应用全副的CPU外围,因为这会使得网络性能不佳。
  • device:一个字符串,指定计算设施。默认为cpu。能够为gpucpu

    • 倡议应用较小的max_bin来取得更快的计算速度。
    • 为了放慢学习速度,GPU默认应用32位浮点数来求和。你能够设置gpu_use_dp=True来启动64位浮点数,然而它会使得训练速度升高。

(2) 学习控制参数

  • max_depth:一个整数,限度了树模型的最大深度,默认值为-1。如果小于0,则示意没有限度。
  • min_data_in_leaf或者min_data_per_leaf或者min_data或者min_child_samples:一个整数,示意一个叶子节点上蕴含的起码样本数量。默认值为20。
  • min_sum_hessian_in_leaf或者min_sum_hessian_per_leaf或者min_sum_hessian或者min_hessian或者min_child_weight:一个浮点数,示意一个叶子节点上的最小hessian之和。(也就是叶节点样本权重之和的最小值)默认为1e-3。
  • feature_fraction或者sub_feature或者colsample_bytree:一个浮点数,取值范畴为[0.0,1.0],默认值为0。如果小于1.0,则LightGBM会在每次迭代中随机抉择局部特色。如0.8示意:在每棵树训练之前抉择80%的特色来训练。
  • feature_fraction_seed:一个整数,示意feature_fraction的随机数种子,默认为2。
  • bagging_fraction或者sub_row或者subsample:一个浮点数,取值范畴为[0.0,1.0],默认值为0。如果小于1.0,则LightGBM会在每次迭代中随机抉择局部样本来训练(非反复采样)。如0.8示意:在每棵树训练之前抉择80%的样本(非反复采样)来训练。
  • bagging_freq或者subsample_freq:一个整数,示意每bagging_freq次执行bagging。如果该参数为0,示意禁用bagging。
  • bagging_seed或者bagging_fraction_seed:一个整数,示意bagging的随机数种子,默认为3。
  • early_stopping_round或者early_stopping_rounds或者early_stopping:一个整数,默认为0。如果一个验证集的度量在early_stopping_round循环中没有晋升,则进行训练。如果为0则示意不开启早停。
  • lambda_l1或者reg_alpha:一个浮点数,示意L1正则化系数。默认为0。
  • lambda_l2或者reg_lambda:一个浮点数,示意L2正则化系数。默认为0。
  • min_split_gain或者min_gain_to_split:一个浮点数,示意执行切分的最小增益,默认为0。
  • drop_rate:一个浮点数,取值范畴为[0.0,1.0],示意dropout的比例,默认为1。该参数仅在dart中应用。
  • skip_drop:一个浮点数,取值范畴为[0.0,1.0],示意跳过dropout的概率,默认为5。该参数仅在dart中应用。
  • max_drop:一个整数,示意一次迭代中删除树的最大数量,默认为50。如果小于等于0,则示意没有限度。该参数仅在dart中应用。
  • uniform_drop:一个布尔值,示意是否想要平均的删除树,默认值为False。该参数仅在dart中应用。
  • xgboost_dart_mode:一个布尔值,示意是否应用xgboost dart模式,默认值为False。该参数仅在dart中应用。
  • drop_seed:一个整数,示意dropout的随机数种子,默认值为4。该参数仅在dart中应用。
  • top_rate:一个浮点数,取值范畴为[0.0,1.0],示意在goss中,大梯度数据的保留比例,默认值为2。该参数仅在goss中应用。
  • other_rate:一个浮点数,取值范畴为[0.0,1.0],示意在goss中,小梯度数据的保留比例,默认值为1。该参数仅在goss中应用。
  • min_data_per_group:一个整数,示意每个分类组的最小数据量,默认值为100。用于排序工作
  • max_cat_threshold:一个整数,示意category特色的取值汇合的最大大小。默认为32。
  • cat_smooth:一个浮点数,用于category特色的概率平滑。默认值为10。它能够升高噪声在category特色中的影响,尤其是对于数据很少的类。
  • cat_l2:一个浮点数,用于category切分中的L2正则化系数。默认为10。
  • top_k或者topk:一个整数,用于投票并行中。默认为20。将它设置为更大的值能够取得更准确的后果,然而会升高训练速度。

(3) IO参数

  • max_bin:一个整数,示意最大的桶的数量。默认值为255。LightGBM会依据它来主动压缩内存。如max_bin=255时,则LightGBM将应用uint8来示意特色的每一个值。
  • min_data_in_bin:一个整数,示意每个桶的最小样本数。默认为3。该办法能够避免出现一个桶只有一个样本的状况。
  • data_random_seed:一个整数,示意并行学习数据分隔中的随机数种子。默认为1它不包含特色并行。
  • output_model或者model_output或者model_out:一个字符串,示意训练中输入的模型被保留的文件的文件名。默认txt。
  • input_model或者model_input或者model_in:一个字符串,示意输出模型的文件的文件名。默认空字符串。对于prediction工作,该模型将用于预测数据,对于train工作,训练将从该模型持续
  • output_result或者predict_result或者prediction_result:一个字符串,给出了prediction后果寄存的文件名。默认为txt。
  • pre_partition或者is_pre_partition:一个布尔值,批示数据是否曾经被划分。默认值为False。如果为true,则不同的机器应用不同的partition来训练。它用于并行学习(不包含特色并行)
  • is_sparse或者is_enable_sparse或者enable_sparse:一个布尔值,示意是否开启稠密优化,默认为True。如果为True则启用稠密优化。
  • two_round或者two_round_loading或者use_two_round_loading:一个布尔值,批示是否启动两次加载。默认值为False,示意只须要进行一次加载。默认状况下,LightGBM会将数据文件映射到内存,而后从内存加载特色,这将提供更快的数据加载速度。然而当数据文件很大时,内存可能会被耗尽。如果数据文件太大,则将它设置为True
  • save_binary或者is_save_binary或者is_save_binary_file:一个布尔值,示意是否将数据集(包含验证集)保留到二进制文件中。默认值为False。如果为True,则能够放慢数据的加载速度。
  • verbosity或者verbose:一个整数,示意是否输入两头信息。默认值为1。如果小于0,则仅仅输入critical信息;如果等于0,则还会输入error,warning信息;如果大于0,则还会输入info信息。
  • header或者has_header:一个布尔值,示意输出数据是否有头部。默认为False。
  • label或者label_column:一个字符串,示意标签列。默认为空字符串。你也能够指定一个整数,如label=0示意第0列是标签列。你也能够为列名增加前缀,如label=prefix:label_name
  • weight或者weight_column:一个字符串,示意样本权重列。默认为空字符串。你也能够指定一个整数,如weight=0示意第0列是权重列。留神:它是剔除了标签列之后的索引。如果标签列为0,权重列为1,则这里weight=0。你也能够为列名增加前缀,如weight=prefix:weight_name
  • query或者query_column或者gourp或者group_column:一个字符串,query/groupID列。默认为空字符串。你也能够指定一个整数,如query=0示意第0列是query列。留神:它是剔除了标签列之后的索引。如果标签列为0,query列为1,则这里query=0。你也能够为列名增加前缀,如query=prefix:query_name
  • ignore_column或者ignore_feature或者blacklist:一个字符串,示意训练中疏忽的一些列,默认为空字符串。能够用数字做索引,如ignore_column=0,1,2示意第0,1,2列将被疏忽。留神:它是剔除了标签列之后的索引。
  • 你也能够为列名增加前缀,如ignore_column=prefix:ign_name1,ign_name2
  • categorical_feature或者categorical_column或者cat_feature或者cat_column:一个字符串,指定category特色的列。默认为空字符串。能够用数字做索引,如categorical_feature=0,1,2示意第0,1,2列将作为category特色。留神:它是剔除了标签列之后的索引。你也能够为列名增加前缀,如categorical_feature=prefix:cat_name1,cat_name2在categorycal特色中,负的取值被视作缺失值。
  • predict_raw_score或者raw_score或者is_predict_raw_score:一个布尔值,示意是否预测原始得分。默认为False。如果为True则仅预测原始得分。该参数只用于prediction工作。
  • predict_leaf_index或者leaf_index或者is_predict_leaf_index:一个布尔值,示意是否预测每个样本在每棵树上的叶节点编号。默认为False。在预测时,每个样本都会被调配到每棵树的某个叶子节点上。该参数就是要输入这些叶子节点的编号。该参数只用于prediction工作。
  • predict_contrib或者contrib或者is_predict_contrib:一个布尔值,示意是否输入每个特色对于每个样本的预测的奉献。默认为False。输入的后果形态为[nsamples,nfeatures+1],之所以+1是思考到bais的奉献。所有的奉献加起来就是该样本的预测后果。该参数只用于prediction工作。
  • bin_construct_sample_cnt或者subsample_for_bin:一个整数,示意用来构建直方图的样本的数量。默认为200000。如果数据十分稠密,则能够设置为一个更大的值,如果设置更大的值,则会提供更好的训练成果,然而会减少数据加载工夫。
  • num_iteration_predict:一个整数,示意在预测中应用多少棵子树。默认为-1。小于等于0示意应用模型的所有子树。该参数只用于prediction工作。
  • pred_early_stop:一个布尔值,示意是否应用早停来减速预测。默认为False。如果为True,则可能影响精度。
  • pred_early_stop_freq:一个整数,示意查看早停的频率。默认为10
  • pred_early_stop_margin:一个浮点数,示意早停的边际阈值。默认为0
  • use_missing:一个布尔值,示意是否应用缺失值性能。默认为True如果为False则禁用缺失值性能。
  • zero_as_missing:一个布尔值,示意是否将所有的零(包含在libsvm/sparse矩阵中未显示的值)都视为缺失值。默认为False。如果为False,则将nan视作缺失值。如果为True,则np.nan和零都将视作缺失值。
  • init_score_file:一个字符串,示意训练时的初始化分数文件的门路。默认为空字符串,示意train_data_file+”.init”(如果存在)
  • valid_init_score_file:一个字符串,示意验证时的初始化分数文件的门路。默认为空字符串,示意valid_data_file+”.init”(如果存在)。如果有多个(对应于多个验证集),则能够用逗号,来分隔。

(4) 指标参数

  • sigmoid:一个浮点数,用sigmoid函数的参数,默认为0。它用于二分类工作和lambdarank工作。
  • alpha:一个浮点数,用于Huber损失函数和Quantileregression,默认值为0。它用于huber回归工作和Quantile回归工作。
  • fair_c:一个浮点数,用于Fair损失函数,默认值为0。它用于fair回归工作。
  • gaussian_eta:一个浮点数,用于管制高斯函数的宽度,默认值为0。它用于regression_l1回归工作和huber回归工作。
  • posson_max_delta_step:一个浮点数,用于Poisson regression的参数,默认值为7。它用于poisson回归工作。
  • scale_pos_weight:一个浮点数,用于调整正样本的权重,默认值为0它用于二分类工作。
  • boost_from_average:一个布尔值,批示是否将初始得分调整为平均值(它能够使得收敛速度更快)。默认为True。它用于回归工作。
  • is_unbalance或者unbalanced_set:一个布尔值,批示训练数据是否平衡的。默认为True。它用于二分类工作。
  • max_position:一个整数,批示将在这个NDCG地位优化。默认为20。它用于lambdarank工作。
  • label_gain:一个浮点数序列,给出了每个标签的增益。默认值为0,1,3,7,15,….它用于lambdarank工作。
  • num_class或者num_classes:一个整数,批示了多分类工作中的类别数量。默认为1它用于多分类工作。
  • reg_sqrt:一个布尔值,默认为False。如果为True,则拟合的后果为:\sqrt{label}。同时预测的后果被主动转换为:{pred}^2。它用于回归工作。

(5) 度量参数

  • metric:一个字符串,指定了度量的指标,默认为:对于回归问题,应用l2;对于二分类问题,应用binary_logloss;对于lambdarank问题,应用ndcg。如果有多个度量指标,则用逗号,分隔。

    • l1或者mean_absolute_error或者mae或者regression_l1:示意绝对值损失。
    • l2或者mean_squared_error或者mse或者regression_l2或者regression:示意平方损失。
    • l2_root或者root_mean_squared_error或者rmse:示意开方损失。
    • quantile:示意Quantile回归中的损失。
    • mape或者mean_absolute_percentage_error:示意MAPE损失。
    • huber:示意huber损失。
    • fair:示意fair损失。
    • poisson:示意poisson回归的负对数似然。
    • gamma:示意gamma回归的负对数似然。
    • gamma_deviance:示意gamma回归的残差的方差。
    • tweedie:示意Tweedie回归的负对数似然。
    • ndcg:示意NDCG。
    • map或者mean_average_precision:示意均匀的精度。
    • auc:示意AUC。
    • binary_logloss或者binary:示意二类分类中的对数损失函数。
    • binary_error:示意二类分类中的分类错误率。
    • multi_logloss或者multiclass或者softmax或者‘multiclassova或者multiclass_ova,或者ova或者ovr`:示意多类分类中的对数损失函数。
    • multi_error:示意多分类中的分类错误率。
    • xentropy或者cross_entropy:示意穿插熵。
    • xentlambda或者cross_entropy_lambda:示意intensity加权的穿插熵。
    • kldiv或者kullback_leibler:示意KL散度。
  • metric_freq或者output_freq:一个正式,示意每隔多少次输入一次度量后果。默认为1。
  • train_metric或者training_metric或者is_training_metric:一个布尔值,默认为False。如果为True,则在训练时就输入度量后果。
  • ndcg_at或者ndcg_eval_at或者eval_at:一个整数列表,指定了NDCG评估点的地位。默认为1、2、3、4、5。

2.2 参数影响与调参倡议

以下为总结的外围参数对模型的影响,及与之对应的调参倡议。

(1) 对树成长管制

  • num_leaves:叶节点的数目。它是管制树模型复杂度的主要参数。

    • 如果是level-wise,则该参数为$2^{depth}$,其中depth为树的深度。然而当叶子数量雷同时,leaf-wise的树要远远深过level-wise树,非常容易导致过拟合。因而应该让num_leaves小于$2^{depth}$。在leaf-wise树中,并不存在depth的概念。因为不存在一个从leaves到depth的正当映射。
  • min_data_in_leaf:每个叶节点的起码样本数量。

    • 它是解决leaf-wise树的过拟合的重要参数。将它设为较大的值,能够防止生成一个过深的树。然而也可能导致欠拟合。
  • max_depth:树的最大深度。该参数能够显式的限度树的深度。

(2) 更快的训练速度

  • 通过设置bagging_fractionbagging_freq参数来应用bagging办法。
  • 通过设置feature_fraction参数来应用特色的子抽样。
  • 应用较小的max_bin
  • 应用save_binary在将来的学习过程对数据加载进行减速。

(3) 更好的模型成果

  • 应用较大的max_bin(学习速度可能变慢)。
  • 应用较小的learning_rate和较大的num_iterations
  • 应用较大的num_leaves(可能导致过拟合)。
  • 应用更大的训练数据。
  • 尝试dart

(4) 缓解过拟合问题

  • 应用较小的max_bin
  • 应用较小的num_leaves
  • 应用min_data_in_leafmin_sum_hessian_in_leaf
  • 通过设置bagging_fractionbagging_freq来应用bagging
  • 通过设置feature_fraction来应用特色子抽样。
  • 应用更大的训练数据。
  • 应用lambda_l1lambda_l2min_gain_to_split来应用正则。
  • 尝试max_depth来防止生成过深的树。

3.LightGBM内置建模形式

3.1 内置建模形式

LightGBM内置了建模形式,有如下的数据格式与外围训练方法:

  • 基于lightgbm.Dataset格局的数据。
  • 基于lightgbm.train接口训练。

上面是官网的一个简略示例,演示了读取libsvm格局数据(成Dataset格局)并指定参数建模的过程。

# coding: utf-8import jsonimport lightgbm as lgbimport pandas as pdfrom sklearn.metrics import mean_squared_error# 加载数据汇合print('加载数据...')df_train = pd.read_csv('./data/regression.train.txt', header=None, sep='\t')df_test = pd.read_csv('./data/regression.test.txt', header=None, sep='\t')# 设定训练集和测试集y_train = df_train[0].valuesy_test = df_test[0].valuesX_train = df_train.drop(0, axis=1).valuesX_test = df_test.drop(0, axis=1).values# 构建lgb中的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,    'verbose': 0}print('开始训练...')# 训练gbm = lgb.train(params,                lgb_train,                num_boost_round=20,                valid_sets=lgb_eval,                early_stopping_rounds=5)# 保留模型print('保留模型...')# 保留模型到文件中gbm.save_model('model.txt')print('开始预测...')# 预测y_pred = gbm.predict(X_test, num_iteration=gbm.best_iteration)# 评估print('预估后果的rmse为:')print(mean_squared_error(y_test, y_pred) ** 0.5)

加载数据...开始训练...[1]  valid_0's l2: 0.24288   valid_0's auc: 0.764496Training until validation scores don't improve for 5 rounds.[2]  valid_0's l2: 0.239307  valid_0's auc: 0.766173[3]  valid_0's l2: 0.235559  valid_0's auc: 0.785547[4]  valid_0's l2: 0.230771  valid_0's auc: 0.797786[5]  valid_0's l2: 0.226297  valid_0's auc: 0.805155[6]  valid_0's l2: 0.223692  valid_0's auc: 0.800979[7]  valid_0's l2: 0.220941  valid_0's auc: 0.806566[8]  valid_0's l2: 0.217982  valid_0's auc: 0.808566[9]  valid_0's l2: 0.215351  valid_0's auc: 0.809041[10] valid_0's l2: 0.213064  valid_0's auc: 0.805953[11] valid_0's l2: 0.211053  valid_0's auc: 0.804631[12] valid_0's l2: 0.209336  valid_0's auc: 0.802922[13] valid_0's l2: 0.207492  valid_0's auc: 0.802011[14] valid_0's l2: 0.206016  valid_0's auc: 0.80193Early stopping, best iteration is:[9]  valid_0's l2: 0.215351  valid_0's auc: 0.809041保留模型...开始预测...预估后果的rmse为:0.4640593794679212

3.2 设置样本权重

LightGBM的建模非常灵活,它能够反对咱们对于每个样本设置不同的权重学习,设置的形式也非常简单,咱们须要提供给模型一组权重数组数据,长度和样本数统一。

如下是一个典型的例子,其中binary.trainbinary.test读取后加载为lightgbm.Dataset格局的输出,而在lightgbm.Dataset的构建参数中能够设置样本权重(这个例子中是numpy array的状态)。再基于lightgbm.train接口应用内置建模形式训练。

# coding: utf-8import jsonimport lightgbm as lgbimport pandas as pdimport numpy as npfrom sklearn.metrics import mean_squared_errorimport warningswarnings.filterwarnings("ignore")# 加载数据集print('加载数据...')df_train = pd.read_csv('./data/binary.train', header=None, sep='\t')df_test = pd.read_csv('./data/binary.test', header=None, sep='\t')W_train = pd.read_csv('./data/binary.train.weight', header=None)[0]W_test = pd.read_csv('./data/binary.test.weight', header=None)[0]y_train = df_train[0].valuesy_test = df_test[0].valuesX_train = df_train.drop(0, axis=1).valuesX_test = df_test.drop(0, axis=1).valuesnum_train, num_feature = X_train.shape# 加载数据的同时加载权重lgb_train = lgb.Dataset(X_train, y_train,                        weight=W_train, free_raw_data=False)lgb_eval = lgb.Dataset(X_test, y_test, reference=lgb_train,                       weight=W_test, free_raw_data=False)# 设定参数params = {    'boosting_type': 'gbdt',    'objective': 'binary',    'metric': 'binary_logloss',    'num_leaves': 31,    'learning_rate': 0.05,    'feature_fraction': 0.9,    'bagging_fraction': 0.8,    'bagging_freq': 5,    'verbose': 0}# 产出特色名称feature_name = ['feature_' + str(col) for col in range(num_feature)]print('开始训练...')gbm = lgb.train(params,                lgb_train,                num_boost_round=10,                valid_sets=lgb_train,  # 评估训练集                feature_name=feature_name,                categorical_feature=[21])
加载数据...开始训练...[1]  training's binary_logloss: 0.68205[2]  training's binary_logloss: 0.673618[3]  training's binary_logloss: 0.665891[4]  training's binary_logloss: 0.656874[5]  training's binary_logloss: 0.648523[6]  training's binary_logloss: 0.641874[7]  training's binary_logloss: 0.636029[8]  training's binary_logloss: 0.629427[9]  training's binary_logloss: 0.623354[10] training's binary_logloss: 0.617593

3.3 模型存储与加载

上述建模过程失去的模型对象,能够通过save_model成员函数进行保留。保留好的模型能够通过lgb.Booster加载回内存,并对测试集进行预测。

具体示例代码如下:

# 查看特色名称print('实现10轮训练...')print('第7个特色为:')print(repr(lgb_train.feature_name[6]))# 存储模型gbm.save_model('./model/lgb_model.txt')# 特色名称print('特色名称:')print(gbm.feature_name())# 特色重要度print('特色重要度:')print(list(gbm.feature_importance()))# 加载模型print('加载模型用于预测')bst = lgb.Booster(model_file='./model/lgb_model.txt')# 预测y_pred = bst.predict(X_test)# 在测试集评估成果print('在测试集上的rmse为:')print(mean_squared_error(y_test, y_pred) ** 0.5)

实现10轮训练...第7个特色为:'feature_6'特色名称:['feature_0', 'feature_1', 'feature_2', 'feature_3', 'feature_4', 'feature_5', 'feature_6', 'feature_7', 'feature_8', 'feature_9', 'feature_10', 'feature_11', 'feature_12', 'feature_13', 'feature_14', 'feature_15', 'feature_16', 'feature_17', 'feature_18', 'feature_19', 'feature_20', 'feature_21', 'feature_22', 'feature_23', 'feature_24', 'feature_25', 'feature_26', 'feature_27']特色重要度:[8, 5, 1, 19, 7, 33, 2, 0, 2, 10, 5, 2, 0, 9, 3, 3, 0, 2, 2, 5, 1, 0, 36, 3, 33, 45, 29, 35]加载模型用于预测在测试集上的rmse为:0.4629245607636925

3.4 持续训练

LightGBM为boosting模型,每一轮训练会减少新的基学习器,LightGBM还反对基于现有模型和参数持续训练,无需每次从头训练。

如下是典型的示例,咱们加载曾经训练10轮(即10颗树集成)的lgb模型,在此基础上持续训练(在参数层面做了一些扭转,调整了学习率,减少了一些bagging等缓解过拟合的解决办法)

# 持续训练# 从./model/model.txt中加载模型初始化gbm = lgb.train(params,                lgb_train,                num_boost_round=10,                init_model='./model/lgb_model.txt',                valid_sets=lgb_eval)print('以旧模型为初始化,实现第 10-20 轮训练...')# 在训练的过程中调整超参数# 比方这里调整的是学习率gbm = lgb.train(params,                lgb_train,                num_boost_round=10,                init_model=gbm,                learning_rates=lambda iter: 0.05 * (0.99 ** iter),                valid_sets=lgb_eval)print('逐渐调整学习率实现第 20-30 轮训练...')# 调整其余超参数gbm = lgb.train(params,                lgb_train,                num_boost_round=10,                init_model=gbm,                valid_sets=lgb_eval,                callbacks=[lgb.reset_parameter(bagging_fraction=[0.7] * 5 + [0.6] * 5)])print('逐渐调整bagging比率实现第 30-40 轮训练...')

[11] valid_0's binary_logloss: 0.616177[12] valid_0's binary_logloss: 0.611792[13] valid_0's binary_logloss: 0.607043[14] valid_0's binary_logloss: 0.602314[15] valid_0's binary_logloss: 0.598433[16] valid_0's binary_logloss: 0.595238[17] valid_0's binary_logloss: 0.592047[18] valid_0's binary_logloss: 0.588673[19] valid_0's binary_logloss: 0.586084[20] valid_0's binary_logloss: 0.584033以旧模型为初始化,实现第 10-20 轮训练...[21] valid_0's binary_logloss: 0.616177[22] valid_0's binary_logloss: 0.611834[23] valid_0's binary_logloss: 0.607177[24] valid_0's binary_logloss: 0.602577[25] valid_0's binary_logloss: 0.59831[26] valid_0's binary_logloss: 0.595259[27] valid_0's binary_logloss: 0.592201[28] valid_0's binary_logloss: 0.589017[29] valid_0's binary_logloss: 0.586597[30] valid_0's binary_logloss: 0.584454逐渐调整学习率实现第 20-30 轮训练...[31] valid_0's binary_logloss: 0.616053[32] valid_0's binary_logloss: 0.612291[33] valid_0's binary_logloss: 0.60856[34] valid_0's binary_logloss: 0.605387[35] valid_0's binary_logloss: 0.601744[36] valid_0's binary_logloss: 0.598556[37] valid_0's binary_logloss: 0.595585[38] valid_0's binary_logloss: 0.593228[39] valid_0's binary_logloss: 0.59018[40] valid_0's binary_logloss: 0.588391逐渐调整bagging比率实现第 30-40 轮训练...

3.5 自定义损失函数

LightGBM反对在训练过程中,自定义损失函数和评估准则,其中损失函数的定义须要返回损失函数一阶和二阶导数的计算方法,评估准则局部须要对数据的label和预估值进行计算。其中损失函数用于训练过程中的树结构学习,而评估准则很多时候是用在验证集上进行成果评估。

# 自定义损失函数须要提供损失函数的一阶和二阶导数模式def loglikelood(preds, train_data):    labels = train_data.get_label()    preds = 1. / (1. + np.exp(-preds))    grad = preds - labels    hess = preds * (1. - preds)    return grad, hess# 自定义评估函数def binary_error(preds, train_data):    labels = train_data.get_label()    return 'error', np.mean(labels != (preds > 0.5)), Falsegbm = lgb.train(params,                lgb_train,                num_boost_round=10,                init_model=gbm,                fobj=loglikelood,                feval=binary_error,                valid_sets=lgb_eval)print('用自定义的损失函数与评估规范实现第40-50轮...')

[41] valid_0's binary_logloss: 0.614429  valid_0's error: 0.268[42] valid_0's binary_logloss: 0.610689  valid_0's error: 0.26[43] valid_0's binary_logloss: 0.606267  valid_0's error: 0.264[44] valid_0's binary_logloss: 0.601949  valid_0's error: 0.258[45] valid_0's binary_logloss: 0.597271  valid_0's error: 0.266[46] valid_0's binary_logloss: 0.593971  valid_0's error: 0.276[47] valid_0's binary_logloss: 0.591427  valid_0's error: 0.278[48] valid_0's binary_logloss: 0.588301  valid_0's error: 0.284[49] valid_0's binary_logloss: 0.586562  valid_0's error: 0.288[50] valid_0's binary_logloss: 0.584056  valid_0's error: 0.288用自定义的损失函数与评估规范实现第40-50轮...

4.LightGBM预估器状态接口

4.1 SKLearn状态预估器接口

和XGBoost一样,LightGBM也反对用SKLearn中对立的预估器状态接口进行建模,如下为典型的参考案例,对于读取为Dataframe格局的训练集和测试集,能够间接应用LightGBM初始化LGBMRegressor进行fit拟合训练。应用办法与接口,和SKLearn中其余预估器统一。

# coding: utf-8import lightgbm as lgbimport pandas as pdfrom sklearn.metrics import mean_squared_errorfrom sklearn.model_selection import GridSearchCV# 加载数据print('加载数据...')df_train = pd.read_csv('./data/regression.train.txt', header=None, sep='\t')df_test = pd.read_csv('./data/regression.test.txt', header=None, sep='\t')# 取出特色和标签y_train = df_train[0].valuesy_test = df_test[0].valuesX_train = df_train.drop(0, axis=1).valuesX_test = df_test.drop(0, axis=1).valuesprint('开始训练...')# 初始化LGBMRegressorgbm = lgb.LGBMRegressor(objective='regression',                        num_leaves=31,                        learning_rate=0.05,                        n_estimators=20)# 应用fit函数拟合gbm.fit(X_train, y_train,        eval_set=[(X_test, y_test)],        eval_metric='l1',        early_stopping_rounds=5)# 预测print('开始预测...')y_pred = gbm.predict(X_test, num_iteration=gbm.best_iteration_)# 评估预测后果print('预测后果的rmse是:')print(mean_squared_error(y_test, y_pred) ** 0.5)

加载数据...开始训练...[1]  valid_0's l1: 0.491735Training until validation scores don't improve for 5 rounds.[2]  valid_0's l1: 0.486563[3]  valid_0's l1: 0.481489[4]  valid_0's l1: 0.476848[5]  valid_0's l1: 0.47305[6]  valid_0's l1: 0.469049[7]  valid_0's l1: 0.465556[8]  valid_0's l1: 0.462208[9]  valid_0's l1: 0.458676[10] valid_0's l1: 0.454998[11] valid_0's l1: 0.452047[12] valid_0's l1: 0.449158[13] valid_0's l1: 0.44608[14] valid_0's l1: 0.443554[15] valid_0's l1: 0.440643[16] valid_0's l1: 0.437687[17] valid_0's l1: 0.435454[18] valid_0's l1: 0.433288[19] valid_0's l1: 0.431297[20] valid_0's l1: 0.428946Did not meet early stopping. Best iteration is:[20] valid_0's l1: 0.428946开始预测...预测后果的rmse是:0.4441153344254208

4.2 网格搜寻调参

下面提到LightGBM的预估器接口,整体应用办法和SKLearn中其余预估器统一,所以咱们也能够应用SKLearn中的超参数调优办法来进行模型调优。

如下是一个典型的网格搜寻交法调优超参数的代码示例,咱们会给出候选参数列表字典,通过GridSearchCV进行穿插验证试验评估,选出LightGBM在候选参数中最优的超参数。

# 配合scikit-learn的网格搜寻穿插验证抉择最优超参数estimator = lgb.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('用网格搜寻找到的最优超参数为:')print(gbm.best_params_)

用网格搜寻找到的最优超参数为:{'learning_rate': 0.1, 'n_estimators': 40}

4.3 绘图解释

LightGBM反对对模型训练进行可视化出现与解释,包含对于训练过程中的损失函数取值与评估准则后果的可视化、训练实现后特色重要度的排序与可视化、基学习器(比方决策树)的可视化。

以下为参考代码:

# coding: utf-8import lightgbm as lgbimport pandas as pdtry:    import matplotlib.pyplot as pltexcept ImportError:    raise ImportError('You need to install matplotlib for plotting.')# 加载数据集print('加载数据...')df_train = pd.read_csv('./data/regression.train.txt', header=None, sep='\t')df_test = pd.read_csv('./data/regression.test.txt', header=None, sep='\t')# 取出特色和标签y_train = df_train[0].valuesy_test = df_test[0].valuesX_train = df_train.drop(0, axis=1).valuesX_test = df_test.drop(0, axis=1).values# 构建lgb中的Dataset数据格式lgb_train = lgb.Dataset(X_train, y_train)lgb_test = lgb.Dataset(X_test, y_test, reference=lgb_train)# 设定参数params = {    'num_leaves': 5,    'metric': ('l1', 'l2'),    'verbose': 0}evals_result = {}  # to record eval results for plottingprint('开始训练...')# 训练gbm = lgb.train(params,                lgb_train,                num_boost_round=100,                valid_sets=[lgb_train, lgb_test],                feature_name=['f' + str(i + 1) for i in range(28)],                categorical_feature=[21],                evals_result=evals_result,                verbose_eval=10)print('在训练过程中绘图...')ax = lgb.plot_metric(evals_result, metric='l1')plt.show()print('画出特色重要度...')ax = lgb.plot_importance(gbm, max_num_features=10)plt.show()print('画出第84颗树...')ax = lgb.plot_tree(gbm, tree_index=83, figsize=(20, 8), show_info=['split_gain'])plt.show()#print('用graphviz画出第84颗树...')#graph = lgb.create_tree_digraph(gbm, tree_index=83, name='Tree84')#graph.render(view=True)

加载数据...开始训练...[10] training's l2: 0.217995 training's l1: 0.457448 valid_1's l2: 0.21641   valid_1's l1: 0.456464[20] training's l2: 0.205099 training's l1: 0.436869 valid_1's l2: 0.201616  valid_1's l1: 0.434057[30] training's l2: 0.197421 training's l1: 0.421302 valid_1's l2: 0.192514  valid_1's l1: 0.417019[40] training's l2: 0.192856 training's l1: 0.411107 valid_1's l2: 0.187258  valid_1's l1: 0.406303[50] training's l2: 0.189593 training's l1: 0.403695 valid_1's l2: 0.183688  valid_1's l1: 0.398997[60] training's l2: 0.187043 training's l1: 0.398704 valid_1's l2: 0.181009  valid_1's l1: 0.393977[70] training's l2: 0.184982 training's l1: 0.394876 valid_1's l2: 0.178803  valid_1's l1: 0.389805[80] training's l2: 0.1828   training's l1: 0.391147 valid_1's l2: 0.176799  valid_1's l1: 0.386476[90] training's l2: 0.180817 training's l1: 0.388101 valid_1's l2: 0.175775  valid_1's l1: 0.384404[100]   training's l2: 0.179171 training's l1: 0.385174 valid_1's l2: 0.175321  valid_1's l1: 0.382929

参考资料

  • 图解机器学习算法 | 从入门到精通系列
  • 图解机器学习 | LightGBM模型详解

ShowMeAI系列教程举荐

  • 图解Python编程:从入门到精通系列教程
  • 图解数据分析:从入门到精通系列教程
  • 图解AI数学根底:从入门到精通系列教程
  • 图解大数据技术:从入门到精通系列教程
  • 图解机器学习算法:从入门到精通系列教程
  • 机器学习实战:手把手教你玩转机器学习系列

相干文章举荐

  • Python机器学习算法利用实际
  • SKLearn入门与简略利用案例
  • SKLearn最全利用指南
  • XGBoost建模利用详解
  • LightGBM建模利用详解
  • Python机器学习综合我的项目-电商销量预估
  • Python机器学习综合我的项目-电商销量预估<进阶计划>
  • 机器学习特色工程最全解读
  • 自动化特色工程工具Featuretools利用
  • AutoML自动化机器学习建模