機器學習實戰k近鄰演算法(kNN)應用之手寫數字識別程式碼解讀
阿新 • • 發佈:2019-01-02
from numpy import * from os import listdir import operator import time #k-NN簡單實現函式 def classify0(inX,dataSet,labels,k): #求出樣本集的行數,也就是labels標籤的數目 dataSetSize = dataSet.shape[0] #構造輸入值和樣本集的差值矩陣 diffMat = tile(inX,(dataSetSize,1)) - dataSet #計算歐式距離 sqDiffMat = diffMat**2 sqDistances = sqDiffMat.sum(axis=1) distances = sqDistances**0.5 #求距離從小到大排序的序號 sortedDistIndicies = distances.argsort() #對距離最小的k個點統計對應的樣本標籤 classCount = {} for i in range(k): #取第i+1近鄰的樣本對應的類別標籤 voteIlabel = labels[sortedDistIndicies[i]] #以標籤為key,標籤出現的次數為value將統計到的標籤及出現次數寫進字典 classCount[voteIlabel] = classCount.get(voteIlabel,0) + 1 #對字典按value從大到小排序 sortedClassCount = sorted(classCount.items(),key=operator.itemgetter(1),reverse=True) #返回排序後字典中最大value對應的key return sortedClassCount[0][0] #---------------------------------------------------------------------------- #函式執行耗時統計函式 def time_me(fn): def _wrapper(*args, **kwargs): start = time.clock() fn(*args, **kwargs) print ("\n%s cost %s second"%(fn.__name__, time.clock() - start)) return _wrapper #---------------------------------------------------------------------------- #影象轉換函式(32*32影象轉換為1*1024向量) def img2vector(filename): #初始化待返回的向量 returnVect = zeros((1,1024)) fr = open(filename) for i in range(32): #每次讀取一行內容,以字串形式儲存 lineStr = fr.readline() #逐個取出當前行的每一個字元,並轉化為數字 for j in range(32): returnVect[0,32*i+j] = int(lineStr[j]) return returnVect #---------------------------------------------------------------------------- #手寫數字識別測試函式 @time_me def handwritingClassTest(): #初始化類別標籤為空列表 hwLabels = [] #列出給定目錄下所有訓練資料的檔名 trainingFileList = listdir('F:/machinelearninginaction/Ch02/trainingDigits') #求訓練資料數目 m = len(trainingFileList) #初始化m個影象的訓練矩陣 trainingMat = zeros((m,1024)) #遍歷每一個訓練資料 for i in range(m): #取出一個訓練資料的檔名 fileNameStr = trainingFileList[i] #去掉該訓練資料的字尾名.txt fileStr = fileNameStr.split('.')[0] #取出代表該訓練資料類別的數字 classNumStr = int(fileStr.split('_')[0]) #將代表該訓練資料類別的數字存入類別標籤列表 hwLabels.append(classNumStr) #呼叫影象轉換函式將該訓練資料的輸入特徵轉換為向量並存儲 trainingMat[i,:] = img2vector('F:/machinelearninginaction/Ch02/trainingDigits/%s' % fileNameStr) #列出給定目錄下所有測試資料的檔名 testFileList = listdir('F:/machinelearninginaction/Ch02/testDigits') #初始化測試犯錯的樣本個數 errorCount = 0.0 #求測試資料數目 mTest = len(testFileList) #遍歷每一個測試資料 for i in range(mTest): #取出一個測試資料的檔名 fileNameStr = testFileList[i] #去掉該測試資料的字尾名.txt fileStr = fileNameStr.split('.')[0] #取出代表該測試資料類別的數字 classNumStr = int(fileStr.split('_')[0]) #呼叫影象轉換函式將該測試資料的輸入特徵轉換為向量 vectorUnderTest = img2vector('F:/machinelearninginaction/Ch02/testDigits/%s' % fileNameStr) #呼叫k-NN簡單實現函式,並返回分類器對該測試資料的分類結果 classifierResult = classify0(vectorUnderTest,trainingMat,hwLabels,3) print("the classifier came back with: %d, the real answer is: %d" % (classifierResult,classNumStr)) #統計分類器對測試資料分類犯錯的個數 if (classifierResult != classNumStr): errorCount += 1.0 print("\nthe total number of error is: %d" % errorCount) #輸出分類器錯誤率 print("\nthe total error rate is: %f" % (errorCount/float(mTest)))
三.詳細解讀
仍然是在前面kNN模組的基礎上繼續新增新的函式或方法。 kNN的核心實現程式碼前面已給出: 機器學習實戰k-鄰近演算法(kNN)簡單實施程式碼解讀為了防止程式碼看上去很冗長,刪除了一些無關的函式,新增了3個函式或方法,分別是函式執行耗時統計函式time_me,影象轉換函式img2vector和手寫數字識別測試函式handwritingClassTest。