集成學(xué)習(xí)——AdaBoost

集成學(xué)習(xí)

???簡(jiǎn)單來(lái)說(shuō),集成學(xué)習(xí)就是將一組個(gè)體學(xué)習(xí)器結(jié)合起來(lái),通過(guò)某種策略,將其結(jié)合成一個(gè)總學(xué)習(xí)器來(lái)完成相應(yīng)任務(wù);集成學(xué)習(xí)是為了得到比單一學(xué)習(xí)器更好的泛化性能。主要分為兩種類型:若每個(gè)個(gè)體學(xué)習(xí)器是通過(guò)同一算法得到,則稱為同質(zhì),每個(gè)各體學(xué)習(xí)器稱為基學(xué)習(xí)器;若每個(gè)個(gè)體學(xué)習(xí)器是由不同算法得到,則稱為異質(zhì),個(gè)體學(xué)習(xí)器也可稱為組件學(xué)習(xí)器。
???集成學(xué)習(xí)的一個(gè)核心是:如何產(chǎn)生并結(jié)合“好而不同”的個(gè)體學(xué)習(xí)器。下面是西瓜書里,一個(gè)關(guān)于集成學(xué)習(xí)的直觀舉例,像下面有三種集成學(xué)習(xí)的情況,前兩種情況的個(gè)體學(xué)習(xí)器都是66%的準(zhǔn)確率,可是第一種情況個(gè)體學(xué)習(xí)器之前存在差距,因此集成后效果得到提高;而第二種情況,個(gè)體學(xué)習(xí)器由于之間沒(méi)有差距,因此集成后效果沒(méi)有提高;而第三種因?yàn)閭€(gè)體學(xué)習(xí)器不夠好,因此集成后反而沒(méi)有提高。

“好而不同”

集成學(xué)習(xí)的簡(jiǎn)單數(shù)學(xué)解釋

???下面是關(guān)于集成學(xué)習(xí)的一個(gè)簡(jiǎn)單分析:一個(gè)二分類問(wèn)題y \in \{ -1, 1 \}和其實(shí)際對(duì)應(yīng)函數(shù)f(x);假設(shè)每個(gè)基分類器h_i(x)的錯(cuò)誤率為\epsilon_i,即:
P(h_i(x) \neq f(x)) = \epsilon 通過(guò)投票法集成T個(gè)基本分類器,即:
H(x) = \sum _{i=1} ^{T} {h_i(x)} 假設(shè)每個(gè)基分類器h_i(x)錯(cuò)誤率相互獨(dú)立,那么:
\begin{aligned} P(H(x) \neq f(x)) &= \sum _{k=0} ^{ \lfloor {T \over 2} \rfloor } {T \choose K} {(1 - \epsilon)}^k {\epsilon}^{{T \over 2} - k} \\ & \leq e^{-{1 \over 2} T {(1 - 2 \epsilon)}^2 } \end{aligned} 上述公式的第一行可通過(guò)排列組合知識(shí)來(lái)解釋;第二行的不等式是利用Hoeffding不等式所推出得知。上述公式隨著T的增加,其錯(cuò)誤率則不斷的下降;這意味著當(dāng)個(gè)體分類數(shù)目越多,其集成后分類錯(cuò)誤率則越低。
???集成學(xué)習(xí)的方法主要分為兩大類:第一類是串行序列化方法,先從初始訓(xùn)練集得到一個(gè)基學(xué)習(xí)器,然后再調(diào)整訓(xùn)練樣本分布,再訓(xùn)練下一個(gè)基學(xué)習(xí)器,學(xué)習(xí)器之間存在較強(qiáng)的依賴關(guān)系;第二類是并行化方法。第一類的代表是boosting,第二類是bagging隨機(jī)森林。


boosting

???boosting是一種串行序列化方法,先從初始訓(xùn)練集得到一個(gè)基學(xué)習(xí)器,然后再調(diào)整訓(xùn)練樣本分布,再訓(xùn)練下一個(gè)基學(xué)習(xí)器,學(xué)習(xí)器之間存在較強(qiáng)的依賴關(guān)系;其中AdaBoost就是其中的代表算法。下面是AdaBoost算法的整體流程:

Adaboost(訓(xùn)練集D, 基學(xué)習(xí)算法b, 迭代次數(shù)T){
      初始化訓(xùn)練集D的權(quán)重分布D_1(x) = 1 / m
      
      for t = 1 to T {
          ht = b(D, D_t)    #根據(jù)數(shù)據(jù)集D與數(shù)據(jù)的權(quán)重分布D_t生成基學(xué)習(xí)器ht
          計(jì)算h_t的錯(cuò)誤率p
          
          if p > 0.5
             break
         
         更新當(dāng)前基學(xué)習(xí)器ht的權(quán)重a_t
         更新訓(xùn)練集D的權(quán)重分布D_t+1
      }

     返回基學(xué)習(xí)器的加權(quán)和:H(x)
}

AdaBoost的優(yōu)化目標(biāo)

???可以看到AdaBoost算法是一個(gè)迭代優(yōu)化算法,該算法的優(yōu)化目標(biāo)是最小化指數(shù)損失函數(shù)的期望,假設(shè)問(wèn)題是解決一個(gè)二分類問(wèn)題。
\begin{aligned} loss(H | D) &= E[ e^{ -f(x)H(x) } ] \\ &= e^{-H(x)} P(f(x) = 1) + e^{H(x)} P(f(x) = -1) \end{aligned} 然后損失函數(shù)對(duì)H進(jìn)行求導(dǎo)可得:
{ {\partial loss} \over {\partial H} } = -e^{-H(x)} P(f(x) = 1) + e^{H(x)} P(f(x) = -1) 令上式取零解后,可得:
H(x) = {1 \over 2} ln{ P(f(x) = 1) \over P(f(x) = -1) } 進(jìn)一步可得到:
\begin{aligned} sign( H(x) ) &= sign( {1 \over 2} ln{ P(f(x) = 1) \over P(f(x) = -1) } ) \\ &= \begin{cases} 1, &P(f(x) = 1) > P(f(x) = -1) \\ -1, &P(f(x) = 1) > P(f(x) = -1) \end{cases} \end{aligned} 上述過(guò)程說(shuō)明sign( H(x) )達(dá)到貝葉斯最優(yōu)錯(cuò)誤率,即最小化上述指數(shù)損失函數(shù)的期望,也可將錯(cuò)誤率最小化;并且該損失函數(shù)更具比較好的數(shù)學(xué)性質(zhì)。因此AdaBoost的優(yōu)化目標(biāo)是:最小化指數(shù)損失函數(shù)的期望。

AdaBoost的參數(shù)更新

???損失函數(shù)loss(H|D)中,其中H的定義是:
H(x) = \sum _{t=1} ^{T} {\alpha_t h_t(x)} 而基分類器h_t(x)是由關(guān)于數(shù)據(jù)集的權(quán)重D_t(x)與數(shù)據(jù)集D共同生成,因此AdaBoost算法中,需要更新的參數(shù)為:\alpha_tD_t(x)。
???關(guān)于\alpha_t,將t時(shí)刻的分類器代入損失函數(shù)中可得:
\begin{aligned} loss(\alpha_t h_t | D_t) &= E[ e^{-f(x) \alpha_t h_t(x)} ] \\ &= E [ e^{- \alpha_t } bool(f(x) = h_t(x)) + e^{\alpha_t} bool(f(x) \neq h_t(x)) ] \\ &= e^{- \alpha_t } E[ bool(f(x) = h_t(x)) ] + e^{\alpha_t} E[ bool(f(x) \neq h_t(x)) ] \\ &= e^{- \alpha_t } P( f(x) = h_t(x) ) + e^{\alpha_t} P( f(x) \neq h_t(x) ) \\ &= e^{- \alpha_t } (1 - \epsilon_t) + e^{\alpha_t} \epsilon_t \end{aligned} 求上述式子關(guān)于\alpha_t的偏導(dǎo),可得:
{\partial loss \over \partial {\alpha_t}} = -e^{- \alpha_t } (1 - \epsilon_t) + e^{\alpha_t} \epsilon_t 取上式的零解,可得:
\alpha_t = {1 \over 2} ln ( {{1 - \epsilon_t} \over {\epsilon_t}} ) 這就是\alpha_t的更新公式。
??? 下面是關(guān)于AdaBoost算法中,h_t是對(duì)H_{t-1}錯(cuò)判的數(shù)據(jù)極可能的關(guān)注的一個(gè)證明,使得基學(xué)習(xí)器h_t盡可能的糾正H_{t-1}的錯(cuò)誤,即最小化:
\begin{aligned} loss(H_{t-1} + h_t | D) &= E[ e^{-f(x)(H_{t-1}(x) + h_t(x) )} ] \\ &= E[ e^{-f(x) H_{t-1}(x)} e^{-f(x) h_t(x)}] \end{aligned} 對(duì)上述式子后半部分進(jìn)行泰勒展開(kāi),可得:
\begin{aligned} loss(H_{t-1} + h_t | D) & \approx E[ e^{-f(x) H_{t-1}(x)} (1 - f(x) h_t(x) + { f^2(x) {h_t}^2(x) \over 2}) ] \\ & = E[ e^{-f(x) H_{t-1}(x)} (1 - f(x) h_t(x) + {1 \over 2} ) ] \end{aligned} 那么想h_t可以糾正更多錯(cuò)誤,則可以最小化損失函數(shù),即:
\begin{aligned} arg min_h loss(H_{t-1} + h | D) \\ &= arg min_h E[ e^{-f(x) H_{t-1}(x)} (1 - f(x) h(x) + {1 \over 2} ) ] \\ &= arg max_h E[ e^{-f(x) H_{t-1}(x)} f(x) h(x) ] \\ &= arg max_h E[ {e^{-f(x) H_{t-1}(x)} \over E[e^{-f(x) H_{t-1}(x)}] } f(x) h(x) ] \end{aligned} 設(shè)分布D_t(x)為:
D_t(x) = { { D(x) e^{-f(x) H_{t-1}(x) } } \over E[ e^{-f(x) H_{t-1}(x)} ] } 由數(shù)學(xué)期望定義,上式等價(jià)于:
\begin{aligned} arg max_h E _{x \sim D} [ {e^{-f(x) H_{t-1}(x)} \over E[e^{-f(x) H_{t-1}(x)}] } f(x) h(x) ] &= arg max_h E _{x \sim D_t} [f(x)h(x)] \\ &= arg max_h E _{x \sim D_t} [1 - 2*bool(f(x) \neq h(x) )] \\ &= arg min_h E _{x \sim D_t} [bool(f(x) \neq h(x) )] \end{aligned} 個(gè)人對(duì)于上式第一行的理解是,左半部分是計(jì)算一個(gè)基于分布D的一個(gè)數(shù)學(xué)期望,簡(jiǎn)單來(lái)寫就是:分布D \times 取值,而再結(jié)合分布D_t(x)的定義,就變成右半部的隨機(jī)變量f(x)h(x)關(guān)于分布D_t(x)的數(shù)學(xué)期望。
???上面的過(guò)程是關(guān)于基分類器h_t(x)是對(duì)之前分布錯(cuò)誤的一個(gè)調(diào)整后的分類器,使得h_t(x)將在分布D_t下最小化誤差
???關(guān)于分布D_t的更新,則可從式子出發(fā):
\begin{aligned} D_{t+1}(x) &= { { D(x) e^{-f(x) H_{t}(x) } } \over E[ e^{-f(x) H_{t}(x)} ] } \\ &= { { D(x) e^{-f(x) H_{t-1}(x) } e^{-f(x) \alpha_t h_t(x) } } \over E[ e^{-f(x) H_{t-1}(x)} ] } \\ &= D_t(x) \cdot e ^{-f(x) \alpha_t h_t(x)} { E[ e^{-f(x) H_{t-1}(x) } ] \over E[ e^{-f(x) H_{t}(x) } ] } \end{aligned}
???總的來(lái)說(shuō),AdaBoost算法最主要的是下面兩個(gè)式子:
\begin{aligned} \alpha_t &= {1 \over 2} ln( { {1 - \epsilon_i} \over \epsilon_i } ) \\ D_{t + 1}(x) &= {D_t(x) e^{- \alpha_t f(x) h_t(x) } \over z_t } \end{aligned}


AdaBoost的實(shí)現(xiàn)

???這里關(guān)于AdatBoost的實(shí)現(xiàn),是參考《機(jī)器學(xué)習(xí)實(shí)戰(zhàn)》里面的實(shí)現(xiàn)。該實(shí)現(xiàn)中使用的弱分類器是決策樹(shù)樁(decision stump),其是單層決策樹(shù),既只通過(guò)某個(gè)特征的某個(gè)特征值的大于小于來(lái)進(jìn)行分類。
???下面這段代碼是關(guān)于決策樹(shù)樁的分類,其實(shí)只是根據(jù)某個(gè)特征的某個(gè)值進(jìn)行二分:

def stumpClassify(dataset, index, value, ops):
    
    m, n = dataset.shape
    res = np.ones((m))
    
    #lt代表小于value值的為負(fù)類,gt代表大于value值的為負(fù)類
    if ops == 'lt':
        res[ np.where( dataset[:, index] <= value )[0] ] = -1.0
    elif ops== 'gt':
        res[ np.where( dataset[:, index] > value )[0] ] = -1.0
        
    return res

這一段是關(guān)于如何建立一個(gè)決策樹(shù)樁,通過(guò)遍歷所有特征的特征值,選擇其中帶權(quán)誤差率(分布D的作用主要是計(jì)算誤差率)最小的作為建立的決策樹(shù)樁。:

def buildStump(dataset, D):
    
    m, n = dataset.shape
    bestStump = {}
    bestClassEst = np.zeros(m)
    numSteps = 10.0
    min_err = np.inf
    
    for i in range( n - 1 ):
        
        #將值范圍分成numSteps等份,再以該等份的值作為分類的值
        min_value = np.min( dataset[:, i] ); max_value =  np.max( dataset[:, i] )
        step_size = (max_value - min_value) / numSteps
        
        for j in range(-1, int(numSteps) + 1):
            for o in ['lt', 'gt']:
                value = min_value + float(j) * step_size
                predictions = stumpClassify(dataset, i, value, o)
                mistake = (predictions != dataset[:, -1] )
                weight_err = np.dot(D, mistake)
                
                if weight_err < min_err:
                    min_err = weight_err
                    bestClassEst = predictions.copy()
                    bestStump['idx'] = i
                    bestStump['val'] = value
                    bestStump['ops'] = o
                    
    return bestStump, min_err, bestClassEst

下面這段代碼是AdaBoost的主體:

def AdaBoot(dataset, numIter=40):
    
    bases = []
    m, n = dataset.shape
    
    D = np.ones( m ) / m
    acc_res = np.zeros( m )
    
    for i in range( numIter ):
        #根據(jù)分布D和數(shù)據(jù)集,建立基分類器
        stump, err_rate, classEnt = buildStump(dataset, D)
        
        #若單個(gè)基分類器錯(cuò)誤率大于0.5拋棄并退出循環(huán)
        if err_rate > 0.5:
            break
        
        #更新基分類器權(quán)重
        alpha = np.log( (1.0 - err_rate) / np.maximum(err_rate, 1e-6) ) * 0.5
        stump['alpha'] = alpha
        bases.append( stump )
        
        #更新下一次的權(quán)重分布D
        D = D * np.exp( -1.0 * classEnt * dataset[:, -1] * alpha ) / np.sum( D )
        
        #計(jì)算當(dāng)前集成后的分類器的錯(cuò)誤率
        acc_res += alpha * classEnt
        acc_err = np.mean(np.sign( acc_res ) != dataset[:, -1])
ji        
        #若集成后的分類器已經(jīng)達(dá)到零差錯(cuò),則無(wú)需繼續(xù)進(jìn)行下去
        if acc_err == 0.0:
            break
            
    return bases

而到實(shí)際用于分類時(shí),只需遍歷base中的分類器,將分類結(jié)果加權(quán)求和即可。


sklearn中的AdaBoost

???在sklearn中,AdaBoost的使用與其他模型類似;其默認(rèn)的base_estimator是一層的決策樹(shù),而具體的實(shí)現(xiàn)算法有:SAMMESAMME.R,SAMME是以分類的類別作為調(diào)整權(quán)值分布,而SAMME.R是以分類的類別概率來(lái)調(diào)整權(quán)值分布。


?著作權(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ù)。

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