免費(fèi)的制作網(wǎng)站網(wǎng)絡(luò)營(yíng)銷(xiāo)類(lèi)型
前言
????????我使用LightGBM有一段時(shí)間了,它一直是我處理大多數(shù)表格數(shù)據(jù)問(wèn)題的首選算法。它有很多強(qiáng)大的功能,如果你還沒(méi)有看過(guò)的話(huà),我建議你去了解一下。
????????但我一直對(duì)了解哪些參數(shù)對(duì)性能影響最大,以及如何調(diào)整LightGBM參數(shù)以發(fā)揮最大作用很感興趣。
????????我決定進(jìn)行一些研究,深入了解LightGBM的參數(shù),并分享我的經(jīng)驗(yàn)。
1.梯度增強(qiáng)方法
????????使用 LightGBM,您可以運(yùn)行不同類(lèi)型的梯度增強(qiáng)方法。 您有:GBDT、DART 和 GOSS,可以使用 boosting 參數(shù)指定。
????????在接下來(lái)的部分中,我將解釋并比較這些方法。
1.1?lgbm gbdt(梯度提升決策樹(shù))
????????該方法是本文首次提出的傳統(tǒng)梯度提升決策樹(shù),也是 XGBoost 和 pGBRT 等一些優(yōu)秀庫(kù)背后的算法。
????????如今,gbdt 因其準(zhǔn)確性、高效性和穩(wěn)定性而被廣泛使用。
????????它基于三個(gè)重要原則:
- 弱學(xué)習(xí)器(決策樹(shù))
- 梯度優(yōu)化
- 升壓技術(shù)
????????所以在gbdt方法中我們有很多決策樹(shù)(弱學(xué)習(xí)器)。 這些樹(shù)是按順序構(gòu)建的:
- 第一棵樹(shù)學(xué)習(xí)如何適應(yīng)目標(biāo)變量
- 第二棵樹(shù)學(xué)習(xí)如何適應(yīng)第一棵樹(shù)的預(yù)測(cè)和地面實(shí)況之間的殘差(差異)
- 第三棵樹(shù)學(xué)習(xí)如何擬合第二棵樹(shù)的殘差,依此類(lèi)推。
????????所有這些樹(shù)都是通過(guò)在整個(gè)系統(tǒng)中傳播誤差梯度來(lái)訓(xùn)練的。
????????gbdt 的主要缺點(diǎn)是在每個(gè)樹(shù)節(jié)點(diǎn)中找到最佳分割點(diǎn)是一項(xiàng)耗時(shí)且消耗內(nèi)存的操作,其他 boosting 方法試圖解決該問(wèn)題。
1.2?dart 梯度提升
????????在這篇出色的論文論文論文中,您可以了解有關(guān) DART 梯度提升的所有知識(shí),這是一種使用神經(jīng)網(wǎng)絡(luò)標(biāo)準(zhǔn) dropout 的方法,以改進(jìn)模型正則化并處理其他一些不太明顯的問(wèn)題。
????????也就是說(shuō),gbdt 存在過(guò)度專(zhuān)業(yè)化的問(wèn)題,這意味著在后續(xù)迭代中添加的樹(shù)往往只會(huì)影響少數(shù)實(shí)例的預(yù)測(cè),而對(duì)其余實(shí)例的貢獻(xiàn)可以忽略不計(jì)。 添加 dropout 使得后續(xù)迭代中的樹(shù)更難專(zhuān)門(mén)處理那些少數(shù)樣本,從而提高模型性能。
1.3?lgbm goss(基于梯度的一側(cè)采樣)
????????事實(shí)上,將該方法命名為lightgbm的最重要原因是使用了基于本文的Goss方法。 Goss 是更新且更輕的 GBDT 實(shí)現(xiàn)(因此是“輕”GBM)。
????????標(biāo)準(zhǔn) GBDT 很可靠,但在大型數(shù)據(jù)集上速度不夠快。 因此,戈斯提出了一種基于梯度的采樣方法,以避免搜索整個(gè)搜索空間。 我們知道,對(duì)于每個(gè)數(shù)據(jù)實(shí)例,當(dāng)梯度很小時(shí),意味著不用擔(dān)心數(shù)據(jù)經(jīng)過(guò)良好訓(xùn)練,而當(dāng)梯度很大時(shí),應(yīng)該再次重新訓(xùn)練。 所以我們這里有兩個(gè)方面,即具有大梯度和小梯度的數(shù)據(jù)實(shí)例。 因此,goss 保留所有具有大梯度的數(shù)據(jù),并對(duì)具有小梯度的數(shù)據(jù)進(jìn)行隨機(jī)采樣(這就是為什么它被稱(chēng)為單側(cè)采樣)。 這使得搜索空間更小,goss 可以更快地收斂。 最后,為了更深入地了解 goss,
????????讓我們將這些差異放在表格中:
2.正則化
????????我將介紹 lightgbm 的一些重要的正則化參數(shù)。 顯然,這些是您需要調(diào)整以對(duì)抗過(guò)度擬合的參數(shù)。
????????應(yīng)該意識(shí)到,對(duì)于小型數(shù)據(jù)集(<10000 條記錄),lightGBM 可能不是最佳選擇。 調(diào)整 lightgbm 參數(shù)可能對(duì)您沒(méi)有幫助。
????????另外,lightgbm使用leaf-wise樹(shù)生長(zhǎng)算法,而XGBoost使用深度wise樹(shù)生長(zhǎng)算法。 Leaf-wise方法允許樹(shù)更快地收斂,但過(guò)度擬合的機(jī)會(huì)增加。
根據(jù) lightGBM 文檔,當(dāng)面臨過(guò)度擬合時(shí),您可能需要進(jìn)行以下參數(shù)調(diào)整:
- 使用較小的 max_bin
- 使用小的 num_leaves
- 使用 min_data_in_leaf 和 min_sum_hessian_in_leaf
- 通過(guò)設(shè)置 bagging_fraction 和 bagging_freq 使用 bagging
- 通過(guò)設(shè)置feature_fraction來(lái)使用特征子采樣
- 使用更大的訓(xùn)練數(shù)據(jù)
- 嘗試 lambda_l1、lambda_l2 和 min_gain_to_split 進(jìn)行正則化
- 嘗試 max_depth 以避免樹(shù)長(zhǎng)得很深
????????在下面的部分中,我將更詳細(xì)地解釋每個(gè)參數(shù)。
2.1?lambda_l1?
????????Lambda_l1(和 lambda_l2)對(duì) l1/l2 的控制以及 min_gain_to_split 用于對(duì)抗過(guò)度擬合。 我強(qiáng)烈建議您使用參數(shù)調(diào)整(在后面的部分中探討)來(lái)找出這些參數(shù)的最佳值。
2.2?num_leaves
????????當(dāng)然,"num_leaves" 絕對(duì)是控制模型復(fù)雜度的最重要參數(shù)之一。通過(guò)這個(gè)參數(shù),你設(shè)定了每個(gè)弱學(xué)習(xí)器的最大葉子節(jié)點(diǎn)數(shù)。較大的 "num_leaves" 可以提高在訓(xùn)練集上的準(zhǔn)確性,但同時(shí)也增加了過(guò)擬合的風(fēng)險(xiǎn)。根據(jù)文檔的描述,一種簡(jiǎn)單的設(shè)置方式是 num_leaves = 2^(max_depth)
,然而,考慮到在LightGBM中,基于葉子節(jié)點(diǎn)的樹(shù)比基于層級(jí)的樹(shù)更深,因此你需要謹(jǐn)慎處理過(guò)擬合問(wèn)題!因此,有必要將 "num_leaves" 與 "max_depth" 一起進(jìn)行調(diào)整。
2.3?subsample
????????使用 subsample (或 bagging_fraction),您可以指定每次樹(shù)構(gòu)建迭代使用的行的百分比。 這意味著將隨機(jī)選擇一些行來(lái)適合每個(gè)學(xué)習(xí)器(樹(shù))。 這提高了泛化能力,也提高了訓(xùn)練速度。
????????我建議對(duì)基線模型使用較小的子樣本值,然后在完成其他實(shí)驗(yàn)(不同的特征選擇、不同的樹(shù)結(jié)構(gòu))時(shí)增加該值。????
? ? 2.4?feature_fraction
????????特征分?jǐn)?shù)或 sub_feature 處理列采樣,LightGBM 將在每次迭代(樹(shù))上隨機(jī)選擇特征子集。 例如,如果將其設(shè)置為 0.6,LightGBM 將在訓(xùn)練每棵樹(shù)之前選擇 60% 的特征。
????????該功能有兩種用途:
- ????????可用于加速訓(xùn)練
- ????????可以用來(lái)處理過(guò)擬合
2.5?max_depth
????????該參數(shù)控制每個(gè)訓(xùn)練樹(shù)的最大深度,并將影響:
- ????????num_leaves 參數(shù)的最佳值
- ????????模型性能
- ????????訓(xùn)練時(shí)間
????????注意如果您使用較大的 max_depth 值,您的模型可能會(huì)過(guò)度擬合訓(xùn)練集。
2.6?max_bin??
????????分箱是一種以離散視圖(直方圖)表示數(shù)據(jù)的技術(shù)。 Lightgbm 使用基于直方圖的算法來(lái)找到最佳分割點(diǎn),同時(shí)創(chuàng)建弱學(xué)習(xí)器。 因此,每個(gè)連續(xù)的數(shù)字特征(例如視頻的觀看次數(shù))應(yīng)分為離散的容器。
????????
?????????max_bin 對(duì) CPU 和 GPU 的影響如下圖:
????????如果將 max_bin 定義為 255,則意味著每個(gè)特征最多可以有 255 個(gè)唯一值。 那么較小的 max_bin 會(huì)導(dǎo)致更快的速度,而較大的值會(huì)提高準(zhǔn)確性。
3.訓(xùn)練參數(shù)
????????當(dāng)您想使用 lightgbm 訓(xùn)練模型時(shí),訓(xùn)練 lightgbm 模型時(shí)可能會(huì)出現(xiàn)的一些典型問(wèn)題是:
- ????????訓(xùn)練是一個(gè)耗時(shí)的過(guò)程
- ????????處理計(jì)算復(fù)雜性(CPU/GPU RAM 限制)
- ????????處理分類(lèi)特征
- ????????數(shù)據(jù)集不平衡
- ????????自定義指標(biāo)的需求
- 需要針對(duì)分類(lèi)或回歸問(wèn)題進(jìn)行的調(diào)整
3.1?num_iterations
????????Num_iterations 指定提升迭代(要構(gòu)建的樹(shù))的數(shù)量。 您構(gòu)建的樹(shù)越多,模型就越準(zhǔn)確,但代價(jià)是:
- ????????訓(xùn)練時(shí)間更長(zhǎng)
- ????????過(guò)擬合的可能性更高
????????建議使用較小的learning_rate和較大的num_iterations。 另外,如果您選擇更高的 num_iterations 來(lái)在沒(méi)有學(xué)習(xí)到任何有用的東西時(shí)停止訓(xùn)練,則應(yīng)該使用 Early_stopping_rounds .
3.2?early_stopping_rounds
????????如果驗(yàn)證指標(biāo)在最后一輪提前停止后沒(méi)有改善,則該參數(shù)將停止訓(xùn)練。 這應(yīng)該與多次迭代一起定義。 如果將其設(shè)置得太大,則會(huì)增加過(guò)度擬合的機(jī)會(huì)(但您的模型可以更好)。
????????經(jīng)驗(yàn)法則是讓它占 num_iterations 的 10%。
3.3?lightgbm categorical_feature
????????使用lightgbm的優(yōu)點(diǎn)之一是它可以很好地處理分類(lèi)特征。 是的,這個(gè)算法非常強(qiáng)大,但是你必須小心如何使用它的參數(shù)。 lightgbm 使用特殊的整數(shù)編碼方法(由 Fisher 提出)來(lái)處理分類(lèi)特征
????????實(shí)驗(yàn)表明,該方法比常用的 one-hot 編碼具有更好的性能。
????????它的默認(rèn)值是“auto”,這意味著:讓 lightgbm 決定,這意味著 lightgbm 將推斷哪些特征是分類(lèi)的。
????????它并不總是工作得很好(一些實(shí)驗(yàn)說(shuō)明了為什么在這里和這里),我強(qiáng)烈建議您使用此代碼手動(dòng)設(shè)置分類(lèi)特征
?cat_col = dataset_name.select_dtypes(‘object’).columns.tolist()
????????但是幕后發(fā)生了什么以及 lightgbm 如何處理分類(lèi)特征?
????????根據(jù)lightgbm的文檔,我們知道樹(shù)學(xué)習(xí)器不能很好地使用一種熱門(mén)的編碼方法,因?yàn)樗鼈冊(cè)跇?shù)中生長(zhǎng)得很深。 在所提出的替代方法中,樹(shù)學(xué)習(xí)器是最優(yōu)構(gòu)造的。 例如,對(duì)于具有 k 個(gè)不同類(lèi)別的一個(gè)特征,有 2^(k-1) – 1 個(gè)可能的分區(qū),并且使用 Fisher 方法,可以通過(guò)在值的排序直方圖上找到最佳分割方式來(lái)改進(jìn)為 k * log(k) 在分類(lèi)特征中。
3.4?lightgbm is_unbalance vs scale_pos_weight
????????在二元分類(lèi)問(wèn)題中您可能面臨的問(wèn)題之一是如何處理不平衡的數(shù)據(jù)集。 顯然,您需要平衡正/負(fù)樣本,但是在 lightgbm 中到底如何做到這一點(diǎn)呢?
????????lightgbm中有兩個(gè)參數(shù)可以讓你處理這個(gè)問(wèn)題is_unbalance和scale_pos_weight,但是它們之間有什么區(qū)別以及如何使用它們呢?
????????當(dāng)您設(shè)置 Is_unbalace: True 時(shí),算法將嘗試自動(dòng)平衡主導(dǎo)標(biāo)簽的權(quán)重(與訓(xùn)練集中的 pos/neg 分?jǐn)?shù))
????????如果您想在數(shù)據(jù)集不平衡的情況下更改scale_pos_weight(默認(rèn)為1,這意味著假設(shè)正標(biāo)簽和負(fù)標(biāo)簽相等),您可以使用以下公式(基于lightgbm存儲(chǔ)庫(kù)上的此問(wèn)題)來(lái)正確設(shè)置它
sample_pos_weight = number of negative samples / number of positive samples
3.5?lgbm feval
????????有時(shí)您想要定義自定義評(píng)估函數(shù)來(lái)衡量模型的性能,您需要?jiǎng)?chuàng)建 feval 函數(shù)。
????????Feval 函數(shù)應(yīng)接受兩個(gè)參數(shù):
- preds?
- train_data
????????并返回
- eval_name
- eval_result
- is_higher_better
????????讓我們逐步創(chuàng)建一個(gè)自定義指標(biāo)函數(shù)。定義一個(gè)單獨(dú)的Python函數(shù)???
def feval_func(preds, train_data):# Define a formula that evaluates the resultsreturn ('feval_func_name', eval_result, False)
?????????使用此函數(shù)作為參數(shù):
print('Start training...')
lgb_train = lgb.train(...,metric=None,feval=feval_func)
3.6 classification 參數(shù)?vs regression 參數(shù)
????????我之前提到的大多數(shù)內(nèi)容對(duì)于分類(lèi)和回歸都是正確的,但有些事情需要調(diào)整。
????????具體來(lái)說(shuō),您應(yīng)該:
名稱(chēng) | 分類(lèi)注意事項(xiàng) | 回歸注意事項(xiàng) |
objective | Set it binary or multiclass | Set it regression |
metric | Binary_logloss or AUC or etc. | RMSE or mean_absolute_error and or etc. |
is_unbalance | True or false | – |
scale_pos_weight | used only in binary and multi class applications | – |
num_class | used only in multi-class classification application | – |
reg_sqrt | – | Used to fit sqrt(label) instead of original values for large range label |
4.?最重要的lightgbm參數(shù)
????????我們?cè)谇懊娴牟糠种谢仡櫜⒘私饬艘恍┯嘘P(guān) lightgbm 參數(shù)的知識(shí),但是如果不提及 Laurae 令人難以置信的基準(zhǔn),任何增強(qiáng)樹(shù)文章都是不完整的 。
????????您可以了解 lightGBM 和 XGBoost 的許多問(wèn)題的最佳默認(rèn)參數(shù)。
????????您可以在這里查看,但一些最重要的要點(diǎn)是:
參數(shù)名稱(chēng) | 默認(rèn)值 | 范圍 | 參數(shù)類(lèi)型r | 別名 | 約束或注釋 | 用途 |
objective | regression | regression, binary | enum | objective_type, app | when you change it affects other parameters | specify the type of ML model |
metric | null | +20 different metrics | multi-enum | metrics, metric_types | null means that metric corresponding to specified objective will be used | specify metric, support multiple metrics |
boosting | gbdt | gbdt, rf, dart, goss | enum | boosting_type | if you set it RF, that would be a bagging approach | method of boosting |
lambda_l1 | 0.0 | [0, ∞] | double | reg_alpha | lambda_l1 >= 0.0 | regularization |
bagging_fraction | 1.0 | [0, 1] | double | subsample | 0.0 < bagging_fraction <= 1.0 | randomly select part of data without resampling |
bagging_freq | 0.0 | [0, ∞] | int | subsample_freq | to enable bagging, bagging_fraction should be set to value smaller than 1.0 as well | 0 means disable bagging; k means perform bagging at every k iteration |
num_leaves | 31 | [1, ∞] | int | num_leaf | 1 < num_leaves <= 131072 | max number of leaves in one tree |
feature_fraction | 1.0 | [0,1] | double | sub_feature | 0.0 < feature_fraction <= 1.0 | if you set it to 0.8, LightGBM will select 80% of features |
max_depth | -1 | [-1, ∞] | int | max_depth | larger is usually better, but overfitting speed increases | limit the max depth for tree model |
max_bin | 255 | [2, ∞] | int | histogram binning | max_bin > 1 | eal with over-fitting |
num_iterations | 100 | [1, ∞] | int | num_boost_round, n_iter | num_iterations >= 0 | number of boosting iterations |
learning_rate | 0.1 | [0, 1] | double | eta | learning_rate > 0.0Typical: 0.05 | in dart, it also affects on normalization weights of dropped trees |
early_stopping _round | 0 | [0, ∞] | double | early_stopping _round | will stop training if validation doesn’t improve in last early_stopping _round | model performance, number of iterations, training time |
categorical_feature | empty string | specify a number for a column index | multi-int or string | cat_feature | – | handle categorical features |
bagging_freq | 0.0 | [0, ∞] | int | subsample_freq | 0 means disable bagging; k means perform bagging at every k iteration | to enable bagging, bagging_fraction should be set to value smaller than 1.0 as well |
verbosity | 0 | [-∞, ∞] | int | verbose | < 0: Fatal, = 0: Error (Warning), = 1: Info, > 1: Debug | useful for debging |
min_data_in_leaf | 20 | min_data | int | min_data | min_data_in_leaf >= 0 | can be used to deal with over-fitting |
5.python中的Lightgbm參數(shù)調(diào)整示例?
????????最后,在解釋了所有重要參數(shù)之后,是時(shí)候進(jìn)行一些實(shí)驗(yàn)了!
????????我將使用流行的 Kaggle 競(jìng)賽之一:桑坦德客戶(hù)交易預(yù)測(cè)(Santander Customer Transaction Prediction.?)。
- ????????我將使用這篇文章解釋如何在 Python 中對(duì)任何腳本運(yùn)行超參數(shù)調(diào)整。
- ????????在我們開(kāi)始之前,有一個(gè)重要問(wèn)題! 我們應(yīng)該調(diào)整哪些參數(shù)?
????????注意你想要解決的問(wèn)題,例如桑坦德數(shù)據(jù)集是高度不平衡的,在你的調(diào)整中應(yīng)該考慮到這一點(diǎn)! Laurae2,lightgbm 的貢獻(xiàn)者之一,在這里對(duì)此做了很好的解釋。
????????有些參數(shù)是相互依賴(lài)的,必須一起調(diào)整或一項(xiàng)一項(xiàng)調(diào)整。 例如,min_data_in_leaf 取決于訓(xùn)練樣本的數(shù)量和 num_leaves。
????????注意:最好為超參數(shù)創(chuàng)建兩個(gè)字典,一個(gè)包含您不想調(diào)整的參數(shù)和值,另一個(gè)包含您想要調(diào)整的參數(shù)和值范圍。
SEARCH_PARAMS = {'learning_rate': 0.4,'max_depth': 15,'num_leaves': 20,'feature_fraction': 0.8,'subsample': 0.2}FIXED_PARAMS={'objective': 'binary','metric': 'auc','is_unbalance':True,'boosting':'gbdt','num_boost_round':300,'early_stopping_rounds':30}
?5.1 結(jié)果分析
????????這里我一步一步解釋如何調(diào)整超參數(shù)的值。創(chuàng)建基線訓(xùn)練代碼:
?
from sklearn.metrics import roc_auc_score, roc_curve
from sklearn.model_selection import train_test_split
import neptunecontrib.monitoring.skopt as sk_utils
import lightgbm as lgb
import pandas as pd
import neptune
import skopt
import sys
import osSEARCH_PARAMS = {'learning_rate': 0.4,'max_depth': 15,'num_leaves': 32,'feature_fraction': 0.8,'subsample': 0.2}FIXED_PARAMS={'objective': 'binary','metric': 'auc','is_unbalance':True,'bagging_freq':5,'boosting':'dart','num_boost_round':300,'early_stopping_rounds':30}def train_evaluate(search_params):# you can download the dataset from this link(https://www.kaggle.com/c/santander-customer-transaction-prediction/data)# import Dataset to play with itdata= pd.read_csv("sample_train.csv")X = data.drop(['ID_code', 'target'], axis=1)y = data['target']X_train, X_valid, y_train, y_valid = train_test_split(X, y, test_size=0.2, random_state=1234)train_data = lgb.Dataset(X_train, label=y_train)valid_data = lgb.Dataset(X_valid, label=y_valid, reference=train_data)params = {'metric':FIXED_PARAMS['metric'],'objective':FIXED_PARAMS['objective'],**search_params}model = lgb.train(params, train_data,valid_sets=[valid_data],num_boost_round=FIXED_PARAMS['num_boost_round'],early_stopping_rounds=FIXED_PARAMS['early_stopping_rounds'],valid_names=['valid'])score = model.best_score['valid']['auc']return score
Use the hyperparameter optimization library of your choice (for example scikit-optimize):neptune.init('mjbahmani/LightGBM-hyperparameters')
neptune.create_experiment('lgb-tuning_final', upload_source_files=['*.*'],tags=['lgb-tuning', 'dart'],params=SEARCH_PARAMS)SPACE = [skopt.space.Real(0.01, 0.5, name='learning_rate', prior='log-uniform'),skopt.space.Integer(1, 30, name='max_depth'),skopt.space.Integer(10, 200, name='num_leaves'),skopt.space.Real(0.1, 1.0, name='feature_fraction', prior='uniform'),skopt.space.Real(0.1, 1.0, name='subsample', prior='uniform')
]
@skopt.utils.use_named_args(SPACE)
def objective(**params):return -1.0 * train_evaluate(params)monitor = sk_utils.NeptuneMonitor()
results = skopt.forest_minimize(objective, SPACE,n_calls=100, n_random_starts=10,callback=[monitor])
sk_utils.log_results(results)neptune.stop()
?嘗試不同類(lèi)型的配置并在 Neptune 應(yīng)用程序中跟蹤您的結(jié)果。
?最后,在下表中,您可以看到參數(shù)發(fā)生了哪些變化。
超參數(shù) | 微調(diào)前 | 微調(diào)后 |
learning_rate | 0.4 | 0.094 |
max_depth | 15 | 10 |
num_leaves | 32 | 12 |
feature_fraction | 0.8 | 0.1 |
subsample | 0.2 | 0.75 |
boosting | gbdt | dart |
Score(auc) | 0.8256 | 0.8605 |
總結(jié)
????????長(zhǎng)話(huà)短說(shuō),本博客您了解到:
- lightgbm的主要參數(shù)是什么
- 如何使用 feval 函數(shù)創(chuàng)建自定義指標(biāo)
- 主要參數(shù)的默認(rèn)值是多少
- 看到了如何調(diào)整 lightgbm 參數(shù)以提高模型性能的示例