Adaboost就是通过迭代训练若干个弱分类器,直到错误率为零,所有分类器的加权(D)和的sign值就是结果。每一次迭代之后的下一个分类器都更加关注分错类的个体(每一个弱分类器都是通过阈值划分确定的,找到使总体的错误最小的切分方式,
即min(D.T*(判断错误为1,正确为0的矩阵)),这一次划分错误的个体权值就会在下一个分类器里权值加强,为了使min(D.T*(判断错误为1,正确为0的矩阵)),所以上一个错误的这次肯定对,根据前几次的分类器加权,但是总体的错误率会降低,所以这个弱分类器的权值会逐步的赠大。
具体步骤,看代码吧,跑一遍,啥都明白了
from numpy import *
def loadASamplData():
dataMat=matrix([[1,2.1],[1.3,1.],[2.,1.1],[1.,1.],[2.,1.]])
classLabels=[1.0,1.0,-1.0,-1.0,1.0]
# m, n = shape(dataMat)
# print(n)
return dataMat,classLabels
def stumpClassify(dataMatrix,dimen,threshval,threshIneq):
"""根据threshIneq的两个值及进行判断,threshInq为It时大于threshVal的一边为+1,另一边为-1,另一种情况与他相反
dimen 是输入的第dimen+1个特征,这里共有两个特征 dimen最大为1
"""
retArray=ones((dataMatrix.shape[0],1))
if threshIneq=="It":
retArray[dataMatrix[:,dimen]<=threshval]=-1.0
else:
retArray[dataMatrix[:, dimen] > threshval] = -1.0
return retArray
def buildStump(dataArr,classLabels,D):
"""
进行三重循环:
for 每一个特征:
for 每一个步长
for 每一个不等号
返回最佳单层决策树
:param dataArr:
:param classLabels: 真实的y
:param D: 权值列表
:return:bestStump,minError,bestClassEst
"""
dataMatrix=mat(dataArr)
labelMat=mat(classLabels).T
m,n=shape(dataMatrix)
numSteps=10.0
bestStump={}
bestClassEst=mat(zeros((m,1)))
minError=inf
for i in range(n):##n代表特征,遍历每一个特征这里是2
rangeMin=dataMatrix[:,i].min()#dataMax每一列的最小值
rangeMax=dataMatrix[:,i].max()#dataMax每一列的最大值
stepSize=(rangeMax-rangeMin)/numSteps
for j in range(-1,int(numSteps)+1):#对每一个步长进行遍历
for inequal in ['It','gt']:
threshVal=rangeMin+j*stepSize
predictedVals=stumpClassify(dataMatrix,i,threshVal,inequal)
errArr=ones((m,1))
errArr[predictedVals==labelMat]=0#与真正的label相同的为0,不同的为1
weightedEorror=D.T*errArr#根据权值计算损失函数
if weightedEorror<minError:#在所有的取值中,取最小的损失函数
minError=weightedEorror
bestStump['thresh']=threshVal#根据thresh及进行特征划分
bestStump['dim']=i#根据第dim+1个特征划分
bestStump['ineq']=inequal#根据第'It'或者不是'It'进行特征划分
bestClassEst=predictedVals.copy()
return bestStump,minError,bestClassEst
# #进行检验
# D=mat(ones((5,1))/5)
# a,b=loadASamplData()
#
# bestStump,minError,bestClassEst=buildStump(a,b,D)
# print(bestStump,minError,bestClassEst)
##结果
# {'thresh': 0.9, 'dim': 0, 'ineq': 'It'}
# [[0.4]]
# [[1.]
# [1.]
# [1.]
# [1.]
# [1.]]
#dataMatrix[:0]<0.9的为-1,所以判断都为+1,第三和第四个错误,0.2*2=0.4
def adaBoostTrainDS(dataArr,classLabels,numIt=40):
"""
:param dataArr: 数据标签
:param classLabels: 类别标签
:param numIt: 迭代次数,需要用户指定
:return:
"""
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=float((1/2)*log((1-error)/max(error,1e-16)))#根据错误率算出每个弱分类器的权重大小,分类效果差的权重占的小
bestStump['alpha']=alpha
weakClassArr.append(bestStump)
c=-1*alpha*mat(classLabels).T
expon=multiply(c,ClassEst)#把估计的标签与真实的标签相乘相同为1,不同为-1
D=multiply(D,exp(expon))
D=D/sum(D)
aggClassEst+=alpha*ClassEst
aggErrors=multiply(sign(aggClassEst)!=mat(classLabels).T,ones((m,1)))
errorRate=aggErrors.sum()/m
if(errorRate==0):
break
return weakClassArr
a,b=loadASamplData()
#print(mat(b).T.shape)
print(adaBoostTrainDS(a,b,40))