1 AdaBoost算法总结
AdaBoost算法:通过样本来训练数据,主要是将训练过程中分类正确的样本点权值降低,反之则增加;各个弱分类器训练结束后加大分类错误率小的权重,反之增加权重。最终构成各个分类能力较强的分类器。
2 AdaBoost的应用场景和优缺点
应用场景:1)用于二分类或多分类的应用场景;2)用于做分类任务的baseline;3)用于特征选择(feature selection)等
优点:1)很好的利用了弱分类器进行级联;2)可以将不同的分类算法作为弱分类器;3)AdaBoost具有很高的精度;4)相对于bagging算法和Random Forest算法,AdaBoost充分考虑的每个分类器的权重等
缺点:1) AdaBoost迭代次数也就是弱分类器数目不太好设定,可以使用交叉验证来进行确定; 2) 数据不平衡导致分类精度下降;3) 训练比较耗时,每次重新选择当前分类器最好切分点等
3 AdaBoost的算法过程
通过训练样本将弱的的分类器进行叠加,用残差缩小的来提高分类的准确性。样本通过对错误率的计算,不断改变权值,然后对弱分类器也改变权重,最终变成一个强的分类器。
4 具体实例
4.1 实现简单数据数据的分类
from numpy import *
'''
#添加数据函数
'''
def loadSimpData():
datMat = matrix([[ 1. , 2.1], #创建数据
[ 2. , 1.1],
[ 1.3, 1. ],
[ 1. , 1. ],
[ 2. , 1. ]])
classLabels = [1.0, 1.0, -1.0, -1.0, 1.0] #数据标签列
return datMat,classLabels #返回数据和标签
'''
#找到最低错误率的单层决策树
# dataMatrix : 输入数据矩阵
# dimen : 维度
# threshVal : 阈值
# threshIneq : 决定不等号的大小
'''
def stumpClassify(dataMatrix,dimen,threshVal,threshIneq):
retArray = ones((shape(dataMatrix)[0],1)) #读取其行列,构建以行为长度的单位向量
if threshIneq == 'lt': #然后根据阈值和不等号将满足要求的都设为-1
retArray[dataMatrix[:,dimen] <= threshVal] = -1.0
else:
retArray[dataMatrix[:,dimen] > threshVal] = -1.0
return retArray
'''
#通过阈值对数据分类函数
# dataArr : 输入数据矩阵
# classLabels : 输入数据标签
# D : 数据集权重 用于计算加权错误率
'''
def buildStump(dataArr,classLabels,D):
dataMatrix = mat(dataArr); # mat()转换成矩阵类型
#将标签列表转置成一个行向量
labelMat = mat(classLabels).T
m,n = shape(dataMatrix) # 得到数据矩阵的大小m行,n列
numSteps = 10.0; #初始化步数,用于在特征的所有可能值上进行遍历
bestStump = {}; #存储给定权重向量 D 时所得到的最佳单层决策树的信息
bestClasEst = mat(zeros((m,1))) #初始化类别估计值
minError = inf #最小误差率初值设为无穷大
for i in range(n): #第一层循环 对数据集中的每一个特征 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)
errArr = mat(ones((m,1))) #初始化错误计数向量
errArr[predictedVals == labelMat] = 0 #然后把预测结果正确的标记为0
weightedError = D.T*errArr #计算权值误差,这就是AdaBoost和分类器交互的地方
#将加权错误率最小的结果保存下来
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 #分类结果,最小错误率,最佳单层决策树
'''
#ada的训练函数
# dataArr : 输入数据矩阵
# classLabels : 输入数据标签
# numIt : 迭代次数
'''
def adaBoostTrainDS(dataArr,classLabels,numIt=40):
weakClassArr = [] #初始化列表,用来存放单层决策树的信息
m = shape(dataArr)[0] #获取数据集行数
D = mat(ones((m,1))/m) #初始化向量D每个值均为1/m,D包含每个数据点的权重
aggClassEst = mat(zeros((m,1))) #初始化列向量,记录每个数据点的类别估计累计值
for i in range(numIt): #开始迭代
#利用buildStump()函数找到最佳的单层决策树
bestStump,error,classEst = buildStump(dataArr,classLabels,D)
#print "D:",D.T
#根据公式计算alpha的值,max(error, 1e-16)用来确保在没有错误时不会发生除零溢出
alpha = float(0.5*log((1.0-error)/max(error,1e-16)))
bestStump['alpha'] = alpha #保存alpha的值
weakClassArr.append(bestStump) #填入数据到列表
#print "classEst: ",classEst.T
#为下一次迭代计算D
expon = multiply(-1*alpha*mat(classLabels).T,classEst)
D = multiply(D,exp(expon))
D = D/D.sum()
#累加类别估计值
aggClassEst += alpha*classEst
#print "aggClassEst: ",aggClassEst.T
#计算错误率,aggClassEst本身是浮点数,需要通过sign来得到二分类结果
aggErrors = multiply(sign(aggClassEst) != mat(classLabels).T,ones((m,1)))
errorRate = aggErrors.sum()/m
print ("total error: ",errorRate)
#如果总错误率为0则跳出循环
if errorRate == 0.0: break
return weakClassArr,aggClassEst #返回单层决策树列表和累计错误率
'''
#ada的分类函数
# datToClass : 输入待分类库数据矩阵
# classifierArr : 多个弱分类器组成的数组
'''
def adaClassify(datToClass,classifierArr):
dataMatrix = mat(datToClass) #初始化数据集
m = shape(dataMatrix)[0] #获得待分类样例个数
aggClassEst = mat(zeros((m,1))) #构建一个初始化为0的列向量,记录每个数据点的类别估计累计值
for i in range(len(classifierArr)): #遍历每个弱分类器
#基于stumpClassify得到类别估计值
classEst = stumpClassify(dataMatrix,classifierArr[i]['dim'],\
classifierArr[i]['thresh'],\
classifierArr[i]['ineq'])
#累加类别估计值
aggClassEst += classifierArr[i]['alpha']*classEst
print (aggClassEst)
return sign(aggClassEst) #返回分类结果,aggClassEst大于0则返回+1,否则返回-1
以上程序可以在jupyter中实现,可以实现简单数据的分类,类别分别用0和1进行表示。