CART,GBDT,XGBoost

迴歸樹=》GBDT=》XGBoost

迴歸樹(Reression Decision Tree)

在這裏插入圖片描述

一個例子

訓練數據中臂長,年齡,體重爲特徵變量X,身高爲標籤值Y,下面開始種樹

臂長(m) 年齡(歲) 體重(kg) 身高(m)(標籤值)
0.5 5 20 1.1
0.7 7 30 1.3
0.9 21 70 1.7

在這裏插入圖片描述
在這裏插入圖片描述

迴歸樹算法流程

在這裏插入圖片描述

補充:

在這裏插入圖片描述

梯度提升樹( Gradient Boosting Decision Tree,GBDT)

GBDT中的樹都是迴歸樹,不是分類樹,無論是處理迴歸問題還是二分類以及多分類,這點對理解GBDT相當重要(儘管GBDT調整後也可用於分類但不代表GBDT的樹是分類樹)

爲什麼不用分類樹呢?因爲GBDT每次迭代要擬合的是梯度值,是連續值所以要用迴歸樹。

因爲單棵 樹的能力有限,GBDT 通過構造多棵迴歸樹去預測,每棵樹都預測前面所有樹預測之後的殘差(損失函數爲平方誤差時),因此殘差越來越小,預測的精度也就越來越高。

具體形式可以如下表示:
在這裏插入圖片描述

一個例子:

年齡預測,簡單起見訓練集只有4個人,A,B,C,D,他們的年齡分別是14,16,24,26。其中A、B分別是高一和高三學生;C,D分別是應屆畢業生和工作兩年的員工。如果是用一棵傳統的迴歸決策樹來訓練,會得到如下圖1所示結果:

在這裏插入圖片描述

現在我們使用GBDT來做這件事,由於數據太少,我們限定葉子節點做多有兩個,即每棵樹都只有一個分枝,並且限定只學兩棵樹。我們會得到如下圖2所示結果:

在這裏插入圖片描述

在第一棵樹分枝和圖1一樣,由於A,B年齡較爲相近,C,D年齡較爲相近,他們被分爲兩撥,每撥用平均年齡作爲預測值。此時計算殘差(殘差的意思就是: A的預測值 + A的殘差 = A的實際值),所以A的殘差就是16-15=1(注意,A的預測值是指前面所有樹累加的和,這裏前面只有一棵樹所以直接是15,如果還有樹則需要都累加起來作爲A的預測值)。進而得到A,B,C,D的殘差分別爲-1,1,-1,1。然後我們拿殘差替代A,B,C,D的原值,到第二棵樹去學習,如果我們的預測值和它們的殘差相等,則只需把第二棵樹的結論累加到第一棵樹上就能得到真實年齡了。這裏的數據顯然是我可以做的,第二棵樹只有兩個值1和-1,直接分成兩個節點。此時所有人的殘差都是0,即每個人都得到了真實的預測值。

換句話說,現在A,B,C,D的預測值都和真實年齡一致了。Perfect!:

A: 14歲高一學生,購物較少,經常問學長問題;預測年齡A = 15 – 1 = 14

B: 16歲高三學生;購物較少,經常被學弟問問題;預測年齡B = 15 + 1 = 16

C: 24歲應屆畢業生;購物較多,經常問師兄問題;預測年齡C = 25 – 1 = 24

D: 26歲工作兩年員工;購物較多,經常被師弟問問題;預測年齡D = 25 + 1 = 26

那麼哪裏體現了Gradient呢?其實回到第一棵樹結束時想一想,無論此時的cost function是什麼,是均方差還是均差,只要它以誤差作爲衡量標準,殘差向量(-1, 1, -1, 1)都是它的全局最優方向,這就是Gradient。

問題:既然圖1和圖2 最終效果相同,爲何還需要GBDT呢?

答案是過擬合。過擬合是指爲了讓訓練集精度更高,學到了很多”僅在訓練集上成立的規律“,導致換一個數據集當前規律就不適用了。其實只要允許一棵樹的葉子節點足夠多,訓練集總是能訓練到100%準確率的(大不了最後一個葉子上只有一個instance)。在訓練精度和實際精度(或測試精度)之間,後者纔是我們想要真正得到的。

我們發現圖1爲了達到100%精度使用了3個feature(上網時長、時段、網購金額),其中分枝“上網時長>1.1h” 很顯然已經過擬合了,這個數據集上A,B也許恰好A每天上網1.09h, B上網1.05小時,但用上網時間是不是>1.1小時來判斷所有人的年齡很顯然是有悖常識的;

相對來說圖2的boosting雖然用了兩棵樹 ,但其實只用了2個feature就搞定了,後一個feature是問答比例,顯然圖2的依據更靠譜。(當然,這裏是LZ故意做的數據,所以才能靠譜得如此狗血。實際中靠譜不靠譜總是相對的) Boosting的最大好處在於,每一步的殘差計算其實變相地增大了分錯instance的權重,而已經分對的instance則都趨向於0。這樣後面的樹就能越來越專注那些前面被分錯的instance。

補充:

GBDT的思想就是在每次迭代中擬合殘差來學習一個弱學習器。而殘差的方向即爲我們全局最優的方向。但是當損失函數不爲平方損失時,我們該如何擬合弱學習器呢?

大牛Friedman提出使用損失函數負梯度的方向代替殘差方向,我們稱損失函數負梯度爲僞殘差。而僞殘差的方向即爲我們局部最優的方向。所以在GBDT中,當損失函數不爲平方損失時,用每次迭代的局部最優方向代替全局最優方向。

我們可以證明,當損失函數爲平方損失時,葉節點中使平方損失誤差達到最小值的是葉節點中所有值的均值;而當損失函數爲絕對值損失時,葉節點中使絕對損失誤差達到最小值的是葉節點中所有值的中位數。相關證明將在最後的附錄中給出

爲什麼基於殘差的gbdt不是一個好的選擇

基於殘差的gbdt在解決迴歸問題上不算是一個好的選擇,一個比較明顯的缺點就是對異常值過於敏感。我們來看一個例子:

img

很明顯後續的模型會對第4個值關注過多,這不是一種好的現象,所以一般迴歸類的損失函數會用絕對損失或者huber損失函數來代替平方損失函數:

img

GBDT的損失函數

在sklearn中梯度提升迴歸樹有四種可選的損失函數,分別爲’ls:平方損失’,‘lad:絕對損失’,‘huber:huber損失’,‘quantile:分位數損失’;而在sklearn中梯度提升分類樹有兩種可選的損失函數,一種是‘exponential:指數損失’,一種是‘deviance:對數損失’。下面分別介紹這幾種損失函數。

梯度提升迴歸樹損失函數介紹:
在這裏插入圖片描述

GBDT迴歸算法描述

平方損失GBDT算法描述

在這裏插入圖片描述

絕對損失GBDT算法描述

在這裏插入圖片描述

huber損失GBDT算法描述

在這裏插入圖片描述

GBDT和XGBoost的區別

  • xgboost損失函數是用泰勒展式二項逼近,而不是像gbdt裏的就是一階導數

  • 對樹的結構進行了正則化約束,防止模型過度複雜,降低了過擬合的可能性

  • 節點分裂的方式不同,gbdt利用最小平方誤差作爲分裂準則,xgboost是經過優化推導後的

XGBoost

一個例子:

我們要預測一家人對電子遊戲的喜好程度:

在這裏插入圖片描述

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

[外鏈圖片轉存失敗(img-kbZTO3tI-1563438889813)(C:\Users\lexi\AppData\Roaming\Typora\typora-user-images\1563248849590.png)]

損失函數

恩,你可能要拍案而起了,驚呼,這不是跟上文介紹的gbdt乃異曲同工麼?

事實上,如果不考慮工程實現、解決問題上的一些差異,xgboost與gbdt比較大的不同就是目標函數的定義。xgboost的目標函數如下圖所示:

[外鏈圖片轉存失敗(img-uIsoyyWq-1563438889814)(C:\Users\lexi\AppData\Roaming\Typora\typora-user-images\1563249386656.png)]

其中

• 紅色箭頭所指向的L 即爲損失函數(比如平方損失函數或logistic損失函數)
• 紅色方框所框起來的是正則項(包括L1正則、L2正則)

T表示葉子節點的個數,w表示葉子節點的分數。直觀上看,目標要求預測誤差儘量小,且葉子節點T儘量少(γ控制葉子結點的個數),節點數值w儘量不極端(λ控制葉子節點的分數不會過大),防止過擬合。

• 紅色圓圈所圈起來的爲常數項
• 對於f(x),xgboost利用泰勒展開三項,做一個近似

我們可以很清晰地看到,最終的目標函數只依賴於每個數據點的在誤差函數上的一階導數和二階導數。

​ 考慮到我們的第t 顆迴歸樹是根據前面的t-1顆迴歸樹的殘差得來的,相當於t-1顆樹的值是已知的。換句話說,對目標函數的優化不影響,可以直接去掉,且常數項也可以移除,從而得到如下一個比較統一的目標函數。

我們可以把之前的目標函數進行如下變形:

在這裏插入圖片描述

其中被定義爲每個葉節點j上面樣本下標的集合,g是一階導數,h是二階導數。

接着,我們可以定義:

在這裏插入圖片描述

分裂節點

Obj代表了當我們指定一個樹的結構的時候,我們在目標上面最多減少多少。我們可以把它叫做結構分數(structure score),可以認爲這個就是類似基尼係數一樣更加一般的對於樹結構進行打分的函數。

在這裏插入圖片描述

現在的情況是隻要知道樹的結構,就能得到一個該結構下的最好分數,那如何確定樹的結構呢?

從樹深度0開始,每一節點都遍歷所有的特徵,比如年齡、性別等等,然後對於某個特徵,先按照該特徵裏的值進行排序,然後線性掃描該特徵進而確定最好的分割點,最後對所有特徵進行分割後,我們選擇所謂的增益Gain最高的那個特徵,而Gain如何計算呢?

[外鏈圖片轉存失敗(img-82ip4Y2N-1563438889824)(C:\Users\lexi\AppData\Roaming\Typora\typora-user-images\1563257076608.png)]

換句話說,對於所有的特徵x,我們只要做一遍從左到右的掃描就可以枚舉出所有分割的梯度和GL和GR。然後用計算Gain的公式計算每個分割方案的分數就可以了。

然後後續則依然按照這種劃分方法繼續第二層、第三層、第四層、第N層的分裂。

第二個值得注意的事情就是引入分割不一定會使得情況變好,所以我們有一個引入新葉子的懲罰項。優化這個目標對應了樹的剪枝, 當引入的分割帶來的增益小於一個閥值γ的時候,則忽略這個分割。

換句話說,當引入某項分割,結果分割之後得到的分數 - 不分割得到的分數得到的值太小(比如小於我們的最低期望閥值γ),但卻因此得到的複雜度過高,則相當於得不償失,不如不分割。即做某個動作帶來的好處比因此帶來的壞處大不了太多,則爲避免複雜 多一事不如少一事的態度,不如不做。

得情況變好,所以我們有一個引入新葉子的懲罰項。優化這個目標對應了樹的剪枝, 當引入的分割帶來的增益小於一個閥值γ的時候,則忽略這個分割。

換句話說,當引入某項分割,結果分割之後得到的分數 - 不分割得到的分數得到的值太小(比如小於我們的最低期望閥值γ),但卻因此得到的複雜度過高,則相當於得不償失,不如不分割。即做某個動作帶來的好處比因此帶來的壞處大不了太多,則爲避免複雜 多一事不如少一事的態度,不如不做。

附錄

在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章