元算法是对其他算法进行组合的一种方式。
主要关注boosting方法及其代表分类器Adaboost。
1. boosting
bagging(自举汇聚法),是从原始数据集选择S次后得到S个新数据集的一种技术。新数据集和原数据集的大小相等。每个数据集都是通过在原始数据集中随机选择一个样本来进行替换而得到的。这里的替换就意味着可以多次地选择同一样本 。这一性质就允许新数据集中可以有重复的值,而原始数据集的某些值在新集合中则不再出现。
在S个数据集建好之后, 将某个学习算法分别作用于每个数据集就得到了S个分类器。当我们要对新数据进行分类时,就可以应用这S个分类器进行分类。与此同时,选择分类器投票结果中最多的类别作为最后的分类结果。
boosting是一种与bagging很类似的技术。
通过集中关注被已有分类器错分的那些数据来获得新的分类器。
分类器权重并不相等,每个权重代表的是其对应的分类器在上一轮迭代中的成功度。
2. AdaBoost
训练数据中的每个样本,并赋予其一个权重,这些权重构成了向量D。一开始,这些权重都初始化成相等值。
首先在训练数据上训练出一个弱分类器并计算该分类器的错误率,然后在同一数据集上再次训练弱分类器。
在分类器的第二次训练当中,将会重新调整每个样本的权重,其中第一次分对的样本的权重将会降低,而第一次分错的样本的权重将会提高。
为了从所有弱分类器中得到最终的分类结果 ,AdaBoost为每个分类器都分配了一个权重值alpha,这些alpha值是基于每个弱分类器的错误率进行计算的。其中,错误率的定义为:
而alpha的计算公式如下:
计算出alpha值之后,可以对权重向量D进行更新,以使得那些正确分类的样本的权重降低而错分样本的权重升高。D的计算方法如下。
如果某个样本被正确分类,那么该样本的权重更改为:
而如果某个样本被错分,那么该样本的权重更改为:
在计算出D之后,AdaBoost对又开始进入下一轮迭代。AdaBoost算法会不断地重复训练和调整权重的过程,直到训练错误率为0或者弱分类器的数目达到用户的指定值为止。
博客链接:点击跳转-浅谈AdaBoost算法
3. 代码
buildStump()函数伪代码
将最小错误率minError设为无穷大
对数据集中的每一个特征(第一层循环):
对每个步长(第二层循环):
对每个不等号(第三层循环):
建立一棵单层决策树并利用加权数据集对它进行测试
如果错误率低于minError,则将当前单层决策树设为最佳单层决策树
返回最佳单雇决策树
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
# 计算最小值和最大值来了解应该需要多大的步长
for j in range(-1,int(numSteps)+1):
#在大于 小于之间切换不等式
for inequal in ['lt', 'gt']:
threshVal = (rangeMin + float(j) * stepSize)
predictedVals = stumpClassify(dataMatrix,i,threshVal,inequal)#call stump classify with i, j, lessThan
# 如果预测值不等于真实值,则相应的位置为1
errArr = mat(ones((m,1)))
errArr[predictedVals == labelMat] = 0
# 将错误向量errArr和权重向量D的相应元素相乘并求和,就得到了数值weightedError。这就是AdaBoost和分类器交互的地方
weightedError = D.T*errArr
if weightedError < minError:
minError = weightedError
bestClasEst = predictedVals.copy()
bestStump['dim'] = i
bestStump['thresh'] = threshVal
bestStump['ineq'] = inequal
return bestStump,minError,bestClasEst
完整AdaBoost算法的实现
对每次迭代:
利用buildStump()函数找到最佳的单层决策树
将最佳单层决策树加入到单层决策树数组
计算alpha
计算新的权重向量D
更新累计类别估计值
如果错误率等于0,则退出循环
向量D非常重要,它包含了每个数据点的权重。一开始,这些权重都赋予了相等的值。
在后续的迭代中,AdaBoost算法会在增加错分数据的权重的同时,降低正确分类数据的权重。
D是一个概率分布向量,因此其所有的元素之和为1.0。为了满足此要求,一开始的所有元素都会被初始化成1/m 。同时,程序还会建立另一个列向量aggClassEst,记录每个数据点的类别估计累计值。
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)/max(error,1e-16)))
bestStump['alpha'] = alpha
weakClassArr.append(bestStump)
expon = multiply(-1*alpha*mat(classLabels).T,classEst)
D = multiply(D,exp(expon))
D = D/D.sum()
aggClassEst += alpha*classEst
aggErrors = multiply(sign(aggClassEst) != mat(classLabels).T,ones((m,1)))
errorRate = aggErrors.sum()/m
if errorRate == 0.0: break
return weakClassArr,aggClassEst