![](https://img.laitimes.com/img/_0nNw4CM6IyYiwiM6ICdiwiIn5GcuUDO0ATN2QDMy0iNzgTMxgzMzITMyMDMyIDMy0CO1QzNzYjMvw1MwIjMwIzLchTN0czM2IzLcd2bsJ2Lc12bj5ycn9Gbi52YuIjMwIzZtl2Lc9CX6MHc0RHaiojIsJye.png)
本篇詳細講解LightGBM的工程應用方法。LightGBM是微軟開發的boosting內建模型,和XGBoost一樣是對GBDT的優化和高效實作,但它很多方面比XGBoost有着更為優秀的表現。
作者:韓信子@ShowMeAI
教程位址:https://www.showmeai.tech/tutorials/41
本文位址:https://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
-
:表示是模型轉換任務。将模型檔案轉換成if-else格式。convert_model
-
-
或者application
或者objective
:一個字元串,表示問題類型。可以為:app
-
或regression
或regression_l2
或mean_squared_error
或mse
或l2_root
或root_mean_squred_error
:表示回歸任務,但是使用L2損失函數。預設為rmse
。regression
-
或者regression_l1
或者mae
:表示回歸任務,但是使用L1損失函數。mean_absolute_error
-
:表示回歸任務,但是使用huber損失函數。huber
-
:表示回歸任務,但是使用fair損失函數。fair
-
:表示Poisson回歸任務。poisson
-
:表示quantile回歸任務。quantile
-
:表示quantile回歸任務,但是使用了L2損失函數。quantile_l2
-
或者mape
:表示回歸任務,但是使用MAPE損失函數mean_absolute_precentage_error
-
:表示gamma回歸任務。gamma
-
:表示tweedie回歸任務。tweedie
-
:表示二分類任務,使用對數損失函數作為目标函數。binary
-
:表示多分類任務,使用softmax函數作為目标函數。必須設定multiclass
參數num_class
-
或者multiclassova
或者multiclass_ova
或者ova
:表示多分類任務,使用ovr
的二分類目标函數。必須設定one-vs-all
參數。num_class
-
或者xentropy
:目标函數為交叉熵(同時具有可選擇的線性權重)。要求标簽是[0,1]之間的數值。cross_entropy
-
或者xentlambda
:替代了參數化的cross_entropy_lambda
。要求标簽是[0,1]之間的數值。cross_entropy
-
:表示排序任務。在lambdarank
任務中,标簽應該為整數類型,數值越大表示相關性越高。lambdarank
參數可以用于設定整數标簽的增益(權重)。label_gain
-
-
或者boosting
或者boost
:一個字元串,給出了基學習器模型算法。可以為:boosting_type
-
:表示傳統的梯度提升決策樹。預設值為gbdt
。gbdt
-
:表示随機森林。rf
-
:表示帶dropout的gbdt。dart
-
:表示Gradient-based One-Side Sampling 的gbdt。goss
-
-
或者data
或者train
:一個字元串,給出了訓練資料所在的檔案的檔案名。預設為空字元串。LightGBM将使用它來訓練模型。train_data
-
或者valid
或者test
或者valid_data
:一個字元串,表示驗證集所在的檔案的檔案名。預設為空字元串。LightGBM将輸出該資料集的度量。如果有多個驗證集,則用逗号分隔。test_data
-
或者num_iterations
或者num_iteration
或者num_tree
或者num_trees
或者num_round
或者num_rounds
一個整數,給出了num_boost_round
的疊代次數。預設為100。boosting
- 對于Python/R包,該參數是被忽略的。對于Python,使用
的輸入參數train()/cv()
來代替。num_boost_round
- 在内部,LightGBM對于multiclass問題設定了
棵樹。num_class*num_iterations
- 對于Python/R包,該參數是被忽略的。對于Python,使用
-
或者learning_rate
:個浮點數,給出了學習率。預設為1。在dart中,它還會影響dropped trees的歸一化權重。shrinkage_rate
-
或者num_leaves
:一個整數,給出了一棵樹上的葉子數。預設為31。num_leaf
-
或者tree_learner
:一個字元串,給出了tree learner,主要用于并行學習。預設為tree
。可以為:serial
-
:單台機器的tree learnerserial
-
:特征并行的tree learnerfeature
-
:資料并行的tree learnerdata
-
:投票并行的tree learnervoting
-
-
或者num_threads
或者num_thread
:一個整數,給出了LightGBM的線程數。預設為nthread
。OpenMP_default
- 為了更快的速度,應該将它設定為真正的CPU核心數,而不是線程的數量(大多數CPU使用超線程來使每個CPU核心生成2個線程)。
- 當資料集較小的時候,不要将它設定的過大。
- 對于并行學習,不應該使用全部的CPU核心,因為這會使得網絡性能不佳。
-
:一個字元串,指定計算裝置。預設為device
。可以為cpu
、gpu
。cpu
- 建議使用較小的
來獲得更快的計算速度。max_bin
- 為了加快學習速度,GPU預設使用32位浮點數來求和。你可以設定
來啟動64位浮點數,但是它會使得訓練速度降低。gpu_use_dp=True
- 建議使用較小的
(2) 學習控制參數
-
:一個整數,限制了樹模型的最大深度,預設值為-1。如果小于0,則表示沒有限制。max_depth
-
或者min_data_in_leaf
或者min_data_per_leaf
或者min_data
:一個整數,表示一個葉子節點上包含的最少樣本數量。預設值為20。min_child_samples
-
或者min_sum_hessian_in_leaf
或者min_sum_hessian_per_leaf
或者min_sum_hessian
或者min_hessian
:一個浮點數,表示一個葉子節點上的最小hessian之和。(也就是葉節點樣本權重之和的最小值)預設為1e-3。min_child_weight
-
或者feature_fraction
或者sub_feature
:一個浮點數,取值範圍為[0.0,1.0],預設值為0。如果小于1.0,則LightGBM會在每次疊代中随機選擇部分特征。如0.8表示:在每棵樹訓練之前選擇80%的特征來訓練。colsample_bytree
-
:一個整數,表示feature_fraction_seed
的随機數種子,預設為2。feature_fraction
-
或者bagging_fraction
或者sub_row
:一個浮點數,取值範圍為[0.0,1.0],預設值為0。如果小于1.0,則LightGBM會在每次疊代中随機選擇部分樣本來訓練(非重複采樣)。如0.8表示:在每棵樹訓練之前選擇80%的樣本(非重複采樣)來訓練。subsample
-
或者bagging_freq
:一個整數,表示每subsample_freq
次執行bagging。如果該參數為0,表示禁用bagging。bagging_freq
-
或者bagging_seed
:一個整數,表示bagging的随機數種子,預設為3。bagging_fraction_seed
-
或者early_stopping_round
或者early_stopping_rounds
:一個整數,預設為0。如果一個驗證集的度量在early_stopping
循環中沒有提升,則停止訓練。如果為0則表示不開啟早停。early_stopping_round
-
或者lambda_l1
:一個浮點數,表示L1正則化系數。預設為0。reg_alpha
-
或者lambda_l2
:一個浮點數,表示L2正則化系數。預設為0。reg_lambda
-
或者min_split_gain
:一個浮點數,表示執行切分的最小增益,預設為0。min_gain_to_split
-
:一個浮點數,取值範圍為[0.0,1.0],表示dropout的比例,預設為1。該參數僅在dart中使用。drop_rate
-
:一個浮點數,取值範圍為[0.0,1.0],表示跳過dropout的機率,預設為5。該參數僅在dart中使用。skip_drop
-
:一個整數,表示一次疊代中删除樹的最大數量,預設為50。如果小于等于0,則表示沒有限制。該參數僅在dart中使用。max_drop
-
:一個布爾值,表示是否想要均勻的删除樹,預設值為False。該參數僅在dart中使用。uniform_drop
-
:一個布爾值,表示是否使用xgboost dart模式,預設值為False。該參數僅在dart中使用。xgboost_dart_mode
-
:一個整數,表示dropout的随機數種子,預設值為4。該參數僅在dart中使用。drop_seed
-
:一個浮點數,取值範圍為[0.0,1.0],表示在goss中,大梯度資料的保留比例,預設值為2。該參數僅在goss中使用。top_rate
-
:一個浮點數,取值範圍為[0.0,1.0],表示在goss中,小梯度資料的保留比例,預設值為1。該參數僅在goss中使用。other_rate
-
:一個整數,表示每個分類組的最小資料量,預設值為100。用于排序任務min_data_per_group
-
:一個整數,表示category特征的取值集合的最大大小。預設為32。max_cat_threshold
-
:一個浮點數,用于category特征的機率平滑。預設值為10。它可以降低噪聲在category特征中的影響,尤其是對于資料很少的類。cat_smooth
-
:一個浮點數,用于category切分中的L2正則化系數。預設為10。cat_l2
-
或者top_k
:一個整數,用于投票并行中。預設為20。将它設定為更大的值可以獲得更精确的結果,但是會降低訓練速度。topk
(3) IO參數
-
:一個整數,表示最大的桶的數量。預設值為255。LightGBM會根據它來自動壓縮記憶體。如max_bin
時,則LightGBM将使用uint8來表示特征的每一個值。max_bin=255
-
:一個整數,表示每個桶的最小樣本數。預設為3。該方法可以避免出現一個桶隻有一個樣本的情況。min_data_in_bin
-
:一個整數,表示并行學習資料分隔中的随機數種子。預設為1它不包括特征并行。data_random_seed
-
或者output_model
或者model_output
:一個字元串,表示訓練中輸出的模型被儲存的檔案的檔案名。預設txt。model_out
-
或者input_model
或者model_input
:一個字元串,表示輸入模型的檔案的檔案名。預設空字元串。對于prediction任務,該模型将用于預測資料,對于train任務,訓練将從該模型繼續model_in
-
或者output_result
或者predict_result
:一個字元串,給出了prediction結果存放的檔案名。預設為txt。prediction_result
-
或者pre_partition
:一個布爾值,訓示資料是否已經被劃分。預設值為False。如果為true,則不同的機器使用不同的partition來訓練。它用于并行學習(不包括特征并行)is_pre_partition
-
或者is_sparse
或者is_enable_sparse
:一個布爾值,表示是否開啟稀疏優化,預設為True。如果為True則啟用稀疏優化。enable_sparse
-
或者two_round
或者two_round_loading
:一個布爾值,訓示是否啟動兩次加載。預設值為False,表示隻需要進行一次加載。預設情況下,LightGBM會将資料檔案映射到記憶體,然後從記憶體加載特征,這将提供更快的資料加載速度。但是當資料檔案很大時,記憶體可能會被耗盡。如果資料檔案太大,則将它設定為Trueuse_two_round_loading
-
或者save_binary
或者is_save_binary
:一個布爾值,表示是否将資料集(包括驗證集)儲存到二進制檔案中。預設值為False。如果為True,則可以加快資料的加載速度。is_save_binary_file
-
或者verbosity
:一個整數,表示是否輸出中間資訊。預設值為1。如果小于0,則僅僅輸出critical資訊;如果等于0,則還會輸出error,warning資訊;如果大于0,則還會輸出info資訊。verbose
-
或者header
:一個布爾值,表示輸入資料是否有頭部。預設為False。has_header
-
或者label
:一個字元串,表示标簽列。預設為空字元串。你也可以指定一個整數,如label=0表示第0列是标簽列。你也可以為列名添加字首,如label_column
。label=prefix:label_name
-
或者weight
:一個字元串,表示樣本權重列。預設為空字元串。你也可以指定一個整數,如weight=0表示第0列是權重列。注意:它是剔除了标簽列之後的索引。假如标簽列為0,權重列為1,則這裡weight=0。你也可以為列名添加字首,如weight_column
。weight=prefix:weight_name
-
或者query
或者query_column
或者gourp
:一個字元串,query/groupID列。預設為空字元串。你也可以指定一個整數,如query=0表示第0列是query列。注意:它是剔除了标簽列之後的索引。假如标簽列為0,query列為1,則這裡query=0。你也可以為列名添加字首,如group_column
。query=prefix:query_name
-
或者ignore_column
或者ignore_feature
:一個字元串,表示訓練中忽略的一些列,預設為空字元串。可以用數字做索引,如blacklist
表示第0,1,2列将被忽略。注意:它是剔除了标簽列之後的索引。ignore_column=0,1,2
- 你也可以為列名添加字首,如
。ignore_column=prefix:ign_name1,ign_name2
-
或者categorical_feature
或者categorical_column
或者cat_feature
:一個字元串,指定category特征的列。預設為空字元串。可以用數字做索引,如cat_column
表示第0,1,2列将作為category特征。注意:它是剔除了标簽列之後的索引。你也可以為列名添加字首,如categorical_feature=0,1,2
在categorycal特征中,負的取值被視作缺失值。categorical_feature=prefix:cat_name1,cat_name2
-
或者predict_raw_score
或者raw_score
:一個布爾值,表示是否預測原始得分。預設為False。如果為True則僅預測原始得分。該參數隻用于prediction任務。is_predict_raw_score
-
或者predict_leaf_index
或者leaf_index
:一個布爾值,表示是否預測每個樣本在每棵樹上的葉節點編号。預設為False。在預測時,每個樣本都會被配置設定到每棵樹的某個葉子節點上。該參數就是要輸出這些葉子節點的編号。該參數隻用于prediction任務。is_predict_leaf_index
-
或者predict_contrib
或者contrib
:一個布爾值,表示是否輸出每個特征對于每個樣本的預測的貢獻。預設為False。輸出的結果形狀為[nsamples,nfeatures+1],之是以+1是考慮到bais的貢獻。所有的貢獻加起來就是該樣本的預測結果。該參數隻用于prediction任務。is_predict_contrib
-
或者bin_construct_sample_cnt
:一個整數,表示用來建構直方圖的樣本的數量。預設為200000。如果資料非常稀疏,則可以設定為一個更大的值,如果設定更大的值,則會提供更好的訓練效果,但是會增加資料加載時間。subsample_for_bin
-
:一個整數,表示在預測中使用多少棵子樹。預設為-1。小于等于0表示使用模型的所有子樹。該參數隻用于prediction任務。num_iteration_predict
-
:一個布爾值,表示是否使用早停來加速預測。預設為False。如果為True,則可能影響精度。pred_early_stop
-
:一個整數,表示檢查早停的頻率。預設為10pred_early_stop_freq
-
:一個浮點數,表示早停的邊際門檻值。預設為0pred_early_stop_margin
-
:一個布爾值,表示是否使用缺失值功能。預設為True如果為False則禁用缺失值功能。use_missing
-
:一個布爾值,表示是否将所有的零(包括在libsvm/sparse矩陣中未顯示的值)都視為缺失值。預設為False。如果為False,則将nan視作缺失值。如果為True,則zero_as_missing
和零都将視作缺失值。np.nan
-
:一個字元串,表示訓練時的初始化分數檔案的路徑。預設為空字元串,表示train_data_file+”.init”(如果存在)init_score_file
-
:一個字元串,表示驗證時的初始化分數檔案的路徑。預設為空字元串,表示valid_data_file+”.init”(如果存在)。如果有多個(對應于多個驗證集),則可以用逗号valid_init_score_file
來分隔。,
(4) 目标參數
-
:一個浮點數,用sigmoid函數的參數,預設為0。它用于二分類任務和lambdarank任務。sigmoid
-
:一個浮點數,用于Huber損失函數和Quantileregression,預設值為0。它用于huber回歸任務和Quantile回歸任務。alpha
-
:一個浮點數,用于Fair損失函數,預設值為0。它用于fair回歸任務。fair_c
-
:一個浮點數,用于控制高斯函數的寬度,預設值為0。它用于regression_l1回歸任務和huber回歸任務。gaussian_eta
-
:一個浮點數,用于Poisson regression的參數,預設值為7。它用于poisson回歸任務。posson_max_delta_step
-
:一個浮點數,用于調整正樣本的權重,預設值為0它用于二分類任務。scale_pos_weight
-
:一個布爾值,訓示是否将初始得分調整為平均值(它可以使得收斂速度更快)。預設為True。它用于回歸任務。boost_from_average
-
或者is_unbalance
:一個布爾值,訓示訓練資料是否均衡的。預設為True。它用于二分類任務。unbalanced_set
-
:一個整數,訓示将在這個NDCG位置優化。預設為20。它用于lambdarank任務。max_position
-
:一個浮點數序列,給出了每個标簽的增益。預設值為0,1,3,7,15,….它用于lambdarank任務。label_gain
-
或者num_class
:一個整數,訓示了多分類任務中的類别數量。預設為1它用于多分類任務。num_classes
-
:一個布爾值,預設為False。如果為True,則拟合的結果為:\sqrt{label}。同時預測的結果被自動轉換為:{pred}^2。它用于回歸任務。reg_sqrt
(5) 度量參數
-
:一個字元串,指定了度量的名額,預設為:對于回歸問題,使用l2;對于二分類問題,使用metric
;對于lambdarank問題,使用ndcg。如果有多個度量名額,則用逗号binary_logloss
分隔。,
-
或者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
:表示MAPE損失。mean_absolute_percentage_error
-
:表示huber損失。huber
-
:表示fair損失。fair
-
:表示poisson回歸的負對數似然。poisson
-
:表示gamma回歸的負對數似然。gamma
-
:表示gamma回歸的殘差的方差。gamma_deviance
-
:表示Tweedie回歸的負對數似然。tweedie
-
:表示NDCG。ndcg
-
或者map
:表示平均的精度。mean_average_precision
-
:表示AUC。auc
-
或者binary_logloss
:表示二類分類中的對數損失函數。binary
-
:表示二類分類中的分類錯誤率。binary_error
-
或者multi_logloss
或者multiclass
或者‘multiclassovasoftmax
multiclass_ova或者
ova,或者
ovr`:表示多類分類中的對數損失函數。或者
-
:表示多分類中的分類錯誤率。multi_error
-
或者xentropy
:表示交叉熵。cross_entropy
-
或者xentlambda
:表示intensity權重的交叉熵。cross_entropy_lambda
-
或者kldiv
:表示KL散度。kullback_leibler
-
-
或者metric_freq
:一個正式,表示每隔多少次輸出一次度量結果。預設為1。output_freq
-
或者train_metric
或者training_metric
:一個布爾值,預設為False。如果為True,則在訓練時就輸出度量結果。is_training_metric
-
或者ndcg_at
或者ndcg_eval_at
:一個整數清單,指定了NDCG評估點的位置。預設為1、2、3、4、5。eval_at
2.2 參數影響與調參建議
以下為總結的核心參數對模型的影響,及與之對應的調參建議。
(1) 對樹生長控制
-
:葉節點的數目。它是控制樹模型複雜度的主要參數。num_leaves
- 如果是
,則該參數為\(2^{depth}\),其中depth為樹的深度。但是當葉子數量相同時,leaf-wise的樹要遠遠深過level-wise樹,非常容易導緻過拟合。是以應該讓num_leaves小于\(2^{depth}\)。在leaf-wise樹中,并不存在depth的概念。因為不存在一個從leaves到depth的合理映射。level-wise
- 如果是
-
:每個葉節點的最少樣本數量。min_data_in_leaf
- 它是處理
樹的過拟合的重要參數。将它設為較大的值,可以避免生成一個過深的樹。但是也可能導緻欠拟合。leaf-wise
- 它是處理
-
:樹的最大深度。該參數可以顯式的限制樹的深度。max_depth
(2) 更快的訓練速度
- 通過設定
和bagging_fraction
參數來使用bagging方法。bagging_freq
- 通過設定
參數來使用特征的子抽樣。feature_fraction
- 使用較小的
。max_bin
- 使用
在未來的學習過程對資料加載進行加速。save_binary
(3) 更好的模型效果
- 使用較大的
(學習速度可能變慢)。max_bin
- 使用較小的
和較大的learning_rate
。num_iterations
- 使用較大的
(可能導緻過拟合)。num_leaves
- 使用更大的訓練資料。
- 嘗試
。dart
(4) 緩解過拟合問題
- 使用較小的
。max_bin
- 使用較小的
。num_leaves
- 使用
和min_data_in_leaf
。min_sum_hessian_in_leaf
- 通過設定
和bagging_fraction
來使用bagging_freq
。bagging
- 通過設定
來使用特征子抽樣。feature_fraction
- 使用更大的訓練資料。
- 使用
、lambda_l1
和lambda_l2
來使用正則。min_gain_to_split
- 嘗試
來避免生成過深的樹。max_depth
3.LightGBM内置模組化方式
3.1 内置模組化方式
LightGBM内置了模組化方式,有如下的資料格式與核心訓練方法:
- 基于
格式的資料。lightgbm.Dataset
- 基于
接口訓練。lightgbm.train
下面是官方的一個簡單示例,示範了讀取libsvm格式資料(成
Dataset
格式)并指定參數模組化的過程。
# coding: utf-8
import json
import lightgbm as lgb
import pandas as pd
from 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].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中的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.764496
Training 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.80193
Early stopping, best iteration is:
[9] valid_0's l2: 0.215351 valid_0's auc: 0.809041
儲存模型...
開始預測...
預估結果的rmse為:
0.4640593794679212
3.2 設定樣本權重
LightGBM的模組化非常靈活,它可以支援我們對于每個樣本設定不同的權重學習,設定的方式也非常簡單,我們需要提供給模型一組權重數組資料,長度和樣本數一緻。
如下是一個典型的例子,其中
binary.train
和
binary.test
讀取後加載為
lightgbm.Dataset
格式的輸入,而在
lightgbm.Dataset
的建構參數中可以設定樣本權重(這個例子中是numpy array的形态)。再基于
lightgbm.train
接口使用内置模組化方式訓練。
# coding: utf-8
import json
import lightgbm as lgb
import pandas as pd
import numpy as np
from sklearn.metrics import mean_squared_error
import warnings
warnings.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].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
num_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)), False
gbm = 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-8
import lightgbm as lgb
import pandas as pd
from sklearn.metrics import mean_squared_error
from 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].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
print('開始訓練...')
# 初始化LGBMRegressor
gbm = 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.491735
Training 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.428946
Did 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-8
import lightgbm as lgb
import pandas as pd
try:
import matplotlib.pyplot as plt
except 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].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中的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 plotting
print('開始訓練...')
# 訓練
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模型詳解
機器學習【算法】系列教程
- 圖解機器學習 | 機器學習基礎知識
- 圖解機器學習 | 模型評估方法與準則
- 圖解機器學習 | KNN算法及其應用
- 圖解機器學習 | 邏輯回歸算法詳解
- 圖解機器學習 | 樸素貝葉斯算法詳解
- 圖解機器學習 | 決策樹模型詳解
- 圖解機器學習 | 随機森林分類模型詳解
- 圖解機器學習 | 回歸樹模型詳解
- 圖解機器學習 | GBDT模型詳解
- 圖解機器學習 | XGBoost模型最全解析
- 圖解機器學習 | LightGBM模型詳解
- 圖解機器學習 | 支援向量機模型詳解
- 圖解機器學習 | 聚類算法詳解
- 圖解機器學習 | PCA降維算法詳解
機器學習【實戰】系列教程
- 機器學習實戰 | Python機器學習算法應用實踐
- 機器學習實戰 | SKLearn入門與簡單應用案例
- 機器學習實戰 | SKLearn最全應用指南
- 機器學習實戰 | XGBoost模組化應用詳解
- 機器學習實戰 | LightGBM模組化應用詳解
- 機器學習實戰 | Python機器學習綜合項目-電商銷量預估
- 機器學習實戰 | Python機器學習綜合項目-電商銷量預估<進階方案>
- 機器學習實戰 | 機器學習特征工程最全解讀
- 機器學習實戰 | 自動化特征工程工具Featuretools應用
- 機器學習實戰 | AutoML自動化機器學習模組化
ShowMeAI系列教程推薦
- 大廠技術實作方案系列
- 圖解Python程式設計:從入門到精通系列教程
- 圖解資料分析:從入門到精通系列教程
- 圖解AI數學基礎:從入門到精通系列教程
- 圖解大資料技術:從入門到精通系列教程
- 圖解機器學習算法:從入門到精通系列教程
- 機器學習實戰:手把手教你玩轉機器學習系列
- 深度學習教程:吳恩達專項課程 · 全套筆記解讀
- 自然語言處理教程:斯坦福CS224n課程 · 課程帶學與全套筆記解讀
- 深度學習與計算機視覺教程:斯坦福CS231n · 全套筆記解讀