AdaBoost算法

AdaBoost的全稱是(Adaptiva Boosting),即自適應(yīng)提升方法。他的自適應(yīng)在于:前一個(gè)弱分類器分錯(cuò)的樣本權(quán)重會(huì)得到加強(qiáng),權(quán)重更新后的全體樣本再次被用來(lái)訓(xùn)練下一個(gè)弱分類器。同時(shí),在每一輪中加入一個(gè)新的弱分類器,直到達(dá)到某個(gè)預(yù)定的足夠小的錯(cuò)誤率或達(dá)到預(yù)先指定的最大迭代次數(shù)。

具體來(lái)講,AdaBoost算法可以分為三步:

  1. 初始化訓(xùn)練數(shù)據(jù)的權(quán)值分布。如果有N個(gè)樣本,則每一個(gè)訓(xùn)練樣本最開(kāi)始時(shí)都被賦予相同的權(quán)值:1/N。

  2. 訓(xùn)練弱分類器。具體訓(xùn)練過(guò)程中,如果某個(gè)樣本點(diǎn)已經(jīng)被準(zhǔn)確地分類,那么在構(gòu)造下一個(gè)訓(xùn)練集中,它的權(quán)值就被降低;相反,如果某個(gè)樣本點(diǎn)沒(méi)有被準(zhǔn)確地分類,那么它的權(quán)值就得到提高。然后,權(quán)值更新過(guò)的樣本集被用于訓(xùn)練下一個(gè)分類器,整個(gè)訓(xùn)練過(guò)程如此迭代地進(jìn)行下去。

  3. 將各個(gè)訓(xùn)練得到的弱分類器組合成強(qiáng)分類器。各個(gè)弱分類器的訓(xùn)練過(guò)程結(jié)束后,加大分類誤差率小的弱分類器的權(quán)重,使其在最終的分類函數(shù)中起著較大的決定作用,而降低分類誤差率大的弱分類器的權(quán)重,使其在最終的分類函數(shù)中起著較小的決定作用。換言之,誤差率低的弱分類器在最終分類器中占的權(quán)重較大,否則較小。

AdaBoost二分類問(wèn)題算法流程

  1. 初始化每個(gè)訓(xùn)練樣本的權(quán)重值,每個(gè)樣本的權(quán)重相等,共N個(gè)樣本。

    w_i^0 = \frac{1}{N}, i = 1,2,...,N

  2. 循環(huán),對(duì)第t=1,2,...,T個(gè)弱分類器依次訓(xùn)練:

    1. 訓(xùn)練權(quán)重分布為W_t的樣本數(shù)據(jù),得到弱分類器f_t,計(jì)算它對(duì)樣本集的錯(cuò)誤率e_t

    e_t = P(f_t(x_i) \neq y_i) = \frac{\sum\limits_{i=1}^{N}w_i^tI(f_t(x_i) \neq y_i)}{\sum\limits_{i=1}^{N}w_i^t}

    1. 計(jì)算弱分類器的權(quán)重

    \alpha_t = \frac{1}{2}\ln\frac{1 - e_t}{e_t}

    1. 更新訓(xùn)練樣本的權(quán)重

    w_i^t = w_i^{t-1}exp(-y_i \alpha_t f_t(x_i))/Z_t

    其中Z_t為歸一化因子,是所有訓(xùn)練樣本的權(quán)重之和,

    Z_t = \sum\limits_{i=1}^{N}w_i^{t-1}exp(-y_i \alpha_t f_t(x_i))

  3. 結(jié)束循環(huán),得到一系列的權(quán)重為\alpha_t的弱分類器f_t,將弱分類器根據(jù)權(quán)重線性組合,得到最終的強(qiáng)分類器:

    G(x) = sgn(F(x)) = sgn(\sum\limits_{t=1}^{T}\alpha_tf_t(x))

關(guān)于弱分類器權(quán)重和樣本權(quán)重的分析(二分類問(wèn)題)

關(guān)于弱分類器的權(quán)重,由于每個(gè)弱分類器的分類性能要好于隨機(jī)分類器,故而誤差率e_t<0.5,\alpha_t>0\alpha_t隨著e_t的減小而增大,所以,分類誤差率越小的弱分類器在最終的分類器中所占的權(quán)重越大。

對(duì)于被被弱分類器正確分類的樣本,有:

y_if_t(x_i) = 1

對(duì)于被弱分類器錯(cuò)誤分類的樣本,有:

y_if_t(x_i) = -1

其中y_i代表真實(shí)分布,f_t(x_i)代表弱學(xué)習(xí)器的預(yù)測(cè)值即非真實(shí)分布。

因此樣本權(quán)重的更新公式可以寫成:
w_i^{t+1} = \begin{cases} e^{-\alpha_t}*w_i^t & f_t(x_i) = y_i \\ e^{\alpha_t}*w_i^t & f_t(x_i) \neq y_i \\ \end{cases}
又有:

e^{-\alpha_t} = e^{-\frac{1}{2}\ln\frac{1-e_t}{e_t}} = \sqrt{\frac{e_t}{1-e_t}}

由于\alpha_t大于0,故而e^{-\alpha_t}小于1,分對(duì)的樣本權(quán)重減小;e^{\alpha_t}大于1,分錯(cuò)的樣本權(quán)重增大。

AdaBoost多分類

對(duì)于多分類問(wèn)題,流程原理與二分類基本類似。

只是弱學(xué)習(xí)器的權(quán)重為\alpha_t = \frac{1}{2}(\ln\frac{1-e_t}{e_t} + \ln(R - 1))

其中R是類別的數(shù)量,對(duì)于二分類問(wèn)題,R=2,于是有了\alpha_t = \frac{1}{2}\ln\frac{1-e_t}{e_t}

對(duì)于樣本權(quán)重的更新,公式為:

w^t = w^{t-1}*exp(\alpha_t*(y\_true \neq y\_pred))

對(duì)于弱學(xué)習(xí)器正確分類的樣本,y\_true \neq y\_pred返回False,也就是0,權(quán)重不變

對(duì)于弱學(xué)習(xí)器錯(cuò)誤分類的樣本,y\_true \neq y\_pred返回True,也就是1,權(quán)重放大

對(duì)于多分類的輸出,我們可以轉(zhuǎn)換成二進(jìn)制編碼,或者叫獨(dú)熱編碼,舉個(gè)例子:

例如三分類,類別一可以用[1,0,0]表示,類別二可以用[0,1,0]表示,類別三可以用[0,0,1]表示。

AdaBoost算例

接下來(lái)我們通過(guò)一個(gè)算例,比較sklearn中AdaBoost算法的計(jì)算結(jié)果和我們手動(dòng)計(jì)算的結(jié)果,進(jìn)一步了解AdaBoost算法的流程和原理。

給定以下訓(xùn)練樣本:

X 0 1 2 3 4 5 6 7 8 9
Y 1 1 1 -1 -1 -1 1 1 1 -1

以sklearn中AdaBoost算法,訓(xùn)練這10個(gè)樣本數(shù)據(jù)。

# 導(dǎo)包
from sklearn.ensemble import AdaBoostClassifier
import numpy as np
from sklearn import tree

# 樣本數(shù)據(jù)
X = np.arange(10).reshape(-1,1)
y = np.array([1,1,1,-1,-1,-1,1,1,1,-1])

# 訓(xùn)練和預(yù)測(cè)數(shù)據(jù)
ada = AdaBoostClassifier(algorithm='SAMME',n_estimators=3)
ada.fit(X,y)
ada.predict(X)    # 結(jié)果為array([ 1,  1,  1, -1, -1, -1,  1,  1,  1, -1])

# 分別畫出3棵樹(shù)
_ = tree.plot_tree(ada[0],filled=True)
ada[0].predict(X)
# _ = tree.plot_tree(ada[0],filled=True)
# ada[0].predict(X)
# _ = tree.plot_tree(ada[0],filled=True)
# ada[0].predict(X)

畫出三棵樹(shù),我們可以看出依次是從第3個(gè),第9個(gè),第6個(gè)樣本劃分分類。

接下來(lái)我們根據(jù)上文的公式來(lái)看看AdaBoost的算法流程。

初始化,每個(gè)樣本的權(quán)重都為0.1

w1 = np.full(shape = 10,fill_value=0.1)
w1

第一棵樹(shù)劃分前,將10個(gè)樣本劃分為10個(gè)閾值,以最小誤差率劃分。

t = np.arange(0.5,10)
print(t)
for i,t_i in enumerate(t,start = 1):#enumerate,獲取索引,默認(rèn)從0開(kāi)始, 
#     y_是弱分類器,預(yù)測(cè)值
    y_ = np.array([1]*i + [-1]*(10-i))
#     print(y_)
    print(t_i,((y !=y_)*w1).sum())

從結(jié)果可以看出閾值為2.5或者8.5時(shí)誤差最小,所以從第三個(gè)樣本劃分。

然后根據(jù)公式\alpha_t = \frac{1}{2}log{\frac{1-e_t}{e_t}}計(jì)算第一個(gè)弱學(xué)習(xí)器的權(quán)重

e1 = 0.3
alpha1 = 1/2*np.log((1-e1)/e1)
print('第一個(gè)學(xué)習(xí)器的權(quán)重:',alpha1)

得到結(jié)果為 0.42364893019360184

接下來(lái)更新所有樣本的權(quán)重w_i^t = w_i^{t-1}exp(-y_i\alpha_tf_t(x_i))/Z_t

y_ = np.array([1]*3 + [-1]*7)    # f(x)
w2 = w1*np.exp(-y*y_*alpha1)
w2 = w2/w2.sum()
print('更新后樣本的權(quán)重:',w2)

同理,第二棵樹(shù)和第三棵樹(shù)也能同樣計(jì)算出來(lái)

第二棵樹(shù):

# 根據(jù)結(jié)果找出從第九棵樹(shù)劃分
t = np.arange(0.5,10)
print(t)
for i,t_i in enumerate(t,start = 1):#enumerate,獲取索引,默認(rèn)從0開(kāi)始, 
#     y_是弱分類器,預(yù)測(cè)值
    y_ = np.array([1]*i + [-1]*(10-i))
    print(t_i,((y !=y_)*w2).sum())
    
# 計(jì)算第二個(gè)弱學(xué)習(xí)器的權(quán)重
e2 = 0.214
alpha2 = 1/2*np.log((1-e2)/e2)
print('第二個(gè)學(xué)習(xí)器的權(quán)重:',alpha2)

# 更新樣本的權(quán)重
y_ = np.array([1]*9 + [-1]*1)    # f(x)
w3 = w2*np.exp(-y*y_*alpha2)
w3 = w3/w3.sum()
print('更新后樣本的權(quán)重:',w3)

第二棵樹(shù)是從第九個(gè)樣本劃分,權(quán)重是 0.6504903887036776

第三棵樹(shù):

t = np.arange(0.5,10)
print(t)
for i,t_i in enumerate(t,start = 1): #enumerate,獲取索引,默認(rèn)從0開(kāi)始, 
#     y_是弱分類器,預(yù)測(cè)值
    y_ = np.array([-1]*i + [1]*(10-i))
    print(t_i,((y !=y_)*w3).sum())
    
# 計(jì)算第三個(gè)弱學(xué)習(xí)器的權(quán)重
e3 = 0.18163
alpha3 = 1/2*np.log((1-e3)/e3)
print('第二個(gè)學(xué)習(xí)器的權(quán)重:',alpha3)

# 更新樣本的權(quán)重
y_ = np.array([-1]*6 + [1]*4)    # f(x)
w4 = w3*np.exp(-y*y_*alpha3)
w4 = w4/w4.sum()
print('更新后樣本的權(quán)重:',w4)

第三棵樹(shù)是從第6個(gè)樣本劃分,權(quán)重是 0.7526714531563444

接下來(lái)將弱學(xué)習(xí)器組合成強(qiáng)學(xué)習(xí)器F(x) = \sum\limits_{t = 1}^N\alpha_tf_t(x)

print(alpha1,alpha2,alpha3)
# 0.42364893019360184 0.6504903887036776 0.7526714531563444

# 第一棵樹(shù)ft(x)
y1 = np.array([1]*3 + [-1]*(10-3))
# 第二棵樹(shù)的預(yù)測(cè)值
y2 = np.array([1]*9 + [-1]*(10-9))#預(yù)測(cè)值
# 第三棵樹(shù),預(yù)測(cè)值
y3 = np.array([-1]*6 + [1]*(10-6))
F =  alpha1*y1 + alpha2*y2 + alpha3*y3
# 將多個(gè)弱分類器,整合,變成了強(qiáng)分類器F(X)
F

打印輸出結(jié)果為:
array([ 0.32146787, 0.32146787, 0.32146787, -0.52582999, -0.52582999,
-0.52582999, 0.97951291, 0.97951291, 0.97951291, -0.32146787])

根據(jù)F的結(jié)果,劃分為類別1和類別-1

result = [-1 if i <0 else 1  for i in F]
result

[1, 1, 1, -1, -1, -1, 1, 1, 1, -1]

結(jié)果和sklearn中算法計(jì)算的一樣!

總結(jié)

AdaBoost算是是一種實(shí)現(xiàn)簡(jiǎn)單、易于運(yùn)用的算法,具有分類精度高,不會(huì)出現(xiàn)過(guò)擬合的優(yōu)點(diǎn),是一種適用于各種分類場(chǎng)景下應(yīng)用的算法。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 轉(zhuǎn)自:http://www.cnblogs.com/pinard/p/6133937.html 在集成學(xué)習(xí)原理小結(jié)...
    孫志杰_6bb7閱讀 1,803評(píng)論 0 2
  • 內(nèi)容 一、Adaboost簡(jiǎn)介 二、Adaboost算法過(guò)程 三、Adaboost算法的訓(xùn)練誤差分析 四、Adab...
    小小orange閱讀 1,726評(píng)論 0 6
  • 鏈接:1. 線性回歸總結(jié)2. 正則化3. 邏輯回歸4. Boosting5. Adaboost算法 轉(zhuǎn)自:原地址提...
    SUNFC閱讀 2,612評(píng)論 0 6
  • 微信公眾號(hào):芥子觀須彌 1. Adaboost簡(jiǎn)介 1.1 集成學(xué)習(xí)(ensemble learning)背景介紹...
    芥子觀須彌閱讀 1,436評(píng)論 0 2
  • 1. Boosting Boosting(提升方法)是將弱學(xué)習(xí)器算法提升為強(qiáng)學(xué)習(xí)算法的統(tǒng)計(jì)學(xué)習(xí)方法。在分類問(wèn)題中,...
    songsong_H閱讀 1,848評(píng)論 1 1

友情鏈接更多精彩內(nèi)容