GBDT相對於經典的決策樹,算是一種比較成熟而且可以實際應用的決策樹演算法了。我們想要理解GBDT這種決策樹,得先從感性上理解這棵樹的工作方式。
首先我們要了解到,DBDT是一種迴歸樹(Regression Decision tree)。迴歸樹與分類樹的差距請看我的文章《經典的迴歸樹演算法》。
我們知道,分類樹在每一次分支的時候,窮舉每一個特徵的每一個閾值,然後按照大於或者小於閾值的方式將其相互分開。這就是分類樹的演算法。
而迴歸樹也十分類似,但是在每個節點都會得到一個預測值。
以年齡為例,該預測值等於屬於這個節點的所有人年齡的平均值。分枝時窮舉每一個feature的每個閾值找最好的分割點,但衡量最好的標準不再是最大熵,而是最小化均方差--即(每個人的年齡-預測年齡)^2 的總和 / N,或者說是每個人的預測誤差平方和 除以 N。這很好理解,被預測出錯的人數越多,錯的越離譜,均方差就越大,通過最小化均方差能夠找到最靠譜的分枝依據。分枝直到每個葉子節點上人的年齡都唯一(這太難了)或者達到預設的終止條件(如葉子個數上限),若最終葉子節點上人的年齡不唯一,則以該節點上所有人的平均年齡做為該葉子節點的預測年齡。
BDT(Boosting Decision Tree 提升決策樹)
這其實是一個很好的思維方式。
Boosting,提升。這涉及到機器學習中的整合學習。原理就是通過多個特徵生成多個樹,來決策一件事情。也就是“三個臭皮匠,頂一個諸葛亮”的原理。這是如何實現的呢?我們舉一個簡單的例子。BDT的核心就在於,每一棵樹學的是之前所有樹結論和的殘差,這個殘差就是一個加預測值後能得真實值的累加量。比如A的真實年齡是18歲,我們訓練的時候,第一棵樹的擬合過後預測年齡是12歲,我們與真實資料比對差了6歲,即殘差為6歲。那麼在第二棵樹裡我們把A的年齡設為6歲去擬合學習,如果第二棵樹真的能把A分到6歲的葉子節點,那累加兩棵樹的結論就是A的真實年齡;如果第二棵樹的結論是5歲,則A仍然存在1歲的殘差,第三棵樹裡A的年齡就變成1歲,繼續學。
如果還有疑問,請看下面這個例子:
還是年齡預測,簡單起見訓練集只有4個人,A,B,C,D,他們的年齡分別是14,16,24,26。其中A、B分別是高一和高三學生;C,D分別是應屆畢業生和工作兩年的員工。如果是用一棵傳統的迴歸決策樹來訓練,會得到如下圖1所示結果:
這是一棵普通的迴歸樹,我們可以看到,我們通過年齡平均值將少年和青年分開
,再用上網時長將每個分支繼續細分到不能分割或者達到要求為止。
接下來看BDT實現:
在第一棵樹分枝和圖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的預測值都和真實年齡一致了:
- 14歲高一學生,購物較少,經常問學長問題;預測年齡A = 15 – 1 = 14
- 16歲高三學生;購物較少,經常被學弟問問題;預測年齡B = 15 + 1 = 16
- 24歲應屆畢業生;購物較多,經常問師兄問題;預測年齡C = 25 – 1 = 24
- 26歲工作兩年員工;購物較多,經常被師弟問問題;預測年齡D = 25 + 1 = 26
GBDT核心思想就是這樣,但是既然普通的樹和GBDT結果一樣,那為什麼還需要GBDT呢?
原因就是過擬合。過擬合就是模型在訓練資料集上表現的過於好,分的過於細。以致於容錯能力很低,也可以稱作”泛化能力“低。這就會導致在實際測試資料中表現明顯差很多。我們發現圖1為了達到100%精度使用了3個feature(上網時長、時段、網購金額),其中分枝“上網時長>1.1h” 很顯然已經過擬合了,這個資料集上A,B也許恰好A每天上網1.09h, B上網1.05小時,但用上網時間是不是>1.1小時來判斷所有人的年齡很顯然是有悖常識的;
相對來說圖2的boosting雖然用了兩棵樹 ,但其實只用了2個feature就搞定了,後一個feature是問答比例,顯然圖2的依據更靠譜(這是杜撰的資料,為了顯示效果誇張的一下,實際有實驗證明以上論點)。
GB(Gradient Boosting 梯度提升)
我們前面一直都在討論GBDT的基本原理,是從巨集觀上對於這種演算法有個感性的認識。但是我們要想進一步理解GBDT,就得知道負梯度擬合,或者我們也叫梯度提升。
我們都知道,在機器學習演算法中,為了降低誤差函式,我們會有一個方法叫做梯度下降法。其做法是誤差函式中,每一步都走當前的梯度方向,也就是下降最快的方向進行下降,這樣多次迭代步長之後,誤差函式就會降到一個區域性最低點(凸函式中也是全域性最低點),也就得到了最小的誤差函式。
我們嘗試使用這種方法去訓練一棵迴歸樹,或者更精確的說,是一棵CART,如有朋友不太熟悉CART,請看我之前的文章《CART》。正如前面所提到,我們GBDT每次訓練的時候都是擬合上一棵樹的殘差,那麼我們使用損失函式來擬合這棵樹:
使用損失函式的負梯度來擬合它的殘差:
這樣將所有的負梯度加起來之後就會得到一個整體的梯度下降。使得整個系統的誤差函式最小。
我貼出梯度提升演算法以輔助理解,內容來自李航的《統計學習方法》:
我們來看看這梯度提升演算法的流程:
- 我們先初始化第一棵迴歸樹,使這個分界點讓整體誤差最小。具體細節上為什麼初始化成這種形式,請看我之前寫過的文章《CART》;
- 我們每生成一棵樹之後,就將這棵樹的每一條資料的損失函式的梯度求出來;損失函式我們一般寫作是均方誤差,每個資料與切分點之間的均方差就是損失函式;
- 求出每個資料的負梯度之後,我們依據已有資料和每個資料的負梯度,生成一個新樹出來,我們先將每個資料的負梯度當作新的資料的yi,這樣就得到了一組新資料,也確定了新資料的空間劃分。然後再計算每一條資料的誤差函式,取誤差函式最小的那個點做為下一個分支切分點,這也就生成了一顆新樹;
- 我們將新樹加到原來那棵樹上;
- 最後總和得到一棵樹;
如果不夠理解,請將這個負梯度擬合的殘差直接帶入之前文章《CART》例子中的殘差資料中去,這樣就有一個例子可供參考輔助理解。