sklearn與XGBoost庫xgboost演算法引數總結

帥澤澤發表於2020-12-27

前言

  1. 本文是自學課程 菜菜的機器學習,從課件總結的一下部分內容,講的細緻並且適合初學者,確實感覺不錯推薦給大家
    2.本文主要內容是sklearn與XGBoost庫使用xgboost的引數講解,重點關注XGBoost庫的使用即可,sklearn知識起到引申的作用

1 sklearn與XGBoost

1.1 xgboost庫

在這裡插入圖片描述
其中最核心的,是DMtarix這個讀取資料的類,以及train()這個用於訓練的類。與sklearn把所有的引數都寫在類中的方式不同,xgboost庫中必須先使用字典設定引數集,再使用train來將引數及輸入,然後進行訓練。會這樣設計的原因,是因為XGB所涉及到的引數實在太多,全部寫在xgb.train()中太長也容易出錯。在這裡,我為大家準備了
params可能的取值以及xgboost.train的列表,給大家一個印象。

params {eta, gamma, max_depth, min_child_weight, max_delta_step, subsample, colsample_bytree,
colsample_bylevel, colsample_bynode, lambda, alpha, tree_method string, sketch_eps, 
scale_pos_weight, updater,refresh_leaf, process_type, grow_policy, max_leaves,
 max_bin, predictor, num_parallel_tree}

xgboost.train (params, dtrain, num_boost_round=10, evals=(), obj=None, feval=None, 
maximize=False,early_stopping_rounds=None, evals_result=None, verbose_eval=True, 
xgb_model=None, callbacks=None,learning_rates=None)

1.2 sklearn中XGB的 API

我們也可以選擇第二種方法,使用xgboost庫中的sklearn的API。這是說,我們可以呼叫如下的類,並用我們sklearn當中慣例的例項化,fit和predict的流程來執行XGB,並且也可以呼叫屬性比如coef_等等。當然,這是我們迴歸的類,我們也有用於分類,用於排序的類。他們與迴歸的類非常相似,因此瞭解一個類即可。

class xgboost.XGBRegressor (max_depth=3, learning_rate=0.1, n_estimators=100, silent=True,
objective='reg:linear', booster='gbtree', n_jobs=1, nthread=None, gamma=0, min_child_weight=1, 
max_delta_step=0,subsample=1, colsample_bytree=1, colsample_bylevel=1, reg_alpha=0,
reg_lambda=1, scale_pos_weight=1,base_score=0.5, random_state=0, seed=None,
missing=None, importance_type='gain', **kwargs)

呼叫xgboost.train和呼叫sklearnAPI中的類XGBRegressor,需要輸入的引數是不同的,而且看起來相當的不同。但其實,這些引數只是寫法不同,功能是相同的。比如說,我們的params字典中的第一個引數eta,其實就是我們XGBRegressor裡面的引數learning_rate,他們的含義和實現的功能是一模一樣的。只不過在sklearnAPI中,開發團隊友好地幫助我們將引數的名稱調節成了與sklearn中其他的演算法類更相似的樣子。所以對我們來說,使用xgboost中設定的建模流程來建模,和使用sklearnAPI中的類來建模,模型效果是比較相似的,但是xgboost庫本身的運算速度(尤其是交叉驗證)以及調參手段比sklearn要簡單

1.3 XGBoost的三大板塊

在這裡插入圖片描述

2 梯度提升樹

class xgboost.XGBRegressor (max_depth=3, learning_rate=0.1, n_estimators=100, silent=True,
objective='reg:linear', booster='gbtree', n_jobs=1, nthread=None, gamma=0, min_child_weight=1, 
max_delta_step=0,subsample=1, colsample_bytree=1, colsample_bylevel=1, reg_alpha=0, 
reg_lambda=1, scale_pos_weight=1,base_score=0.5, random_state=0, seed=None, missing=None, 
importance_type='gain', **kwargs)

2.1 提升整合演算法:重要引數n_estimators

梯度提升(Gradient boosting)是構建預測模型的最強大技術之一,它是整合演算法中提升法(Boosting)的代表演算法。整合演算法通過在資料上構建多個弱評估器,彙總所有弱評估器的建模結果,以獲取比單個模型更好的迴歸或分類表現。弱評估器被定為是表現至少比隨機猜測更好的模型,即預測準確率不低於50%的任意模型。

整合不同弱評估器的方法有很多種。有像我們曾經在隨機森林的課中介紹的,一次性建立多個平行獨立的弱評估器的裝袋法。也有像我們今天要介紹的提升法這樣,逐一構建弱評估器,經過多次迭代逐漸累積多個弱評估器的方法。提升法的中最著名的演算法包括Adaboost和梯度提升樹,XGBoost就是由梯度提升樹發展而來的。梯度提升樹中可以有迴歸樹也可以有分類樹,兩者都以CART樹演算法作為主流,XGBoost背後也是CART樹,這意味著XGBoost中所有的樹都是二叉的

XGB vs GBDT 核心區別1:求解預測值 的方式不同:

GBDT中預測值是由所有弱分類器上的預測結果的加權求和,其中每個樣本上的預測結果就是樣本所在的葉子節點的均值。
而XGBT中的預測值是所有弱分類器上的葉子權重直接求和得到,計算葉子權重是一個複雜的過程。

引數含義xgb.train()xgb.XGBRegressor()
整合中弱評估器的數量num_round,預設10n_estimators,預設100
訓練中是否列印每次訓練的結果slient,預設Falseslient,預設True

n_estimators引數對模型的影響:

  1. 首先,XGB中的樹的數量決定了模型的學習能力,樹的數量越多,模型的學習能力越強。只要XGB中樹的數量足夠了,即便只有很少的資料,模型也能夠學到訓練資料100%的資訊,所以XGB也是天生過擬合的模型。但在這種情況下,模型會變得非常不穩定。
  2. 第二,XGB中樹的數量很少的時候,對模型的影響較大,當樹的數量已經很多的時候,對模型的影響比較小,只能有微弱的變化。當資料本身就處於過擬合的時候,再使用過多的樹能達到的效果甚微,反而浪費計算資源。當唯一指標 R 2 R^{2} R2或者準確率給出的n_estimators看起來不太可靠的時候,我們可以改造學習曲線來幫助我們。
  3. 第三,樹的數量提升對模型的影響有極限,最開始,模型的表現會隨著XGB的樹的數量一起提升,但到達某個點之後,樹的數量越多,模型的效果會逐步下降,這也說明了暴力增加n_estimators不一定有效果。

這些都和隨機森林中的引數n_estimators表現出一致的狀態。在隨機森林中我們總是先調整n_estimators,當n_estimators的極限已達到,我們才考慮其他引數,但XGB中的狀況明顯更加複雜,當資料集不太尋常的時候會更加複雜。這是我們要給出的第一個超引數,因此還是建議優先調整n_estimators,一般都不會建議一個太大的數目,300以下為佳

2.2 有放回隨機抽樣:重要引數subsample

subsample隨機抽樣的時候抽取的樣本比例,資料量過大時,考慮使用

引數含義xgb.train()xgb.XGBRegressor()
隨機抽樣的時候抽取的樣本比例,範圍(0,1]subsample,預設1subsample,預設1

2.3 迭代決策樹:重要引數eta

在這裡插入圖片描述
在邏輯迴歸中,我們自定義步長 α \alpha α 來干涉我們的迭代速率,在XGB中看起來卻沒有這樣的設定,但其實不然。在XGB中,我們完整的迭代決策樹的公式應該寫作:
y ^ i k + 1 = y ^ i k + η f k + 1 ( x i ) \widehat{y}_{i}^{k+1}=\widehat{y}_{i}^{k}+\eta f_{k+1}\left( x_{i}\right) y ik+1=y ik+ηfk+1(xi)
其中 η \eta η 讀作"eta",是迭代決策樹時的步長(shrinkage),又叫做學習率(learning rate)。和邏輯迴歸中的 α \alpha α 類似, η \eta η 越大,迭代的速度越快,演算法的極限很快被達到,有可能無法收斂到真正的最佳。 α \alpha α 越小,越有可能找到更精確的最佳值,更多的空間被留給了後面建立的樹,但迭代速度會比較緩慢。
在這裡插入圖片描述

引數含義xgb.train()xgb.XGBRegressor()
整合中的學習率,又稱為步長 以控制迭代速率,常用於防止過擬合 eta預設0.3 取值範圍[0,1]預設0.1 取值範圍[0,1]

結論:

通常, η \eta η (學習率)我們不調整 ,即便調整,一般它也會在[0.01,0.2]之間變動。如果我們希望模型的效果更好,更多的可能是從樹本身的角度來說,對樹進行剪枝,而不會寄希望於調整學習率

3 XGBoost的智慧

3.1 選擇弱評估器:重要引數booster

梯度提升演算法中不只有梯度提升樹,XGB作為梯度提升演算法的進化,自然也不只有樹模型一種弱評估器。在XGB中,除了樹模型,我們還可以選用線性模型,比如線性迴歸,來進行整合。雖然主流的XGB依然是樹模型,但我們也可以使用其他的模型。基於XGB的這種性質,我們有引數“booster"來控制我們究竟使用怎樣的弱評估器。

xgb.train() & paramsxgb.XGBRegressor()
引數名稱xgb_modelbooster
說明使用哪種弱評估器。可以輸入gbtree, gblinear或dart。輸入的評估器不同,使用 的params引數也不同,每種評估器都有自 己的params列表。評估器必須於param參 數相匹配,否則報錯。使用哪種弱評估器。可以輸入gbtree,gblinear或dart。 gbtree代表梯度提升樹,dart是Dropouts meet Multiple Additive Regression Trees,可譯為拋棄提升樹,在建樹的過 程中會拋棄一部分樹,比梯度提升樹有更好的防過擬合功能。 輸入gblinear使用線性模型。

3.2 XGB的目標函式:重要引數objective

xgb.train()xgb.XGBRegressor()xgb.XGBClassifier()
引數obj:預設binary:logisticobjective:預設reg:linearobjective:預設binary:logistic

常用的選擇有:

輸入選用的損失函式
reg:linear使用線性迴歸的損失函式,均方誤差,迴歸時使用
binary:logistic使用邏輯迴歸的損失函式,對數損失log_loss,二分類時使用
binary:hinge使用支援向量機的損失函式,Hinge Loss,二分類時使用
multi:softmax使用softmax損失函式,多分類時使用

在xgboost中,我們被允許自定義損失函式,但通常我們還是使用類已經為我們設定好的損失函式。我們的迴歸類中本來使用的就是reg:linear,因此在這裡無需做任何調整。注意:分型別的目標函式匯入迴歸類中會直接報錯。現在來試試看xgb自身的呼叫方式。

3.3 求解XGB的目標函式

在這裡插入圖片描述

3.4 引數化決策樹 :引數alpha, lambda

在這裡插入圖片描述
這個結構中有兩部分內容,一部分是控制樹結構的γT ,另一部分則是我們的正則項。葉子數量T 可以代表整個樹結構,這是因為在XGBoost中所有的樹都是CART樹(二叉樹),所以我們可以根據葉子的數量 判斷出樹的深度,而γ是我們自定的控制葉子數量的引數。
至於第二部分正則項,類比一下我們嶺迴歸和Lasso的結構,引數 α \alpha α λ \lambda λ的作用其實非常容易理解,他們都是控制正則化強度的引數,我們可以二選一使用,也可以一起使用加大正則化的力度。當 α \alpha α λ \lambda λ都為0的時候,目標函式就是普通的梯度提升樹的目標函式。

引數含義xgb.train()xgb.XGBClassifier()
L1正則項的引數 α \alpha αalpha,預設0,取值範圍[0, +∞]reg_alpha,預設0,取值範圍[0, +∞]
L2正則項的引數 γ \gamma γlambda,預設1,取值範圍[0, +∞]reg_lambda,預設1,取值範圍[0, +∞]

根據我們以往的經驗,我們往往認為兩種正則化達到的效果是相似的,只不過細節不同。比如在邏輯迴歸當中,兩種正則化都會壓縮 θ \theta θ引數的大小,只不過L1正則化會讓 θ \theta θ 為0,而L2正則化不會。在XGB中也是如此。當 α \alpha α λ \lambda λ越大,懲罰越重,正則項所佔的比例就越大,在盡全力最小化目標函式的最優化方向下,葉子節點數量就會被壓制,模型的複雜度就越來越低,所以對於天生過擬合的XGB來說,正則化可以一定程度上提升模型效果。

對於兩種正則化如何選擇的問題,從XGB的預設引數來看,我們優先選擇的是L2正則化。當然,如果想嘗試L1也不是不可。兩種正則項還可以互動,因此這兩個引數的使用其實比較複雜在實際應用中,正則化引數往往不是我們調參的最優選擇,如果真的希望控制模型複雜度,我們會調整 γ \gamma γ
而不是調整這兩個正則化引數,因此大家不必過於在意這兩個引數最終如何影響了我們的模型效果。對於樹模型來說,還是剪枝引數地位更高更優先
。大家只需要理解這兩個引數從數學層面上如何影響我們的模型就足夠了。如果我們希望調整 α \alpha α
λ \lambda λ ,我們往往會使用網格搜尋來幫助我們。

3.5 尋找最佳樹結構:求解w 與 T

目標函式:
在這裡插入圖片描述
比起最初的損失函式 + 複雜度的樣子,我們的目標函式已經發生了巨大變化。我們的樣本量 已經被歸結到了每個葉子當中去,我們的目標函式是基於每個葉子節點,也就是樹的結構來計算。所以,我們的目標函式又叫做“結構分數”(structure score),分數越低,樹整體的結構越好。如此,我們就建立了樹的結構(葉子)和模型效果的直接聯絡。

3.6 尋找最佳分枝:結構分數之差

貪婪演算法指的是控制區域性最優來達到全域性最優的演算法,決策樹演算法本身就是一種使用貪婪演算法的方法。XGB作為樹的整合模型,自然也想到採用這樣的方法來進行計算,所以我們認為,如果每片葉子都是最優,則整體生成的樹結構就是最優,如此就可以避免去列舉所有可能的樹結構

在這裡插入圖片描述
回憶一下決策樹中我們是如何進行計算:我們使用基尼係數或資訊熵來衡量分枝之後葉子節點的不純度,分枝前的資訊熵與分治後的資訊熵之差叫做資訊增益,資訊增益最大的特徵上的分枝就被我們選中,當資訊增益低於某個閾值時,就讓樹停止生長。在XGB中,我們使用的方式是類似的:我們首先使用目標函式來衡量樹的結構的優劣,然後讓樹從深度0開始生長,每進行一次分枝,我們就計算目標函式減少了多少,當目標函式的降低低於我們設定的某個閾值時,就讓樹停止生長

分枝後的結構分數之差為:

在這裡插入圖片描述

3.7 讓樹停止生長:重要引數gamma

在之前所有的推導過程中,我們都沒有提到 γ \gamma γ 這個變數。從目標函式和結構分數之差Gain的式子中來看, γ \gamma γ是我們每增加一片葉子就會被剪去的懲罰項。增加的葉子越多,結構分數之差Gain會被懲罰越重,所以 γ \gamma γ又被稱之為是“複雜性控制”(complexity control),所以 γ \gamma γ是我們用來防止過擬合的重要引數。實踐證明, γ \gamma γ是對梯度提升樹影響最大的引數之一,其效果絲毫不遜色於n_estimators和防止過擬合的神器max_depth。同時, γ \gamma γ 還是我們樹停止生長的重要引數。

在這裡插入圖片描述

引數含義xgb.train()xgb.XGBClassifier()
L1正則項的引數 α \alpha αalpha,預設0,取值範圍[0, +∞]reg_alpha,預設0,取值範圍[0, +∞]
L2正則項的引數 γ \gamma γlambda,預設1,取值範圍[0, +∞]reg_lambda,預設1,取值範圍[0, +∞]

4 XGBoost應用中的其他問題

4.1 過擬合:剪枝引數與迴歸模型調參

class xgboost.XGBRegressor (max_depth=3, learning_rate=0.1, n_estimators=100, silent=True,
objective='reg:linear', booster='gbtree', n_jobs=1, nthread=None, gamma=0, min_child_weight=1,
max_delta_step=0, subsample=1, colsample_bytree=1, colsample_bylevel=1, reg_alpha=0, reg_lambda=1,
scale_pos_weight=1, base_score=0.5, random_state=0, seed=None, missing=None, importance_type='gain', kwargs)
引數含義xgb.train()xgb.XGBClassifier()
樹的最大深度max_depth,預設6max_depth,預設6
每次生成樹時隨機抽樣特徵的比例colsample_bytree,預設1colsample_bytree,預設1
每次生成樹的一層時 隨機抽樣特徵的比例colsample_bylevel,預設1colsample_bylevel,預設1
每次生成一個葉子節點時,隨機抽樣特徵的比例colsample_bynode,預設1N.A.
一個葉子節點上所需要的最小hi,即葉子節點上的二階導數之和 ,類似於樣本權重min_child_weight,預設1 min_child_weight,預設1

這些引數中,樹的最大深度是決策樹中的剪枝法寶,算是最常用的剪枝引數,不過在XGBoost中,最大深度的功能與引數 γ \gamma γ相似,因此如果先調節了 γ \gamma γ,則最大深度可能無法展示出巨大的效果。當然,如果先調整了最大深度,則 γ \gamma γ也有可能無法顯示明顯的效果。通常來說,這兩個引數中我們只使用一個,不過兩個都試試也沒有壞處。

在這裡插入圖片描述

相關文章