統計学習方法第八章AdaBoost


adaboostの原理は,PAC学習の枠組みの下で,一つの概念の強い学習可能な要件は,この概念が弱い学習可能であることであるため,二分類のデータに対して弱い分類器をシリアル学習し,重み付け多数決法を用いて弱い分類器を強い分類器に組み合わせる構想を導いた.再引用後,adaboostも損失関数が指数関数である加算モデルであり,順方向ステップ学習アルゴリズムを用いて得られた.現在、コードを通じて論理を直接示しています.このコードの一部は「機械学習実戦」に由来しています.
import numpy as np

#    
def stumpClassify(dataMatrix,dimen,threshVal,threshIneq):
    retArray = np.ones((np.shape(dataMatrix)[0],1))
    if threshIneq == "lt":
        retArray[dataMatrix[:,dimen] <= threshVal] = -1.0
    else:
        retArray[dataMatrix[:,dimen] > threshVal] = -1.0
        
    return retArray
 
#           
def buildStump(dataArr,classLabels,D):
    dataMatrix = np.mat(dataArr)
    labelMat = np.mat(classLabels).T
    m,n = np.shape(dataMatrix)
    numSteps = 10.0
    bestStump = {
     }
    bestClasEst = np.mat(np.zeros((m,1)))
    minError = np.inf
    for i in range(n):
        rangeMin = dataMatrix[:,i].min()
        rangeMax = dataMatrix[:,i].max()
        stepSize = (rangeMax - rangeMin) / numSteps
        for j in range(-1,int(numSteps) + 1):
            for inequal in ["lt","gt"]:
                threshVal = rangeMin + float(j) * stepSize
                predictedVals = stumpClassify(dataMatrix,i,threshVal,inequal)
                errArr = np.mat(np.ones((m,1)))
                #        ,      
                errArr[predictedVals == labelMat] = 0
                weightedError = D.T * errArr
                print("split : dim %d,thresh %.2f,thresh inequal: %s,the weighted error is %.3f" % (i,threshVal,inequal,weightedError))
                if weightedError < minError:
                    minError = weightedError
                    bestClasEst = predictedVals.copy()
                    bestStump["dim"] = i
                    bestStump["ineq"] = inequal
                    bestStump["thresh"] = threshVal
                    
    return bestStump,minError,bestClasEst

#           
def adaBoostTrainDS(dataArr,classLabels,numIt = 40):
    weakClassArr = []
    m = np.shape(dataArr)[0]
    D = np.mat(np.ones((m,1)) / m)
    aggClassEst = np.mat(np.zeros((m,1)))
    for i in range(numIt):
        bestStump,error,classEst = buildStump(dataArr,classLabels,D)
        print("D:",D.T)
        #    ,      
        alpha = float(0.5 * np.log((1.0 - error) / max(error,1e-16)))
        bestStump["alpha"] = alpha
        weakClassArr.append(bestStump)
        print("classEst:",classEst.T)
        #    
        expon = np.multiply(-1 * alpha * np.mat(classLabels).T,classEst)
        D = np.multiply(D,np.exp(expon))
        D = D / D.sum()
        #     
        aggClassEst += alpha * classEst
        print("aggClassEst:",aggClassEst.T)
        #        
        aggErrors = np.multiply(np.sign(aggClassEst) !=np.mat(classLabels).T,np.ones((m,1)))
        errorRate = aggErrors.sum() / m
        print("total error:",errorRate,"
"
) if errorRate == 0.0: break return weakClassArr # def adaClassify(datToClass,classifierArr): dataMatrix = np.mat(datToClass) m = np.shape(dataMatrix)[0] aggClassEst = np.mat(np.zeros((m,1))) for i in range(len(classifierArr)): classEst = stumpClassify(dataMatrix,classifierArr[i]["dim"],classifierArr[i]["thresh"],classifierArr[i]["ineq"]) aggClassEst += classifierArr[i]["alpha"] * classEst print(aggClassEst) return np.sign(aggClassEst)

授業後の練習問題1に対して、データを入力します.
dataMat = np.mat([[0,1,3],[0,3,1],[1,2,2],[1,1,3],[1,2,3],[0,1,2],[1,1,2],[1,1,1],[1,3,1],[0,2,1]])
classLabels = [-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,1.0,1.0,-1.0,-1.0]
classifierArr = adaBoostTrainDS(dataMat,classLabels,30)
print(classifierArr)

強力な分類器が得られます.sklearnのパッケージは
from sklearn.ensemble import AdaBoostClassifier

AdaBoostClassiferフレームワークには5つのパラメータがあり、base_estimator(ベース分類器)、algorithm(分類アルゴリズム、SAMMEとSAMME.Rの2種類あり)、loss(損失関数、linear、square、exponentialの3種類あり)、n_estimators(最大の弱い学習器個数)、learning_rate(弱い学習器ごとの重み縮小係数).
AdaBoostClassiferの弱い学習器のパラメータは6つあって、max_ですFeatures(分割時の最大フィーチャー数、デフォルトはNone、オプションlog 2またはsqrt)、max_depth(ツリーの最大深さ)、min_samples_split(内部ノード再分割に必要なサンプル数)、min_samples_leaf(リーフノードの最小サンプル数)、min_weight_fraction_leaf(リーフノードの最小サンプルウェイト和)、max_leaf_Nodes(最大リーフノード数).