1. 前戏
集成学习,通过构建并结合多个学习器来完成学习任务,主要分以下两个种类:
- 个体学习器间存在强依赖关系、必须串行生成的序列化方法。代表为boosting,如adaboost。
- 个体学习器间不存在强依赖关系、可同时生成的并行化方法。代表为bagging和随机森林(RF)。
2. adaboost解释
本质上就是三个臭皮匠顶个诸葛亮,将有限个弱分类器组合成为一个强分类器,从而增强分类效果。弱分类器的构建是串行的,也就是说有了上一个分类器的错误率才会构建下一个分类器,直到强分类器能够达到要求。如果想要了解具体数学算法,可搜索加法模型,损失函数(使用的是指数损失函数),前向分步函数,可参阅李航《统计学习方法》,讲的较清楚。
算法流程:
- 给定初始样本数据权重(1/m),权重相等
- 放入基础弱学习器学习,得到一个弱分类器
- 计算该分类器错误率,根据错误率计算分类器权重alpha(注意此处权重为分类器权重)
- 根据分类器权重计算样本权重矩阵D(分类错误的权重增加,分类正确的权重减少,注意此处的权重为样本的权重)
- 将所有的弱分类器按权重alpha线性组合得到最终的强分类器
- 判断强分类器的错误率是否为零,或者迭代次数是否到达阈值,否则重复步骤2,3,4,5
3. 实例:基于单层决策树的弱分类器
1 from numpy import * 2 3 # 1.新建数据 4 def loadSimpData(): 5 datMat=mat([[1,2.1], 6 [2,1.1], 7 [1.3,1], 8 [1,1], 9 [2,1]]) 10 classLabels=[1.0,1.0,-1.0,-1.0,1.0] 11 return datMat,classLabels 12 13 # 2. 通过阈值比较对数据进行分类 14 def stumpClassify(dataMatrix,dimen,threshVal,threshIneq): 15 retArray=ones((shape(dataMatrix)[0],1)) 16 if threshIneq=='lt': 17 retArray[dataMatrix[:,dimen]<=threshVal]=-1.0 18 else: 19 retArray[dataMatrix[:,dimen]>threshVal]=-1.0 20 return retArray 21 22 # 3. 单层决策树,是决策树的一个弱化版本 23 # 遍历stumpClassify()函数所有的可能输入值,并找到数据集上的最佳单层决策树 24 def buildStump(dataArr,classLabels,D): 25 dataMatrix=mat(dataArr) 26 labelMat=mat(classLabels).T 27 m,n=shape(dataMatrix) 28 numSteps=10.0;bestStump={};bestClassEst=mat(zeros((m,1))) 29 minError=inf # 初始最小错误为正无穷 30 # 数据集上的所有特征进行循环 31 for i in range(n): 32 rangeMin =dataMatrix[:,i].min() 33 rangeMax =dataMatrix[:,i].max() 34 stepSize=(rangeMax-rangeMin)/numSteps 35 # 在每个特征里(即每一列数),从最小值到最大值之间按照固定步长遍历,寻找到一个最小分类错误率 36 for j in range(-1,int(numSteps)+1): 37 # 在大于和小于之间切换不等式 38 for inequal in ['lt','gt']: 39 threshVal=(rangeMin+float(j)*stepSize) 40 predictedVals=stumpClassify(dataMatrix,i,threshVal,inequal) #按阈值分类 41 errArr=mat(ones((m,1))) 42 errArr[predictedVals==labelMat]=0 #分类错误为1 43 weightedError=D.T*errArr 44 # print("split: dim %d,thresh %.2f,thresh inequal: %s,the weighted error is %.3f"% 45 # (i,threshVal,inequal,weightedError)) 46 if weightedError<minError: 47 minError=weightedError 48 bestClassEst=predictedVals.copy() 49 bestStump['dim']=i 50 bestStump['thresh']=threshVal 51 bestStump['ineq']=inequal 52 return bestStump,minError,bestClassEst 53 54 # 4. adaboost算法,返回各弱分类器 55 def adaBoostTrainDS(dataArr,classLabels,numIt=40): 56 weakClassArr=[] 57 m=shape(dataArr)[0] 58 D=mat(ones((m,1))/m) 59 aggClassEst=mat(zeros((m,1))) 60 for i in range(numIt): 61 bestStump,error,classEst=buildStump(datMat,classLabels,D) # 弱分类器,单层决策树 62 # print("D:",D.T) 63 alpha=float(0.5*log((1.0-error)/max(error,1e-16))) # 计算分类器权重alpha值,此处一个分类器就是一次单层决策树 64 bestStump['alpha']=alpha 65 weakClassArr.append(bestStump) 66 # print("classEst:",classEst.T) 67 # 计算expon, 正确分类的样本为exp(-alpha),错误分类的样本为为exp(alpha) 68 # D为权重矩阵,这里的权重是样本的权重,由alpha计算而来 69 expon=multiply(-1*alpha*mat(classLabels).T,classEst) 70 D=multiply(D,exp(expon)) 71 D=D/D.sum() 72 aggClassEst+=alpha*classEst # 记录每个数据点的类别估计累计值,也就是分类器加权求和 73 # print("aggclassest:",aggClassEst.T) 74 # 分类错误结果置1 sign取数字符号,正数为1,负数为-1,0为0 75 aggErrors=multiply(sign(aggClassEst)!=mat(classLabels).T,ones((m,1))) 76 errorRate=aggErrors.sum()/m 77 print("total error:",errorRate," ") 78 if errorRate==0.0: 79 break 80 return weakClassArr