Adaboost算法简单实现

来源:互联网 发布:vb的数值型的初始值 编辑:程序博客网 时间:2024/05/29 18:50
#encoding=utf-8__author__ = 'freedom'from numpy import *def LoadData():    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,classLabelsdef StumnpClassify(dataMatrix,dimen,threshVal,threshIneq):    '''    本函数用于进行最简单分类    :param dataMatrix: 数据集,要求是矩阵形式    :param dimen: 选中的特征,以此特征进行划分    :param threshVal: 选取划分的阈值    :param threshIneq: 选取划分的不等式符号    :return:分类的结果,数组形式    '''    retArray = ones((shape(dataMatrix)[0],1)) #生成返回数组,维度为(样例数*1)    if threshIneq == 'lt':  #选取的不等式为小于等于        retArray[dataMatrix[:,dimen] <= threshVal] = -1.0 #将所有小于等于阈值的值全部表位-1.0    else:        retArray[dataMatrix[:,dimen] > threshVal] = -1.0    return retArraydef BuildStump(dataArr,labels,D):    '''    本函数用于产生一个简单的树桩分类器    :param dataArr: 数据集。要求不一定为矩阵形式    :param labels: 标签集,要求不一定为矩阵形式    :param D: 权重    :return:最优分类器,字典形式,包含最佳分类特征、阈值和不等式形式,最小误差和最优分类结果    '''    dataMat = mat(dataArr)    labelMat = mat(labels).T #本函数中所有数据均要矩阵化,方便之后的比较工作    m,n = shape(dataMat)    numSteps = 10.0 #迭代次数    bestStump = {}    bestClassEst = mat(zeros((m,1)))    minError = inf    for i in range(n):    #本层循环是遍历所有的特征,选取误差最小的作为分类器        rangeMin = dataMat[:,i].min()        rangeMax = dataMat[:,i].max()        stepSize = (rangeMax - rangeMin)/numSteps #迭代的阈值初始化        for j in range(-1,int(numSteps)+1): #遍历所有离散的阈值            for inequal in ['lt','gt']: #遍历两种不等式形式                threshVal = rangeMin+float(j)*stepSize                predictVal = StumnpClassify(dataMat,i,threshVal,inequal) #获得分类结果                errArr = mat(ones((m,1)))                errArr[predictVal == labelMat] = 0 #获得分类误差列向量,如果与标签不同,该项值为1                weightError = D.T*errArr   #加权计算误差,获得的值是一个数,分类正确的数据权重减小,分类错误的数据权重增加,但是在某次寻找最优单分类器时D是保持不变的                if weightError <= minError:                    minError = weightError #更新误差                    bestClassEst = predictVal.copy() #复制分类结果                    bestStump['dim'] = i     #记录下最佳分类器的三个参数                    bestStump['threshVal'] = threshVal                    bestStump['ineq'] = inequal    return bestStump,minError,bestClassEstdef AdaBoostTrainDS(dataArr,labels,numIt = 40):    '''    本函数用于AdaBoost学习    :param dataArr: 数据集,不要求为矩阵形式    :param labels: 标签集,不要求为矩阵形式    :param numIt: 迭代次数,可自由设定,默认为40    :return:所有弱分类器,列表形式,嵌套有所有弱分类器,字典形式,包含有有划分特征、阈值、不等式形式和alpha值四个参数    '''    weakClassArr = []    m = shape(dataArr)[0]    D = mat(ones((m,1))/m) # 初始化权重,平均分为m份,m为样例数,目的是对分类错误的样例加大权重,详见BuildStump函数    aggClasssEst = mat(zeros((m,1)))    for i in range(numIt): #迭代        bestStump,error,classEst = BuildStump(dataArr,labels,D) # 获得弱分类器、分类误差和分类结果        alpha = float(0.5*log((1.0-error)/max(error,1e-16))) # 计算alpha,这里1e-16是为了保证不会出现除零错误        bestStump['alpha'] = alpha   # 这里的alpha值就是该弱分类器的权重        weakClassArr.append(bestStump) # 将弱分类器加入列表        expon = (multiply(-1*alpha*mat(labels).T,classEst))  # 更新权重,对于分类错误的要加大权重,分类正确的减小权重#注意,这里multiply应该是列向量的元素对应相乘        #print D        D = multiply(D,exp(expon))        D = D/D.sum()        aggClasssEst += alpha*classEst #计算叠加了当前弱分类器后的分类结果        aggError = multiply(sign(aggClasssEst)!= mat(labels).T,ones((m,1))) #计算叠加当前分类器后的误差        errorRate = aggError.sum()/m #计算误差率        #print 'Error is ',errorRate,'\n'        if errorRate == 0.0:break #如果误差率为0,则提前结束迭代循环    return weakClassArrdef AdaClassify(dataSet,classifer):    '''    本函数用于分类    :param dataSet: 数据集,不要求为矩阵形式    :param classifer: 分类器,字典形式,应该是多个弱分类器的组合    :return:类型    '''    dataMat = mat(dataSet) #数据集矩阵化    m = shape(dataMat)[0]    aggClassEst = mat(zeros((m,1)))    for i in range(len(classifer)): #遍历所有的分类器        ClassEst = StumnpClassify(dataMat,classifer[i]['dim'],classifer[i]['threshVal'],classifer[i]['ineq'])        #应用每一个弱分类器分类        aggClassEst += classifer[i]['alpha']*ClassEst#对每个弱分类器的结果加权求和        #print aggClassEst    return sign(aggClassEst)def LoadBigData(filename):    '''    本函数用于加载大量数据    :param filename: 数据文件名    :return:数据集和标签集,均为列表形式    '''    numFeat = len(open(filename).readline().split('\t')) #获得特征数目    dataSet = []    labels = []    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])) #读出的是字符串,要转换为浮点型        dataSet.append(lineArr)        labels.append(float(curLine[-1]))    return dataSet,labelstrainData,trainLabels =LoadBigData('train.txt')testData,testLabels = LoadBigData('test.txt')classifer =  AdaBoostTrainDS(trainData,trainLabels,60)# 用数据集进行训练predictValue = AdaClassify(testData,classifer) # 用测试数据观察分类numTest = len(testLabels) # 获取测试数据数目for i in range(len(predictValue)): # 比对预测数值和真实数值    if predictValue[i] == testLabels[i]:        print 'YES!'    else:        print 'No!'errArr = mat(ones((numTest,1)))errRate = errArr[predictValue != mat(testLabels).T].sum()/numTest #求误差率print errRate'''d,l = LoadData()AdaBoostTrainDS(d,l,numIt=40)'''

0 0
原创粉丝点击