基于单决策树的AdaBoost算法的python实现

import numpy as np
import matplotlib.pyplot as plt
def loadDataSet(fileName): """ 读取数据集 :param fileName: 文件名称 :return: 以列表的形式返回数据集和数据标签 """ # 获取特征数 numFeat = len(open(fileName).readline().split('\t')) # 定义空列表用于保存特征 dataMat = [] # 定义空列表用于保存标签 labelMat = [] # 读取文件 fr = open(fileName) # 按行读取 for line in fr.readlines(): # 定义空列表用于保存每行的数据 lineArr =[] # 将每行数据转为str,并按\t分割 curLine = line.strip().split('\t') # 添加每行的数据 for i in range(numFeat-1): lineArr.append(float(curLine[i]))#将每行的数据保存到lineArr dataMat.append(lineArr)#将每行的数据存到dataMat # 添加标签 labelMat.append(float(curLine[-1])) return dataMat,labelMat def stumpClassify(dataMatrix,dimen,threshVal,threshIneq): """ 定义一个单决策树分类器 :param dataMatrix: 数据矩阵(数组格式) :param dimen:dataMatrix的某一列 :param threshVal:阈值 :param threshIneq:切换不等式的控制参数 :return: """ # 定义一个(样本数,1)的1数组 retArray = np.ones((dataMatrix.shape[0],1)) if threshIneq == 'lt': # 当参数为'lt'时,阈值分类方式以下 retArray[dataMatrix[:,dimen] <= threshVal] = -1.0 else: retArray[dataMatrix[:,dimen] > threshVal] = -1.0 return retArray def buildStump(dataArr,classLabels,D): """ 找到数据集上最佳的单决策树 :param dataArr: 数据集(列表) :param classLabels: 分类标签 :param D: 参数D :return:最优单决策树参数、最小识别错误率、最好的预测值 """ # 将列表数据转化成数组格式 dataMatrix = np.mat(dataArr) # 将标签数据转化成数据格式 labelMat = np.mat(classLabels).T # m为样本数,n为特征数 m,n = dataMatrix.shape # numSteps = 10.0 # 构建一个空字典,用于存放给定权重向量D时 # 所获得的最佳单层决策树参数 bestStump = {} # 定义一个数组,用于存放预测结果 bestClasEst = np.mat(np.zeros((m,1))) # 定义最小的错误为无穷大 minError = np.inf # 对每一个特征数进行遍历 for i in range(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 = np.mat(np.ones((m,1))) errArr[predictedVals == labelMat] = 0 weightedError = D.T*errArr # 找出最佳的决策树,即分类结果错误率最小的, if weightedError < minError: minError = weightedError bestClasEst = predictedVals.copy() bestStump['dim'] = i bestStump['thresh'] = threshVal bestStump['ineq'] = inequal # 返回最优的单决策树参数 return bestStump,minError,bestClasEst def adaBoostTrainDS(dataArr,classLabels,numIt=40): """ :param dataArr: 数据集 :param classLabels: 类别标签 :param numIt: 弱分类器数,默认定义40个 :return: """ # 定义列表用于保存弱分类器的参数 weakClassArr = [] # 获取样本数 dataArr=np.mat(dataArr) m = dataArr.shape[0] # 初始化权重D D = np.mat(np.ones((m,1))/m) # 用于保存更新的权重值 aggClassEst = np.mat(np.zeros((m,1))) # 训练每一个弱分类器的参数 for i in range(numIt): # 得到第i弱分类器的参数、错误率 bestStump,error,classEst = buildStump(dataArr,classLabels,D) # 计算第i个弱分类器的alpha值 alpha = float(0.5*np.log((1.0-error)/max(error,1e-16))) # 保存alpha值 bestStump['alpha'] = alpha # 保存第i弱分类器参数 weakClassArr.append(bestStump) # 更新D expon = np.multiply(-1*alpha*np.mat(classLabels).T,classEst) D = np.multiply(D,np.exp(expon)) D = D/D.sum() # 打印该分类器分类结果 print("Number "+str(i) +" of Errorrate : "+str(error)) # alpha做为分类结果的权重,进行求和 aggClassEst += alpha*classEst # 计算错误率 aggErrors = np.multiply(np.sign(aggClassEst) != np.mat(classLabels).T,np.ones((m,1))) errorRate = aggErrors.sum()/m # 打印错误率 print("total error: ",errorRate) if errorRate == 0.0: break return weakClassArr,aggClassEst def adaClassify(datToClass,classifierArr): """ AdaBoost分类器 :param datToClass: 数据集 :param classifierArr: 分类器参数 :return: """ # 输入数据 dataMatrix = np.mat(datToClass) # 获取样本数 m = dataMatrix.shape[0] aggClassEst = np.mat(np.zeros((m,1))) for i in range(len(classifierArr)): # 预测结果 classEst = stumpClassify(dataMatrix,classifierArr[i]['dim'], classifierArr[i]['thresh'], classifierArr[i]['ineq']) # # alpha做为分类结果的权重,进行求和 aggClassEst += classifierArr[i]['alpha']*classEst return np.sign(aggClassEst)
if __name__=="__main__": # 获取训练数据 dataMat, labelMat=loadDataSet('horseColicTraining2.txt') # 训练弱分类器 weakClassArr,_=adaBoostTrainDS(dataMat,labelMat,numIt=50) # 获取测试数据集 testMat,testlabel=loadDataSet('horseColicTest2.txt') # 获取测试结果 predicted=adaClassify(testMat,weakClassArr) # 计算测试结果正确率 errArr=np.mat(np.ones(predicted.shape)) RightRate=1-errArr[predicted!=np.mat(testlabel).T].sum()/predicted.shape[0] # 打印结果 print("正确率:",1-errArr[predicted!=np.mat(testlabel).T].sum()/predicted.shape[0])

代码中的数据集:https://files.cnblogs.com/files/CDXHU6A328/AdaBoost_data.rarhtml

原理参考:http://www.javashuo.com/article/p-aqhxqbdj-dn.html数组