終於有人說清楚了--XGBoost算法

1. 什麼是XGBoost

XGBoost是陳天奇等人開發的一個開源機器學習項目,高效地實現了GBDT算法並進行了算法和工程上的許多改進,被普遍應用在Kaggle競賽及其餘許多機器學習競賽中並取得了不錯的成績。git

說到XGBoost,不得不提GBDT(Gradient Boosting Decision Tree)。由於XGBoost本質上仍是一個GBDT,可是力爭把速度和效率發揮到極致,因此叫X (Extreme) GBoosted。包括前面說過,二者都是boosting方法。github

關於GBDT,這裏再也不提,能夠查看我前一篇的介紹,點此跳轉面試

1.1 XGBoost樹的定義

先來舉個例子,咱們要預測一家人對電子遊戲的喜愛程度,考慮到年輕和年老相比,年輕更可能喜歡電子遊戲,以及男性和女性相比,男性更喜歡電子遊戲,故先根據年齡大小區分小孩和大人,而後再經過性別區分開是男是女,逐一給各人在電子遊戲喜愛程度上打分,以下圖所示。算法

就這樣,訓練出了2棵樹tree1和tree2,相似以前gbdt的原理,兩棵樹的結論累加起來即是最終的結論,因此小孩的預測分數就是兩棵樹中小孩所落到的結點的分數相加:2 + 0.9 = 2.9。爺爺的預測分數同理:-1 + (-0.9)= -1.9。具體以下圖所示:機器學習

恩,你可能要拍案而起了,驚呼,這不是跟上文介紹的GBDT乃殊途同歸麼?函數

事實上,若是不考慮工程實現、解決問題上的一些差別,XGBoost與GBDT比較大的不一樣就是目標函數的定義。XGBoost的目標函數以下圖所示:學習

其中:優化

  • 紅色箭頭所指向的L 即爲損失函數(好比平方損失函數:l(y_i,y^i)=(y_i-y^i)^2)
  • 紅色方框所框起來的是正則項(包括L1正則、L2正則)
  • 紅色圓圈所圈起來的爲常數項
  • 對於f(x),XGBoost利用泰勒展開三項,作一個近似。f(x)表示的是其中一顆迴歸樹。

看到這裏可能有些讀者會頭暈了,這麼多公式,我在這裏只作一個簡要式的講解,具體的算法細節和公式求解請查看這篇博文,講得很仔細通俗理解kaggle比賽大殺器xgboost.net

XGBoost的核心算法思想不難,基本就是:設計

  1. 不斷地添加樹,不斷地進行特徵分裂來生長一棵樹,每次添加一個樹,實際上是學習一個新函數f(x),去擬合上次預測的殘差。
  2. 當咱們訓練完成獲得k棵樹,咱們要預測一個樣本的分數,其實就是根據這個樣本的特徵,在每棵樹中會落到對應的一個葉子節點,每一個葉子節點就對應一個分數
  3. 最後只須要將每棵樹對應的分數加起來就是該樣本的預測值。

顯然,咱們的目標是要使得樹羣的預測值y_i^{'}儘可能接近真實值y_i,並且有儘可能大的泛化能力。相似以前GBDT的套路,XGBoost也是須要將多棵樹的得分累加獲得最終的預測得分(每一次迭代,都在現有樹的基礎上,增長一棵樹去擬合前面樹的預測結果與真實值之間的殘差)。

那接下來,咱們如何選擇每一輪加入什麼 f 呢?答案是很是直接的,選取一個 f 來使得咱們的目標函數儘可能最大地下降。這裏 f 可使用泰勒展開公式近似。

實質是把樣本分配到葉子結點會對應一個obj,優化過程就是obj優化。也就是分裂節點到葉子不一樣的組合,不一樣的組合對應不一樣obj,全部的優化圍繞這個思想展開。到目前爲止咱們討論了目標函數中的第一個部分:訓練偏差。接下來咱們討論目標函數的第二個部分:正則項,即如何定義樹的複雜度。

1.2 正則項:樹的複雜度

XGBoost對樹的複雜度包含了兩個部分:

  • 一個是樹裏面葉子節點的個數T
  • 一個是樹上葉子節點的得分w的L2模平方(對w進行L2正則化,至關於針對每一個葉結點的得分增長L2平滑,目的是爲了不過擬合)

咱們再來看一下XGBoost的目標函數(損失函數揭示訓練偏差 + 正則化定義複雜度):

L(\phi)=\sum_{i}l(y_i^{'}-y_i)+\sum_k\Omega(f_t)

正則化公式也就是目標函數的後半部分,對於上式而言,y_i^{'}是整個累加模型的輸出,正則化項∑kΩ(ft)是則表示樹的複雜度的函數,值越小複雜度越低,泛化能力越強。

1.3 樹該怎麼長

頗有意思的一個事是,咱們從頭至尾瞭解了xgboost如何優化、如何計算,但樹到底長啥樣,咱們卻一直沒看到。很顯然,一棵樹的生成是由一個節點一分爲二,而後不斷分裂最終造成爲整棵樹。那麼樹怎麼分裂的就成爲了接下來咱們要探討的關鍵。對於一個葉子節點如何進行分裂,XGBoost做者在其原始論文中給出了一種分裂節點的方法:枚舉全部不一樣樹結構的貪心法

不斷地枚舉不一樣樹的結構,而後利用打分函數來尋找出一個最優結構的樹,接着加入到模型中,不斷重複這樣的操做。這個尋找的過程使用的就是貪心算法。選擇一個feature分裂,計算loss function最小值,而後再選一個feature分裂,又獲得一個loss function最小值,你枚舉完,找一個效果最好的,把樹給分裂,就獲得了小樹苗。

總而言之,XGBoost使用了和CART迴歸樹同樣的想法,利用貪婪算法,遍歷全部特徵的全部特徵劃分點,不一樣的是使用的目標函數不同。具體作法就是分裂後的目標函數值比單子葉子節點的目標函數的增益,同時爲了限制樹生長過深,還加了個閾值,只有當增益大於該閾值才進行分裂。從而繼續分裂,造成一棵樹,再造成一棵樹,每次在上一次的預測基礎上取最優進一步分裂/建樹。

1.4 如何中止樹的循環生成

凡是這種循環迭代的方式一定有中止條件,何時中止呢?簡言之,設置樹的最大深度、當樣本權重和小於設定閾值時中止生長以防止過擬合。具體而言,則

  1. 當引入的分裂帶來的增益小於設定閥值的時候,咱們能夠忽略掉這個分裂,因此並非每一次分裂loss function總體都會增長的,有點預剪枝的意思,閾值參數爲(即正則項裏葉子節點數T的係數);
  2. 當樹達到最大深度時則中止創建決策樹,設置一個超參數max_depth,避免樹太深致使學習局部樣本,從而過擬合;
  3. 樣本權重和小於設定閾值時則中止建樹。什麼意思呢,即涉及到一個超參數-最小的樣本權重和min_child_weight,和GBM的 min_child_leaf 參數相似,但不徹底同樣。大意就是一個葉子節點樣本太少了,也終止一樣是防止過擬合;

2. XGBoost與GBDT有什麼不一樣

除了算法上與傳統的GBDT有一些不一樣外,XGBoost還在工程實現上作了大量的優化。總的來講,二者之間的區別和聯繫能夠總結成如下幾個方面。

  1. GBDT是機器學習算法,XGBoost是該算法的工程實現。
  2. 在使用CART做爲基分類器時,XGBoost顯式地加入了正則項來控制模 型的複雜度,有利於防止過擬合,從而提升模型的泛化能力。
  3. GBDT在模型訓練時只使用了代價函數的一階導數信息,XGBoost對代 價函數進行二階泰勒展開,能夠同時使用一階和二階導數。
  4. 傳統的GBDT採用CART做爲基分類器,XGBoost支持多種類型的基分類 器,好比線性分類器。
  5. 傳統的GBDT在每輪迭代時使用所有的數據,XGBoost則採用了與隨機 森林類似的策略,支持對數據進行採樣。
  6. 傳統的GBDT沒有設計對缺失值進行處理,XGBoost可以自動學習出缺 失值的處理策略。

3. 爲何XGBoost要用泰勒展開,優點在哪裏?

XGBoost使用了一階和二階偏導, 二階導數有利於梯度降低的更快更準. 使用泰勒展開取得函數作自變量的二階導數形式, 能夠在不選定損失函數具體形式的狀況下, 僅僅依靠輸入數據的值就能夠進行葉子分裂優化計算, 本質上也就把損失函數的選取和模型算法優化/參數選擇分開了. 這種去耦合增長了XGBoost的適用性, 使得它按需選取損失函數, 能夠用於分類, 也能夠用於迴歸。

4. 代碼實現

GitHub:點擊進入

機器學習通俗易懂系列文章

3.png

5. 參考文獻

通俗理解kaggle比賽大殺器xgboost

做者:@mantchs

GitHub:github.com/NLP-LOVE/ML…

歡迎你們加入討論!共同完善此項目!羣號:【541954936】NLP面試學習羣

相關文章
相關標籤/搜索