【机器学习基础】XGBoost、LightGBM与CatBoost算法对比与调参
機器學習
Author:louwill
Machine Learning Lab
? ? ?
雖然現在深度學習大行其道,但以XGBoost、LightGBM和CatBoost為代表的Boosting算法仍有其廣闊的用武之地。拋開深度學習適用的圖像、文本、語音和視頻等非結構化的數據應用,Boosting算法對于訓練樣本較少的結構化數據領域仍然是第一選擇。本文先對前述章節的三大Boosting的聯系與區別進行簡單闡述,并一個實際數據案例來對三大算法進行對比。然后對常用的Boosting算法超參數調優方法進行介紹,包括隨機調參法、網格搜索法和貝葉斯調參法,并給出相應的代碼示例。
三大Boosting算法對比
首先,XGBoost、LightGBM和CatBoost都是目前經典的SOTA(state of the art)Boosting算法,都可以歸類到梯度提升決策樹算法系列。三個模型都是以決策樹為支撐的集成學習框架,其中XGBoost是對原始版本的GBDT算法的改進,而LightGBM和CatBoost則是在XGBoost基礎上做了進一步的優化,在精度和速度上都有各自的優點。
三大模型的原理細節我們本文不做敘述,可參考【原創首發】機器學習公式推導與代碼實現30講.pdf。那么這三大Boosting算法又有哪些大的方面的區別呢?主要有兩個方面。第一個是三個模型樹的構造方式有所不同,XGBoost使用按層生長(level-wise)的決策樹構建策略,LightGBM則是使用按葉子生長(leaf-wise)的構建策略,而CatBoost使用了對稱樹結構,其決策樹都是完全二叉樹。第二個有較大區別的方面是對于類別特征的處理。XGBoost本身不具備自動處理類別特征的能力,對于數據中的類別特征,需要我們手動處理變換成數值后才能輸入到模型中;LightGBM中則需要指定類別特征名稱,算法即可對其自動進行處理;CatBoost以處理類別特征而聞名,通過目標變量統計等特征編碼方式也能實現類別特征的高效處理。
下面我們以kaggle 2015年航班延誤數據集為示例,分別用XGBoost、LightGBM和CatBoost模型進行實驗。圖1是flights數據集簡介。
圖2?flights數據集
該數據集完整數據量有500多萬條航班記錄數據,特征有31個,僅作演示用的情況下,我們采用抽樣的方式從原始數據集中抽樣1%的數據,并篩選11個特征,經過預處理后重新構建訓練數據集,目標是構建對航班是否延誤的二分類模型。數據讀取和簡單預處理過程如代碼1所示。
代碼1 數據處理
# 導入pandas和sklearn數據劃分模塊 import pandas as pd from sklearn.model_selection import train_test_split # 讀取flights數據集 flights = pd.read_csv('flights.csv') # 數據集抽樣1% flights = flights.sample(frac=0.01, random_state=10) # 特征抽樣,獲取指定的11個特征 flights = flights[["MONTH", "DAY", "DAY_OF_WEEK", "AIRLINE", "FLIGHT_NUMBER","DESTINATION_AIRPORT", "ORIGIN_AIRPORT","AIR_TIME", "DEPARTURE_TIME", "DISTANCE", "ARRIVAL_DELAY"]] # 對標簽進行離散化,延誤10分鐘以上才算延誤 flights["ARRIVAL_DELAY"] = (flights["ARRIVAL_DELAY"]>10)*1 #?類別特征 cat_cols?=?["AIRLINE",?"FLIGHT_NUMBER",?"DESTINATION_AIRPORT", "ORIGIN_AIRPORT"] #?類別特征編碼 for?item?in?cat_cols:flights[item]?=?flights[item].astype("category").cat.codes?+1# 數據集劃分 X_train,?X_test,?y_train,?y_test?=?train_test_split(flights.drop(["ARRIVAL_DELAY"],?axis=1),flights["ARRIVAL_DELAY"], random_state=10, test_size=0.3) # 打印劃分后的數據集大小 print(X_train.shape,?y_train.shape,?X_test.shape,?y_test.shape)輸出:
(39956, 10) (39956,) (17125, 10) (17125,)在代碼1中,我們先讀取了flights原始數據集,因為原始數據集量太大,我們對其進行抽樣1%,并篩選了11個特征,構建有57081條1、11個特征的航班記錄數據集。然后對抽樣數據集進行簡單的預處理,先對訓練標簽進行二值離散化,延誤大于10分鐘的轉化為1(延誤),延誤小于10分鐘的轉化為0(不延誤),然后對“航線”、“航班號”、“目的地機場”、“出發地機場”等類別特征進行類別編碼處理。最后劃分數據集,得到有39956條訓練樣本,17125條測試樣本。
XGBoost
下面我們開始來測試三個模型在該數據集上的效果。先來看XGBoost,如代碼2所示。
代碼2?XGBoost
# 導入xgboost模塊 import xgboost as xgb # 導入模型評估auc函數 from sklearn.metrics import roc_auc_score # 設置模型超參數 params = {'booster': 'gbtree','objective': 'binary:logistic', 'gamma': 0.1,'max_depth': 8,'lambda': 2,'subsample': 0.7,'colsample_bytree': 0.7,'min_child_weight': 3,'eta': 0.001,'seed': 1000,'nthread': 4, } # 封裝xgboost數據集 dtrain = xgb.DMatrix(X_train, y_train) # 訓練輪數,即樹的棵數 num_rounds = 500 # 模型訓練 model_xgb = xgb.train(params, dtrain, num_rounds) # 對測試集進行預測 dtest = xgb.DMatrix(X_test) y_pred = model_xgb.predict(dtest) print('AUC?of?testset?based?on?XGBoost:?',?roc_auc_score(y_test,?y_pred))輸出:
在代碼15-2中,我們測試了XGBoost在flights數據集上的表現,導入相關模塊并設置模型超參數,便可基于訓練集進行XGBoost模型擬合,最后將訓練好的模型用于測試集預測,可得到測試集AUC為0.6845。
LightGBM
LightGBM在flights數據集上的測試過程如代碼3所示。
代碼3?LightGBM
# 導入lightgbm模塊 import lightgbm as lgb dtrain = lgb.Dataset(X_train, label=y_train) params = { "max_depth": 5, "learning_rate" : 0.05, "num_leaves": 500, "n_estimators": 300 }# 指定類別特征 cate_features_name = ["MONTH","DAY","DAY_OF_WEEK","AIRLINE", "DESTINATION_AIRPORT", "ORIGIN_AIRPORT"]# lightgbm模型擬合 model_lgb = lgb.train(params, d_train, categorical_feature = cate_features_name)# 對測試集進行預測 y_pred = model_lgb.predict(X_test) print('AUC?of?testset?based?on?XGBoost:?'roc_auc_score(y_test,?y_pred))輸出:
在代碼3中,我們測試了LightGBM在flights數據集上的表現,導入相關模塊并設置模型超參數,便可基于訓練集進行LightGBM模型擬合,最后將訓練好的模型用于測試集預測,可得到測試集AUC為0.6873,跟XGBoost效果差不多。
CatBoost
CatBoost在flights數據集上的測試過程如代碼4所示。
代碼4?CatBoost
# 導入lightgbm模塊 import catboost as cb # 類別特征索引 cat_features_index = [0,1,2,3,4,5,6] # 創建catboost模型實例 model_cb?=?cb.CatBoostClassifier(eval_metric="AUC",one_hot_max_size=50,?depth=6,?iterations=300,?l2_leaf_reg=1,learning_rate=0.1) # catboost模型擬合 model_cb.fit(X_train, y_train, cat_features=cat_features_index) # 對測試集進行預測 y_pred = model_cb.predict(X_test) print('AUC?of?testset?based?on?CatBoost:?'roc_auc_score(y_test,?y_pred))輸出:
AUC of testset based on CatBoost: 0.5463773041667715在代碼4中,我們測試了CatBoost在flights數據集上的表現,導入相關模塊并設置模型超參數,便可基于訓練集進行CatBoost模型擬合,最后將訓練好的模型用于測試集預測,可得到測試集AUC為0.54,相較于XGBoost和LightGBM,CatBoost在該數據集上的效果要差不少。表1是針對flights數據集三大模型的綜合對比結果。
從表1的綜合對比結果來看,LightGBM無論是在精度上還是速度上,都要優于XGBoost和CatBoost。當然了,我們只是在數據集上直接用三個模型做了比較,沒有做進一步的數據特征工程和超參數調優,表1的結果均可做進一步的優化。
常用的超參數調優方法
機器學習模型中有大量需要事先進行人為設定的參數,比如說神經網絡訓練的batch-size,XGBoost等集成學習模型的樹相關參數,我們將這類不是經過模型訓練得到的參數叫做超參數(hyperparameter)。人為的對超參數調整的過程也就是我們熟知的調參。機器學習中常用的調參方法包括網格搜索法(grid search)、隨機搜索法(random search)和貝葉斯優化(bayesian optimization)。
網格搜索法
網格搜索是一項常用的超參數調優方法,常用于優化三個或者更少數量的超參數,本質是一種窮舉法。對于每個超參數,使用者選擇一個較小的有限集去探索。然后,這些超參數笛卡爾乘積得到若干組超參數。網格搜索使用每組超參數訓練模型,挑選驗證集誤差最小的超參數作為最好的超參數。
例如,我們有三個需要優化的超參數a,b,c,候選的取值分別是{1,2},{3,4},{5,6}。則所有可能的參數取值組合組成了一個8個點的3維空間網格如下:{(1,3,5),(1,3,6),(1,4,5),(1,4,6),(2,3,5),(2,3,6),(2,4,5),(2,4,6)},網格搜索就是通過遍歷這8個可能的參數取值組合,進行訓練和驗證,最終得到最優超參數。
Sklearn中通過model_selection模塊下的GridSearchCV來實現網格搜索調參,并且這個調參過程是加了交叉驗證的。我們同樣以前述flights數據集為例,展示XGBoost的網格搜索代碼示例。
代碼5 網格搜索
### 基于XGBoost的GridSearch搜索范例 # 導入GridSearch模塊 from sklearn.model_selection import GridSearchCV # 創建xgb分類模型實例 model = xgb.XGBClassifier() # 待搜索的參數列表空間 param_lst = {"max_depth": [3,5,7],"min_child_weight" : [1,3,6],"n_estimators": [100,200,300],"learning_rate": [0.01, 0.05, 0.1]} # 創建網格搜索 grid_search = GridSearchCV(model, param_grid=param_lst, cv=3, verbose=10, n_jobs=-1) # 基于flights數據集執行搜索 grid_search.fit(X_train, y_train) # 輸出搜索結果 print(grid_search.best_estimator_)輸出:
XGBClassifier(max_depth=5, min_child_weight=6, n_estimators=300)代碼5給出了基于XGBoost的網格搜索范例。我們先創建XGBoost分類模型實例,然后給出需要搜索的參數和對應的參數范圍列表,并基于GridSearch創建網格搜索對象,最后擬合訓練數據,輸出網格搜索的參數結果。可以看到,當樹最大深度為5、最小子樹權重取6以及樹的棵數為300時,模型能達到相對最優的效果。
隨機搜索
隨機搜索,顧名思義,即在指定的超參數范圍或者分布上隨機搜索和尋找最優超參數。相較于網格搜索方法,給定超參數分布內并不是所有的超參數都會進行嘗試,而是會從給定分布中抽樣一個固定數量的參數,實際僅對這些抽樣到的超參數進行實驗。相較于網格搜索,隨機搜索有時候會是一種更高效的調參方法。Sklearn中通過model_selection模塊下RandomizedSearchCV方法進行隨機搜索。基于XGBoost的隨機搜索調參示例如代碼6所示。
代碼6 隨機搜索
### 基于XGBoost的GridSearch搜索范例 # 導入GridSearch模塊 from sklearn.model_selection import GridSearchCV # 創建xgb分類模型實例 model = xgb.XGBClassifier() # 待搜索的參數列表空間 param_lst = {"max_depth": [3,5,7],"min_child_weight" : [1,3,6],"n_estimators": [100,200,300],"learning_rate": [0.01, 0.05, 0.1]} # 創建網格搜索 grid_search = GridSearchCV(model, param_grid=param_lst, cv=3, verbose=10, n_jobs=-1) # 基于flights數據集執行搜索 grid_search.fit(X_train, y_train) # 輸出搜索結果 print(grid_search.best_estimator_)輸出:
代碼6給出了隨機搜索的使用示例,模式上跟網格搜索基本一致,可以看到,隨機搜索的結果認為樹的棵樹取300,最小子樹權重為6,最大深度為5,學習率取0.1的時候模型達到最優。
?
貝葉斯調參
除了上述兩種調參方法外,本小節介紹第三種,也有可能是最好的一種調參方法,即貝葉斯優化。貝葉斯優化是一種基于高斯過程(gaussian process)和貝葉斯定理的參數優化方法,近年來被廣泛用于機器學習模型的超參數調優。這里不詳細探討高斯過程和貝葉斯優化的數學原理,僅展示貝葉斯優化的基本用法和調參示例。
貝葉斯優化其實跟其他優化方法一樣,都是為了為了求目標函數取最大值時的參數值。作為一個序列優化問題,貝葉斯優化需要在每一次迭代時選取一個最佳觀測值,這是貝葉斯優化的關鍵問題。而這個關鍵問題正好被上述的高斯過程完美解決。關于貝葉斯優化的大量數學原理,包括高斯過程、采集函數、Upper Confidence Bound(UCB)和Expectation Improvements(EI)等概念原理,本節限于篇幅不做展開描述。貝葉斯優化可直接借用現成的第三方庫BayesianOptimization來實現。使用示例如代碼7所示。
代碼7 貝葉斯優化
### 基于XGBoost的BayesianOptimization搜索范例 # 導入xgb模塊 import xgboost as xgb # 導入貝葉斯優化模塊 from bayes_opt import BayesianOptimization # 定義目標優化函數 def xgb_evaluate(min_child_weight,colsample_bytree,max_depth,subsample,gamma,alpha):# 指定要優化的超參數params['min_child_weight'] = int(min_child_weight)params['cosample_bytree'] = max(min(colsample_bytree, 1), 0)params['max_depth'] = int(max_depth)params['subsample'] = max(min(subsample, 1), 0)params['gamma'] = max(gamma, 0)params['alpha'] = max(alpha, 0)# 定義xgb交叉驗證結果cv_result?=?xgb.cv(params,?dtrain,?num_boost_round=num_rounds,?nfold=5,seed=random_state,callbacks=[xgb.callback.early_stop(50)])return cv_result['test-auc-mean'].values[-1]# 定義相關參數 num_rounds = 3000 random_state = 2021 num_iter = 25 init_points = 5 params = {'eta': 0.1,'silent': 1,'eval_metric': 'auc','verbose_eval': True,'seed': random_state } # 創建貝葉斯優化實例 # 并設定參數搜索范圍 xgbBO = BayesianOptimization(xgb_evaluate, {'min_child_weight': (1, 20),'colsample_bytree': (0.1, 1),'max_depth': (5, 15),'subsample': (0.5, 1),'gamma': (0, 10),'alpha': (0, 10),}) # 執行調優過程 xgbBO.maximize(init_points=init_points,?n_iter=num_iter)代碼7給出了基于XGBoost的貝葉斯優化示例,在執行貝葉斯優化前,我們需要基于XGBoost的交叉驗證xgb.cv定義一個待優化的目標函數,獲取xgb.cv交叉驗證結果,并以測試集AUC為優化時的精度衡量指標。最后將定義好的目標優化函數和超參數搜索范圍傳入貝葉斯優化函數BayesianOptimization中,給定初始化點和迭代次數,即可執行貝葉斯優化。
圖2?貝葉斯優化結果
部分優化過程如圖2所示,可以看到,貝葉斯優化在第23次迭代時達到最優,當alpha參數取4.099、列抽樣比例為0.1、gamma參數為0、樹最大深度為5、最小子樹權重取5.377以及子抽樣比例為1.0時,測試集AUC達到最優的0.72。
總結
本章是在前述幾章集成學習內容基礎上的一個簡單綜合對比,并給出了集成學習常用的超參數調優方法和示例。我們針對常用的三大Boosting集成學習模型:XGBoost、LightGBM和CatBoost,以具體的數據實例做了一個精度和速度上的性能對比,但限于具體的數據集和調優差異,對比結果僅作為演示說明使用,并不能真正代表LightGBM模型一定就要優于CatBoost模型。
三大常用的超參數調優方法:網格搜索法、隨機搜索法和貝葉斯優化法。本章也基于同樣的數據集給出了三大超參數調優方法的使用示例,但限于篇幅,并沒有太多深入每個方法的數學原理闡述。
往期精彩回顧適合初學者入門人工智能的路線及資料下載機器學習及深度學習筆記等資料打印機器學習在線手冊深度學習筆記專輯《統計學習方法》的代碼復現專輯 AI基礎下載機器學習的數學基礎專輯溫州大學《機器學習課程》視頻 本站qq群851320808,加入微信群請掃碼:總結
以上是生活随笔為你收集整理的【机器学习基础】XGBoost、LightGBM与CatBoost算法对比与调参的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: win7系统怎么更改语言及字体
- 下一篇: Win7电脑设置定时关机的操作方法