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