《机器学习实战》代码片段学习5 AdaBoost元算法

来源:互联网 发布:python下载后怎么使用 编辑:程序博客网 时间:2024/05/20 09:10

svm那一章看的太吃力…先缓缓,回头再收拾它(

简介

基于同一分类器多个不同实例的两种计算方法:bagging与boosting

Bagging:从原始数据集选择S次后得到S个新数据集的一种技术,将某个学习算法串行作用于每个数据集就得到了S个分类器。对新数据进行分类时,用这S个分类器进行分类,并选择分类器投票结果中最多的类别作为最后的分类结果。

Boosting:关注被已有分类器错分的数据来获取新的分类器。分类结果为基于所有分类器的结果进行加权求和。

Adaboost是boosting方法中最为流行的一个版本。

AdaBoost优缺点:
优点:泛化错误率低,易编码,可以应用在大部分分类器上,无参数调整。
缺点:对离群点敏感。
适用数据类型:数值型和标称型数据。

例子中使用的分类器是单层决策树。
单层决策树:仅基于单个特征做分类,只有一次分裂过程(树桩)

数学基础

分类器错误率定义:
这里写图片描述

分类器每次迭代后的权重alpha计算:
这里写图片描述

分类器每次迭代后样本权重的更新:
如果某个样本被正确分类,那么该样本的权重更改为:
这里写图片描述

而如果某个样本被错分,那么该样本的权重更改为:
这里写图片描述

Adaboost算法流程图:
这里写图片描述

代码学习

首先先把作为分类器的单层决策树弄起来。

单层决策树伪代码:

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

单层决策树生成函数:

#分类函数,通过数组过滤实现#传入的参数分别为:dataMatrix数据矩阵,dimen特征类型(维度),threshVal用于作为分类标准的阈值,由(特征值最小值+步长)获得,threshIneq不等号def stumpClassify(dataMatrix,dimen,threshVal,threshIneq):    retArray = ones((shape(dataMatrix)[0],1))  #用于记录dimen特征类型的分类结果    if threshIneq == 'lt':  #若不等号为<        retArray[dataMatrix[:,dimen] <= threshVal] = -1.0  #将特征值小于threshVal的置为-1    else:  #若不等号为>        retArray[dataMatrix[:,dimen] > threshVal] = -1.0  #将特征值大于threshVal的置为-1    return retArray#遍历所有能传给stumpClassify()的数据组合,在其寻找最佳的单层决策树#传入参数:dataArr数据样本,classLabels数据样本分类结果数组,D为初始权重向量def buildStump(dataArr,classLabels,D):    #数组转为numpy矩阵    dataMatrix = mat(dataArr); labelMat = mat(classLabels).T #T转置    m,n = shape(dataMatrix)    numSteps = 10.0; bestStump = {}; bestClasEst = 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 ['lt', 'gt']:  #对每个不等号进行循环                threshVal = (rangeMin + float(j) * stepSize)                #以threshVal作为标准进行分类                predictedVals = stumpClassify(dataMatrix,i,threshVal,inequal)                 errArr = mat(ones((m,1)))  #记录错误情况的列向量                errArr[predictedVals == labelMat] = 0  #分类结果正确的记为0                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  #更新最好的作为分类标准的threshVal值                    bestStump['ineq'] = inequal  #更新最好的用于分类的不等号    return bestStump,minError,bestClasEst  #返回带有最好单层决策树的字典、错误率,分类结果(类别估计值)

有了单层决策树后,我们就可以实现一个完整的adaboost算法了。

完整adaboost算法伪代码:

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

基于单层决策树的AdaBoost训练过程,DS代表单层决策树:

#输入参数:dataArr数据样本数组,classLabels样本分类结果数组,numIt迭代次数def adaBoostTrainDS(dataArr,classLabels,numIt=40):    weakClassArr = []  #弱分类器的分类结果,是一个二维数组    m = shape(dataArr)[0]    D = mat(ones((m,1))/m)  #初始权重向量矩阵    aggClassEst = mat(zeros((m,1)))  #记录特征类别估计累计值    for i in range(numIt):          #获取最好的单层决策树(树桩)字典,最好的错误率,最好的分类结果        bestStump,error,classEst = buildStump(dataArr,classLabels,D)        #根据分类错误率计算分类器权重alpha        alpha = float(0.5*log((1.0-error)/max(error,1e-16)))          bestStump['alpha'] = alpha  #字典中加入权重        weakClassArr.append(bestStump)  #记录最好的分类结果        #(以下三行)更新样本权重D        expon = multiply(-1*alpha*mat(classLabels).T,classEst)        D = multiply(D,exp(expon))          D = D/D.sum()        aggClassEst += alpha*classEst  #累计值        #记录每个特征错误情况的数组aggErrors,sign(n)获取二值分类结果,若n大于0返回1.0,若小于0返回-1.0,若等于0返回0.0        aggErrors = multiply(sign(aggClassEst) != mat(classLabels).T,ones((m,1)))        errorRate = aggErrors.sum()/m        print "total error: ",errorRate        if errorRate == 0.0: break    return weakClassArr,aggClassEst

拥有了复数的分类器与对应的alpha值,我们就可以进行分类操作了。

AdaBoost分类函数:

#输入参数:datToClass待分类数据,classifierArr多个弱分类器组成的数组def adaClassify(datToClass,classifierArr):    dataMatrix = mat(datToClass)     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        print aggClassEst    return sign(aggClassEst)

总结

通常情况下,AdaBoost会得到一个稳定的测试错误率,而不会随着分类器数目增多而提高。但有时候也会发生过拟合现象。

“本章以单层决策树作为弱学习器构建了AdaBoost分类器。实际上,AdaBoost函数可以应用于任意分类器,只要该分类器能够处理加权数据即可。AdaBoost算法十分强大,它能够快速处理其他分类器很难处理的数据集。”

阅读全文
0 0
原创粉丝点击