AdaBoostメタアルゴリズムを利用した分類器(コードノート)

4327 ワード

AdaBoostは統合方法です.監督学習に属する.
不要な分類器を組み合わせて、この方法を集積方法(ensemble method)またはメタアルゴリズム(meta-algorithm)と呼ぶ.
------------------------------------------------------------------------------------------------------------------------
bagging:本名は自挙集積法(bootstrap aggregating).元のデータセット(サイズN)からS個の新しいデータセット(サイズもN)が戻されて抽出される.これは、ある新しいデータセットが重複していても、元のデータの値がなくてもよいことを意味する.ある学習アルゴリズムにS個のデータセットを用いてS個の分類器(これらの分類器のタイプが一致する)を得,S個の分類器で新しいデータを投票分類する.各分類器の重みは等しく,並列訓練と呼ぶ.例えば、ランダム森林は先進的なbagging方法である.
boosting:baggingに似た統合分類器.しかし、ここでは異なる分類器はシリアルトレーニングで得られる.なぜなら、新しい分類器は訓練された分類器の性能を参照し(新しい分類器は既存の分類器が間違っているデータに集中する)、これらの分類器の重みは等しくないからである.(次の重みDを見ると、stumpが1つ得られるたびにアルゴリズムは誤りデータの重みを増やし、データの重みを下げる)
------------------------------------------------------------------------------------------------------------------------
↓単層決定ツリーに基づくAdaBoost分類器、一般的なboosting方法:
import numpy as np
'''
1      ,      
2            AdaBoost
'''
#              
def stumpClassify(dataM, dim, threshV, threshIneq):
    retArray = np.ones((np.shape(dataM)[0], 1))
    if threshIneq == 'lt':
        retArray[dataM[:, dim] <= threshV ] = -1.0
    else:
        retArray[dataM[:, dim] > threshV] = -1.0
    return retArray

#             (        D)
def buildStump(dataArr, classLabels, D):
    dataM = np.mat(dataArr)
    labelM = np.mat(classLabels).T
    m,n = np.shape(dataM)
    numSteps = 10.0
    bestStump = {}
    bestClassEst = np.mat(np.zeros((m,1)))
    minErr = inf
    for i in range(n):  #         (  n )
        rangeMin = dataM[:,i].min()
        rangeMax = dataM[:,i].max()
        stepSize = (rangeMax-rangeMin)/numSteps
        for j in range(-1, int(numSteps)+1):  #          ,       
            for inequal in ['lt', 'gt']:
                threshV = rangeMin+float(j)*stepSize
                predV = stumpClassify(dataM, i, threshV, inequal)
                errArr = np.mat(np.ones((m,1)))
                errArr[predV == labelM] = 0
                weightErr = D.T*errArr  #         (        )
                print('split: dim %d, thresh %.2f, thresh inequal: %s , weightErr is %.3f' %
                      (i, threshV, inequal, weightErr))
                if weightErr < minErr:
                    minErr = weightErr
                    bestClassEst = predV.copy()
                    bestStump['dim'] = i
                    bestStump['thresh'] = threshV
                    bestStump['ineq'] = inequal
    return bestStump, minErr, bestClassEst
    
#        (decision stump) AdaBoost
def adaBoostTrainDS(data, classLabels, iters = 40):
    weakClassArr = []
    m = np.shape(data)[0]
    D = np.mat(np.ones((m,1))/m)  #     
    aggClassEst = np.mat(np.zeros((m,1)))
    for i in range(iters):
        bestStump, err, classEst = buildStump(data, classLabels, D)
        print('D: ', D.T)
        alpha = float(0.5*np.log((1.0-err)/np.max(err, 1e-16)))  #   DS       
        bestStump['alpha'] = alpha
        weakClassArr.append(bestStump)  #                (  D  )        
        expon = np.multiply(-1*alpha*np.mat(classLabels).T, classEst)  #     D
        D = np.multiply(D, np.exp(expon))
        D = D/D.sum()
        aggClassEst += alpha*classEst  #          ,         
        aggErrors = np.multiply(np.sign(aggClassEst)!=np.mat(classLabels).T, np.ones((m,1)))
        errRate = aggErrors.sum()/m    # np.sign 1 -1(      )
        print('total error: ', errRate, '
') if errRate == 0.0: break return weakClassArr # --------------------------------------- -------------------------------------------- def adaBoostClassify(dataTest, classifyArr): dataM = np.mat(dataTest) m = np.shape(dataTest)[0] aggClassEst = np.mat(np.zeros((m,1))) for i in range(len(classifyArr)): # classEst = stumpClassify(dataM, classifyArr[i]['dim'], classifyArr[i]['thresh'], classifyArr[i]['ineq']) aggClassEst += classifyArr[i]['alpha']*classEst # print(aggClassEst) return np.sign(aggClassEst) # ( ) dataTrain, labelTrain, dataTest, labelTest = loadData(filename) classifyArr = adaBoostTrainDS(dataTrain, labelTrain) labelPred = adaBoostClassify(dataTest, classifyArr)