0 數據說明
手寫識別也是一個非常經典的應用實例。在本次應用當中,數據的格式如下:
- File name:‘_’爲劃分,前爲標籤,後爲例子數。例如‘0_0’就是0的手寫體的第一個實例。
- 內容:文本內容爲32×32 的1-0像素存儲的點,如果使用img可視化,可以看到黑白的數字的效果。待會需要處理成1*1024矩陣的形式。
1 數據處理
這一步需要比較注意的點是:
- 使用readline()方法讀取的 lineStr = fr.readline(),是字符串格式的,因此在後續填充中,使用下標的形式而不是進行整體填充
- 時刻注意數據類型 如我們需要的是數字類型就絕不能放一個str
from numpy import *
from KNN import classify0
from os import listdir #用於獲取當前目錄下的所有文件名
#讀取一個像素進制文件並將其轉化爲1*1024矩陣的函數方法
def img2vector(filename):
returnVect = zeros((1,1024))
fr = open(filename)
for i in range(32):
lineStr = fr.readline() #讀取一行,讀取出來的格式是str
for j in range(32):
returnVect[0,32*i+j] = int(lineStr[j]) #填充,注意單位的轉換
return returnVect
2 應用實例
代碼描述:
- 使用os庫中的lisdir讀取訓練文件夾下的所有文件名,存儲,進行加工。分離。主要是將文件名字符串根據相應的特性進行分離。
- 將文件中的內容放到訓練庫中
- 對於測試集,也執行相似的操作,並使用之前寫好的KNN.classify0分類器進行測試。返回結果和答案。
提取(下面其實有兩步筆者認爲可以合成一步,如果有興趣的話大家可以試一試)
def handwritingClassTest():
hwLabels = [] #存儲lable用的list
path="C:\\Users\\70956\\Desktop\\Data Science\\Algorithm"
trainingFileList = listdir(path+'\\trainingDigits') #獲取所有的文件的名字
m = len(trainingFileList) #一共有多少個訓練實例
trainingMat = zeros((m,1024)) #建立訓練矩陣
for i in range(m): #填充,獲取完整的訓練數據
fileNameStr = trainingFileList[i] #獲取一個名字
fileStr = fileNameStr.split('.')[0] #去掉後綴txt 保留前方名字
classNumStr = int(fileStr.split('_')[0]) #去掉_後綴,保留分類標籤
hwLabels.append(classNumStr) #標籤入庫
trainingMat[i,:] = img2vector(path+"\\trainingDigits\\%s" % fileNameStr) #將一個文件內的數據轉換成矩陣
測試
testFileList = listdir(path+'\\testDigits') #測試數據
errorCount = 0.0
mTest = len(testFileList)
for i in range(mTest):
fileNameStr = testFileList[i]
fileStr = fileNameStr.split('.')[0] #take off .txt
classNumStr = int(fileStr.split('_')[0])
vectorUnderTest = img2vector(path+'\\testDigits\\%s' % fileNameStr)
classifierResult = classify0(vectorUnderTest, trainingMat, hwLabels, 3)
print ("返回的結果是: %d, 真實的類別是: %d" % (classifierResult, classNumStr))
if (classifierResult != classNumStr): errorCount += 1.0
print ("\n判定錯誤的總數爲: %d" % errorCount)
print ("\n錯誤率爲: %f" % (errorCount/float(mTest)))
從這個實例中,其實我們可以看到對於線性的結構來執行KNN算法時,其實計算量是非常大的:
900個測試用例,2000個距離(訓練用例),每次計算需要1024個特徵參與。結果是18億次。筆者的筆記本大概需要35秒左右。
試想如果在具體的十萬級別的數據,或者是維度更大,計算量可能都…
如果讀者有接觸過數據結構,那麼可能會想到我們在學習這門課程的時候學完線性表後,也考慮過這個問題(如果你的老師有用這種引入的例子的話),因此樹結構就是非常有必要。
在KNN中,我們在理論部分也提到這個問題,在應用中我們確實也會碰到這個問題。
因此,我們在下次的章節。我們嘗試解釋KD樹(K-Dimension)結構。