主要内容:
一.提升方法与AdaBoost算法的简介
二.AdaBoost算法
三.代码解释
一.提升方法与AdaBoost算法的简介
1.提升方法:从弱学习算法出发,反复学习,得到一系列弱分类器(又称为基本分类器),然后组合这些弱分类器,构成一个强分类器。大多数的提升方法都是改变训练数据的概率分布(权值分布),针对不同的训练数据分布(相同的数据,不同的概率分布)调用弱学习算法学习一系列弱分了器。
所以,对于提升方法来说,需要回答两个问题:
1)在每一轮如何改变训练数据的的权值或概率分布?
2)如何将弱分类器组合成一个强分类器?
2.AdaBoost算法是最具代表性的提升方法。对于上述两个问题,AdaBoost的做法是:
1)提高那些被前一轮弱分类器错误分类样本的权值,而降低那些被正确分类样本的权值,这样一来,那些没有得到正确分类的数据,由于其权值的加大而受到后一轮弱分类器的更大关注。于是,分类问题被一系列的弱分类器“分而治之”。
2)加大分类误差率小的弱分类器的权值,使其在表决中起较大的作用,减小分类误差率大的弱分类器的权值,使得其在表决中起较小的作用。
二.AdaBoost算法
三.代码解释
1 # coding:utf-8 2 3 ''' 4 Created on Nov 28, 2010 5 Adaboost is short for Adaptive Boosting 6 @author: Peter 7 ''' 8 from numpy import * 9 10 def loadSimpData(): #手动生成数据 11 datMat = matrix([[1., 2.1], 12 [2., 1.1], 13 [1.3, 1.], 14 [1., 1.], 15 [2., 1.]]) 16 classLabels = [1.0, 1.0, -1.0, -1.0, 1.0] 17 return datMat, classLabels 18 19 def loadDataSet(fileName): # 从文件中加载数据 20 numFeat = len(open(fileName).readline().split('\t')) # get number of fields 21 dataMat = [] 22 labelMat = [] 23 fr = open(fileName) 24 for line in fr.readlines(): 25 lineArr = [] 26 curLine = line.strip().split('\t') 27 for i in range(numFeat - 1): 28 lineArr.append(float(curLine[i])) 29 dataMat.append(lineArr) 30 labelMat.append(float(curLine[-1])) 31 return dataMat, labelMat 32 33 def stumpClassify(dataMatrix, dimen, threshVal, threshIneq): # just classify the data 34 retArray = ones((shape(dataMatrix)[0], 1)) 35 if threshIneq == 'lt': 36 retArray[dataMatrix[:, dimen] <= threshVal] = -1.0 37 else: 38 retArray[dataMatrix[:, dimen] > threshVal] = -1.0 39 return retArray 40 41 '''构建单层决策树,即只分裂一次''' 42 def buildStump(dataArr, classLabels, D): 43 dataMatrix = mat(dataArr) #把特征X和标签Y都转成numpy的数组 44 labelMat = mat(classLabels).T 45 m, n = shape(dataMatrix) 46 numSteps = 10.0 #步长为10,由于特征的值是连续型的,且在一个区间之内。所以要设置合适的步数,而范围和步数又决定了步长,即精度。 47 bestStump = {} 48 bestClasEst = mat(zeros((m, 1))) #最好的预测值 49 minError = inf # 初始化最小误差 50 for i in range(n): # 枚举每一个特征进行分裂 51 rangeMin = dataMatrix[:, i].min() #该特征的最小值 52 rangeMax = dataMatrix[:, i].max() #该特征的最大值 53 stepSize = (rangeMax - rangeMin) / numSteps #步长,即精度 54 for j in range(-1, int(numSteps) + 1): # 枚举步数,从而确定阈值 55 for inequal in ['lt', 'gt']: # 用大于号还是小于号进行分割,这一步的影响大吗?感觉应该没什么区别 56 threshVal = (rangeMin + float(j) * stepSize) #阈值 57 predictedVals = stumpClassify(dataMatrix, i, threshVal,inequal) # 通过阈值进行分类 58 errArr = mat(ones((m, 1))) #分别错误列表 59 errArr[predictedVals == labelMat] = 0 60 ''' 61 计算错误率。这是决策树,为什么不是用信息增益来衡量呢?等等,信息增益好像不是用来计算错误率的。 62 因为是“单层决策树”,即只分裂一次就可直接得到分类结果了。所以直接用分类错误的比率来衡量决策树的好坏就可以了。 63 ''' 64 weightedError = D.T * errArr 65 if weightedError < minError: #更新最优的分类条件 66 minError = weightedError 67 bestClasEst = predictedVals.copy() 68 bestStump['dim'] = i 69 bestStump['thresh'] = threshVal 70 bestStump['ineq'] = inequal 71 return bestStump, minError, bestClasEst 72 73 '''adaboost算法''' 74 def adaBoostTrainDS(dataArr, classLabels, numIt=40): 75 weakClassArr = [] #弱分类器列表 76 m = shape(dataArr)[0] 77 D = mat(ones((m, 1)) / m) # 每个数据的权值都初始化为1/m 78 aggClassEst = mat(zeros((m, 1))) #用于累加所有分类器的(带系数)结果,从而确定最终的分类。由于有m个数据,所以为长度为m的列表。 79 for i in range(numIt): #迭代次数 80 bestStump, error, classEst = buildStump(dataArr, classLabels, D) # 构建单层决策树,即为一个弱分类器 81 alpha = float(0.5 * log((1.0 - error) / max(error, 1e-16))) # 计算弱分类器的系数alpha,1e-16用于防止溢出 82 bestStump['alpha'] = alpha #保存弱分类器的系数alpha 83 weakClassArr.append(bestStump) # 将弱分类器放到分类器列表的尾部 84 '''''' 85 expon = multiply(-1 * alpha * mat(classLabels).T, classEst) # 从此开始到第三步:重新计算每个数据的权值 86 D = multiply(D, exp(expon)) # Calc New D for next iteration 87 D = D / D.sum() 88 '''''' 89 aggClassEst += alpha * classEst #累加最终分类结果 90 '''''' 91 aggErrors = multiply(sign(aggClassEst) != mat(classLabels).T, ones((m, 1))) #计算分类错误率 92 errorRate = aggErrors.sum() / m 93 print "total error: ", errorRate 94 if errorRate == 0.0: break #如果错误率为0,则可退出 95 return weakClassArr, aggClassEst 96 97 '''根据学习得到的弱分类器队列来对数据进行分类,第一个参数为数据,第二个参数为弱分类器队列''' 98 def adaClassify(datToClass, classifierArr): 99 dataMatrix = mat(datToClass) # do stuff similar to last aggClassEst in adaBoostTrainDS 100 m = shape(dataMatrix)[0] 101 aggClassEst = mat(zeros((m, 1))) #用于累计分类结果 102 for i in range(len(classifierArr)): #将数据输入、通过这m个弱分类器 103 classEst = stumpClassify(dataMatrix, classifierArr[i]['dim'], classifierArr[i]['thresh'],classifierArr[i]['ineq']) 104 aggClassEst += classifierArr[i]['alpha'] * classEst #累加分类结果 105 print aggClassEst 106 return sign(aggClassEst) #将累加结果输入到sign()函数中,得到最终的分类结果