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.rar
原理參考:https://www.cnblogs.com/pinard/p/6133937.html
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/228770.html
標籤:其他
上一篇:Vue 快速入門
下一篇:監督學習和kNN分類初學者教程
