第七章AdaBoost算法

 

首先我们可以将不同的分类器进行组合,这种方法叫做集成方法(ensemble method)或元算法(meta-algorithm)。

bagging:

bootstrapping的简称,我的理解:重复采样,每次都将新采样的样本作为数据集,随机采样替换的方式,得到与原来数据集规模一样的的数据集,以此来得到不一样的结果。

boosting:

通过对弱分类器结果进行分析,将正确的缩小权重,错误的加大权重来重新分配权重,不停地进行调整来降低错误率。

应用多个不同的分类器。

Adaboost:

详细看笔记,简要写一下基本原理:先用一个弱分类器去处理训练集,得出它的错误率\varepsilon。然后对错误量重新分配它的权重(重视程度),分对则是降低它的权重。经过几次迭代后,得出了最终分类结果,因为不止一个分类器(重新分配一次权重代表用了一种分类器),然后计算将它们组成线性组合时前面的\alpha值。

\varepsilon =未正确分类的样本数目/所有样本数目

\alpha = \frac{1}{2}ln\left (1-\varepsilon /\varepsilon \right )

计算出alpha值之后,对权重向量进行更新,降低正确分类权重,增加错误分类权重。

被正确分类:

D_{i}^{t+1} = D_{i}^{t} *e^{-\alpha }/Sum\left ( D \right )

被错误分类:

D_{i}^{t+1} = D_{i}^{t} *e^{\alpha }/Sum\left ( D \right )

import random
import numpy as np
from  numpy import *
import matplotlib.pyplot as  plt
from sklearn.tree import DecisionTreeClassifier
from sklearn.ensemble import AdaBoostClassifier
#构建一个简单数据集
def loadSimpleData():
    dataMat = 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 dataMat,classLabels
#单层决策树函数:是决策树的一个简化版本,弱学习器
#这个函数作用就是通过阈值来给数据集给出分类预测
def stumpClassify(dataMatrix,dimen,threshVal,threshIneq):
    retArray = ones((shape(dataMatrix)[0],1)) #初始化
    if threshIneq == 'It':
        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 = {}#字典,用于储存最低错误率情况下的单层决策树信息
    bestClassEst = mat(zeros((m,1))) #用于记录最低错误率情况下的预测结果
    minError = 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 ['It','gt']:#来回切换
                threshVal = (rangeMin + float(j) * stepSize) #设定的阈值
                predictedVals = stumpClassify(dataMatrix,i,threshVal,inequal)
                errArr = mat(ones((m,1)))
                errArr[predictedVals == labelMat] = 0
                weightedError = D.T * errArr #通过权重向量D的相应元素与错误向量相乘并求和
                #print 'split: dim %d, thresh %.2f, thresh ineqal:\
                # %s, the weighted error is %.3f' %\
                 #     (i,threshVal,inequal,weightedError)
                if weightedError < minError:
                    minError = weightedError
                    bestClassEst = predictedVals.copy()
                    bestStump['dim'] = i
                    bestStump['thresh'] = threshVal
                    bestStump['ineq'] = inequal
    return bestStump,minError,bestClassEst

#基于单层决策树的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):
        bestStump,error,classEst = buildStump(dataArr,classLabels,D)
        #返回最优单层决策树的信息、最小错误率、最优预测
        #print 'D:',D.T #权重分量
        alpha = float(0.5 * log((1.0 - error) / max(error,1e-16)))
        #其中log里这样写是为了确保在没有错误时不会发生分母上出现0
        bestStump['alpha'] = alpha #更新alpha值
        weakClassArr.append(bestStump)
        #print 'classEst:',classEst.T #预测估计
        expon = multiply(-1*alpha*mat(classLabels).T,classEst)
        #如果正确即classLabels和classEst相同时,则相乘为1,否则为-1
        D = multiply(D,exp(expon))
        D = D/D.sum()
        aggClassEst += alpha * classEst
        #print 'aggClassEst:',aggClassEst#累积的预测估计(已经乘以alpha分量)
        aggErrors = multiply(sign(aggClassEst) != mat(classLabels).T,ones((m,1)))
        #利用sign函数得到二值分类结果
        errorRate = aggErrors.sum() / m
        print 'total error: ',errorRate,'\n' #总的错误率
        if errorRate == 0.0 :
            break
    return weakClassArr,aggClassEst
#datMat,classLabels = loadSimpleData()
#adaBoostTrainDs(datMat,classLabels,9)

利用该算法对简单数据分类的结果:

#7-3AdaBoost分类函数
def adaClassify(datToClass,classifierArr):
    dataMatrix = mat(datToClass)#将输入的数据集转变为一个Numpy数组
    m = shape(dataMatrix)[0] #样本个数
    aggClassEst = mat(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
        #输出的类别估计值乘上该单层决策树的alpha权重然后累加到aggClassEst上
        print aggClassEst
    return sign(aggClassEst)

#第五章用logistic预测病马,这里利用多个单层决策树和AdaBoost来试试
#自适应数据加载函数
def loadDataSet(fileName):
    numFeat = len(open(fileName).readline().split('\t'))
    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
#datArr,labelArr = loadDataSet('D:\pythonml\horseColicTraining2.txt')

def classify():
    #利用训练集训练分类器
    datArr,labelArr = loadDataSet('horseColicTraining.txt')
    #得到训练好的分类器
    classifierArray = adaBoostTrainDs(datArr,labelArr,10)
    #利用测试集测试分类器的分类效果
    testArr,testLabelArr = loadDataSet('horseColicTest.txt')
    prediction = adaClassify(testArr,classifierArray)
    #输出错误率
    num=shape(mat(testLabelArr))[1]
    #print num
    errArr = mat(ones((num,1)))
    error = errArr[prediction != mat(testLabelArr).T].sum()
    print 'the errorRate is: %.2f'%(float(error)/float(num))

对第五章logistic回归的病马预测,现在使用Adaboost配合决策树算法来实现,结果如下:

采用10个分类器:

运用sklearn库,使用Adaboost:

如何调参:https://www.cnblogs.com/pinard/p/6136914.html

#使用sklearn来实现Adaboost病马预测
datArr,labelArr = loadDataSet('D:\pythonml\horseColicTraining2.txt')#训练集
testArr,testLabelArr = loadDataSet('D:\pythonml\horseColicTest2.txt')#测试集
#决策树桩
dt_stump=DecisionTreeClassifier()
#dt_stump.fit(datArr,labelArr)
#dt_stump_err=1.0-dt_stump.score(testArr,testLabelArr)

ada_discrete=AdaBoostClassifier(base_estimator=dt_stump,learning_rate=0.35,n_estimators=10,algorithm='SAMME.R')
ada_discrete.fit(datArr,labelArr) #训练样本

print 'score:',ada_discrete.score(datArr,labelArr)
test = ada_discrete.predict(testArr)
errArr = mat(ones((67,1)))
error = errArr[test != testLabelArr].sum()
print 'the errorRate is: %.2f'%(float(error)/67)

最优结果:

参数:learning_rate=0.35,n_estimators=10

 

正确率、召回率和ROC曲线:

    预测结果
    +1 -1
真实结果 +1 真正例(TP) 伪反例(FN)
-1 伪正例(FP) 真反例(TN)

正确率:TP/(TP+FP) 预测为正例的样本中的真正正例的比例

召回率:TP/(TP+FN) 预测为正例的真实正例占所有真实正例的比例

我们很难构造一个正确率和召回率都很大的分类器。

ROC曲线(receiver operating characteristic 接收者操作特征):横轴是伪正例比例(FP/FP+TN),纵轴是真正例的比例(TP/TP+FN)。在理想情况下最佳分类器应该处于左上角,在假阳率很低的同时获得了很高的真阳率。对不同的ROC曲线进行比较的一个指标是曲线下的面积(Area Unser the Curve,AUC)

#7-5ROC曲线的绘制及AUC计算函数
def plotROC(predStrengths, classLabels):
    #第一个参数是一个Numpy数组,代表着分类器的预测强度;第二个参数是标签
    cur = (1.0,1.0)#绘制光标的位置
    ySum = 0.0#该变量用于计算AUC的值(Area Under the Curve曲线下的面积)
    numPosClas = sum(array(classLabels) == 1.0)#标签只有-1和1,统计标签为1的数目
    yStep = 1 / float(numPosClas) #y的步长
    xStep = 1 / float(len(classLabels) - numPosClas) #x的步长
    sortedIndicies = predStrengths.argsort() #排序
    fig = plt.figure()
    fig.clf()
    ax = plt.subplot(111)
    for index in sortedIndicies.tolist()[0]:#tolist():将数组或者矩阵转换成列表
        if classLabels[index] == 1.0:
            delX = 0;delY = yStep;
            #当遍历表时,每得到一个标签为1.0的类,则要沿着y轴的方向下降一个步长,即不断降低真阳率
        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()
    print 'the Area Under the Curve is: ',ySum*xStep

datArr,labelArr = loadDataSet('D:\pythonml\horseColicTraining2.txt')
classifierArray,aggClassEst = adaBoostTrainDs(datArr,labelArr,60)
plotROC(aggClassEst.T,labelArr)

发布了30 篇原创文章 · 获赞 29 · 访问量 2225

猜你喜欢

转载自blog.csdn.net/weixin_41938314/article/details/90216724