AdaBoost算法

来源:互联网 发布:win10 适用于linux 编辑:程序博客网 时间:2024/06/05 14:11

由于本人也是小白一只,所以本文将基于机器学习实战或者互联网作此记录,如有侵权告知将删……

    • 1AdaBoost
    • 2AdaBoost优缺点
    • 3公式
    • 4伪代码
    • 5代码

1、AdaBoost

Adaboost算法是通过改变数据分布来实现的,他根据每次训练集之中的每个样本的分类是否正确,以及上次的总体分类的准确率,来确定每个样本的权值。将修改过权值的新数据集送给下层分类器进行训练,最后将每次得到的分类器最后进行融合起来,作为最后的决策分类器。
AdaBoost是以弱学习作为基分类的分类器,并且输入数据,使其通过权重向量进行加权。在第一迭代当中,所有数据都等权重。但是在后续迭代当中,前次迭代中分错的数据的权重会增大。这种对错误调节的能力正是AdaBoost的长处。AdaBoost可以应用于任意分类器,只要该分类器能够处理加权数据即可。
由于是基于机器学习实战这本书,所以AdaBoost算法是按照书上写的应用于单层决策树分类器之上的。难的我也不会 哇哈哈哈……
#

2、AdaBoost优缺点

优点:泛化错误率低
缺点:对离群点敏感
适用数据范围:数值型和标称型

3、公式

学习AdaBoost先了解一下公式:
错误率ϵ

ϵ=

而alpha计算公式:
α=12ln(1ϵϵ)

如果某个样本被正确分类,那么该样本的权重更改为:
D(t+1)i=D(t)ieaSum(D)

如果某个样本被分错,那么样本的权重更改为:
D(t+1)i=D(t)ieaSum(D)

4、伪代码

构建基于单层决策树弱分类器

将最小错误率minError设为inf对数据集中的每一特征(第一层循环):    对每个步长(第二层循环):         对每个等号(第三层循环):                 建立一个单层决策树利用数据集对它进行测试                 如果错误率低于minError,则将当前单层决策树设为最佳单层决策树返回最佳单层决策树

AdaBoost算法

对每次迭代:    利用buildStump()函数找到最佳单层决策树    将最佳单层决策树加入到单层决策树数组    计算alpha    计算新的权重向量D    更新累计类别估计值    如果错误率等于0.0,退出循环

5、代码

#encoding:utf-8import numpy as npfrom numpy import *from math import log#简单的训练集def loadSimData():    datMat = mat([[1,2],[2,1.1],[1.3,1.],[1,1],[2,1]])    classLabels=[1.0,1.0,-1.0,-1.0,1.0]    return datMat, classLabels#通过特征值中的阀值进行分类,‘It’,‘gt’用于buildStump函数进行互换分类,#由于本例是一个二分类问题,所以只有-1,1def stumpClassify(datMat, dimen, val, Ineq):    reArray = ones((shape(datMat)[0], 1))    if Ineq == 'It':        reArray[datMat[:, dimen] <= val] = -1.0    else:        reArray[datMat[:, dimen] > val] = -1.0    return reArray#寻找最佳特征值和最佳阀值进行分类def buildStump(dataArr, classLabels, D):#D为权重向量    datMat = mat(dataArr);labelMat = mat(classLabels).T    m,n = shape(datMat)    numSteps = 10;#用于分割区间用    bestStump = {};#记录最佳的分割信息    bestClasEst = mat(ones((m,1)))#预测最佳的分类    minError = inf    for i in range(n):        rangeMin = datMat[:,i].min();rangeMax = datMat[:, i].max()        stepSize = (rangeMax - rangeMin)/numSteps#步长               for j in range(-1, int(numSteps)+2):#-1和numStep+2,是将他们分到一边,            for inequal in ['It','gt']:#用于分类转换,因为以前已经规定好了分类了                Val = rangeMin + float(j)*stepSize#阀值                preVal = stumpClassify(datMat, i, Val, inequal)#预测的分类                errArr = mat(ones((m,1)))                errArr[preVal == labelMat] = 0#分类一致的errArr置为0                weightedErr = D.T*errArr#计算加权错误率                '''自己的理解                D向量相当于一个惩罚措施,它会使错误的分类样本的对应的权重变大,如果想要                                  减小加权错误率那么就需要变换的另一边去,这样加权错误率就会减少,通过D就可以改正                                  错误                  '''#                 print "split: dim %d, thresh %.2f, thresh ineqal: %s, the weighted error is %.3f" % (i, Val, inequal, weightedErr)                if weightedErr < minError:                    minError = weightedErr                    bestClasEst = preVal.copy()                    bestStump['dim'] = i                     bestStump['thresh'] = Val                     bestStump['ineq'] = inequal    return bestStump, minError, bestClasEst#基于单层决策树的AdaBoost训练过程def adaBoostTrainDS(dataArr, classLabels, numIt = 40):#numIt其实就是弱分类器的个数    weakClassArr=[]#记录不同的弱分类器    m = shape(dataArr)[0]    #D是一个概率分布,所有元素之和为1.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        #通过错误率计算alpha值,max(error, 1e-16)防止发生0溢出        alpha = float(0.5*log((1 - error)/ max(error, 1e-16)))        bestStump['alpha'] = alpha #将alpha记录到词典当中        weakClassArr.append(bestStump)        print 'classEst',classEst.T         '''迭代D向量'''        #计算  错误的权重 Di+1= Di*e^(a)/sum(D)和正确的权重Di+1= Di*e^(-a)/sum(D)        expon = multiply(-1*(alpha)*classEst, mat(classLabels).T)#这里进行的比较巧妙,        #对于分类相同的乘积一定为1,不同的分类的乘积为-1,利用这个性质可以简化代码        D = multiply(D, exp(expon))        D = D/D.sum()        #累加估计值        '''                个人理解        这里的alpha是根据错误率计算的来的alpha=1/2*ln((1-error)/error),可以看出来error越大alpha        越小,alpha*classEst这里代表的意思其实就可以这样理解,正确率越高说明可信度就越高,占得比重        就得越大        '''        aggClassEst += alpha*classEst        print "aggClassEst",aggClassEst.T            print "classLabels",classLabels        #sign函数将小于0的值变为-1,将大于0的值变为1        aggErrors = multiply(sign(aggClassEst) != mat(classLabels).T,ones((m,1)))        errorRate = float(aggErrors.sum()/m)        print "total error: ",errorRate        if errorRate == 0.0:             break     return weakClassArr#AdaBoost分类函数def adaClassify(datToClass, classifierArr):    datMat = mat(datToClass)    m = shape(datMat)[0]    aggClassEst=mat(zeros((m,1)))    for i in range(len(classifierArr)):        preVal = stumpClassify(datMat, classifierArr[i]['dim'], classifierArr[i]['thresh'],                             classifierArr[i]['ineq'])        aggClassEst+=preVal*classifierArr[i]['alpha']#         print aggClassEst     return sign(aggClassEst)#--------------预测马疝病----------------------def loadDataSet(filename):    numFeat = len(open(filename).readline().strip().split('\t')) - 1    datMat=[];labelMat=[]    for line in open(filename).readlines():        curline = line.strip().split('\t')        furline=map(float,curline)        datMat.append(furline[:-1])        labelMat.append(furline[-1])    return datMat, labelMatif __name__ == '__main__':    D = mat(ones((5,1))/5)    a,b=loadSimData()#     buildStump(a, b, D)  #     classfy = adaBoostTrainDS(a, b, 40)  #     adaClassify([[5,5],[0,0]],classfy)    datArr, labelArr = loadDataSet(r'horseColicTraining2.txt')    classifierArr = adaBoostTrainDS(datArr, labelArr, 10)#可以设置数量不同的分类器    '''    当分类器数目设置为50的时候预测的错误率最低。    其实我们发现测试错误率在随着分类器数目增多的同时,测试错误率在达到一个最小值之后又开始上升了    这类学习称为过拟合,有文献称,对于表现好的数据集,AdaBoost测试错误率会达到一个稳定值,并不会    随着分类器的数目增多而增多    '''    testArr, labelArr = loadDataSet(r'horseColicTest2.txt')    preVal = adaClassify(testArr, classifierArr)    print shape(preVal)    errArr = mat(ones((67,1)))    print errArr[preVal != mat(labelArr).T].sum()/67
原创粉丝点击