Sklearn構建k 近鄰分類器用於手寫數字識別

2021-10-03 20:21:03 字數 3872 閱讀 5168

示例:使用k-近鄰演算法的手寫識別系統

(1) 收集資料:提供文字檔案。

(2) 準備資料:編寫函式classify0(),將影象格式轉換為分類器使用的list格式。

(3) 分析資料:在python命令提示符中檢查資料,確保它符合要求。

(4) 訓練演算法:此步驟不適用於k-近鄰演算法。

(5) 測試演算法:編寫函式使用提供的部分資料集作為測試樣本,測試樣本與非測試樣本的區別在於測試樣本是已經完成分類的資料,如果**分類與實際類別不同,則標記為乙個錯誤。

(6) 使用演算法:本例沒有完成此步驟,若你感興趣可以構建完整的應用程式,從影象中提取數字,並完成數字識別,美國的郵件分揀系統就是乙個實際執行的類似系統。

構造的系統只能識別數字0到9,目錄trainingdigits中包含了大約2000個例子,每個數字大約有200個樣本;目錄testdigits中包含了大約900個測試資料。儘管採用文字格式儲存影象不能有效地利用記憶體空間,但是為了方便理解,我們將轉換為文字格式,數字的文字格式如圖所示。

檔案的名字也是有特殊含義的,格式為:數字的值_該數字的樣本序號。

把乙個32×32的二進位制影象矩陣轉換為1×1024的向量,這樣前兩節使用的分類器就可以處理數字影象資訊了。

import numpy as np

import operator

from os import listdir

from sklearn.neighbors import kneighborsclassifier as knn

"""parameters:

filename - 檔名

returns:

returnvect - 返回的二進位制影象的1x1024向量

"""# 函式說明:將32x32的二進位制影象轉換為1x1024向量。

defimg2vector

(filename)

:#建立1x1024零向量

returnvect = np.zeros((1

,1024))

#開啟檔案

fr =

open

(filename)

#按行讀取

for i in

range(32

):#讀一行資料

linestr = fr.readline(

)#每一行的前32個元素依次新增到returnvect中

for j in

range(32

):returnvect[0,

32*i+j]

=int

(linestr[j]

)#返回轉換後的1x1024向量

return returnvect

# 函式說明:手寫數字分類測試

defhandwritingclasstest()

:#測試集的labels

hwlabels =

#返回trainingdigits目錄下的檔名

trainingfilelist = listdir(

'trainingdigits'

)#返回資料夾下檔案的個數

m =len(trainingfilelist)

#初始化訓練的mat矩陣,測試集

trainingmat = np.zeros(

(m,1024))

#從檔名中解析出訓練集的類別

for i in

range

(m):

#獲得檔案的名字

filenamestr = trainingfilelist[i]

#獲得分類的數字

classnumber =

int(filenamestr.split(

'_')[0

])#將獲得的類別新增到hwlabels中

#將每乙個檔案的1x1024資料儲存到trainingmat矩陣中

trainingmat[i,:]

= img2vector(

'trainingdigits/%s'

%(filenamestr)

)#構建knn分類器

neigh = knn(n_neighbors =

3, algorithm =

'auto'

)#擬合模型, trainingmat為測試矩陣,hwlabels為對應的標籤

neigh.fit(trainingmat, hwlabels)

#返回testdigits目錄下的檔案列表

testfilelist = listdir(

'testdigits'

)#錯誤檢測計數

errorcount =

0.0#測試資料的數量

mtest =

len(testfilelist)

#從檔案中解析出測試集的類別並進行分類測試

for i in

range

(mtest)

:#獲得檔案的名字

filenamestr = testfilelist[i]

#獲得分類的數字

classnumber =

int(filenamestr.split(

'_')[0

])#獲得測試集的1x1024向量,用於訓練

vectorundertest = img2vector(

'testdigits/%s'

%(filenamestr)

)#獲得**結果

# classifierresult = classify0(vectorundertest, trainingmat, hwlabels, 3)

classifierresult = neigh.predict(vectorundertest)

print

("分類返回結果為%d\t真實結果為%d"

%(classifierresult, classnumber))if

(classifierresult != classnumber)

: errorcount +=

1.0print

("總共錯了%d個資料\n錯誤率為%f%%"

%(errorcount, errorcount/mtest *

100)

)if __name__ ==

'__main__'

: handwritingclasstest(

)

>>

>

分類返回結果為9 真實結果為9

分類返回結果為9 真實結果為9

分類返回結果為9 真實結果為9

分類返回結果為9 真實結果為9

總共錯了12個資料

錯誤率為1.268499

%

上述**使用的algorithm引數是auto,更改algorithm引數為brute,使用暴力搜尋,你會發現,執行時間變長了,變為10s+。更改n_neighbors引數,你會發現,不同的值,檢測精度也是不同的。可以嘗試更改這些引數的設定,加深對其函式的理解。

k-近鄰演算法是分類資料最簡單最有效的演算法,通過兩個例子(約會**和手寫數字識別)講述了如何使用k-近鄰演算法構造分類器。。k-近鄰演算法是基於例項的學習,使用演算法時我們必須有接近實際資料的訓練樣本資料。k-近鄰演算法必須儲存全部資料集,如果訓練資料集的很大,必須使用大量的儲存空間。此外,由於必須對資料集中的每個資料計算距離值,實際使用時可能非常耗時。

k-近鄰演算法的另乙個缺陷是它無法給出任何資料的基礎結構資訊,因此也無法知曉平均例項樣本和典型例項樣本具有什麼特徵。下一章我們將使用概率測量方法處理分類問題,該演算法可以解決這個問題。

sklearn學習 k近鄰

比如我們要 中心點的顏色,以k 3為半徑畫乙個圓 圖中實線圓 此時紅點多於藍點,那麼我們推測中心點為紅色,以k 5為半徑畫乙個圓 圖中虛線圓 此時藍點多於紅點,那麼我們推測中心點為藍色。鳶尾花種類的 如下 from sklearn import datasets from sklearn.model...

K近鄰分類

k 近鄰 待會介紹 的一種極端情況。近朱者赤,近墨者黑 def distance p0,p1 computes squared euclidean distance return np.sqrt np.sum p0 p1 2 defnn classify training set,training ...

k近鄰分類 kNN

k近鄰分類 knn 一 knn原理 knn屬於監督分類方法,原理是利用某種距離度量方式來計算未知資料與已知資料的距離,並根據距離來確定資料光譜間的相似性,選取最近的k個距離作為判定未知資料類別的依據。在分類時,knn常用方法有 投票法,根據k個距離對應已知資料的類別進行統計,把出現次數最多的類別作為...