LESSON 11.4 原理进阶:AdaBoost算法流程详解
2 原理進階:AdaBoost的求解流程
在使用AdaBoost算法時,我們并不需要對AdaBoost的具體求解流程掌握太過于深入。嚴格來說,只要知道參數的含義,即便我們完全不了解AdaBoost的求解流程,我們也能夠自由地調用這個算法。然而,對于參數較少、原理簡單的AdaBoost來說或許是okay的,對于后續即將要學習的復雜Boosting算法而言,我們卻很難再避開復雜數學推導與原理。即便是為了應對面試中會出現的“你都知道哪些boosting算法?這些算法之間有什么異同?”,我們也必須對Boosting算法的原理有所掌握。
對于任意Boosting算法,我們都需要明確以下幾點:
損失函數 𝐿(𝑥,𝑦) 的表達式是什么?損失函數如何影響模型構建?
弱評估器 𝑓(𝑥) 是什么,當下boosting算法使用的具體建樹過程是什么?
綜合集成結果 𝐻(𝑥) 是什么?集成算法具體如何輸出集成結果?
同時,還可能存在其他需要明確的問題,例如:
是加權求和嗎?如果是,加權求和中的權重如何求解?
訓練過程中,擬合的數據 𝑋 與 𝑦 分別是什么?
模型訓練到什么時候停下來最好?
在此基本指導思想下,我們來梳理回歸算法的基本流程(考慮到后續Boosting算法也是以回歸為主流,因此在這里我們梳理回歸算法的基本流程)。
- AdaBoost.R2
AdaBoost.R2算法是當前AdaBoost實現流程中使用最多的回歸類實踐方式,它囊括了對數據進行有放回抽樣、按損失函數結果調整樣本權重、自動計算弱分類器權重、并輸出預測結果等AdaBoost算法經典的全流程。假設現有數據集N,含有樣本𝑀個,任意樣本編號為𝑖,同時,弱評估器為決策樹𝑓,總共學習𝑇輪,則AdaBoost.R2的基本流程如下所示:
初始化原始數據集的權重𝑤i𝑤_{i}wi?,其中任意𝑤i𝑤_{i}wi?=1/M
開始循環,for t in 1,2,…T:
在現有數據集𝑁中,有放回抽樣𝑀個樣本,構成訓練集𝑁t𝑁^{t}Nt。在每次抽取一個樣本時,任意樣本被抽中的概率為𝑃𝑖𝑡𝑃^{𝑡}_𝑖Pit?=𝑤i𝑤_{i}wi?/(∑𝑤i𝑤_{i}wi?),很顯然,該概率就是當前樣本在訓練集𝑁t𝑁^{t}Nt中的權重。當從初始權重中抽樣時,概率𝑃𝑖1𝑃^{1}_𝑖Pi1?=1/𝑀,當后續權重變化時,擁有更大權重的樣本被抽中的概率會更大。
在訓練集𝑁t𝑁^{t}Nt上按照CART樹規則建立一棵回歸樹𝑓𝑡𝑓^{𝑡}ft,訓練時所擬合的標簽為樣本的真實標簽𝑦it𝑦^{t}_iyit?。
將𝑁𝑡𝑁^{𝑡}Nt上所有的樣本輸入f𝑡f^{𝑡}ft進行預測,得出預測結果𝑓𝑡(xi)𝑓^{𝑡}(x_{i})ft(xi?),其中i = 1,2,…M。
計算單一樣本𝑖上的損失函數LitL^{t}_iLit?=𝐿(𝑓𝑡(xi)𝑓^{𝑡}(x_{i})ft(xi?),𝑦𝑖𝑦_{𝑖}yi?),計算過程如下所示:
(1)求解𝐷=𝑠𝑢𝑝|𝑓𝑡(xi)𝑓^{𝑡}(x_{i})ft(xi?)?𝑦𝑖𝑦_{𝑖}yi?|,𝑖=1,2,…,𝑁
(2)選擇線性/平方或指數損失函數中的一種計算𝐿𝑖𝑡𝐿^{𝑡}_𝑖Lit?
(3)線性損失:𝐿𝑖=|𝑓𝑡(xi)𝑓^{𝑡}(x_{i})ft(xi?)?𝑦𝑖𝑦_{𝑖}yi?|/D
(4)平方損失:𝐿𝑖=|𝑓𝑡(xi)𝑓^{𝑡}(x_{i})ft(xi?)?𝑦𝑖𝑦_{𝑖}yi?|/𝐷^2
(5)指數損失:𝐿𝑖=1?𝑒𝑥𝑝(?|𝑓𝑡(xi)𝑓^{𝑡}(x_{i})ft(xi?)?𝑦𝑖𝑦_{𝑖}yi?|/𝐷)
(6)根據AdaBoost的要求,所有損失的值域都在[0,1]之間。
計算全樣本上的加權平均損失Lˉt=∑i=1MLitPit\bar{L}^{t}=\sum_{i=1}^{M} L_{i}^{t} P_{i}^{t}Lˉt=∑i=1M?Lit?Pit?
注意此時𝑃𝑖𝑡𝑃^{𝑡}_𝑖Pit?就等于樣本的權重。由于𝑃𝑖𝑡𝑃^{𝑡}_𝑖Pit?=𝑤i𝑤_{i}wi?/(∑𝑤i𝑤_{i}wi?),所以𝑃𝑖𝑡𝑃^{𝑡}_𝑖Pit?一定位于[0,1]范圍內,并且∑𝑃𝑖𝑡𝑃^{𝑡}_𝑖Pit?,𝑖=1,2,…𝑀一定為1。
當權重之和為1時,加權平均值一定會小于等于單一數值的最大值(同時大于等于單一數值的最小值),因此加權平均的值域不會超出單一平均數的值域。由于所有損失的值域都是[0,1],因此加權平均值Lˉt\bar{L}^{t}Lˉt的值域也是[0,1]。同時,由于損失的最大值為1,而權重𝑃𝑖𝑡𝑃^{𝑡}_𝑖Pit?的最大值一定是遠遠小于1的,因此加權平均值Lˉt\bar{L}^{t}Lˉt的最大值一般也是遠遠小于1的。
βt=Ltˉ1?Ltˉ+λ\beta^t = \frac{\bar{L^t}}{1-\bar{L^t} + \lambda}βt=1?Ltˉ+λLtˉ?,其中λ\lambdaλ是為了防止分母為0的常數
不難發現,當加權平平均損失很高時,βt\beta^tβt很大,因此置信度小,當加權平均損失很低時,βt\beta^tβt很小,因此置信度大。置信度越大,集成算法當前的預測結果越好。
已知Ltˉ\bar{L^t}Ltˉ的理論值域是[0,1],因此βt\beta^tβt的理論值域是[0,+∞+\infty+∞],因此βt\beta_tβt?的值越接近0越好。
同時,我們還知道Ltˉ\bar{L^t}Ltˉ的實際范圍大約都在0.2~0.3之間,因此一般來說βt\beta^tβt的實際范圍基本都是小于1的。
wi=wiβ(1?Li)w_i = w_i\beta^{(1-L_i)}wi?=wi?β(1?Li?)
我們可以根據LiL_iLi?的范圍[0,1],以及β\betaβ的計算公式,繪制出橫坐標為LiL_iLi?,縱坐標為β(1?Li)\beta^{(1-L_i)}β(1?Li?)的圖像。不難發現,單一樣本的損失越大、β(1?Li)\beta^{(1-L_i)}β(1?Li?)也會越大,因此該樣本的權重會被更新得越大。
求解迭代過程中弱分類器ftf^tft所需的權重
?t=log(1βt)\phi^t = log(\frac{1}{\beta^t})?t=log(βt1?)
其中log的底數為e或者為2皆可。當β\betaβ值越接近于0,說明損失越小、置信度越高,則log(1βt)log(\frac{1}{\beta^t})log(βt1?)的值越大。所以,損失更小的樹對應的權重更大,損失更大的樹對應的權重更小。
求解出當前迭代ttt下集成算法的輸出值:
Ht(xi)=Ht?1(xi)+η?tft(xi)H^t(x_i) = H^{t-1}(x_i) + \eta \phi^t f^t(x_i)Ht(xi?)=Ht?1(xi?)+η?tft(xi?)
在步驟2~10中循環,直到迭代次數被使用完畢。理想上來說,Adaboost至少應該迭代到TTT次以滿足下列條件:
(∑t:Ht(x)≤ylog1βt)≥(12∑t=1Tlog1βt)\left(\sum_{t:H^t(x) \leq y} log\frac{1}{\beta^t} \right)\ \ \geq \ \ \left(\frac{1}{2}\sum_{t=1}^T log\frac{1}{\beta^t} \right)???t:Ht(x)≤y∑?logβt1??????≥??(21?t=1∑T?logβt1?)
等同于:
(∑t:Ht(x)≤y?t)≥(12∑t=1T?t)\left(\sum_{t:H^t(x) \leq y} \phi^t \right)\ \ \geq \ \ \left(\frac{1}{2}\sum_{t=1}^T \phi^t \right)???t:Ht(x)≤y∑??t?????≥??(21?t=1∑T??t)
并且,最終算法的輸出值是上述等式滿足“等于”條件時所對應的Ht(x)H^t(x)Ht(x)。對于一個正常迭代的AdaBoost來說,每一輪迭代后獲得的H(xi)H(x_i)H(xi?)都是累加結果,因此H(xi)H(x_i)H(xi?)之間應該滿足以下關系:
H0(xi)<H1(xi)<,...,<HT(xi)H^0(x_i) < H^1(x_i) <, ... , < H^T(x_i)H0(xi?)<H1(xi?)<,...,<HT(xi?)
在H0(xi)H^0(x_i)H0(xi?)到HT(xi)H^T(x_i)HT(xi?)過程中,必然只有部分H(xi)H(x_i)H(xi?)是小于真實標簽yiy_iyi?的,假設有ttt次迭代中H(xi)H(x_i)H(xi?)都小于yiy_iyi?,則理想狀況下,前ttt次迭代中權重的累加,應該大于0.5 * 所有TTT次迭代中權重的累加。當兩者相等時,t就是最佳迭代次數,而ttt對應的Ht(x)H^t(x)Ht(x)也就是最佳預測值。
要完全使用公式來證明以上式子非常困難,但我們可以通過一個簡單的小實驗來驗證該公式的合理性。
yi = 20 lambda_ = 1e-6Hx = np.linspace(1,25,1000,endpoint=False) #逐漸增大的Hx#原則上應該使用fx計算損失,并且在迭代過程中逐漸計算出權重 #但由于計算過程略為復雜,因此我們在這里簡化,直接使用Hx計算損失、beta和權重 #這種方法得出的曲線不是最嚴謹的,但其趨勢與使用fx嚴謹計算的曲線趨勢一致 #因為原則上來說,只要一個樣本被AdaBoost分類正確,這個樣本上的損失應該也是越來越小的 D = np.max(abs(Hx - yi)) L = abs(Hx - yi)/D beta = L/(1-L+lambda_)part1 = 0 #用來計算每一輪迭代后的累加值 part1_ = [] #用來保存每一輪迭代后的累加值 part2 = 0 part2_ = [] for t, beta_t in enumerate(beta):phi = np.log(1/beta_t)#如果Hx小于真實標簽yi,則取倒數取對數后放入part1內if Hx[t] <= yi:part1 += phipart1_.append(part1)#所有beta取倒數取對數 * 0.5后都放入part2內part2 += 0.5*phipart2_.append(part2)plt.plot(range(len(part1_)),part1_,c="red",label = "h < y t") plt.plot(range(1000),part2_,c="blue",label = "all t") plt.legend(); #最佳輸出值 Hx[790] #19.96在課程當中我們專注于AdaBoost回歸的講解,如果你對AdaBoost分類感興趣,可以在任意材料上找到AdaBoost經典分類方法的數學推導,也可以找到包含了SAMME與SAMME.R方法的數學推導,值得注意的是,在AdaBoost回歸方法當中,損失函數并沒有明顯的被“最小化”的過程,我們借助損失函數來自然地調整數據的權重,從而在迭代中不斷減小整體損失,但在AdaBoost分類方法當中,有針對損失函數求解一階導數、并讓一階導數為0的過程,該過程影響AdaBoost分類過程中求解弱分類器權重的內容,同時也影響AdaBoost分類過程中對于樣本權重的迭代更新。感興趣的小伙伴可以參閱論文《Multi-class AdaBoost》以及sklearn源碼(https://github.com/scikit-learn/scikit-learn/blob/0d378913b/sklearn/ensemble/weight boosting.py#L913)。
現在,我們已經完整講解了AdaBoost的回歸過程,該過程中的關鍵步驟可以被推廣到任意Boosting算法,相信了解了這個過程之后,在學習后續Boosting算法時,我們將輕松很多。之后,我們將基于該流程講解后續Boosting算法的原理。
總結
以上是生活随笔為你收集整理的LESSON 11.4 原理进阶:AdaBoost算法流程详解的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: LESSON 10.410.510.6
- 下一篇: LESSON 12.1-12.6 梯度提