这篇文章主要讲解了“Python如何实现AdaBoost算法”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“Python如何实现AdaBoost算法”吧!

一、算法概述

AdaBoost 是英文 Adaptive Boosting(自适应增强)的缩写,由 Yoav Freund 和Robert Schapire 在1995年提出。

AdaBoost 的自适应在于前一个基本分类器分类错误的样本的权重会得到加强,加强后的全体样本再次被用来训练下一个基本分类器。同时,在每一轮训练中加入一个新的弱分类器,直到达到某个预定的足够小的错误率或达到预先指定的最大迭代次数时停止训练。

AdaBoost 算法是一种集成学习的算法,其核心思想就是对多个机器学习模型进行组合形成一个精度更高的模型,参与组合的模型称为弱学习器。

二、算法原理

AdaBoost 的核心思想是针对同一训练集训练不同的分类器(弱分类器),然后把这些弱分类器集合起来,构成一个更强大的最终分类器(强分类器)。也 就是通过一些手段获得多个弱分类器,将它们集成起来构成强分类器,综合所有分类器的预测得出最终的结果。

AdaBoost 算法本身是通过改变数据分布来实现的,它根据每次训练集中每个样本的分类是否正确,以及上次的总体分类的准确率,来确定每个样本的权值。将修改过权值的新数据集送给下层分类器进行训练,最后将每次训练得到的分类器最后融合起来,作为最后的决策分类器。

三、算法实现

fromnumpyimport*importmatplotlib.pyplotasplt#加载数据集defloadDataSet(fileName):numFeat=len(open(fileName).readline().split(''))dataMat=[]labelMat=[]fr=open(fileName)forlineinfr.readlines():lineArr=[]curLine=line.strip().split('')foriinrange(numFeat-1):lineArr.append(float(curLine[i]))dataMat.append(lineArr)labelMat.append(float(curLine[-1]))returndataMat,labelMat#返回分类预测结果根据阈值所以有两种返回情况defstumpClassify(dataMatrix,dimen,threshVal,threshIneq):retArray=ones((shape(dataMatrix)[0],1))ifthreshIneq=='lt':retArray[dataMatrix[:,dimen]<=threshVal]=-1.0else:retArray[dataMatrix[:,dimen]>threshVal]=-1.0returnretArray#返回该弱分类器单层决策树的信息更新D向量的错误率更新D向量的预测目标defbuildStump(dataArr,classLabels,D):dataMatrix=mat(dataArr)labelMat=mat(classLabels).Tm,n=shape(dataMatrix)numSteps=10.0bestStump={}#字典用于保存每个分类器信息bestClasEst=mat(zeros((m,1)))minError=inf#初始化最小误差最大foriinrange(n):#特征循环(三层循环,遍历所有的可能性)rangeMin=dataMatrix[:,i].min()rangeMax=dataMatrix[:,i].max()stepSize=(rangeMax-rangeMin)/numSteps#(大-小)/分割数得到最小值到最大值需要的每一段距离forjinrange(-1,int(numSteps)+1):#遍历步长最小值到最大值的需要次数forinequalin['lt','gt']:#在大于和小于之间切换threshVal=(rangeMin+float(j)*stepSize)#最小值+次数*步长每一次从最小值走的长度predictedVals=stumpClassify(dataMatrix,i,threshVal,inequal)#最优预测目标值用于与目标值比较得到误差errArr=mat(ones((m,1)))errArr[predictedVals==labelMat]=0weightedError=D.T*errArrifweightedError<minError:#选出最小错误的那个特征minError=weightedError#最小误差后面用来更新D权值的bestClasEst=predictedVals.copy()#最优预测值bestStump['dim']=i#特征bestStump['thresh']=threshVal#到最小值的距离(得到最优预测值的那个距离)bestStump['ineq']=inequal#大于还是小于最优距离为-1returnbestStump,minError,bestClasEst#循环构建numIt个弱分类器defadaBoostTrainDS(dataArr,classLabels,numIt=40):weakClassArr=[]#保存弱分类器数组m=shape(dataArr)[0]D=mat(ones((m,1))/m)#D向量每条样本所对应的一个权重aggClassEst=mat(zeros((m,1)))#统计类别估计累积值foriinrange(numIt):bestStump,error,classEst=buildStump(dataArr,classLabels,D)alpha=float(0.5*log((1.0-error)/max(error,1e-16)))bestStump['alpha']=alphaweakClassArr.append(bestStump)#加入单层决策树#得到运算公式中的向量+/-α,预测正确为-α,错误则+α。每条样本一个α#multiply对应位置相乘这里很聪明,用-1*真实目标值*预测值,实现了错误分类则-,正确则+expon=multiply(-1*alpha*mat(classLabels).T,classEst)D=multiply(D,exp(expon))#这三步为更新概率分布D向量拆分开来了,每一步与公式相同D=D/D.sum()#计算停止条件错误率=0以及计算每次的aggClassEst类别估计累计值aggClassEst+=alpha*classEst#很聪明的计算方法计算得到错误的个数,向量中为1则错误值aggErrors=multiply(sign(aggClassEst)!=mat(classLabels).T,ones((m,1)))#sign返回数值的正负符号,以1、-1表示errorRate=aggErrors.sum()/m#错误个数/总个数#print("错误率:",errorRate)iferrorRate==0.0:breakreturnweakClassArr,aggClassEst#预测累加多个弱分类器获得预测值*该alpha得到结果defadaClassify(datToClass,classifierArr):#classifierArr是元组,所以在取值时需要注意dataMatrix=mat(datToClass)m=shape(dataMatrix)[0]aggClassEst=mat(zeros((m,1)))#循环所有弱分类器foriinrange(len(classifierArr[0])):#获得预测结果classEst=stumpClassify(dataMatrix,classifierArr[0][i]['dim'],classifierArr[0][i]['thresh'],classifierArr[0][i]['ineq'])#该分类器α*预测结果用于累加得到最终的正负判断条件aggClassEst+=classifierArr[0][i]['alpha']*classEst#这里就是集合所有弱分类器的意见,得到最终的意见returnsign(aggClassEst)#提取数据符号#ROC曲线,类别累计值、目标标签defplotROC(predStrengths,classLabels):cur=(1.0,1.0)#每次画线的起点游标点ySum=0.0#用于计算AUC的值矩形面积的高度累计值numPosClas=sum(array(classLabels)==1.0)#所有真实正例确定了在y坐标轴上的步进数目yStep=1/float(numPosClas)#1/所有真实正例y轴上的步长xStep=1/float(len(classLabels)-numPosClas)#1/所有真实反例x轴上的步长sortedIndicies=predStrengths.argsort()#获得累计值向量从小到大排序的下表index[50,88,2,71...]fig=plt.figure()fig.clf()ax=plt.subplot(111)#循环所有的累计值从小到大forindexinsortedIndicies.tolist()[0]:ifclassLabels[index]==1.0:delX=0#若为一个真正例,则沿y降一个步长,即不断降低真阳率;delY=yStep#若为一个非真正例,则沿x退一个步长,尖笑阳率else:delX=xStepdelY=0ySum+=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('Falsepositiverate')plt.ylabel('Truepositiverate')plt.title('ROCcurveforAdaBoosthorsecolicdetectionsystem')ax.axis([0,1,0,1])plt.show()print("theAreaUndertheCurveis:",ySum*xStep)#AUC面积我们以高*低的矩形来计算#测试正确率datArr,labelArr=loadDataSet('horseColicTraining2.txt')classifierArr=adaBoostTrainDS(datArr,labelArr,15)testArr,testLabelArr=loadDataSet('horseColicTest2.txt')prediction10=adaClassify(testArr,classifierArr)errArr=mat(ones((67,1)))#一共有67个样本cnt=errArr[prediction10!=mat(testLabelArr).T].sum()print(cnt/67)#画出ROC曲线datArr,labelArr=loadDataSet('horseColicTraining2.txt')classifierArray,aggClassEst=adaBoostTrainDS(datArr,labelArr,10)plotROC(aggClassEst.T,labelArr)四、算法优化

权值更新方法的改进

在实际训练过程中可能存在正负样本失衡的问题,分类器会过于关注大容量样本,导致分类器不能较好地完成区分小样本的目的。此时可以适度增大小样本的权重使重心达到平衡。在实际训练中还会出现困难样本权重过高而发生过拟合的问题,因此有必要设置困难样本分类的权值上限。

训练方法的改进

AdaBoost算法由于其多次迭代训练分类器的原因,训练时间一般会比别的分类器长。对此一般可以采用实现AdaBoost的并行计算或者训练过程中动态剔除掉权重偏小的样本以加速训练过程。

多算法结合的改进

除了以上算法外,AdaBoost还可以考虑与其它算法结合产生新的算法,如在训练过程中使用SVM算法加速挑选简单分类器来替代原始AdaBoost中的穷举法挑选简单的分类器。

感谢各位的阅读,以上就是“Python如何实现AdaBoost算法”的内容了,经过本文的学习后,相信大家对Python如何实现AdaBoost算法这一问题有了更深刻的体会,具体使用情况还需要大家实践验证。这里是亿速云,小编将为大家推送更多相关知识点的文章,欢迎关注!