[機器學習] Boosting算法 --- AdaBoost、GBDT與XGBoost

一、提升算法概論

Boosting(提升)是一族可將弱學習器提升爲強學習器的算法。提升算法基於這樣一種思想:對於一個複雜的任務,將多個專家的判斷總和得出的結果要比任何一個專家單獨的判斷好。這族算法的工作機制類似:先從初始訓練集訓練出一個基學習器,再根據基學習器表現對訓練樣本分佈進行調整,是的先前基學習器做錯的樣本在後續收到更多關注(賦予做錯的樣本更大的權值),然後基於調整後的樣本分佈來訓練下一個基學習器,一直反覆進行,直到達到指定值。boosting方法通過分步迭代(stage-wise)的方式來構建模型,在迭代的每一步構建的弱學習器都是爲了彌補已有模型的不足。(個體學習器之間存在強依賴關係。

對樣本加權的過程如下:

上圖中被放大的點是被加權的樣本,樣本加權後,在下一次的學習中就會收到更多的關注。

也就是說提升算法對分類錯誤的樣本更爲關注,通過改變錯誤樣本所佔的權值來改變分類邊界,從而一步步提升算法的準確度。

 

二、AdaBoost算法

AdaBoost算法是提升算法中最具代表性的。其中AdaBoost是Adaptive Boosting的縮寫, 正如上面所說的,在AdaBoost算法中會提高前一輪分類器分類錯誤的樣本的權值,而降低那些被分類正確樣本的權值。對於弱分類器的組合,AdaBoost算法採取加權多數表決的方法。具體的說就是加大分類誤差率小的弱分類器的權值,使其在表決中起到較大的作用;減小分類誤差率大的弱分類器的權值,使其在表決中起較小的作用。

主要解決的問題:目前對AdaBoost算法的研究以及應用大多集中於分類問題,同時近年也出現了一些在迴歸問題上的應用。就其應用adaBoost系列主要解決了: 兩類問題、多類單標籤問題、多類多標籤問題、大類單標籤問題,迴歸問題。

 

1.    爲數據集裏的每個樣本賦予相同的權重(一般情況),然後開始依據一定的分類標準來對該數據集分類,從而得到第一個Classifier[1](弱分類器)。同時由此可得此次分類中被分錯的樣本,提高他們的權重,用於下一個Classifier[2]的訓練。

2.    依據上一次Classifier訓練更新樣本權重後的樣本集,來訓練此次Classifier[2]。其中可以依據樣本權重來影響此次訓練的錯誤率來使此次Classifier[2]足夠重視之前錯分的樣本。這樣我們可以得到對於上次分錯的樣本有較好分類能力的Classifier[2],然後提高本次分類中被分錯的樣本的權重。重複此過程,得到若干的弱分類器Classifier[i]。

3.    爲1、2步中得到的Classifier[i]確定在最終的強分類器中的權重(此權重的確定也可以在1、2步中確定)。Strong_Classifier = ∑( weight[i] *Classifier[i])(弱分類器的線性組合),計算Strong_Classifier的錯誤率,然後綜合考慮程序迭代次數來判斷是否繼續重複1-3步迭代訓練。

 

對於這個算法需要介紹的是: 
1. 算法開始前,需要將每個樣本的權重初始化爲1/m,這樣一開始每個樣本都是等概率的分佈,每個分類器都會公正對待。 
2. 開始迭代後,需要計算每個弱分類器的分類錯誤的誤差,誤差等於各個分錯樣本的權重和,這裏就體現了樣本權重的作用。如果一個分類器正確分類了一個權重大的樣本,那麼這個分類器的誤差就會小,否則就會大。這樣就對分類錯誤的樣本更大的關注。 
3. 獲取最優分類器後,需要計算這個分類器的權重,然後再更新各個樣本的權重,然後再歸一化。 
4. 算法迭代的次數一般不超過弱分類器的個數,如果弱分類器的個數非常之多,那麼可以權衡自己性價比來折中選擇。 
5. 迭代完成後,最後的分類器是由迭代過程中選擇的弱分類器線性加權得到的。

弱分類器(單層決策樹)

daboost一般使用單層決策樹作爲其弱分類器。單層決策樹是決策樹的最簡化版本,只有一個決策點,也就是說,如果訓練數據有多維特徵,單層決策樹也只能選擇其中一維特徵來做決策,並且還有一個關鍵點,決策的閾值也需要考慮。

這裏寫圖片描述

關於單層決策樹的決策點,來看幾個例子。比如特徵只有一個維度時,可以以小於7的分爲一類,標記爲+1,大於(等於)7的分爲另一類,標記爲-1。當然也可以以13作爲決策點,決策方向是大於13的分爲+1類,小於(等於)13的分爲-1類。在單層決策樹中,一共只有一個決策點,所以下圖的兩個決策點不能同時選取。

這裏寫圖片描述

同樣的道理,當特徵有兩個維度時,可以以縱座標7作爲決策點,決策方向是小於7分爲+1類,大於(等於)7分類-1類。當然還可以以橫座標13作爲決策點,決策方向是大於13的分爲+1類,小於13的分爲-1類。在單層決策樹中,一共只有一個決策點,所以下圖的兩個決策點不能同時選取。

這裏寫圖片描述

擴展到三維、四維、N維都是一樣,在單層決策樹中,一共只有一個決策點,所以只能在其中一個維度中選擇一個合適的決策閾值作爲決策點。

關於Adaboost的兩種權重

Adaboost算法中有兩種權重,一種是數據的權重,另一種是弱分類器的權重。其中,數據的權重主要用於弱分類器尋找其分類誤差最小的決策點,找到之後用這個最小誤差計算出該弱分類器的權重(發言權),分類器權重越大說明該弱分類器在最終決策時擁有更大的發言權。

Adaboost數據權重與弱分類器

剛剛已經介紹了單層決策樹的原理,這裏有一個問題,如果訓練數據保持不變,那麼單層決策樹找到的最佳決策點每一次必然都是一樣的,爲什麼呢?因爲單層決策樹是把所有可能的決策點都找了一遍然後選擇了最好的,如果訓練數據不變,那麼每次找到的最好的點當然都是同一個點了。

所以,這裏Adaboost數據權重就派上用場了,所謂“數據的權重主要用於弱分類器尋找其分類誤差最小的點”,其實,在單層決策樹計算誤差時,Adaboost要求其乘上權重,即計算帶權重的誤差。

舉個例子,在以前沒有權重時(其實是平局權重時),一共10個點時,對應每個點的權重都是0.1,分錯1個,錯誤率就加0.1;分錯3個,錯誤率就是0.3。現在,每個點的權重不一樣了,還是10個點,權重依次是[0.01,0.01,0.01,0.01,0.01,0.01, 0.01,0.01,0.01,0.91],如果分錯了第1一個點,那麼錯誤率是0.01,如果分錯了第3個點,那麼錯誤率是0.01,要是分錯了最後一個點,那麼錯誤率就是0.91。這樣,在選擇決策點的時候自然是要儘量把權重大的點(本例中是最後一個點)分對才能降低誤差率。由此可見,權重分佈影響着單層決策樹決策點的選擇,權重大的點得到更多的關注,權重小的點得到更少的關注。

在Adaboost算法中,每訓練完一個弱分類器都就會調整權重,上一輪訓練中被誤分類的點的權重會增加,在本輪訓練中,由於權重影響,本輪的弱分類器將更有可能把上一輪的誤分類點分對,如果還是沒有分對,那麼分錯的點的權重將繼續增加,下一個弱分類器將更加關注這個點,儘量將其分對。

這樣,達到“你分不對的我來分”,下一個分類器主要關注上一個分類器沒分對的點,每個分類器都各有側重。

Adaboost分類器的權重

由於Adaboost中若干個分類器的關係是第N個分類器更可能分對第N-1個分類器沒分對的數據,而不能保證以前分對的數據也能同時分對。所以在Adaboost中,每個弱分類器都有各自最關注的點,每個弱分類器都只關注整個數據集的中一部分數據,所以它們必然是共同組合在一起才能發揮出作用。所以最終投票表決時,需要根據弱分類器的權重來進行加權投票,權重大小是根據弱分類器的分類錯誤率計算得出的,總的規律就是弱分類器錯誤率越低,其權重就越高。

 

如圖所示爲Adaboost分類器的整體結構。從右到左,可見最終的求和與符號函數,再看到左邊求和之前,圖中的虛線表示不同輪次的迭代效果,第1次迭代時,只有第1行的結構,第2次迭代時,包括第1行與第2行的結構,每次迭代增加一行結構,圖下方的“雲”表示不斷迭代結構的省略。

第i輪迭代要做這麼幾件事: 
1. 新增弱分類器WeakClassifier(i)與弱分類器權重alpha(i) 
2. 通過數據集data與數據權重W(i)訓練弱分類器WeakClassifier(i),並得出其分類錯誤率,以此計算出其弱分類器權重alpha(i) 
3. 通過加權投票表決的方法,讓所有弱分類器進行加權投票表決的方法得到最終預測輸出,計算最終分類錯誤率,如果最終錯誤率低於設定閾值(比如5%),那麼迭代結束;如果最終錯誤率高於設定閾值,那麼更新數據權重得到W(i+1)

 

Adaboost實例解析

例1. Adaboost的一個例子 
下面,給定下列訓練樣本,請用AdaBoost算法學習一個強分類器。 
這裏寫圖片描述 
求解過程: 
  初始化訓練數據的權值分佈,令每個權值W1i = 1/N = 0.1,其中,N = 10,i = 1,2, …, 10,然後分別對於m = 1,2,3, …等值進行迭代。 
  拿到這10個數據的訓練樣本後,根據 X 和 Y 的對應關係,要把這10個數據分爲兩類,一類是“1”,一類是“-1”,根據數據的特點發現:“0 1 2”這3個數據對應的類是“1”,“3 4 5”這3個數據對應的類是“-1”,“6 7 8”這3個數據對應的類是“1”,9是比較孤獨的,對應類“-1”。拋開孤獨的9不講,“0 1 2”、“3 4 5”、“6 7 8”這是3類不同的數據,分別對應的類是1、-1、1,直觀上推測可知,可以找到對應的數據分界點,比如2.5、5.5、8.5 將那幾類數據分成兩類。當然,這只是主觀臆測,下面實際計算下這個過程。 


迭代過程1 
(1) 對於m=1,在權值分佈爲D1(10個數據,每個數據的權值皆初始化爲0.1)的訓練數據上,經過計算可得:

  • 閾值v取2.5時誤差率爲0.3(x < 2.5時取1,x > 2.5時取-1,則6 7 8分錯,誤差率爲0.3),
  • 閾值v取5.5時誤差率最低爲0.4(x < 5.5時取1,x > 5.5時取-1,則3 4 5 6 7 8皆分錯,誤差率0.6大於0.5,不可取。故令x > 5.5時取1,x < 5.5時取-1,則0 1 2 9分錯,誤差率爲0.4),
  • 閾值v取8.5時誤差率爲0.3(x < 8.5時取1,x > 8.5時取-1,則3 4 5分錯,誤差率爲0.3)。

所以無論閾值v取2.5,還是8.5,總得分錯3個樣本,故可任取其中任意一個如2.5,夠成第一個基本分類器爲: 

  • 上面說閾值v取2.5時則6 7 8分錯,所以誤差率爲0.3,更加詳細的解釋是:因爲樣本集中0 1 2對應的類(Y)是1,因它們本身都小於2.5,所以被G1(x)分在了相應的類“1”中,分對了。
  • 3 4 5本身對應的類(Y)是-1,因它們本身都大於2.5,所以被G1(x)分在了相應的類“-1”中,分對了。
  • 但6 7 8本身對應類(Y)是1,卻因它們本身大於2.5而被G1(x)分在了類”-1”中,所以這3個樣本被分錯了。
  • 9本身對應的類(Y)是-1,因它本身大於2.5,所以被G1(x)分在了相應的類“-1”中,分對了。

(2) 從而得到G1(x)在訓練數據集上的誤差率(被G1(x)誤分類樣本“6 7 8”的權值之和)e1=P(G1(xi)≠yi) = 3*0.1 = 0.3。然後根據誤差率e1計算G1的係數: 


這個a1代表G1(x)在最終的分類函數中所佔的權重爲0.4236。 
(3) 接着更新訓練數據的權值分佈,用於下一輪迭代。 
這裏寫圖片描述 
  值得一提的是,由權值更新的公式可知,每個樣本的新權值是變大還是變小,取決於它是被分錯還是被分正確。即如果某個樣本被分錯了,則yi * Gm(xi)爲負,負負等正,結果使得整個式子變大(樣本權值變大),否則變小。 
(4) 第一輪迭代後,最後得到各個數據新的權值分佈: 
       D2 = (0.0715, 0.0715, 0.0715, 0.0715, 0.0715, 0.0715, 0.1666, 0.1666, 0.1666, 0.0715)。 
      由此可以看出,因爲樣本中是數據“6 7 8”被G1(x)分錯了,所以它們的權值由之前的0.1增大到0.1666,反之,其它數據皆被分正確,所以它們的權值皆由之前的0.1減小到0.0715。 
(5) 分類函數:f1(x)= a1*G1(x) = 0.4236G1(x)。

此時,得到的第一個基本分類器sign(f1(x))在訓練數據集上有3個誤分類點(即6 7 8)。從上述第一輪的整個迭代過程可以看出:被誤分類樣本的權值之和影響誤差率,誤差率影響基本分類器在最終分類器中所佔的權重。

 
迭代過程2 
(1) 對於m=2,在權值分佈爲D2 = (0.0715, 0.0715, 0.0715, 0.0715, 0.0715, 0.0715, 0.1666, 0.1666, 0.1666, 0.0715)的訓練數據上,經過計算可得:

  • 閾值v取2.5時誤差率爲0.1666*3(x < 2.5時取1,x > 2.5時取-1,則6 7 8分錯,誤差率爲0.1666*3),
  • 閾值v取5.5時誤差率最低爲0.0715*4(x > 5.5時取1,x < 5.5時取-1,則0 1 2 9分錯,誤差率爲0.0715*3 + 0.0715),
  • 閾值v取8.5時誤差率爲0.0715*3(x < 8.5時取1,x > 8.5時取-1,則3 4 5分錯,誤差率爲0.0715*3)。

所以,閾值v取8.5時誤差率最低,故第二個基本分類器爲: 


(2) 面對的還是下述樣本: 
這裏寫圖片描述 
很明顯,G2(x)把樣本“3 4 5”分錯了,根據D2可知它們的權值爲0.0715, 0.0715, 0.0715,所以G2(x)在訓練數據集上的誤差率e2=P(G2(xi)≠yi) = 0.0715 * 3 = 0.2143。 
計算G2的係數: 


(3) 更新訓練數據的權值分佈: 
D3 = (0.0455, 0.0455, 0.0455, 0.1667, 0.1667, 0.01667, 0.1060, 0.1060, 0.1060, 0.0455)。 
被分錯的樣本“3 4 5”的權值變大,其它被分對的樣本的權值變小。 
(4) f2(x)=0.4236G1(x) + 0.6496G2(x) 
此時,得到的第二個基本分類器sign(f2(x))在訓練數據集上有3個誤分類點(即3 4 5)


迭代過程3 
(1) 對於m=3,在權值分佈爲D3 = (0.0455, 0.0455, 0.0455, 0.1667, 0.1667, 0.01667, 0.1060, 0.1060, 0.1060, 0.0455)的訓練數據上,經過計算可得:

  • 閾值v取2.5時誤差率爲0.1060*3(x < 2.5時取1,x > 2.5時取-1,則6 7 8分錯,誤差率爲0.1060*3),
  • 閾值v取5.5時誤差率最低爲0.0455*4(x > 5.5時取1,x < 5.5時取-1,則0 1 2 9分錯,誤差率爲0.0455*3 + 0.0715),
  • 閾值v取8.5時誤差率爲0.1667*3(x < 8.5時取1,x > 8.5時取-1,則3 4 5分錯,誤差率爲0.1667*3)。

所以閾值v取5.5時誤差率最低,故第三個基本分類器爲: 


(2) 依然還是原樣本: 
這裏寫圖片描述 
此時,被誤分類的樣本是:0 1 2 9,這4個樣本所對應的權值皆爲0.0455, 所以G3(x)在訓練數據集上的誤差率e3 = P(G3(xi)≠yi) = 0.0455*4 = 0.1820。 
計算G3的係數: 

(3) 更新訓練數據的權值分佈: 
D4 = (0.125, 0.125, 0.125, 0.102, 0.102, 0.102, 0.065, 0.065, 0.065, 0.125)。 
被分錯的樣本“0 1 2 9”的權值變大,其它被分對的樣本的權值變小。 
(4) f3(x)=0.4236G1(x) + 0.6496G2(x)+0.7514G3(x) 
此時,得到的第三個基本分類器sign(f3(x))在訓練數據集上有0個誤分類點。至此,整個訓練過程結束。 
 

訓練結束 
G(x) = sign[f3(x)] = sign[ a1 * G1(x) + a2 * G2(x) + a3 * G3(x) ], 
將上面計算得到的a1、a2、a3各值代入G(x)中,得到最終的分類器爲: 
G(x) = sign[f3(x)] = sign[ 0.4236G1(x) + 0.6496G2(x)+0.7514G3(x) ]

 

        毫無疑問這個模型的最大的一個優點是可以自動的組合弱分類器,這在實際應用中的便利之處十分明顯。算法本身簡單,高效,易於編寫而且訓練過程是沒有參數需要調節的。 但是adaboost也是有缺點的,並不是所有問題都能搞定,從wiki上介紹的來看,adaboost對於噪音數據和異常數據是十分敏感的。

對於boosting算法,存在兩個問題:   
1. 如何調整訓練集,使得在訓練集上訓練的弱分類器得以進行;    
2. 如何將訓練得到的各個弱分類器聯合起來形成強分類器。 
針對以上兩個問題,AdaBoost算法進行了調整:   
1. 使用加權後選取的訓練數據代替隨機選取的訓練樣本,這樣將訓練的焦點集中在比較難分的訓練數據樣本上;    
2. 將弱分類器聯合起來,使用加權的投票機制代替平均投票機制。讓分類效果好的弱分類器具有較大的權重,而分類效果差的分類器具有較小的權重。  

 

圖示說明adaboost的實現過程

圖中,“+”和“-”分別表示兩種類別,在這個過程中,我們使用水平或者垂直的直線作爲分類器,來進行分類。 
第一步: 

根據分類的正確率,得到一個新的樣本分佈D2­,一個子分類器h1。

其中劃圈的樣本表示被分錯的。在右邊的途中,比較大的“+”表示對該樣本做了加權。 
也許你對上面的ɛ1,ɑ1怎麼算的也不是很理解。下面我們算一下,算法最開始給了一個均勻分佈 D 。所以h1 裏的每個點的值是0.1。ok,當劃分後,有三個點劃分錯了,根據算法誤差表達式ε1=Pri∼Dt[ht(xi)≠yi]ε1=Pri∼Dt[ht(xi)≠yi],得到誤差爲分錯了的三個點的值之和,所以ɛ1=(0.1+0.1+0.1)=0.3,而ɑ1 根據表達式的可以算出來爲0.42. 然後就根據算法把分錯的點權值變大。如此迭代,最終完成Adaboost算法。 

第二步: 

根據分類的正確率,得到一個新的樣本分佈D3,一個子分類器h2。 
第三步: 

得到一個子分類器h3

整合所有子分類器:

因此可以得到整合的結果,從結果中看,及時簡單的分類器,組合起來也能獲得很好的分類效果,在例子中所有的。

       而a是關於誤差的表達式,到這裏就可以得到比較清晰的答案了,所有的一切都指向了誤差。提高錯誤點的權值,當下一次分類器再次分錯了這些點之後,會提高整體的錯誤率,這樣就導致 a 變的很小,最終導致這個分類器在整個混合分類器的權值變低。也就是說,這個算法讓優秀的分類器佔整體的權值更高,而挫的分類器權值更低。這個就很符合常理了。

 

三、GBDT(Gradient Boosting Decision Tree) 梯度提升決策樹算法

GBDT(Gradient Boosting Decision Tree) 又叫 MART(Multiple Additive Regression Tree),是一種迭代的決策樹算法,該算法由多棵決策樹組成,所有樹的結論累加起來做最終答案。它在被提出之初就和SVM一起被認爲是泛化能力較強的算法。


GBDT是一種基於boosting集成學習(ensemble method)的算法,但和傳統的Adaboost有很大不同。在Adaboost,我們是利用前一輪迭代弱學習器的誤差率來更新訓練集的權重,這樣一輪輪的迭代下去。GBDT也是迭代,使用了前向分佈算法,但是弱學習器限定了只能使用CART迴歸樹模型,同時迭代思路和Adaboost也有所不同。GBDT的訓練過程如下: 

 

GBDT中的樹是迴歸樹(不是分類樹),GBDT用來做迴歸預測,調整後也可以用於分類。

GBDT主要由三個概念組成:

Regression Decistion Tree(即DT),Gradient Boosting(即GB),Shrinkage (算法的一個重要演進分枝,目前大部分源碼都按該版本實現)。搞定這三個概念後就能明白GBDT是如何工作的。

1. DT:迴歸樹 Regression Decision Tree

提起決策樹(DT, Decision Tree) 絕大部分人首先想到的就是C4.5分類決策樹。但如果一開始就把GBDT中的樹想成分類樹,那就錯了。千萬不要以爲GBDT是很多棵分類樹。決策樹分爲兩大類,迴歸樹和分類樹。前者用於預測實數值,如明天的溫度、用戶的年齡、網頁的相關程度;後者用於分類標籤值,如晴天/陰天/霧/雨、用戶性別、網頁是否是垃圾頁面。這裏要強調的是,前者的結果加減是有意義的,如10歲+5歲-3歲=12歲,後者則無意義,如男+男+女=到底是男是女?GBDT的核心在於累加所有樹的結果作爲最終結果,就像前面對年齡的累加(-3是加負3),而分類樹的結果顯然是沒辦法累加的,所以GBDT中的樹都是迴歸樹,不是分類樹,這點對理解GBDT相當重要(儘管GBDT調整後也可用於分類但不代表GBDT的樹是分類樹)。

迴歸樹總體流程類似於分類樹,區別在於,迴歸樹的每一個節點都會得一個預測值,以年齡爲例,該預測值等於屬於這個節點的所有人年齡的平均值。分枝時窮舉每一個feature的每個閾值找最好的分割點,但衡量最好的標準不再是最大熵,而是最小化平方誤差。也就是被預測出錯的人數越多,錯的越離譜,平方誤差就越大,通過最小化平方誤差能夠找到最可靠的分枝依據。分枝直到每個葉子節點上人的年齡都唯一或者達到預設的終止條件(如葉子個數上限),若最終葉子節點上人的年齡不唯一,則以該節點上所有人的平均年齡做爲該葉子節點的預測年齡。

 

迴歸樹算法如下圖(截圖來自《統計學習方法》5.5.1 CART生成):

 

 

 

2. GB:梯度迭代 Gradient Boosting

梯度提升(Gradient boosting)是一種用於迴歸、分類和排序任務的機器學習技術,屬於Boosting算法族的一部分。Boosting是一族可將弱學習器提升爲強學習器的算法,屬於集成學習(ensemble learning)的範疇。Boosting方法基於這樣一種思想:對於一個複雜任務來說,將多個專家的判斷進行適當的綜合所得出的判斷,要比其中任何一個專家單獨的判斷要好。通俗地說,就是“三個臭皮匠頂個諸葛亮”的道理。梯度提升同其他boosting方法一樣,通過集成(ensemble)多個弱學習器,通常是決策樹,來構建最終的預測模型。

Boosting、bagging和stacking是集成學習的三種主要方法。

不同於bagging方法,boosting方法通過分步迭代(stage-wise)的方式來構建模型,在迭代的每一步構建的弱學習器都是爲了彌補已有模型的不足。Boosting族算法的著名代表是AdaBoost。AdaBoost算法通過給已有模型預測錯誤的樣本更高的權重,使得先前的學習器做錯的訓練樣本在後續受到更多的關注的方式來彌補已有模型的不足。

雖然同屬於Boosting族,但是梯度提升方法的優點比較多。

相比於AdaBoost,梯度提升方法的優點:

  • 1、與AdaBoost算法不同,梯度提升方法在迭代的每一步構建一個能夠沿着梯度最陡的方向降低損失(steepest-descent)的學習器來彌補已有模型的不足。
  • 2、經典的AdaBoost算法只能處理採用指數損失函數的二分類學習任務,而梯度提升方法通過設置不同的可微損失函數可以處理各類學習任務(多分類、迴歸、Ranking等),應用範圍大大擴展。
  • 3、AdaBoost算法對異常點(outlier)比較敏感,而梯度提升算法通過引入bagging思想、加入正則項等方法能夠有效地抵禦訓練數據中的噪音,具有更好的健壯性。

       提升樹是迭代多棵迴歸樹來共同決策。當採用平方誤差損失函數時,每一棵迴歸樹學習的是之前所有樹的結論和殘差,擬合得到一個當前的殘差迴歸樹,殘差的意義如公式:殘差 = 真實值 - 預測值 。提升樹即是整個迭代過程生成的迴歸樹的累加。GBDT的核心就在於,每一棵樹學的是之前所有樹結論和的殘差,這個殘差就是一個加預測值後能得真實值的累加量。

 

3. Gradient Boosting Decision Tree:梯度提升決策樹

爲什麼梯度提升方法傾向於選擇決策樹(通常是CART樹)作爲基學習器呢?

這與決策樹算法自身的優點有很大的關係:

  1. 決策樹可以認爲是if-then規則的集合,易於理解,可解釋性強,預測速度快;
  2. 決策樹算法相比於其他的算法需要更少的特徵工程,比如可以不用做特徵標準化,可以很好的處理字段缺失的數據,也可以不用關心特徵間是否相互依賴等
  3. 決策樹能夠自動組合多個特徵,它可以毫無壓力地處理特徵間的交互關係並且是非參數化的,因此你不必擔心異常值或者數據是否線性可分。舉個例子,西瓜a(烏黑色、紋路清晰)可能是好瓜,西瓜b(青綠色,紋路清晰)的也可能是好瓜。決策樹一樣可以處理。

決策樹有優點,自然也有缺點,不過,可以通過梯度提升方法解決這個缺點。單獨使用決策樹算法時,有容易過擬合缺點。

怎麼解決呢?

  • 通過各種方法,抑制決策樹的複雜性,降低單棵決策樹的擬合能力
  • 通過梯度提升的方法集成多個決策樹,則預測效果上來的同時,也能夠很好的解決過擬合的問題。
    (這一點具有bagging的思想,降低單個學習器的擬合能力,提高方法的泛化能力。)

由此可見,梯度提升方法和決策樹學習算法可以互相取長補短,是一對完美的搭檔。

怎麼降低單棵決策樹的複雜度?

抑制單顆決策樹的複雜度的方法有很多:

  • 限制樹的最大深度、限制葉子節點的最少樣本數量、限制節點分裂時的最少樣本數量
  • 吸收bagging的思想對訓練樣本採樣(subsample),在學習單顆決策樹時只使用一部分訓練樣本
  • 借鑑隨機森林的思路在學習單顆決策樹時只採樣一部分特徵
  • 在目標函數中添加正則項懲罰複雜的樹結構等。

現在主流的GBDT算法實現中這些方法基本上都有實現,因此GBDT算法的超參數還是比較多的,應用過程中需要精心調參,並用交叉驗證的方法選擇最佳參數。

提升樹利用加法模型前向分步算法實現學習的優化過程。當損失函數時平方損失和指數損失函數時,每一步的優化很簡單,如平方損失函數學習殘差迴歸樹。

 

前向分佈算法(Forward stagewise additive modeling)

提升方法其實是一個比adaboost概念更大的算法,因爲adaboost可以表示爲boosting的前向分佈算法(Forward stagewise additive modeling)的一個特例,boosting最終可以表示爲:

其中的w是權重,Φ是弱分類器(迴歸器)的集合,其實就是一個加法模型(即基函數的線性組合)

前向分佈算法實際上是一個貪心的算法,也就是在每一步求解弱分類器Φ(m)和其參數w(m)的時候不去修改之前已經求好的分類器和參數:

前向分佈算法 來自《統計學習方法》


爲了表示方便,我們以後用β代替w進行描述了,圖中的b是之前說的Φ弱分類器

OK,這也就是提升方法(之前向分佈算法)的大致結構了,可以看到其中存在變數的部分其實就是極小化損失函數 這關鍵的一步了,如何選擇損失函數決定了算法的最終效果(名字)……這一步你可以看出算法的“趨勢”,以後再單獨把“趨勢”拿出來說吧,因爲我感覺理解算法的關鍵之一就是理解算法公式的“趨勢”

各種提升方法

不同的損失函數和極小化損失函數方法決定了boosting的最終效果,我們現在來說幾個常見的boosting:

廣義上來講,所謂的Gradient Boosting 其實就是在更新的時候選擇梯度下降的方向來保證最後的結果最好,一些書上講的“殘差” 方法其實就是L2Boosting吧,因爲它所定義的殘差其實就是L2Boosting的Derivative,接下來我們着重講一下弱迴歸器是決策樹的情況,也就是GBDT。

加法模型(additive model)

GBDT算法可以看成是由K棵樹組成的加法模型:

其中F爲所有樹組成的函數空間,以迴歸任務爲例,迴歸樹可以看作爲一個把特徵向量映射爲某個score的函數。該模型的參數爲:Θ = {f1, f2, ... , fk} 。於一般的機器學習算法不同的是,加法模型不是學習d維空間中的權重,而是直接學習函數(決策樹)集合。上述加法模型的目標函數定義爲:

其中Ω表示決策樹的複雜度,那麼該如何定義樹的複雜度呢?比如,可以考慮樹的節點數量、樹的深度或者葉子節點所對應的分數的L2範數等等。

如何來學習加法模型呢?

解這一優化問題,可以用前向分佈算法(forward stagewise algorithm)。因爲學習的是加法模型,如果能夠從前往後,每一步只學習一個基函數及其係數(結構),逐步逼近優化目標函數,那麼就可以簡化複雜度。這一學習過程稱之爲Boosting。具體地,我們從一個常量預測開始,每次學習一個新的函數,過程如下:

舉個例子,參考自一篇博客, 該博客舉出的例子較直觀地展現出多棵決策樹線性求和過程以及殘差的意義。
還是年齡預測,簡單起見訓練集只有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的殘差就是15-16=-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。

講到這裏我們已經把GBDT最核心的概念、運算過程講完了!沒錯就是這麼簡單。

該例子很直觀的能看到,預測值等於所有樹值得累加,如A的預測值 = 樹1左節點 值 15 + 樹2左節點 -1 = 14。
因此,給定當前模型 fm-1(x),只需要簡單的擬合當前模型的殘差。現將回歸問題的提升樹算法敘述如下:

1)既然圖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。就像我們做互聯網,總是先解決60%用戶的需求湊合着,再解決35%用戶的需求,最後才關注那5%人的需求,這樣就能逐漸把產品做好,因爲不同類型用戶需求可能完全不同,需要分別獨立分析。如果反過來做,或者剛上來就一定要做到盡善盡美,往往最終會竹籃打水一場空。

4. Shrinkage

Shrinkage(縮減)的思想認爲,每次走一小步逐漸逼近結果的效果,要比每次邁一大步很快逼近結果的方式更容易避免過擬合。即它不完全信任每一個棵殘差樹,它認爲每棵樹只學到了真理的一小部分,累加的時候只累加一小部分,通過多學幾棵樹彌補不足。用方程來看更清晰,即
沒用Shrinkage時:(yi表示第i棵樹上y的預測值, y(1~i)表示前i棵樹y的綜合預測值)
y(i+1) = 殘差(y1~yi), 其中: 殘差(y1~yi) = y真實值 - y(1 ~ i)
y(1 ~ i) = SUM(y1, ..., yi)
Shrinkage不改變第一個方程,只把第二個方程改爲:
y(1 ~ i) = y(1 ~ i-1) + step * yi

即Shrinkage仍然以殘差作爲學習目標,但對於殘差學習出來的結果,只累加一小部分(step殘差)逐步逼近目標,step一般都比較小,如0.01~0.001(注意該step非gradient的step),導致各個樹的殘差是漸變的而不是陡變的。直覺上這也很好理解,不像直接用殘差一步修復誤差,而是隻修復一點點,其實就是把大步切成了很多小步。本質上,Shrinkage爲每棵樹設置了一個weight,累加時要乘以這個weight,但和Gradient並沒有關係*。 這個weight就是step。就像Adaboost一樣,Shrinkage能減少過擬合發生也是經驗證明的,目前還沒有看到從理論的證明。

GBDT的適用範圍

該版本GBDT幾乎可用於所有迴歸問題(線性/非線性),相對logistic regression僅能用於線性迴歸,GBDT的適用面非常廣。亦可用於二分類問題(設定閾值,大於閾值爲正例,反之爲負例)。

 

四、XGBoost算法

 

XGboost/GBDT調參

推薦GBDT樹的深度:6;(橫向比較:DecisionTree/RandomForest需要把樹的深度調到15或更高)

以下摘自知乎上的一個問答(詳見參考文獻8),問題和回覆都很好的闡述了這個參數設置的數學原理。

【問】xgboost/gbdt在調參時爲什麼樹的深度很少就能達到很高的精度?
  用xgboost/gbdt在在調參的時候把樹的最大深度調成6就有很高的精度了。但是用DecisionTree/RandomForest的時候需要把樹的深度調到15或更高。用RandomForest所需要的樹的深度和DecisionTree一樣我能理解,因爲它是用bagging的方法把DecisionTree組合在一起,相當於做了多次DecisionTree一樣。但是xgboost/gbdt僅僅用梯度上升法就能用6個節點的深度達到很高的預測精度,使我驚訝到懷疑它是黑科技了。請問下xgboost/gbdt是怎麼做到的?它的節點和一般的DecisionTree不同嗎?
【答】
  這是一個非常好的問題,題主對各算法的學習非常細緻透徹,問的問題也關係到這兩個算法的本質。這個問題其實並不是一個很簡單的問題,我嘗試用我淺薄的機器學習知識對這個問題進行回答。
  一句話的解釋,來自周志華老師的機器學習教科書( 機器學習-周志華):Boosting主要關注降低偏差,因此Boosting能基於泛化性能相當弱的學習器構建出很強的集成;Bagging主要關注降低方差,因此它在不剪枝的決策樹、神經網絡等學習器上效用更爲明顯。
  隨機森林(random forest)和GBDT都是屬於集成學習(ensemble learning)的範疇。集成學習下有兩個重要的策略Bagging和Boosting。
  Bagging算法是這樣做的:每個分類器都隨機從原樣本中做有放回的採樣,然後分別在這些採樣後的樣本上訓練分類器,然後再把這些分類器組合起來。簡單的多數投票一般就可以。其代表算法是隨機森林。Boosting的意思是這樣,他通過迭代地訓練一系列的分類器,每個分類器採用的樣本分佈都和上一輪的學習結果有關。其代表算法是AdaBoost, GBDT。
  其實就機器學習算法來說,其泛化誤差可以分解爲兩部分,偏差(bias)和方差(variance)。這個可由下圖的式子導出(這裏用到了概率論公式D(X)=E(X2)-[E(X)]2)。偏差指的是算法的期望預測與真實預測之間的偏差程度,反應了模型本身的擬合能力;方差度量了同等大小的訓練集的變動導致學習性能的變化,刻畫了數據擾動所導致的影響。這個有點兒繞,不過你一定知道過擬合。
  如下圖所示,當模型越複雜時,擬合的程度就越高,模型的訓練偏差就越小。但此時如果換一組數據可能模型的變化就會很大,即模型的方差很大。所以模型過於複雜的時候會導致過擬合。
  當模型越簡單時,即使我們再換一組數據,最後得出的學習器和之前的學習器的差別就不那麼大,模型的方差很小。還是因爲模型簡單,所以偏差會很大。

 

模型複雜度與偏差方差的關係圖

 

  也就是說,當我們訓練一個模型時,偏差和方差都得照顧到,漏掉一個都不行。
  對於Bagging算法來說,由於我們會並行地訓練很多不同的分類器的目的就是降低這個方差(variance) ,因爲採用了相互獨立的基分類器多了以後,h的值自然就會靠近.所以對於每個基分類器來說,目標就是如何降低這個偏差(bias),所以我們會採用深度很深甚至不剪枝的決策樹。
  對於Boosting來說,每一步我們都會在上一輪的基礎上更加擬合原數據,所以可以保證偏差(bias),所以對於每個基分類器來說,問題就在於如何選擇variance更小的分類器,即更簡單的分類器,所以我們選擇了深度很淺的決策樹。

 

五、其他

Gradient Boosting算法:xgboost,在計算速度和準確率上,較GBDT有明顯的提升。xgboost 的全稱是eXtreme Gradient Boosting,它是Gradient Boosting Machine的一個c++實現,作者爲正在華盛頓大學研究機器學習的大牛陳天奇 。xgboost最大的特點在於,它能夠自動利用CPU的多線程進行並行,同時在算法上加以改進提高了精度。它的處女秀是Kaggle的 希格斯子信號識別競賽,因爲出衆的效率與較高的預測準確度在比賽論壇中引起了參賽選手的廣泛關注。值得我們在GBDT的基礎上對其進一步探索學習。

 

參考:

  1. https://www.jianshu.com/p/6755107e816d
  2. https://www.jianshu.com/p/a72539acafe5
  3. https://blog.csdn.net/fengying2016/article/details/77239605
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章