您的位置:首页 > 其它

机器学习实战笔记4

2017-08-15 20:41 134 查看

第七章 AdaBoost

adaBoost算法见统计学习方法P138

下面讲一下机器学习实战中的代码:

首先是求出当层最小误分率,这里用到的是决策树生成函数(其实统计学习方法中一直不明白到底是怎么获取基本分类器的,而且给出的例子维度还是1维的,应该说是就没看懂AdaBoost)

训练集如下矩阵所示:

⎡⎣⎢⎢⎢⎢⎢x(1)1x(1)2.x(1)Nx(2)1x(2)2.x(2)N............x(n)1x(n)2.x(n)N⎤⎦⎥⎥⎥⎥⎥

[y1y2...yN]

代码中给出的求解方法是,对上面的每一列进行分析,选取其中的最小值,最大值,从最小值开始,以指定的步长增加,作为阈值;规定大于该阈值为-1或者小于等于该阈值为-1;这样便得到一列预测矩阵,作为基本分类器G(x),并和y比较,求出在给定权值矩阵下的误差率,找到最小的误差率返回

代码如下:

#根据阈值获取预测列矩阵
def stumpClassify(dataMatrix,dimen,threshVal,threshIneq):
retArray=ones((shape(dataMatrix)[0],1))#以dataMatrix为行,1列,值为1的矩阵
if threshIneq=='lt':
retArray[dataMatrix[:,dimen]<=threshVal]=-1.0#表示dataMatrix中第dimen列的元素如果有小于等于threshVal的,就将对应的retArray的值置为-1
else:
retArray[dataMatrix[:,dimen]>threshVal]=-1.0

#获取当前弱分类器下的最小误差率对应的信息
def buildStump(dataArr,classLabels,D):
dataMatrix=mat(dataArr)
labelMat=mat(classLabels).T#转置为列矩阵
m,n=shape(dataMatrix)#获取矩阵的行,列
numSteps=10.0
bestStump={}
bestClasEst=mat(zeros((m,1)))#m行1列的0矩阵
minError=inf#表示无穷大
#这层循环对每一列(特征)遍历
for i in range(n):
rangeMin=dataMatrix[:,i].min()#表示获取矩阵的第i列的最小值
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)#按步长获取一个阈值
predictedVals=stumpClassify(dataMatrix,i,threshVal,inequal)#根据阈值判断,并获取对应的列矩阵(预测值)
errArr=mat(ones((m,1)))#获取m行1列值为1的列矩阵
errArr[predictedVals==labelMat]=0#将预测列矩阵和给出的标签矩阵比较,相同的置为0
weightedError=D.T*errArr#计算分类误差率(即误差的权值求和),D表示的时上一回的权值矩阵
#判断是否小于最小误差率,是则更新
if weightedError<minError:
minError=weightedError#最小误差率
bestClasEst=predictedVals.copy()#对应的预测列矩阵
bestStump['dim']=i#该预测矩阵针对的时第几列(哪个特征)
bestStump['thresh']=threshVal#对该特征的判断阈值
bestStump['ineq']=inequal#是基于小于该特征还是基于大于该特征来分类-1,1
return bestStump,minError,bestClasEst


AdaBoost算法是求解多个弱分类器,将其相加得到最终的分类器,指标是使最终的分类器误差率最小

第一轮的权值矩阵均分给每个训练数据

D1=(w11,w12,w13,...,w1N)w1i=1N,i=1,2,...,N

对m=1,2,3…,M,做如下循环:

使用权值矩阵Dm通过上述方法学习到Gm(x) ,然后将得到的预测矩阵和y矩阵比较,求出分类误差率em ,计算该分类器的系数αm:

αm=12log1−emem

em越小,系数越大,即该分类器对于最终分类器而言作用越大;

更新Dm得到Dm+1:

Dm+1=(wm+1,1,wm+1,2,...,wm+1,N)wm+1,i=wmiZmexp(−αmyiGm(xi))Zm=∑m=1Nwmiexp(−αmyiGm(xi))

上式中第二个式子可以写为:

wm+1,i=⎧⎩⎨⎪⎪wmiZme−αm,Gm=yiwmiZmeαm,Gm≠yi

注意到权值更新原理是,当前分类器分类正确的样本权值缩小,而误分类的样本则权值扩大,这样此轮误分类的样本在下一轮学习中就会起更大的作用,这是Adaboost的一个特点

回到循环处

代码如下:

#AdaBoost算法
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=float(0.5*log((1.0-error)/error))#计算该分类器的系数
bestStump['alpha']=alpha
weakClassArr.append(bestStump)#把每一个弱分类器对应的bestStump添加进去
expon=multiply(-1*alpha*mat(classLabels).T,classEst)#列矩阵内积
D=multiply(D,exp(expon))
D=D/D.sum()#更新权值矩阵
aggClassEst+=alpha*classEst#弱分类器相加
#aggClassEst)!=mat(classLabels).T : 两个列矩阵比较,返回的是一个列矩阵,其中满足条件则为true,否则为false,对应下面的0和1
aggErrors=multiply(sign(aggClassEst)!=mat(classLabels).T,ones((m,1)))#如上,最后的结果为满足条件位置为1,不满足条件的位置为0
errorRate=aggErrors.sum()/m#统计1的个数,占总数的比;
if errorRate==0.0:break
return weakClassArr


完!
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: