【Supervised Learning】 集成學習Ensemble Learning & Boosting 算法(python實現)


零、 Introduction

1.learn over a subset of data

  • choose the subset uniformally randomly (均勻隨機地選擇子集)
  • apply some learning algorithm
  • 解決第一個問題 :Boosting 算法
    • 不再隨機選擇樣本,而是選擇the samples we are not good at?
    • 尋找算法解決我們當下不知道如何解決的問題——學習的意義
    • baic idea behind boosting : focus on the “hardest” examples

2.how do you combine all of those rules of thumbs by saying?
(如何合並憑經驗得到的所有規則)

  • weighted Mean

  • Bagging 算法

  • Keyword

  • emsembles are good
  • bagging is good
  • combing simple -> complex
  • boosting is really good
  • weak learner
  • error

一、集成方法(Ensemble Method)

集成方法主要包括Bagging和Boosting兩種方法。

  • Bagging方法

隨機森林算法是基於Bagging思想的機器學習算法,在Bagging方法中,主要通過對訓練數據集進行隨機采樣,以重新組合成不同的數據集,利用弱學習算法對不同的新數據集進行學習,得到一系列的預測結果,對這些預測結果做平均或者投票做出最終的預測。

  • AdaBoost算法

AdaBoost算法和GBDT(Gradient Boost Decision Tree,梯度提升決策樹)算法是基於Boosting思想的機器學習算法。在Boosting思想中是通過對樣本進行不同的賦值,對錯誤學習的樣本的權重設置的較大,這樣,在后續的學習中集中處理難學的樣本,最終得到一系列的預測結果,每個預測結果有一個權重,較大的權重表示該預測效果較好。

二、AdaBoost算法思想

  • “hardest examples”
  • “weighted mean ”

AdaBoost算法是基於Boosting思想的機器學習算法,其中AdaBoost是Adaptive Boosting的縮寫,AdaBoost是一種迭代型的算法,其核心思想是針對同一個訓練集訓練不同的學習算法,即弱學習算法,然后將這些弱學習算法集合起來,構造一個更強的最終學習算法。

為了構造出一個強的學習算法,首先需要選定一個弱學習算法,並利用同一個訓練集不斷訓練弱學習算法,以提升弱學習算法的性能。在AdaBoost算法中,有兩個權重,第一個數訓練集中每個樣本有一個權重,稱為樣本權重,用向量\(D\)表示;另一個是每一個弱學習算法具有一個權重,用向量\(\alpha\)表示。假設有\(N\)個樣本的訓練集
\(\{(X_1,y_1),(X_2,y_2),\cdots,(X_n,y_n)\} \),初始時,設定每個樣本的權重是相等的,即\(\frac{1}{n}\),利用第一個弱學習算法\(h_1\)對其進行學習,學習完成后進行錯誤率\(\varepsilon\)的統計:

\[\varepsilon = \frac{ error}{ all} \]

其中,\(error\)表示被錯誤分類的樣本數目,\(all\)表示所有樣本的數目。這樣便可以利用錯誤率\(\varepsilon\)計算弱學習算法的權重\(\alpha _1\):

\[\alpha_1 = \frac{1} {2} ln (\frac{1-\varepsilon}{\varepsilon}) \]

在第一次學習完成后,需要重新調整樣本的權重,以使得在第一分類中被錯分的樣本的權重,使得在接下來的學習中可以重點對其進行學習:

其中,表示\(h_t(x_i) = y_i\)對第\(i\)個樣本訓練正確,\(h_t(x_i) \neq y_i\)表示對第\(i\)個樣本訓練錯誤。是一個\(Z_t\)歸一化因子:\(Z_t = sum (D)\)

這樣進行第二次的學習,當學習t輪后,得到了t個弱學習算法\({ h_1,\cdots,h_t}\)及其權重\({ \alpha_1,\cdots,\alpha_t}\)。對新的分類數據,分別計算t個弱分類器的輸出\({ h_1(X),\cdots,h_t(X)}\),最終的AdaBoost算法的輸出結果為:

\(H(X) = sign (\sum_{i=1}^t \alpha_i h_i( X ) )\)

其中,是\(sign(x)\)符號函數。具體過程可見下圖所示:


三、AdaBoost算法流程

上述為AdaBoost的基本原理,下面給出AdaBoost算法的流程:

Boost 算法偽代碼

  • Given training \({(x_i,y_i)} \) ,\(y_i \in {-1,+1}\)

  • For t = 1 to T

    • construct distribution \(D_t\)
    • find weak classifier \(h_t(x)\)

    with small error
    \( \epsilon_t = P_{D_{\scriptsize t}} [h_t(x_i) \neq y_i]\)

  • Output \( H_{final} \)


四、Adaboost之python實現

AdaBoost算法是一種具有很高精度的分類器,其實AdaBoost算法提供的是一種框架,在這種框架下,我們可以使用不同的弱分類器,通過AdaBoost框架構建出強分類器。下面我們使用單層決策樹構建一個分類器處理如下的分類問題:

決策樹算法主要有ID3,C4.5和CART,其中ID3和C4.5主要用於分類,CART可以解決回歸問題。


#coding:UTF-8  
''''' 
Created on 2017年2月22日 
 
@author: P50
 
'''  
  
from numpy import *  
  
def loadSimpleData():  
    datMat = mat([[1., 2.1],  
                  [2., 1.1],  
                  [1.3, 1.],  
                  [1., 1.],  
                  [2., 1.]])  
    classLabels = mat([1.0, 1.0, -1.0, -1.0, 1.0])  
    return datMat, classLabels  
  
def singleStumpClassipy(dataMat, dim, threshold, thresholdIneq):  
    classMat = ones((shape(dataMat)[0], 1))  
    #根據thresholdIneq划分出不同的類,在'-1'和'1'之間切換  
    if thresholdIneq == 'left':#在threshold左側的為'-1'  
        classMat[dataMat[:, dim] <= threshold] = -1.0  
    else:  
        classMat[dataMat[:, dim] > threshold] = -1.0  
      
    return classMat  
  
def singleStump(dataArr, classLabels, D):  
    dataMat = mat(dataArr)  
    labelMat = mat(classLabels).T  
    m, n = shape(dataMat)  
    numSteps = 10.0  
    bestStump = {}  
    bestClasEst = zeros((m, 1))  
    minError = inf  
    for i in xrange(n):#對每一個特征  
        #取第i列特征的最小值和最大值,以確定步長  
        rangeMin = dataMat[:, i].min()  
        rangeMax = dataMat[:, i].max()  
        stepSize = (rangeMax - rangeMin) / numSteps  
        for j in xrange(-1, int(numSteps) + 1):  
            #不確定是哪個屬於類'-1',哪個屬於類'1',分兩種情況  
            for inequal in ['left', 'right']:  
                threshold = rangeMin + j * stepSize#得到每個划分的閾值  
                predictionClass = singleStumpClassipy(dataMat, i, threshold, inequal)  
                errorMat = ones((m, 1))  
                errorMat[predictionClass == labelMat] = 0  
                weightedError = D.T * errorMat#D是每個樣本的權重  
                if weightedError < minError:  
                    minError = weightedError  
                    bestClasEst = predictionClass.copy()  
                    bestStump['dim'] = i  
                    bestStump['threshold'] = threshold  
                    bestStump['inequal'] = inequal  
      
    return bestStump, minError, bestClasEst  
  
def adaBoostTrain(dataArr, classLabels, G):  
    weakClassArr = []  
    m = shape(dataArr)[0]#樣本個數 ,row 


    ### Numpy 之 Shape  ###

# 建立一個4×2的矩陣c
# >>> c = array([[1,1],[1,2],[1,3],[1,4]])  
# >>> c.shape  
# (4, 2)  
# >>> c.shape[0]  
# 4  
# >>> c.shape[1]  
# 2  
    ###  ###
    #初始化D,即每個樣本的權重均為1/n

    D = mat(ones((n, 1)) / m)    
    ### 
    # ones(3,3) 可以用來構造(3,3)全一矩陣
    aggClasEst = mat(zeros((m, 1)))  
      
    for i in xrange(G):#G表示的是迭代次數  
        bestStump, minError, bestClasEst = singleStump(dataArr, classLabels, D)  
        print 'D:', D.T  
        #計算分類器的權重  
        alpha = float(0.5 * log((1.0 - minError) / max(minError, 1e-16)))  
        bestStump['alpha'] = alpha  
        weakClassArr.append(bestStump)  
        print 'bestClasEst:', bestClasEst.T  
          
        #重新計算每個樣本的權重D  
        expon = multiply(-1 * alpha * mat(classLabels).T, bestClasEst)  
        D = multiply(D, exp(expon))  
        D = D / D.sum()  
          
        aggClasEst += alpha * bestClasEst  
        print 'aggClasEst:', aggClasEst  
        aggErrors = multiply(sign(aggClasEst) != mat(classLabels).T, ones((m, 1)))  
        errorRate = aggErrors.sum() / m  
        print 'total error:', errorRate  
        if errorRate == 0.0:  
            break  
    return weakClassArr  
  
def adaBoostClassify(testData, weakClassify):  
    dataMat = mat(testData)  
    m = shape(dataMat)[0]  
    aggClassEst = mat(zeros((m, 1)))  
    for i in xrange(len(weakClassify)):#weakClassify是一個列表  
        classEst = singleStumpClassipy(dataMat, weakClassify[i]['dim'], weakClassify[i]['threshold'], weakClassify[i]['inequal'])  
        aggClassEst += weakClassify[i]['alpha'] * classEst  
        print aggClassEst  
    return sign(aggClassEst)  
              
if __name__ == '__main__':  
    datMat, classLabels = loadSimpleData()  
    weakClassArr = adaBoostTrain(datMat, classLabels, 30)  
    print "weakClassArr:", weakClassArr  
    #test  
    result = adaBoostClassify([1, 1], weakClassArr)  
    print result  


OUTPUT:

weakClassArr: [{'threshold': 1.3, 'dim': 0, 'inequal': 'left', 'alpha': 0.6931471805599453},

{'threshold': 1.0, 'dim': 1, 'inequal': 'left', 'alpha': 0.9729550745276565}, {'threshold':

0.90000000000000002, 'dim': 0, 'inequal': 'left', 'alpha': 0.8958797346140273}]

[[-0.69314718]]

[[-1.66610226]]

[[-0.77022252]]

[[-1.]]

五、思考

5.1 回答Introduction中的問題

 (i)每一次訓練如何選擇不同分布?
     答:給先前學習規則分類錯誤的樣本更高的權重,正確分類樣本權重降低,
     使弱學習器能夠更集中解決這些“困難”的樣本。
     簡單的來說,分類正確的樣本我們可以不用再分了,錯誤分類的才是主要敵人。
 (ii)如何將產生的眾多弱規則整合成一個規則?
     答:按照它們的預測結果通過‘投票法’產生,少數服從多數。

5.2 為什么 Boosting 算法 的效果 這么好?

分布:讓上一次被錯誤分類的樣本 越來越重要 (增加權重)

誤差不會上升——每次迭代必定比隨機猜測更好(即每次錯誤率必小於隨機概率0.5)

逆向推理:什么情況下效果不好

還有大量樣本分類錯誤

5.3 Boosting & 過擬合

boosting 往往不會過擬合,但這種情況仍然有可能會發生

回顧 SVM

solution : try to focus on maximum margin classfiers
(集中在最大邊緣分類器上)

large margins tend to minimize over fitting

Boosting

+error
+confidence (置信度):
general definition:how strongly you believe in a particular answer that you given.

in the boosting case: h_final

boosting 往往不會過擬合,但這種情況仍然有可能會發生

  • possible overfitting case:
    1.□ 進行 Boosting 的弱學習方法是含有多次網絡和多個節點的神經網絡

若boosting調用 ANN算法時發生過擬合 且返回值沒有誤差,all the examples will have equal weight.

when you go through the loop again,you will just call the same learner,which will use the same neural network,and will return the same neural network.

每次調用學習器時,你都會得到零訓練誤差。但所得的神經網絡也是相同的。就此陷入惡性循環。

小結:如果你的基礎學習器本身產生了過擬合,那么Boosting很難克服這一點。

  1. the case of pink noise

pink noise just means uniform noise.

P.S. white noise is Gaussian noise
pink noise is uniform noise.

*不是過擬合的原因:

□ Boosting 訓練的時間過長(極限思想,趨向於分離樣本)

5.4 加權組合 回到最初的起點

通過簡單組合 獲得更復雜事物


參考鏈接:

http://blog.csdn.net/gamer_gyt/article/details/51372309

http://discussions.youdaxue.com/t/boosting/45579

http://blog.csdn.net/google19890102/article/details/46507387

https://www.cnblogs.com/csyuan/p/6537255.html

http://blog.sina.com.cn/s/blog_13ec1876a0102xboj.html

http://blog.csdn.net/google19890102/article/details/46376603

參考論文

1.Introduction to Boosting By Udacity
2.The Boosting Approach to Machine Learning By AT&T Labs Research Shannon Laborator


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM