Adaboost(2)——基于Python的adaboost实例

    xiaoxiao2021-04-17  33

           用Python写的adaboost代码如下,已做了详尽的注释。如果对adaboost算法不太熟悉,可以看上一篇博客:Adaboost(1)——从了解到掌握。

    # coding=utf-8 """ @Time : 2017/4/10 18:57 @Author : EvanChen """ 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 # 该函数可以自动检测出特征的数目,因此不必指定每个文件中的特征数目。 # 同时,该函数也假定最后一个特征是类别标签 def loadDataSet(fileName): numFeat = len(open(fileName).readline().split('\t')) dataMat = []; labelMat = [] fr = open(fileName) for line in fr.readlines(): lineArr = [] curLine = line.strip().split('\t') for i in range(numFeat - 1): lineArr.append(float(curLine[i])) dataMat.append(lineArr) labelMat.append(float(curLine[-1])) return dataMat, labelMat # 该函数用于通过阈值比较对数据进行分类 # 通过数组过滤所有在阈值一边的数据会分类到类别-1,而在另一边的数据会分类到+1 # 特征:dimen,分类的阈值是 threshVal,切换不等号是threshIneq # 返回值retArray:表示根据某个阈值的分类结果 def stumpClassify(dataMatrix, dimen, threshVal, threshIneq): retArray = ones((shape(dataMatrix)[0], 1)) if threshIneq == 'lt': retArray[dataMatrix[:, dimen] <= threshVal] = -1.0 else: retArray[dataMatrix[:, dimen] > threshVal] = -1.0 return retArray # 该函数用于构建一个简单的单层决策树,作为弱分类器 # D作为每个样本的权重,作为最后计算error的时候多项式乘积的作用 # 三层循环 # 第一层:对特征中的每一个特征进行循环,选出单层决策树的划分特征 # 第二层:对步长进行循环,选出阈值 # 第三层:对大于,小于进行切换 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))) # numSteps作为迭代这个单层决策树的步长 minError = inf # 初始化最小误差率为正无穷 for i in range(n): rangeMin = dataMatrix[:, i].min(); rangeMax = dataMatrix[:, i].max(); # 第i个特征值的最大最小值 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 weightedError = D.T * errArr # 计算分类误差率 print "split: dim %d, threshVal %.2f, 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 # 该函数用于基于单层决策树的AdaBoost的训练过程 # numIt 循环次数,表示构造40个单层决策树 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) # 构建最佳决策树 print "D before:",D.T # error越小,计算出来的alpha越大,该分类器在最终的权重越大 alpha = float(0.5 * log((1.0 - error) / max(error, 1e-16))) # 计算alpha, max(error,eps)用于确保在没有错误时不会发生除零溢出 print "alpha: ",alpha bestStump['alpha'] = alpha weakClassArr.append(bestStump) #保存该决策树 print "classEst: ",classEst.T # 使得分错样本的权重增加,而分对的权值减小,从而adaBoost能聚焦于那些较难分的样本上 expon = multiply(-1 * alpha * mat(classLabels).T, classEst) # 为下一次迭代更新权重D D = multiply(D, exp(expon)) D = D / D.sum() print "D after:",D.T # aggClassEst变量用于保持一个运行时的类别估计值,可以理解为最终的强分类器 aggClassEst += alpha * classEst print "aggClassEst: ",aggClassEst.T aggErrors = multiply(sign(aggClassEst) != mat(classLabels).T, ones((m, 1))) # 这里还用到一个sign函数,主要是将概率可以映射到-1,1的类型 # 结束条件,如果总错误率为 0,则结束循环 errorRate = aggErrors.sum() / m print "total error: ", errorRate if errorRate == 0.0: break return weakClassArr # 该函数用于测试AdaBoost def adaClassify(datToClass, classifierArr): dataMatrix = mat(datToClass) # do stuff similar to last aggClassEst in adaBoostTrainDS m = shape(dataMatrix)[0] aggClassEst = mat(zeros((m, 1))) for i in range(len(classifierArr)): classEst = stumpClassify(dataMatrix, classifierArr[i]['dim'], \ classifierArr[i]['thresh'], \ classifierArr[i]['ineq']) # call stump classify aggClassEst += classifierArr[i]['alpha'] * classEst print aggClassEst return sign(aggClassEst)           运行上述adaBoostTrainDS()方法进行训练,代码如下:

    # coding=utf-8 """ @Time : 2017/4/12 10:04 @Author : EvanChen """ from numpy import * import adaboost datMat, classLabels = adaboost.loadSimpData() classifierArr = adaboost.adaBoostTrainDS(datMat, classLabels, 30)         由于该数据集较简单,实际运行过程中仅迭代三次总体错误率就达到0.0,打印输出太长这里只展示最后一次迭代的运行结果,如下:

          

            运行上述adaClassify()方法进行测试,代码如下:

    # coding=utf-8 """ @Time : 2017/4/12 10:04 @Author : EvanChen """ from numpy import * import adaboost datMat, classLabels = adaboost.loadSimpData() classifierArr = adaboost.adaBoostTrainDS(datMat, classLabels, 30) print adaboost.adaClassify([[0, 0], [5, 5]], classifierArr)  

           代码运行结果如下:

           从打印结果可以看出来,这两个点的分类结果会随着迭代的进行而越来越强。最终经过sign函数得到分类结果:[0, 0]类别为1,[5, 5]类别为-1。

    转载请注明原文地址: https://ju.6miu.com/read-673223.html

    最新回复(0)