XGboost入門經驗分享

pchome lam
9 min readMar 7, 2019

--

前言:

這邊會當作已經了解什麼是gradient boosting,以及對於bagging, boosting相關的集成學習(ensemble learning)已經有一定的瞭解。
如果尚未了解什麼是gradient boosting,請看下面這篇,裡面有提到gradient是怎麼運用在boosting裡面以及跟求解的方式有關。

一 前言:

  1. 本文是針對開源庫的xgboost的理論底層去介紹,在Kaggle上常見的ensemble learning其中之一是隨機森林,再來另一個近幾年很紅的就是xgboost了,效果好以及常常拿到Kaggle高分的名次也讓他聲名大噪,其效果好之外速度也快。當初設計的目的之一就是能夠高效能的分析大數據,所以很適合用在巨量級的資料,不僅支援分散式運算,也支援增量學習,對業界是個很好用的工具。

二 目標函數:

目標函數=損失函數+正則項

左邊是損失函數,右邊則是正則項
損失函數能夠說明我們跟資料的擬合程度,而右邊的正則項可以說是懲罰函數,用來懲罰太過複雜的模型

損失函數通常為這樣:

常見的函數有平方差函數

而在正則項裡面呢常見的是L1與L2正則化,這個在參數裡面都可以調整,正則化主要就是用來限制模型避免過擬合,使得模型不要過擬合。

三 Boosted tree:

  1. 學習器:

介紹了上面的有監督學習的概念之後,讓我們回到boosted tree。之所以介紹前面的概念,是因為我們也是從這幾個方面開始講的。 首先講模型,Boosted tree 最基本的組成部分叫做回歸樹(regression tree),也叫做CART5。CART會把輸入根據輸入的屬性分配到各個葉子節點,而每個葉子節點上面都會對應一個實數分數。 上面的例子是一個預測一個人是否會喜歡電腦遊戲的 CART,你可以把葉子的分數理解為有多可能這個人喜歡電腦遊戲。 有人可能會問它和decision tree的關系,其實我們可以簡單地把它理解為decision tree的一個擴展。從簡單的類標到分數之後,我們可以做很多事情,如概率預測,排序。

2. Tree ensembles:

一個CART往往過於簡單無法有效地預測,因此一個更加強力的模型叫做tree ensemble

3. 模型學習:

第一部分是訓練誤差,也就是大家相對比較熟悉的如平方誤差, logistic loss等。 第二部分是每棵樹的覆雜度的和。這個在後面會繼續講到。我們會采用一種叫做additive training的方式(另外,在我個人的理解裏面boosting就是指additive training的意思)。每一次保留原來的模型不變,加入一個新的函數$f$到我們的模型中。

四 XGboost優點:

  1. 高度靈活性:

傳統GBDT以CART作為基分類器,xgboost還支持線性分類器,這個時候xgboost相當於帶L1和L2正則化項的邏輯斯蒂回歸(分類問題)或者線性回歸(回歸問題)。傳統GBDT在優化時只用到一階導數信息,xgboost則對代價函數進行了二階泰勒展開,同時用到了一階和二階導數。順便提一下,xgboost工具支持自定義代價函數,只要函數可一階和二階求導。

2. 正則化:

xgboost在代價函數裏加入了正則項,用於控制模型的覆雜度。正則項裏包含了樹的葉子節點個數、每個葉子節點上輸出的score的L2模的平方和。從Bias-variance tradeoff角度來講,正則項降低了模型的variance,使學習出來的模型更加簡單,防止過擬合,這也是xgboost優於傳統GBDT的一個特性。

3. Shrinkage:

相當於學習速率(xgboost中的eta)。xgboost在進行完一次叠代後,會將葉子節點的權重乘上該系數,主要是為了削弱每棵樹的影響,讓後面有更大的學習空間。實際應用中,一般把eta設置得小一點,然後叠代次數設置得大一點。

4. 剪枝:

當分裂時遇到一個負損失時,GBM會停止分裂。因此GBM實際上是一個貪心算法。XGBoost會一直分裂到指定的最大深度(max_depth),然後回過頭來剪枝。如果某個節點之後不再有正值,它會去除這個分裂。 這種做法的優點,當一個負損失(如-2)後面有個正損失(如+10)的時候,就顯現出來了。GBM會在-2處停下來,因為它遇到了一個負值。但是XGBoost會繼續分裂,然後發現這兩個分裂綜合起來會得到+8,因此會保留這兩個分裂。

5. 缺失值處理:

對缺失值的處理。對於特征的值有缺失的樣本,XGBoost內置處理缺失值的規則,可以自動學習出它的分裂方向。

6. 平行:

xgboost工具支持並行。boosting不是一種串行的結構嗎?怎麽並行的?註意xgboost的並行不是tree粒度的並行,xgboost也是一次叠代完才能進行下一次叠代的(第t次叠代的代價函數裏包含了前面t-1次叠代的預測值)。xgboost的並行是在特征粒度上的。
我們知道,決策樹的學習最耗時的一個步驟就是對特征的值進行排序(因為要確定最佳分割點),xgboost在訓練之前,預先對數據進行了排序,然後保存為block結構,後面的叠代中重覆地使用這個結構,大大減小計算量。這個block結構也使得並行成為了可能,在進行節點的分裂時,需要計算每個特征的增益,最終選增益最大的那個特征去做分裂,那麽各個特征的增益計算就可以開多線程進行。
可並行的近似直方圖算法。樹節點在進行分裂時,我們需要計算每個特征的每個分割點對應的增益,即用貪心法枚舉所有可能的分割點。當數據無法一次載入內存或者在分布式情況下,貪心算法效率就會變得很低,所以xgboost還提出了一種可並行的近似直方圖算法,用於高效地生成候選的分割點

XGB 通用參數:

XGBoost的參數主要可以分為三大類:1.General parameters(通用參數);2.Booster parameters(booster參數);3.Learning Task parameters(學習目標參數)。

1. silent (默認0)
當這個參數值為1時,靜默模式開啟,不會輸出任何信息。
一般這個參數就保持默認的0,因為這樣能幫我們更好地理解模型。

2. nthread (默認值為最大可能的線程數)
這個參數用來進行多線程控制,應當輸入系統的核數。
如果你希望使用CPU全部的核,那就不要輸入這個參數,算法會自動檢測它。

(二) booster參數:
盡管有兩種booster可供選擇,這裏只介紹tree booster,因為它的表現遠遠勝過linear booster,所以linear booster很少用到。

  1. eta (默認0.3)
    和GBM中的 learning rate 參數類似。通過減少每一步的權重,可以提高模型的robust。
    典型值為0.01–0.2。

2. min_child_weight (默認1)
決定最小葉子節點樣本權重和。這個參數用於避免過擬合。當它的值較大時,可以避免模型學習到局部的特殊樣本。
但如果這個值過高,會導致欠擬合。這個參數需要用cv來調整。

3. max_depth (默認6)
和GBM中的參數相同,這個值為樹的最大深度。這個值也是用來避免過擬合的。max_depth越大,模型會學到更具體更局部的樣本。
需要使用CV函數來進行調優。典型值:3–10。

4. max_leaf_nodes
樹上最大的節點或葉子的數量。
可以替代max_depth的作用。因為如果生成的是二叉樹,一個深度為n的樹最多生成n2個葉子。如果定義了這個參數,GBM會忽略max_depth參數。

5. gamma (默認0)
在節點分裂時,只有分裂後損失函數的值下降了,才會分裂這個節點。Gamma指定了節點分裂所需的最小損失函數下降值。
這個參數的值越大,算法越保守。這個參數的值和損失函數息息相關,所以是需要調整的。

6. max_delta_step (默認0)
這參數限制每棵樹權重改變的最大步長。如果這個參數的值為0,那就意味著沒有約束。如果它被賦予了某個正值,那麽它會讓這個算法更加保守。
通常,這個參數不需要設置。但是當各類別的樣本十分不平衡時,它對邏輯回歸是很有幫助的。這個參數一般用不到,但是你可以挖掘出來它更多的用處。

7. subsample (默認1)
和GBM中的subsample參數一模一樣。這個參數控制對於每棵樹,隨機采樣的比例。減小這個參數的值,算法會更加保守,避免過擬合。但是,如果這個值設置得過小,它可能會導致欠擬合。
典型值:0.5–1。

8. colsample_bytree (默認1)
和GBM裏面的max_features參數類似。用來控制每棵隨機采樣的列數的占比(每一列是一個特征)。
典型值:0.5–1。

9. colsample_bylevel (默認1)
用來控制樹的每一級的每一次分裂,對列數的采樣的占比。
一般不太用這個參數,因為subsample參數和colsample_bytree參數可以起到相同的作用。但是如果感興趣,可以挖掘這個參數更多的用處。

10. lambda (默認1)
權重的L2正則化項。(和Ridge regression類似)。這個參數是用來控制XGBoost的正則化部分的。
雖然大部分數據科學家很少用到這個參數,但是這個參數在減少過擬合上還是可以挖掘出更多用處的。

11. alpha (默認1)
權重的L1正則化項。(和Lasso regression類似)。
可以應用在很高維度的情況下,使得算法的速度更快。

12. scale_pos_weight (默認1)
在各類別樣本十分不平衡時,把這個參數設定為一個正值,可以使算法更快收斂。

--

--