使用k-近鄰演算法識別手寫數字
乙個星期沒有更新部落格了,最近在看k-近鄰演算法和決策樹,學習《機器學習實戰》k-近鄰演算法裡的實戰問題**時遇到了些問題,經過幾天的硬啃,終於完成了**。話不多說,下面一起看一下如何用k-近鄰演算法實現識別手寫數字。[例子與**摘自《機器學習實戰》]
簡單起見,該演算法只能識別0~9的數字。這裡識別演算法首先,咱們將數字的影象使用圖形處理軟體,處理成相同大小:寬高均為32畫素的黑白影象。影象儲存為文字格式。如下圖所示:
現在咱們手頭有訓練集trainingdigits大約2000個例子,0~9中每個數字大約200個左右的例子,測試集testdigits大約有900個左右的例子,0~9每個數字大約100個;
[資料取自《機器學習實戰 第2章 k-近鄰演算法》],每個資料命名格式如下圖所示:(後面**裡會根據這個命名格式來讀取相應的數字)
機器學習之路——k-近鄰演算法(knn)。在這個數字識別問題裡同樣,我們的處理思路如下:
1. 首先計算測試集裡的資料與訓練集裡資料的距離差。
2. 計算好測試點與訓練集裡樣本點的距離後,將結果從小到大進行排序;
3. 選取距離最近的k個點,確定這k個點資料所在分類的出現頻率;
4. 選擇頻率最高的分類作為**資料的分類輸出;
def
classify0
(inx, dataset, labels, k):
咱們在這個實戰問題裡其實重點就是怎麼把這些文字裡的資料變成classify0()函式可以處理的資料。
之前classify0()函式裡計算距離的思路是將測試資料乙個1*2的矩陣陣列(x,y)利用tile擴充套件成m*2的陣列(這裡m為訓練集資料總數),然後同訓練集進行相減求平方再開根號得到距離,同樣這裡我們首先先將每個測試集樣本資料先轉化為乙個1*n的矩陣陣列(n代表特徵值個數)。先看這段**如何實現:
#定義資料處理的函式,將訓練集轉化為1*1024的矩陣
defimg2vector
(filename):
returnvect = zeros((1,1024))#先定義乙個空矩陣陣列,下面裡用for迴圈將測試樣本讀入該陣列中
fr = open(filename)
for i in range (32):#因為每個數字樣本在文字裡是32*32的矩陣陣列,一行一行來賦值,所以需要兩個for迴圈巢狀
linestr = fr.readline()#readline()依次讀取每一行,readlines()是輸出檔案共多少行,注意區分
for j in range(32):#讀取第一行後,將第一行裡的32個資料賦值給returnvect前32個數,依次類推,最終將32*32=1024個資料全部賦值完畢
returnvect[0,32*i+j] = int(linestr[j])
return returnvect#返回最終的資料
完成訓練集的處理後,就可以利用classify0()函式對測試集資料進行分類了。好了,一起看下這段**怎麼實現。**有點長,我會一句一句的注釋,讓大家更容易理解,涉及到相關的python內建函式後面有對應的鏈結供學習。
#定義手寫數字識別函式,並計算其錯誤率
defhandwritingclasstest
(): hwlabels = #將訓練集的資料對應的label即數字用乙個list容器儲存,classify0()函式輸入要用到
trainingfilelist = listdir('這裡填訓練集所在資料夾位址') #輸出資料夾裡所有訓練集的檔名稱與字尾,用於讀取訓練集裡每個檔案對應的數字即label
m = len(trainingfilelist)#計算下訓練集共有多少組資料
trainingmat = zeros((m,1024))#構造乙個m*1024的矩陣陣列儲存訓練集裡的所有資料,每一行是一組資料
for i in range(m):#通過for迴圈將m組資料對應的label賦值到hwlabels中去
filenamestr = trainingfilelist[i]
filestr = filenamestr.split('.')[0]
classnumstr = int(filestr.split('_')[0])
trainingmat[i,:] = img2vector('這裡填訓練集所在資料夾位址%s' % filenamestr)#將訓練集裡資料賦值到trainingmat
testfilelist = listdir('這裡填測試集所在資料夾位址')
errorcount = 0.0
#識別函式識別結果是錯誤的個數
mtest = len(testfilelist)#計算測試集資料個數
#以下**將mtest個測試集裡的資料依次進行識別,並輸出識別的結果
for i in range(mtest):
filenamestr = testfilelist[i]
filestr = filenamestr.split('.')[0]
classnumstr = int(filestr.split('_')[0])#讀取測試集資料對應的真實數字是多少即測試集資料的label
vectorundertest = img2vector('這裡填測試集所在資料夾位址%s' % filenamestr)#將測試集裡資料進行img2vector轉換
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 errors is: %d" % errorcount
print
"\nthe total error rate is: %f" % (errorcount/float(mtest))#計算錯誤率並輸出
最終**執行的結果如下所示,由於用了兩個for迴圈巢狀,導致執行的時間有點久。測試集共946組資料,識別錯誤11個,錯誤率1.1628%。
以上介紹的就是利用k-近鄰演算法實現的手寫數字識別,**裡涉及到的一些具體函式如下,如有不懂的同學可以點進鏈結進行學習。
read()、readline()、readlines()函式區別
listdir()函式用法
split()函式用法
《機器學習實戰》 K 近鄰演算法
基本原理 通過計算新資料與給定的樣本資料之間的距離,來確定相似度排名 然後取前k個最相似的樣本,統計這k 一般不大於20 個樣本中出現最多的分類,設為新資料的分類。新資料,訓練樣本集,樣本資料標籤 即分類 最近鄰 前k個最相似資料 最近鄰標籤 演算法實施 首先提取要比較的特徵,確定各特徵的權重,進行...
機器學習實戰 K 近鄰演算法
簡單的說,k 近鄰演算法採用測量不同特徵值之間的距離辦法進行分類.收集資料 可以使用任何方法。準備資料 距離計算所需要的數值,最好是結構化的資料格式。分析資料 可以使用任何方法。訓練演算法 此步驟不適用於k 近鄰演算法。測試演算法 計算錯誤率。使用演算法 首先需要輸入樣本資料和結構化的輸出結果,然後...
機器學習實戰 k 近鄰演算法
本系列是基於 機器學習實戰 這本書做的讀書筆記,原書採用python2作為工具,我則將原書 改為用python3編寫並記錄在此系列中。我將把書中對這些機器學習演算法的定義謄上,然後寫下自己對該演算法的通俗理解,之後貼出書中演算法清單中的 本書講解的第乙個機器學習演算法是k 近鄰演算法 knn 它的工...