XGBoost 引數調優小結
XGBoost在Kaggle比賽大放異彩,在之前的文章已介紹XGBoost演算法原理和XGBoost切分演算法,網上對XGBoost引數的解釋大部分只停留在表面,對剛入門機器學習演算法的人極其不友好,本文在解釋某些重要引數的同時會參考數學公式以增加對XGBoost演算法原理的理解,並通過分類例項闡述XGBoost調參思想 。
本文的框架和例項來自於https://www.analyticsvidhya.com/blog/2016/03/complete-guide-parameter-tuning-xgboost-with-codes-python/的翻譯,並根據自己的理解對內容和程式碼進行了修改,本文例項只處理訓練資料,並以五折交叉驗證率作為衡量模型效能的標準 。
程式碼連結 :https://github.com/zhangleiszu/xgboost-
目錄
-
XGBoost演算法原理簡單回顧
-
XGBoost的優點
-
XGBoost的引數解釋
-
引數調優例項
-
小結
1. XGBoost演算法原理簡單回顧
XGBoost演算法的每顆樹都是對前一個模型損失函式的二階導展開式擬合,然後結合多棵樹給出分類或迴歸結果。因此我們只要知道每棵樹的構建過程,就能很好的理解XGBoost的演算法原理。
假設對於前t-1棵樹的預測結果為 ,真實結果為y,用L表示損失函式,那麼當前模型的損失函式為:
XGBoost法構建樹的同時考慮了正則化,定義每棵樹的複雜度為:
因此,包含正則化項的損失函式為:
最小化(1.3)式得到最終的目標函式:
目標函式也稱為打分函式,它是衡量樹結構好壞的標準,值越小代表樹的結構越好 。因此樹的節點切分規則是選擇樹目標函式值下降最大的點作為切分點 。
如下圖,對於某一節點切分前後的目標函式之差記為Gain。
選擇Gain下降最大的切分點對樹分裂,以此類推,得到完整的樹 。
因此, 只要知道(1.5)式的引數值就能基本確定樹模型 ,其中 表示左子節點損失函式的二階導之和, 表示右子節點損失函式的二階導之和, 表示左子節點損失函式的一階導之和, 表示右子節點損失函式的一階導之和 。 表示正則化係數, 表示切分節點難度, 和 定義了樹的複雜度。 再簡單一點,我們只要設定了損失函式L,正則化係數和切分節點難度,就基本確定了樹模型 。XGBoost引數擇要重點考慮這三個引數 。
2. XGBoost的優點
1. 正則化
XGBoost切分節點時考慮了正則化項(如圖1.3),減少了過擬合。實際上,XGBoost也稱為“正則化提升”技術。
2. 並行處理
雖然XGBoost是序列迭代生成各決策樹,但是我們在切分節點時可以做到並行處理 ,因此XGBoost支援Hadoop實現 。
3. 高度靈活性
XGBoost支援自定義目標函式和評價函式,評價函式是衡量模型好壞的標準,目標函式是損失函式,如上節討論, 只要知道了損失函式,然後求其一階導和二階導,就能確定節點的切分規則 。
4. 缺失值處理
XGBoost內建了處理缺失值的節點切分規則 。使用者需要提供一個和其他樣本不一樣的值(如-999), 然後把該值作為引數的缺失值 。
5. 內建交叉驗證
XGBoost允許每一輪迭代中使用交叉驗證,因此,可以很方便的獲得交叉驗證率,得到最優boosting迭代次數 ,並不需要傳統的網格搜尋法來獲取最優迭代次數 。
6. 在已有的模型基礎上繼續
XGBoost可以從上一輪的結果上繼續訓練,從而節省了執行時間,通過設定模型引數“process_type”= update來實現 。
3. XGBoost引數解釋
XGBoost引數把所有的引數分為三類:
1. 通用引數 :控制了模型的巨集觀功能 。
2. Booster引數 :控制每一輪迭代的樹生成。
3. 學習目標引數 :決定了學習場景,如損失函式和評價函式 。
3.1 通用引數
-
booster [default = gbtree]
供選擇的模型有gbtree和gblinear,gbtree使用基於樹的模型進行提升,gblinear使用線性模型進行提升,預設是gbtree 。這裡只介紹tree booster,因為它的表現遠遠勝過linear booster
-
silent [default = 0]
取0時表示列印執行資訊,取1時表示不列印執行資訊。
-
nthread
XGBoost執行時的執行緒數,預設是當前系統可執行的最大執行緒數。
-
num_pbuffer
預測資料的緩衝區大小,一般設定成訓練樣本個數的大小 。緩衝區保留最後一次迭代後的預測結果 ,系統自動設定 。
-
num_feature
設定特徵維數來構建樹模型, 系統自動設定 。
3.2 booster引數
-
eta [default = 0.3]
控制樹模型的權重,與AdaBoost演算法的學習率(learning rate)含義類似,縮小權重以避免模型處於過擬合,在對eta進行引數擇優時,需要與迭代次數(num_boosting_rounding)結合在一起考慮 , 如減小學習率,那麼增加最大迭代次數;反之,則減小最大迭代次數 。
範圍:[0,1]
模型迭代公式:
其中 表示前t棵樹結合模型的輸出結果, 表示第t棵樹模型,α表示學習率,控制模型更新的權重 。
-
gamma [default = 0]
控制模型切分節點的最小損失函式值, 對應(1.5)式的γ ,若γ設定的過大(1.5)式小於零,則不進行節點切分,因此降低了模型的複雜度。
-
lambda [default = 1]
表示L2正則化引數,對應(1.5)式中的λ ,增大λ的值使模型更保守,避免過擬合 。
-
alpha [default = 0]
表示L1正則化引數,L1正則化的意義在於可以降維 ,增大alpha值使模型更保守,避免過擬合
範圍:[0,∞]
-
max_depth [default=6]
表示樹的最大深度,增加樹的深度提高了樹的複雜度,很有可能會導致過擬合,0表示對樹的最大深度無限制 。
範圍:[0,∞]
-
min_child_weight [default=1]
表示最小葉子節點的樣本權重和,和之前介紹的min_child_leaf引數有差別,min_child_weight表示樣本權重的和,min_child_leaf表示樣本總數和。
範圍:[0,∞]
-
subsample [default=1]
表示隨機取樣一定比例的樣本來構建每棵樹 ,減小比例引數subsample值,演算法會更加保守,避免過擬合
範圍:[0,1]
-
colsample_bytree,colsample_bylevel,colsample_bynode
這個三個引數表示對特徵進行隨機抽樣,且具有累積效應 。
colsample_bytree,表示每棵樹劃分的特徵比重
colsample_bylevel,表示樹的每層劃分的特徵比重
colsample_bynode,表示樹的每個節點劃分的特徵比重 。
比如,樣本共有64個特徵,設定{'colsample_bytree' : 0.5 , 'colsample_bylevel' : 0.5 , 'colsample_bynode' : 0.5 },那麼隨機取樣4個特徵應用於樹的每一個節點切分 。
範圍:[0,1]
-
tree_method string [default = auto ]
表示樹的構建方法,確切來說是切分點的選擇演算法,包括 貪心演算法,近似貪心演算法,直方圖演算法
exact:貪心演算法
aprrox:近似貪心演算法,選擇特徵的分位點進行切分
hist:直方圖切分演算法,LightGBM演算法也採用該切分演算法 。
-
scale_pos_weight [default = 1]
當正負樣本不平衡時,設定該引數為正值 ,可以使演算法更快收斂 。
典型的值可設定為:(負樣本個數)/(正樣本個數)
-
process_type [default = default]
default:正常的構建提升樹過程
update: 從已有的模型構建提升樹
3.3 學習任務引數
根據任務和目的設定引數
objective,訓練目標,分類還是迴歸
reg : linear,線性迴歸
reg : logistic,邏輯迴歸
binary : logistic,使用LR二分類,輸出概率
binary : logitraw,使用LR二分類,輸出Logistic轉換之前的分類得分 。
eval_metric,評價驗證集的指標,預設根據目標函式設定,預設情況下,最小均方差用於迴歸,錯誤率用於分類,平均精確率用於排序 。
rmse:均方差
mae:平均絕對值誤差
error :錯誤率
logloss:負的對數損失
auc : roc曲線下的面積
seed [default=0]
隨機數種子,設定它可以復現隨機資料結果 。
4. 引數調優例項
原始資料集和經過特徵工程處理後的資料集在開頭的連結部分進行下載,演算法在jupter-notebook互動介面開發 。
定義模型評價函式,並根據一定的學習率得到最優迭代次數 ,函式定義 如下:
Step1:
根據經驗設定預設的引數, 呼叫modelfit函式得到最優迭代次數是198 。
Step2: 樹最大深度和最小葉子節點權重調優
根據第一步得到的最優迭代次數 更新模型引數n_estimators ,然後呼叫 model_selection類的GridSearchCV設定交叉驗證模型, 最後呼叫 XGBClassifier類的fit函式得到最優樹的最大深度和最小葉子節點權重 。
a) 設定樹最大深度和最小葉子節點權重範圍:
b) GridSearchCV設定交叉驗證模型:
c) XGBClassfier類的fit函式更新引數:
Step3: gamma引數調優
Step4: subsample and colsample_bytree引數調優
Step5: 正則化引數調優
Step3,Step4和Step5引數調優思想Step2一致,這裡不再展開,可參考程式碼去理解 。
Step6: 減小學習率,增大對應的最大迭代次數 。 引數調優思想與Step1一致,得到最優的迭代次數 ,並輸出交叉驗證率結果。
迭代次數為2346時 ,得到最優分類結果(如下圖)。
5. XGBoost引數調優小結
XGBoost是一個高效能的學習模型演算法,當你不知道怎麼對模型進行引數調優時,可參考上一節的步驟去進行引數調優 。本節根據上節的內容,以及自己的專案經驗闡述一下本人對XGBoost演算法引數調優的一些理解,若有錯誤之處,還忘指正 。
(1) 模型初始化 。在初始化模型引數時,我們儘量讓模型的複雜度較高,然後一步一步的通過引數調優來降低模型複雜度 。如上節初始化引數:葉子節點最小權重為0,最大樹深度為5,最小損失函式下降值為0,這些引數初始化都是複雜化模型 。
(2) 學習率和最大迭代次數 。 這兩個引數的調優一定是聯絡在一起的,學習率越大,達到相同效能的模型所需要的最大迭代次數越小;學習率越小,達到相同效能的模型所需要的最大迭代次數越大 。 XGBoost每個引數的更新都需要進行多次迭代,因此,學習率和最大迭代次數是首先需要考慮的引數 ,且學習率和最大迭代引數的重點不是提高模型的分類準確率,而是提高模型的泛化能力,因此,當模型的分類準確率很高時,我們最後一步應減小學習率的大小,以提高模型的泛化能力 。
(3) 逐步降低模型複雜度 。樹的最大深度,葉子節點最小權重等引數都是影響模型複雜度的因素,這個看自己經驗,第四節的調參順序是:樹的最大深度和葉子節點最小權重->最小損失函式下降值->行取樣和列取樣->正則化引數 。實際專案中,我一般按照這個順序去調參 ,若有不同的理解,歡迎交流。
(4) 特徵工程 :若模型的準確率在很低的範圍,那麼我建議先不用去調參了,去重點關注特徵和訓練資料。特徵和資料決定模型上限,模型只是逼近這個上限 。
參考:
https://www.analyticsvidhya.com/blog/2016/03/complete-guide-parameter-tuning-xgboost-with-codes-python/
https://xgboost.readthedocs.io/en/latest/
推薦閱讀