您的位置:首页 > 其它

机器实战之AdaBoost

2017-04-10 21:01 232 查看
1 算法概述

这是一种基于数据集多重抽样的训练方法。运行过程:首先将所有训练样本赋予一个大小相等的样本权重,然后训练出一个弱分类器(只要识别率大于0.5即可),并计算该分类器的错误率,根据分类错误率动态调整样本权重,即奖励分类错误的样本,同时惩罚分类真确的样本,这样就能扩大分类错误样本的作用而削弱分类真确样本的作用;接着,更新完样本权重后,再用同样的训练样本训练第二个分类器,再根据训练的错误率,更新样本权重,再训练第二个分类器,依此类推,直到训练的错误率收敛到一定的精度或者弱分类器到达指定数目为止。

算法示意图为:



图中表示:首先5个训练有着同样的样本权重D,然后送入一个分类器,通过训练这个分类器,就会得分类错误的样本,根据分类错误的样本就能计算该分类器的错误率





根据分类器的错误率就能计算出该分类器的权值





比如,上图中第一个分类器的权值

=0.69。根据得到的分类器权值

就能动态更新样本权重:


(当样本i为分类真确的样本)


(当样本i为分类错误的样本)

所以,被分类真确的样本权重会越来越小,而分类错误样本权重会越来越大。

比如上图中,在进入第二分类器之前,5个训练样本权重就不一样了,经过第二个分类器训练之后,第二个分类器得到的权值

,然后再更新样本权重,再送入第三个分类器训练,得到第三个分类器的权值

,最后将所有弱分类器得到的权值进行加权

,从而得到最终的输出结果。

2 算法实现

(1)实现单层决策树

#返回错误率最小的单层树桩
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)))
minError = inf #初始误差权重正无穷
for i in range(n):#遍历每个特征
rangeMin = dataMatrix[:,i].min(); rangeMax = dataMatrix[:,i].max()
stepSize = (rangeMax-rangeMin)/numSteps #每个特征的步长大小 0.1
for j in range(-1,int(numSteps)+1):#遍历每个步长 ,12步[-1,0,1,2,3,4,5,6,7,8,9,10]
for inequal in ['lt', 'gt']: #遍历大于和小于某个阈值
threshVal = (rangeMin + float(j) * stepSize)
#建立一颗单层决策树,对数据集进行预测
predictedVals = stumpClassify(dataMatrix,i,threshVal,inequal)#call stump classify with i, j, lessThan
errArr = mat(ones((m,1)))
errArr[predictedVals == labelMat] = 0 #预测对了,误差为0,否则为1
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
bestStump['ineq'] = inequal
return bestStump,minError,bestClasEst


(2)完整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)#利用buildStump()函数找到最佳单层决策树
print "D:",D.T
alpha = float(0.5*log((1.0-error)/max(error,1e-16)))#计算上面最佳单层决策树的权值
bestStump['alpha'] = alpha
weakClassArr.append(bestStump)                  #store Stump Params in Array
print "classEst:",classEst.T
#根据alpha,更新样本权重
expon = multiply(-1*alpha*mat(classLabels).T,classEst) #exponent for D calc, getting messy
D = multiply(D,exp(expon))                              #Calc New D for next iteration
D = D/D.sum()
#更新类别估计
aggClassEst += alpha*classEst
aggClassEst=sign(aggClassEst)
print "aggClassEst:",aggClassEst.T
#累加错误分类样本
aggErrors = multiply(aggClassEst!= mat(classLabels).T,ones((m,1)))
errorRate = aggErrors.sum()/m
print "total error: ",errorRate
if errorRate == 0.0: break
weakClassArr=mat(weakClassArr)
return weakClassArr,aggClassEst


(3)AdaBoost分类

#用多个弱分类器进行分类
def adaClassify(datToClass,classifierArr):
dataMatrix = mat(datToClass)#do stuff similar to last aggClassEst in adaBoostTrainDS
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'])#call stump classify
aggClassEst += classifierArr[i]['alpha']*classEst
aggClassEst=sign(aggClassEst)
print aggClassEst
return aggClassEst
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  机器学习