AdaBoost,是英文"Adaptive Boosting"(自适应增强)的缩写。它的自适应在于:前一个基本分类器分错的样本会得到加强,加权后的全体样本再次被用来训练下一个基本分类器。同时,在每一轮中加入一个新的弱分类器,直到达到某个预定的足够小的错误率或达到预先指定的最大迭代次数。
1.算法流程:
给定一个数据集,类标签,adaboost的目的是学习得到一系列弱分类器(基本分类器),然后组合成一个强分类器。
step1:初始化数据的权重向量D,每一个样本都被赋予相同权重1/N
step2:进行迭代,用m=1,2,..M表示当前第m轮迭代
(1)使用带权值Dm的数据集训练得到弱分类器Gm(选取让误差率最小的阈值来设计基本分类器,本文采用单决策树作为基本分类器)
(2) 计算Gm(x)在训练数据集上的分类误差率
即错分类样本实例的权值之和
(3)计算Gm(x)的系数,表示当前弱分类器在最终分类器中的权重
(4)更新训练集的权值分布,计算向量Dm+1,用于下一轮迭代
其中,Zm是规范化因子,使得Dm+1成为一个概率分布:
(5)组合各个弱分类器
得到强分类器
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%,取得不错的结果。