importnumpy as npimportmatplotlib.pyplot as pltdefloadDataSet(fileName):"""读取数据集
:param fileName: 文件名称
:return: 以列表的形式返回数据集和数据标签"""
#获取特征数
numFeat = len(open(fileName).readline().split('\t'))#定义空列表用于保存特征
dataMat =[]#定义空列表用于保存标签
labelMat =[]#读取文件
fr =open(fileName)#按行读取
for line infr.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]))returndataMat,labelMatdefstumpClassify(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
returnretArraydefbuildStump(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 inrange(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=weightedError
bestClasEst=predictedVals.copy()
bestStump['dim'] =i
bestStump['thresh'] =threshVal
bestStump['ineq'] =inequal#返回最优的单决策树参数
returnbestStump,minError,bestClasEstdef 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 inrange(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
returnweakClassArr,aggClassEstdefadaClassify(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 inrange(len(classifierArr)):#预测结果
classEst = stumpClassify(dataMatrix,classifierArr[i]['dim'],
classifierArr[i]['thresh'],
classifierArr[i]['ineq'])## alpha作为分类结果的权重,进行求和
aggClassEst += classifierArr[i]['alpha']*classEstreturnnp.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])