十四 機器學習之路 K 近鄰演算法實戰

2021-08-10 20:20:50 字數 3750 閱讀 1846

使用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 它的工...