zoukankan      html  css  js  c++  java
  • 我眼中的Adaboost

    步骤:

    def buildStump(dataArr,classLabels,D):

    1。循环取出数据集中的一个特征(一列)输入 (for:)

      2。循环调整阀值threshVal  (for:)

        3,。分成两个子树

        左边:特征值xi<=threshVal 为-1,否则为1

          获得预测结果1

        右边:特征值xi>threshVal 为-1,否则为-1

          获得预测结果2

        4。分别把预测结果同真实标签比较,获得一个向量(对的为零,错误为1)

        5。和权重向量D相乘,获得一个值(权重错误值,用来计算alpha),评判分类器的好坏。

        5。获得最低的错误率结果保存起来

    返回:单层决策树(弱分类器),最小错误,预测的标签

    循环结束后,每一个特征都对应一个阀值,而这个阀值,可以最大准确度地分割特征

     --------------------------------------------------------------------------------------------------------------------------------------------------------------------------

    以上的过程就实现一个分类器,接下来通过训练,来获取一定数量较好的弱分类器

    def buildStump(dataArr,classLabels,D):

    1。 初始化权重D(它与上述过程中的权重D是同一个,它的作用是增加错误分类的权重,降低正确分类的权重)

    2。 迭代过程(for:迭代次数)

      3。 buildStump(dataArr,classLabels,D):(调用上面的过程,创建一个弱分类器)

      4。 计算alpha(Adaboost为每一个弱分类器都分配一个权重alpha,这些alpha值都是基于每一个弱分类器的错误率进行计算)

      5。 保存alpha到决策树集合(弱分类器)中,同时也保存这个分类器

      6。 更新权重向量D

      7。 和真实的标签相比计算错误分类的个数

      8。 计算错误率

      9。 直到错误率为零则退出循环

    返回:弱分类器的集合

    这个过程结束,就获得一个弱分类器的集合,整体来说分类的效果越来越好

    ---------------------------------------------------------------------------------------------------------------------------------------------------------

    调用训练好的模型进行分类

    传入要分类的数据datToClass,传入弱分类器集合classifierArr(也就是训练好的模型)

    def adaClassify(datToClass,classifierArr):

      (for:弱分类器的个数)

        1。使用弱分类器i预测结果标签labeli

        2。乘以它的这个弱分类器的权重alpha

        3。累加每一个弱分类器的这个结果(其实就是一个投票过程)

        4。获得结果

    用一个图表示就是这样的

    为了更好的了解分类器的性能,我们通过画出ROC曲线,来更好的了解。

    什么是ROC :https://www.cnblogs.com/zhxuxu/p/9911660.html

    接下来是机器学习实战中的代码(详细注释),代码和上面的流程搭配看,希望对你有帮助。

    #coding=utf-8
    from numpy import *
    
    def loadSimpData():
        datMat = matrix([[1.0,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 loadDataSet(fileName):
        numFeat = len(open(fileName).readline().split('	'))
        dataMat = [];labelMat = []
        fr = open(fileName)
        for line in fr.readlines():
            lineArr = []
            curLine = line.strip().split('	')
            for i in range(numFeat - 1):
                lineArr.append(float(curLine[i]))
            dataMat.append(lineArr)
            labelMat.append(float(curLine[-1]))
        return dataMat,labelMat
        
    def stumpClassify(dataMatrix,dimen,threshVal,threshIneg):
        #初始化数据类别都为+1
        #分左右子树
        #与阀值比较,左子树小于阀值为-1,大于阀值为1。右侧大于阀值为-1,小于阀值为1。
        #这两种分法,最后取错误率最低的分法
        retArray = ones((shape(dataMatrix)[0],1))
        if threshIneg =='lt':
            retArray[dataMatrix[:,dimen] <= threshVal] = -1.0
        else:
            retArray[dataMatrix[:,dimen] > threshVal] = -1.0
        return retArray
    
    def buildStump(dataArr,classLabels,D):
        dataMatrix = mat(dataArr); labelMat = mat(classLabels).T
        m,n = shape(dataMatrix)
        numSteps = 10.0; bestStump = {}; bestClasEst = mat(zeros((m,1)))
        minError = inf
        #循环取样本的第i个特征
        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 = mat(ones((m,1)))
                    #实际标签与预测标签相等的为0
                    errArr[predictedVals == labelMat] = 0
                    #权重向量D乘错误矩阵,预测正确的权重为零,权重就无需更改
                    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
      
        print ("bestsplit: dim %d, thresh %.2f, thresh ineqal: %s, the weighted error is %.3f" % (bestStump['dim'], bestStump['thresh'], bestStump['ineq'], minError))
        #返回的是bestStump中保存的单层决策树(就是选择出了两类中能使错误率降到最低的特征)
        #最小错误率,最好的类别预测
        return bestStump,minError,bestClasEst
    
    def adaBoostTrainDS(dataArr,classLabels,numIt=40):
        weakClassArr = []
        m = shape(dataArr)[0]
        #D是一个概率分布向量,其和要等于1,因此要除以m
        #权重的初始化可以是一样的随着迭代次数增加
        #增加错误分类的权重,降低错误分类的权重
        D = mat(ones((m,1))/m)
        aggClassEst = mat(zeros((m,1)))
        for i in range(numIt):
            #创建一个弱学习器(树根)
            bestStump,error,classEst = buildStump(dataArr,classLabels,D)
            print ("D:",D.T)
            #Adaboost为每一个弱分类器都分配一个权重alpha
            #这些alpha值都是基于每一个弱分类器的错误率进行计算
            #计算公式alpha = 1/2ln(1-c/c)
            #c是错误率c=错误分类的样本个数/所有样本总数
            #为了防止分母为零,增加1e-16
            alpha = float(0.5*log((1.0-error)/max(error,1e-16)))
            #存到树根中
            bestStump['alpha'] = alpha
            weakClassArr.append(bestStump) 
            print ("classEst: ",classEst.T)
            #更新权重向量D
            #正确分类的expon为负(权重影响小)
            #错误分类的expon为正(权重影响大)
            #这里正确标签和预测样本标签相乘,标签一样为正,不一样为负
            expon = multiply(-1*alpha*mat(classLabels).T,classEst)
            D = multiply(D,exp(expon))
            D = D/D.sum()
            
            aggClassEst += alpha*classEst
            #sign if a>0 return 1,if a<0 return -1,if a==0 return 0
            #计算错误分类的个数
            aggErrors = multiply(sign(aggClassEst) != mat(classLabels).T,ones((m,1)))
            #错误率
            errorRate = aggErrors.sum()/m
            print ("total error: ",errorRate)
            if errorRate == 0.0: break
        #返回每一次迭代获得的最好结果的分类器
        #弱分类器参数集合,和每一个弱分类器对应的alpha(权重)
        return weakClassArr,aggClassEst
        
    def adaClassify(datToClass,classifierArr):
        dataMatrix = mat(datToClass)
        m = shape(dataMatrix)[0]
        aggClassEst = mat(zeros((m,1)))
        #classifierArr是最优分类器的集合
        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 sign(aggClassEst)
    
    #ROC曲线的绘制及AUC计算函数    
    def plotROC(predStrengths, classLabels):    
        import matplotlib.pyplot as plt
        cur = (1.0,1.0)
        #AUC的值
        ySum = 0.0 
        #计算分类为正的个数
        numPosClas = sum(array(classLabels)==1.0)
        yStep = 1/float(numPosClas); xStep = 1/float(len(classLabels)-numPosClas)
        #predStrengths是投票预测结果(非整数),argsort()从大到小排序,返回下标
        #也就是预测结果接近于1(分类为正)的排在前面
        sortedIndicies = predStrengths.argsort()
        #print('predStrengths',predStrengths)
        #print('classLabels',classLabels)
        fig = plt.figure()
        fig.clf()
        ax = plt.subplot(111)
        #classLabels是真实结果,通过比较,为正类,移动y轴,否则移动x轴
        for index in sortedIndicies.tolist()[0]:
            if classLabels[index] == 1.0:
                delX = 0; delY = yStep;
            else:
                delX = xStep; delY = 0;
                ySum += cur[1]
            ax.plot([cur[0],cur[0]-delX],[cur[1],cur[1]-delY], c='b')
            cur = (cur[0]-delX,cur[1]-delY)
        ax.plot([0,1],[0,1],'b--')
        plt.xlabel('False positive rate'); plt.ylabel('True positive rate')
        plt.title('ROC curve for AdaBoost horse colic detection system')
        ax.axis([0,1,0,1])
        plt.show()
        
    def test():
        datMat,classLabels = loadSimpData()
        #D = mat(ones((5,1))/5)
        #buildStump(datMat,classLabels,D)
        #以上就构成了一个弱分类器
        #接下来训练出多个弱分类器,构成Adaboost算法
        classifierArray = adaBoostTrainDS(datMat,classLabels,numIt=9)
        print(classifierArray)
        #接下来进行测试
    
    #实例对马疝病数据集分类使用Adaboost
    def app():
        datArr,labelArr = loadDataSet('horseColicTraining2.txt')
        classifierArray = adaBoostTrainDS(datArr,labelArr,10)
        
        
        testArr,testLabelArr = loadDataSet('horseColicTest2.txt')
        prediction10 = adaClassify(testArr,classifierArray)
        errArr = mat(ones((67,1)))
        errArr[prediction10!=mat(testLabelArr).T].sum()
    #画ROC曲线图
    def plotROCtest():
        datArr,labelArr = loadDataSet('horseColicTraining2.txt')
        classifierArray,aggClassEst = adaBoostTrainDS(datArr,labelArr,10)
        plotROC(aggClassEst.T, labelArr)

    测试代码时,可以分别运行

    def test()
    def app()
    def plotROCtest()

    实现具体的功能
     

     

  • 相关阅读:
    Git代码托管
    Git安装配置
    【知识共享】SSIS的典型应用
    【转贴】正确实施BI项目的四条建议
    SAP ABAP 常用事务代码
    【转贴】WP7 离线升级方法附错误解决方案
    BO Universe(语义层)设计相关
    【转贴】SAP学习经验谈
    七个不放过和四项原则
    SAP BO帮助文档下载页面
  • 原文地址:https://www.cnblogs.com/zhxuxu/p/9880014.html
Copyright © 2011-2022 走看看