示例:使用k-近鄰演算法的手寫識別系統構造的系統只能識別數字0到9,目錄trainingdigits中包含了大約2000個例子,每個數字大約有200個樣本;目錄testdigits中包含了大約900個測試資料。儘管採用文字格式儲存影象不能有效地利用記憶體空間,但是為了方便理解,我們將轉換為文字格式,數字的文字格式如圖所示。(1) 收集資料:提供文字檔案。
(2) 準備資料:編寫函式classify0(),將影象格式轉換為分類器使用的list格式。
(3) 分析資料:在python命令提示符中檢查資料,確保它符合要求。
(4) 訓練演算法:此步驟不適用於k-近鄰演算法。
(5) 測試演算法:編寫函式使用提供的部分資料集作為測試樣本,測試樣本與非測試樣本的區別在於測試樣本是已經完成分類的資料,如果**分類與實際類別不同,則標記為乙個錯誤。
(6) 使用演算法:本例沒有完成此步驟,若你感興趣可以構建完整的應用程式,從影象中提取數字,並完成數字識別,美國的郵件分揀系統就是乙個實際執行的類似系統。
檔案的名字也是有特殊含義的,格式為:數字的值_該數字的樣本序號。
把乙個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個距離對應已知資料的類別進行統計,把出現次數最多的類別作為...