其他分享
首页 > 其他分享> > 《机器学习实战》ch07 adaboost学习记录

《机器学习实战》ch07 adaboost学习记录

作者:互联网

AdaBoost是adaptive boosting的简写(自适应boosting),其基本思想如下:训练数据中的每一个样本,并赋予其一个权重,这些权重构成了向量D,开始时这些权重都被初始化成相等的数值,首先在训练数据上训练出一个弱分类器并计算这个分类器的错误率,然后在同一数据集上再次训练这个弱分类器并重新调整每个样本的权重,降低第一次分对的样本的权重,提高第一次分错的样本的权重。AdaBoost为每个分类器都分配了一个权重值alpha,这些alpha是基于每个弱分类器的错误率进行计算的。同时在每一轮中加入一个新的弱分类器,直到到达某个足够小的错误率或者到达最大迭代次数。

总的来说,整个adaboost算法就分为三步:

(1)初始化训练数据的权值分布

(2)进行多轮迭代,训练弱分类器

(3)将各个训练所得到的所分类器组合成强分类器

AdaBoost的实现代码及实现结果截图分别如下:

(1)首先先建立弱分类器并保存数据集的权重,此次选择单层决策树来构建弱分类器。

先载入一些简单的数据

def loadSimpData():
    datMat = matrix([[ 1. ,  2.1],
        [ 2. ,  1.1],
        [ 1.3,  1. ],
        [ 1. ,  1. ],
        [ 2. ,  1. ]])
    classLabels = [1.0, 1.0, -1.0, -1.0, 1.0]
    return datMat,classLabels

  接下来便是单层决策树的生成函数:

def stumpClassify(dataMatrix, dimen, threshVal, threshIneq):
    #通过阈值比较对数据进行分类,返回分类预测结果
    retArray = ones((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):
    # 建立单层决策树
    # 遍历stumpClassify()中所有的可能输入值,并找到数据集上最佳的单层决策树
    dataMatrix = mat(dataArr); labelMat = mat(classLabels).T
    m,n = shape(dataMatrix)
    numSteps = 10.0; bestStump = {}; bestClasEst = mat(zeros((m,1)))
    minError = inf #init error sum, to +infinity
    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)#call stump classify with i, j, lessThan
                errArr = mat(ones((m,1)))
                errArr[predictedVals == labelMat] = 0
                weightedError = D.T*errArr  #计算加权错误率
                # print("split: dim %d, thresh %.2f, thresh ineqal: %s, the weighted error is %.3f" % (i, threshVal, inequal, weightedError))
                if weightedError < minError:
                    minError = weightedError
                    bestClasEst = predictedVals.copy()
                    bestStump['dim'] = i
                    bestStump['thresh'] = threshVal
                    bestStump['ineq'] = inequal
    return bestStump,minError,bestClasEst

上面的两个函数,第一个是用来测试是否有某个值是大于或者小于我们正在测试的阈值,第二个实在一个加权数据集中循环并找到具有最低错误率的单层决策树。

上述代码测试部分截图如下:

可看到在循环的每一步都会输出此时的特征值,阈值,错误率等(打印语句可以注释掉),循环结束后,返回最佳的单层决策树,错误率和类别估计值。

(2)完整AdaBoost算法的实现

def adaBoostTrainDS(dataArr,classLabels,numIt=40):
    weakClassArr = []
    m = shape(dataArr)[0]
    D = mat(ones((m,1))/m)   # D包含了每个数据点的权重,开始时这些权重被赋予了相等的值(1/m)
    aggClassEst = mat(zeros((m,1)))
    for i in range(numIt):
        '''循环迭代numIt次直到错误率为0时候退出'''
        bestStump,error,classEst = buildStump(dataArr,classLabels,D)# 建立一个单层决策树
        print("D:",D.T)
        alpha = float(0.5*log((1.0-error)/max(error,1e-16)))# alpha值会告诉总分类器本次单层决策树输出结果的权重
        bestStump['alpha'] = alpha
        weakClassArr.append(bestStump)                  #store Stump Params in Array
        print("classEst: ",classEst.T)
        # 为下一次迭代计算D
        expon = multiply(-1*alpha*mat(classLabels).T,classEst) #exponent for D calc, getting messy
        D = multiply(D,exp(expon))
        D = D/D.sum()
        # alc training error of all classifiers, if this is 0 quit for loop early (use break)
        # 错误率累加计算
        aggClassEst += alpha*classEst
        print("aggClassEst: ",aggClassEst.T)
        # sign函数的作用是取符号,正数得1,负数得0,0得0
        aggErrors = multiply(sign(aggClassEst) != mat(classLabels).T,ones((m,1)))
        errorRate = aggErrors.sum()/m
        print("total error: ",errorRate)
        if errorRate == 0.0: break # 训练错误率为0结束循环
    return weakClassArr,aggClassEst

在测试中,我们假定迭代次数为9,但从上面截图可以看到,在第三次迭代之后错误率就已经为0了,便退出了迭代,不用把9次全部完成。AdaBoost算法的核心在于for循环。

(3)基于AdaBoost的分类

为了观察错误率,我们需要编写一些分类的代码。

def adaClassify(datToClass,classifierArr):
    dataMatrix = mat(datToClass)#do stuff similar to last aggClassEst in adaBoostTrainDS
    m = shape(dataMatrix)[0]
    aggClassEst = mat(zeros((m,1)))
    for i in range(len(classifierArr)):
        classEst = stumpClassify(dataMatrix, classifierArr[0][i]["dim"],
                                 classifierArr[0][i]["thresh"],
                                 classifierArr[0][i]["ineq"])
        #call stump classify
        aggClassEst += classifierArr[0][i]['alpha']*classEst
        print(aggClassEst)
    return sign(aggClassEst)

其实在函数adaBoostTrainDS()中,我们已经写完了大部分的代码,而adaClassify()终是将弱分类器的训练过程抽出并应用到具体实例之上,每个弱分类器的结果以其对应的alpha值作为权重,所有结果加权求和就得到了最终的结果。

(4)示例:在一个数据集上应用AdaBoost

我们将在一个病马数据集上应用AdaBoost分类器,来预测患病的马是否能够存活,来看看应用AdaBoost时候的准确率有多少,预测是否准确(结果以错误率来说明)

此时需要一个自适应的数据加载函数,自动载入数据,自动检测出特征的数目并假定最后一个特征是类别标签。

def loadDataSet(fileName):
    # 自适应数据加载函数
    # 能自动检测出每个文件的特征数目,并假定最后一个特征是类别标签
    numFeat = len(open(fileName).readline().split('\t')) #get number of fields
    dataMat = []; labelMat = []
    fr = open(fileName)
    for line in fr.readlines():
        lineArr =[]
        curLine = line.strip().split('\t')
        for i in range(numFeat-1):
            lineArr.append(float(curLine[i]))
        dataMat.append(lineArr)
        labelMat.append(float(curLine[-1]))
    return dataMat,labelMat

  

可以看到,最终使用AdaBoost进行预测所得结果的错误率约为26%,而之前其实对这个数据集我们也使用logistic regression进行过预测,平均错误率为35%左右,可以看到AdaBoost的准确率是高于logistic Regression的

 

标签:分类器,mat,dataMatrix,错误率,ch07,学习,aggClassEst,adaboost,AdaBoost
来源: https://www.cnblogs.com/doggy331/p/11776005.html