AdaBoost算法詳解與python實現

  • 2020 年 11 月 3 日
  • 筆記

1. 概述

1.1 集成學習

目前存在各種各樣的機器學習算法,例如SVM、決策樹、感知機等等。但是實際應用中,或者說在打比賽時,成績較好的隊伍幾乎都用了集成學習(ensemble learning)的方法。集成學習的思想,簡單來講,就是「三個臭皮匠頂個諸葛亮」。集成學習通過結合多個學習器(例如同種算法但是參數不同,或者不同算法),一般會獲得比任意單個學習器都要好的性能,尤其是在這些學習器都是”弱學習器”的時候提升效果會很明顯。

弱學習器指的是性能不太好的學習器,比如一個準確率略微超過50%的二分類器。

下面看看西瓜書對此做的一個簡單理論分析。
考慮一個二分類問題[公式]、真實函數[公式]以及[公式]個相互獨立且犯錯概率均為[公式]的個體學習器(或者稱基學習器)[公式]。我們用簡單的投票進行集成學習,即分類結果取半數以上的基學習器的結果:

[公式]

由Hoeffding不等式知,集成學習後的犯錯(即過半數基學習器犯錯)概率滿足

[公式]

 

[公式]指出,當犯錯概率獨立的基學習器個數[公式]很大時,集成後的犯錯概率接近0,這也很符合直觀想法: 大多數人同時犯錯的概率是比較低的。

就如上面加粗字體強調的,以上推論全部建立在基學習器犯錯相互獨立的情況下,但實際中這些學習器不可能相互獨立,而如何讓基學習器變得「相對獨立一些」,也即增加這些基學習器的多樣性,正是集成學習需要考慮的主要問題。

按照每個基學習器之間是否存在依賴關係可以將集成學習分為兩類:

  1. 基學習器之間存在強依賴關係,一系列基學習器需要串行生成,代表算法是Boosting;
  2. 基學習器之間不存在強依賴關係,一系列基學習器可並行生成,代表算法是Bagging和隨機森林。

Boosting系列算法里最著名算法主要有AdaBoost和提升樹(Boosting tree)系列算法,本文只介紹最具代表性的AdaBoost。提升樹、Bagging以及隨機森林不在本文介紹範圍內,有時間了再另外介紹。

1.2 Boosting

Boosting指的是一類集成方法,其主要思想就是將弱的基學習器提升(boost)為強學習器。具體步驟如下:

  1. 先用每個樣本權重相等的訓練集訓練一個初始的基學習器;
  2. 根據上輪得到的學習器對訓練集的預測表現情況調整訓練集中的樣本權重(例如提高被錯分類的樣本的權重使之在下輪訓練中得到更多的關注), 然後據此訓練一個新的基學習器;
  3. 重複2直到得到[公式]個基學習器,最終的集成結果是[公式]個基學習器的組合。

由此看出,Boosting算法是一個串行的過程。

Boosting算法簇中最著名的就是AdaBoost,下文將會詳細介紹。

2. AdaBoost原理

2.1 基本思想

對於1.2節所述的Boosting算法步驟,需要回答兩個問題:

  1. 如何調整每一輪的訓練集中的樣本權重?
  2. 如何將得到的[公式]個學習器組合成最終的學習器?

AdaBoost(Adaptive Boosting, 自適應增強)算法採取的方法是:

  1. 提高上一輪被錯誤分類的樣本的權值,降低被正確分類的樣本的權值;
  2. 線性加權求和。誤差率小的基學習器擁有較大的權值,誤差率大的基學習器擁有較小的權值。

下面先給出AdaBoost算法具體實現步驟,至於算法解釋(為什麼要這樣做)將在下一大節闡述。

2.2 算法步驟

考慮如下形式的二分類(標準AdaBoost算法只適用於二分類任務)訓練數據集:[公式]其中[公式]是一個含有[公式]個元素的列向量, 即[公式];[公式]是標量,[公式]

Adaboost算法具體步驟如下:

  1. 初始化樣本的權重

[公式]

  1. [公式],重複以下操作得到[公式]個基學習器:
    (1) 按照樣本權重分佈[公式]訓練數據得到第[公式]個基學習器:[公式]

     (2) 計算[公式]在加權訓練數據集上的分類誤差率:

[公式]

上式中[公式]是指示函數,考慮更加周全的AdaBoost算法在這一步還應該判斷是否滿足基本條件(例如生成的基學習器是否比隨機猜測好), 如果不滿足,則當前基學習器被拋棄,學習過程提前終止。

   (3) 計算[公式]的係數(即最終集成使用的的基學習器的權重):

[公式]

(4) 更新訓練樣本的權重,其中[公式]是規範化因子,目的是為了使[公式]的所有元素和為1。

[公式][公式]

[公式]

  1. 構建最終的分類器線性組合

[公式]   得到最終的分類器為

[公式]

由式[公式]知,當基學習器[公式]的誤差率[公式]時,[公式],並且[公式]隨着[公式]的減小而增大,即分類誤差率越小的基學習器在最終集成時佔比也越大。即AdaBoost能夠適應各個弱分類器的訓練誤差率,這也是它的名稱中”適應性(Adaptive)”的由來。

由式[公式]知, 被基學習器[公式]誤分類的樣本權值得以擴大,而被正確分類的樣本的權值被得以縮小。

需要注意的是式[公式]中所有的[公式]的和並不為1(因為沒有做一個softmax操作),[公式]的符號決定了所預測的類,其絕對值代表了分類的確信度。

3. AdaBoost算法解釋

有沒有想過為什麼AdaBoost算法長上面這個樣子,例如為什麼[公式]要用式[公式]那樣計算?本節將探討這個問題。

3.1 前向分步算法

在解釋AdaBoost算法之前,先來看看前向分步算法。就以AdaBoost算法的最終模型表達式為例:

[公式]

可以看到這是一個「加性模型(additive model)」。我們希望這個模型在訓練集上的經驗誤差最小,即

[公式]

通常這是一個複雜的優化問題。前向分步算法求解這一優化問題的思想就是: 因為最終模型是一個加性模型,如果能從前往後,每一步只學習一個基學習器[公式]及其權重[公式], 不斷迭代得到最終的模型,那麼就可以簡化問題複雜度。具體的,當我們經過[公式]輪迭代得到了最優模型[公式]時,因為

[公式]所以此輪優化目標就為[公式]求解上式即可得到第[公式]個基分類器[公式]及其權重[公式]
這樣,前向分步算法就通過不斷迭代求得了從[公式][公式]的所有基分類器及其權重,問題得到了解決。

3.2 AdaBoost算法證明

上一小結介紹的前向分步算法逐一學習基學習器,這一過程也即AdaBoost算法逐一學習基學習器的過程。本節就證明前向分步算法的損失函數是指數損失函數(exponential loss function)時,AdaBoost學習的具體步驟就如2.2節所示。

指數損失函數即[公式],指數損失函數是分類任務原本0/1損失函數的一致(consistent)替代損失函數(損失函數的上界,優化指數損失函數,等價於優化AdaBoost的損失函數)。由於指數損失函數有更好的數學性質,例如處處可微,所以我們用它替代0/1損失作為優化目標。

將指數損失函數代入式[公式],優化目標就為[公式]因為[公式]與優化變量[公式][公式]無關,如果令[公式]

這個[公式]其實就是2.2節中歸一化之前的權重[公式]

那麼式[公式]等價於[公式]

我們分兩步來求解式[公式]所示的優化問題的最優解[公式][公式]:

  1. 對任意的[公式], 求[公式][公式]上式將指數函數換成指示函數是因為前面說的指數損失函數和0/1損失函數是一致等價的。

式子[公式]所示的優化問題其實就是AdaBoost算法的基學習器的學習過程,即2.2節的步驟2(1),得到的[公式]是使第[公式]輪加權訓練數據分類誤差最小的基分類器。

  1. 求解[公式]

將式子[公式]中的目標函數展開[公式]註:為了簡潔,上式子中的[公式]被略去了[公式][公式]被略去了下標[公式],下同
將上式對[公式]求導並令導數為0,即[公式]解得[公式]其中,[公式]是分類誤差率:[公式]如果式子[公式]中的[公式]歸一化成和為1的話那麼式[公式]也就和2.2節式[公式]一模一樣了,進一步地也有上面的[公式]也就是2.2節的[公式]
最後來看看每一輪樣本權值的更新,由[公式][公式]可得[公式]如果將上式進行歸一化成和為1的話就和與2.2節中[公式]完全相同了。

由此可見,2.2節所述的AdaBoost算法步驟是可以經過嚴密推導得來的。總結一下,本節推導有如下關鍵點:

  • AdaBoost算法是一個加性模型,將其簡化成前向分步算法求解;
  • 將0/1損失函數用數學性質更好的指數損失函數替代。

代碼如下

    1. 對任意的[公式], 求[公式][公式]上式將指數函數換成指示函數是因為前面說的指數損失函數和0/1損失函數是一致等價的。
      式子[公式]所示的優化問題其實就是AdaBoost算法的基學習器的學習過程,即2.2節的步驟2(1),得到的[公式]是使第[公式]輪加權訓練數據分類誤差最小的基分類器。