机器学习实战之adaboost

AdaBoost,是英文"Adaptive Boosting"(自适应增强)的缩写。它的自适应在于:前一个基本分类器分错的样本会得到加强,加权后的全体样本再次被用来训练下一个基本分类器。同时,在每一轮中加入一个新的弱分类器,直到达到某个预定的足够小的错误率或达到预先指定的最大迭代次数。

1.算法流程:

给定一个数据集T=(x_{1},y_{1}),(x_{2},y_{2}),...,(x_{n},y_{n}),类标签y_{i}=+1,-1,adaboost的目的是学习得到一系列弱分类器(基本分类器),然后组合成一个强分类器。

step1:初始化数据的权重向量D,每一个样本都被赋予相同权重1/N

                                D=(w_{11},w_{12},...,w_{1i},...w_{1N}),i=1,2,...,N

step2:进行迭代,用m=1,2,..M表示当前第m轮迭代

(1)使用带权值Dm的数据集训练得到弱分类器Gm(选取让误差率最小的阈值来设计基本分类器,本文采用单决策树作为基本分类器)

(2) 计算Gm(x)在训练数据集上的分类误差率

                     e_{m}=P(G_{m}(x_{i})\neq y_{i})=\sum_{i=1}^{N}w_{mi}I(G_{m}(x)\neq y_{i})

即错分类样本实例的权值之和

(3)计算Gm(x)的系数\alpha_{m},表示当前弱分类器在最终分类器中的权重

                                 \alpha_{m}=\frac{1}{2}ln(\frac{1-e_{m}}{e_{m}})

(4)更新训练集的权值分布,计算向量Dm+1,用于下一轮迭代

                      D_{m+1}=(w_{m+1,1},w_{m+1,2},...,w_{m+1,i},...,w_{m+1,N}),i=1,2,...,N

                      w_{m+1,i}=\frac{w_{m,i}}{Z_{m}}exp(-\alpha_{m}y_{i}G_{m}(x_{i})),i=1,2,...,N

其中,Zm是规范化因子,使得Dm+1成为一个概率分布:

                     Z_{m}=\sum_{i=1}^{N}w_{m,i}exp(-\alpha_{m}y_{i}G_{m}(x_{i})),i=1,2,...N

(5)组合各个弱分类器

                          f(x)=\sum_{m=1}^{M}\alpha_{m}G_{m}(x)

得到强分类器

                    G(x)=sign(f(x))

2.实例代码

from numpy import *

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 loadData(filename):
    dataMat=[]
    labelMat=[]
    fr=open(filename)
    for line in fr.readlines():
        currLine=line.strip().split('\t')
        lineArr=[float(a) for a in currLine[:-1]]
        dataMat.append(lineArr)
        labelMat.append(float(currLine[-1]))
    return dataMat,labelMat

#构建单决策树;可根据任意特征分量设置阈值将数据分为两类
def stumpClassify(dataMat,dim,threshVal,threshIneq):
    retArr=ones((shape(dataMat)[0],1))
    if threshIneq=='lt':
        retArr[dataMat[:,dim]<=threshVal]=-1 #数组过滤,小于阈值的归为-1类
    else:
        retArr[dataMat[:,dim]>=threshVal]=-1
    return retArr

#选择最佳决策树;D为样本权重系数向量
def buildStump(dataMat,labelMat,D):
    dataMatrix=mat(dataMat)
    labelMatrix=mat(labelMat).transpose()
    stump={}
    m,n=shape(dataMatrix)
    bestClassEst=ones((m,1))
    numStep=10
    minError=inf
    for i in range(n):#对每一维度特征进行循环
        maxVal=dataMatrix[:,i].max()
        minVal=dataMatrix[:,i].min()
        sizeStep=(maxVal-minVal)/numStep
        for j in range(-1,numStep+1):#对不同阈值循环;
            for threshIneq in ['lt','gt']:#对不等号方向进行循环
                threshVal=minVal+j*sizeStep
                predictVal=stumpClassify(dataMatrix,i,threshVal,threshIneq)
                errArr=mat(ones((m,1)))
                errArr[predictVal==labelMatrix]=0
                weightedError=D.T*mat(errArr)
                #print ("split: dim %d, thresh %.2f, thresh ineqal: %s, the weighted error is %.3f" % (i, threshVal, threshIneq, weightedError))
                if weightedError<minError:
                    minError=weightedError
                    bestClassEst=predictVal
                    stump['dim']=i
                    stump['threshVal']=threshVal
                    stump['threshIneq']=threshIneq
    return stump,minError,bestClassEst

#输出弱分类器集合;加权预测值
def adaboostTrainDS(dataMat,labelMat,numIter=40):
    weakClassArr=[]  #弱分类器集合
    m=shape(dataMat)[0]
    D=mat(ones((m,1))/m) #初始化样本权重向量
    aggClassEst=mat(zeros((m,1))) #预测分类向量
    for i in range(numIter):
        bestStump,error,classEst=buildStump(dataMat,labelMat,D)
        alpha=float(0.5*log((1-error)/max(error,1e-16))) #计算弱分类器权重;max(error,1e-16)防止分母为零
        bestStump['alpha']=alpha
        weakClassArr.append(bestStump)
        exon=multiply(-alpha*mat(labelMat).T,classEst)
        D=multiply(D,exp(exon))
        D=D/D.sum()           #更新矩阵D
        aggClassEst+=alpha*classEst  #累积加权预测值
        aggError=multiply(sign(aggClassEst)!=mat(labelMat).T,ones((m,1)))#计算错误率 ,当错误率 等于零时跳出循环
        errorRate=aggError.sum()/m
        print('total error rate:',errorRate)
        if errorRate==0:
            break
    return weakClassArr,aggClassEst

#利用训练好的弱分类为器集合对待分类数据进行分类
def adaClassify(dataToClass,classArr):
    dataMat=mat(dataToClass)
    m=shape(dataMat)[0]
    aggClassEst=mat(zeros((m,1)))
    for i in range(len(classArr)):
        classEst=stumpClassify(dataMat,classArr[i]['dim'],classArr[i]['threshVal'],classArr[i]['threshIneq'])
        aggClassEst+=classArr[i]['alpha']*classEst
    #print(aggClassEst)
    return sign(aggClassEst)



data,label=loadData('D:\python\code\machinelearninginaction\Ch07\horseColicTraining2.txt')
classArr,classEst=adaboostTrainDS(data,label,100)
datatest,labeltest=loadData('D:\python\code\machinelearninginaction\Ch07\horseColicTest2.txt')
predict=adaClassify(datatest,classArr)
errArr=mat(ones((67,1)))
numError=errArr[predict!=mat(labeltest).T].sum()
print('Error rate for test:',numError/67)

最后通过在马疝病数据集上运用adaboost分类器,对病马是否死亡进行预测。当分类器数目为50时,分类错误率可以达到21%,取得不错的结果。

 

 

 

 

 

 

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值