AdaBoost
-
adaboost是一种迭代算法,其核心思想是针对同一个训练集训练不同的分类器,然后把这些弱分类器集合起来,构成一个更强的最终分类器。
-
优点:泛化错误率低,易编码,可以应用在大部分分类器上,无参数调整。
-
缺点:对离群点敏感。
-
适用数据类型:数值型和标称型数据
bagging:基于数据随机重抽样的分类器构建方法
- 自举汇聚法(bootstrap aggregating),也称为bagging方法,是在从原始数据集选择S次后得到S个新数据集的一种技术。
- 新数据集和原数据集的大小相等。每个数据集都是通过在原始 数据集中随机选择一个样本来进行替换而得到的。
boosting:
- boosting是一种与bagging很类似的技术。不论是在boosting还是bagging当中,所使用的多个
分类器的类型都是一致的。但是在前者当中,不同的分类器是通过串行训练而获得的,每个新分 类器都根据已训练出的分类器的性能来进行训练。 - boosting是通过集中关注被已有分类器错分的 那些数据来获得新的分类器
AdaBoost的一般流程
(1) 收集数据:可以使用任意方法。
(2) 准备数据:依赖于所使用的弱分类器类型,本章使用的是单层决策树,这种分类器可 以处理任何数据类型。当然也可以使用任意分类器作为弱分类器,第2章到第6章中的 任一分类器都可以充当弱分类器。作为弱分类器,简单分类器的效果更好。
(3) 分析数据:可以使用任意方法。
(4) 训练算法:AdaBoost的大部分时间都用在训练上,分类器将多次在同一数据集上训练 弱分类器。
(5) 测试算法:计算分类的错误率。
(6) 使用算法:同SVM一样,AdaBoost预测两个类别中的一个。如果想把它应用到多个类 别的场合,那么就要像多类SVM中的做法一样对AdaBoost进行修改
算法流程
AdaBoost是adaptive boosting(自适应boosting)的缩写,其运行过程如下:训练数据中的每 个样本,并赋予其一个权重,这些权重构成了向量D。为了从所有弱分类器中得到终的分类结 果,AdaBoost为每个分类器都分配了一个权重值alpha,这些alpha值是基于每个弱分类器的错误 率进行计算的。其中,错误率ε的定义为:
而alpha的计算公式如下:
AdaBoost算法的流程如图所示
如果某个样本被正确分类,那么该样本的权重更改为
而如果某个样本被错分,那么该样本的权重更改为
基于单层决策树构建弱分类器
这个程序的伪代码看起来大致如下:
将最小错误率minError设为+∞
对数据集中的每一个特征(第一层循环):
对每个步长(第二层循环):
对每个不等号(第三层循环):
建立一棵单层决策树并利用加权数据集对它进行测试
如果错误率低于minError,则将当前单层决策树设为最佳单层决策树
返回最佳单层决策树
单层决策树生成函数
def buildStump(dataArr, classLabels, D):
dataMat = mat(dataArr); labelMat = mat(classLabels).T
m,n = shape(dataMat)
numSteps = 10.0; bestStump = {}; bestClassErrorList = mat(zeros((m, 1)))
minError = inf
for i in range(n):
rangeMin = dataMat[:,i].min()
rangeMax = dataMat[:, i].max()
stepSize = (rangeMax - rangeMin)/numSteps
for j in range(-1, int(numSteps)+1):
threshod = rangeMin + float(j) * stepSize
for ineq in ['lt', 'gt']:
predictVal = stumpClassify(dataMat, i, threshod, ineq)
errArr = mat(ones((m,1)))
errArr[predictVal == labelMat] = 0
weightedError = D.T * errArr
#print("split: dim %d, thresh %.2f, thresh ineqal: %s, the weighted error is %.3f" % (i, threshod, ineq, weightedError))
if weightedError < minError:
minError = weightedError
bestClassErrorList = predictVal.copy()
bestStump['dim'] = i
bestStump['threshod'] = threshod
bestStump['ineq'] = ineq
return bestStump,minError,bestClassErrorList
完整AdaBoost算法的实现
整个实现的伪代码如下:
对每次迭代:
利用buildStump()函数找到最佳的单层决策树
将最佳单层决策树加入到单层决策树数组
计算alpha
计算新的权重向量D
更新累计类别估计值
如果错误率等于0.0,则退出循环
基于单层决策树的AdaBoost训练过程
def adaBoostTrainDS(dataArr, classLabels, numIt = 40):
labelMat = mat(classLabels).T
weakClassArr = []
m,n = shape(dataArr)
D = mat(ones((m,1))/m)
aggClassEst = mat(zeros((m, 1)))
for i in range(numIt):
bestStump, minError, bestClassEst = buildStump(dataArr, classLabels, D)
#print("D:", D.T)
#print("classEst: ", bestClassEst.T)
alpha = float(0.5*log((1-minError)/max(minError,1e-16)))
bestStump['alpha'] = alpha
weakClassArr.append(bestStump)
)
expon = multiply(-1 * alpha * labelMat, bestClassEst)
D = multiply(D, exp(expon))
D = D/sum(D)
aggClassEst += alpha * bestClassEst
#print("aggClassEst: ",aggClassEst.T)
aggErrors = multiply(sign(aggClassEst) != labelMat, ones((m,1)))
#print("aggErrors error: ", aggErrors)
errorRate = aggErrors.sum() / m
#print("total error: ", errorRate)
if errorRate == 0.0:
break
return weakClassArr
测试算法:基于 AdaBoost的分类
def adaClassfy(dataToClassfy, classifierArr):
dataMat = mat(dataToClassfy)
m = shape(dataMat)[0]
aggClassEst = mat(zeros((m, 1)))
for i in range(len(classifierArr)):
classEst = stumpClassify(dataMat,classifierArr[i]['dim'],classifierArr[i]['threshod'],classifierArr[i]['ineq'])
aggClassEst += classifierArr[i]['alpha']*classEst
print(aggClassEst)
return sign(aggClassEst)