機器學習 KNN演算法 手寫識別

2021-08-03 19:50:47 字數 4389 閱讀 6085

1.1 簡介

knn演算法即k最近鄰分類演算法,是機器學習的一種。從訓練樣本集中選取k個與測試樣本「距離」最近的樣本,這k個樣本中出現頻率最高的類別作為該測試樣本的類別。

1.2 要求

目標:分類未知類別的案例。

輸入:待分類未知類別案例專案(測試集),已知類別案例集合d(訓練集)。

輸出:未知類別案例的可能分類。

1.3 步驟

下面是乙個常見的乙個二分類示意圖。

其中已知類別為三角形與正方形,圓點為待分類的案例。

分類過程如下:

1.首先確定k值,即待分類樣本用多少鄰居進行估計。以上述問題為例,分別選取k為3和5 。

2.確定合適的距離度量公式(如:歐氏距離),然後根據乙個待分類樣本點與所有已知類別的樣本點中,找出待分類樣本點中最近的k個鄰居。

3.統計這k個樣本點的類別,選取類別最多的一類作為待分類樣本點的類別。以上述問題為例,當k=3時圓點為三角形,當k=5時,圓點為正方形。

1.4 優缺點

優點:演算法實現簡單,不需要引數估計,不需要事先訓練模型。

缺點:直到分類時才開始訓練,運算量大,而且訓練樣本儲存在本地,記憶體開銷大。

1.5 注意點

k的選取一般不大於20.

2.1 numpy庫介紹

numpy庫中有兩種基本資料型別,分別是矩陣和陣列array。

shape()檢視矩陣或者陣列的維度

>>>shape(array) 若矩陣有m行n列,返回(m,n)

>>>array.shape[0] 返回m,若下標為1,返回n

tile()構造陣列

>>>tile(a,(m,n)) 將陣列a作為元素構造乙個m行n列的陣列

sum()

>>>array.sum(axis=1)按行累加,axis=0為按列累加

argsort() 返回矩陣中每乙個元素原來的下標號

>>>a=array.argsort() a[0]表示排序後 排在第乙個的那個數在原來陣列中的下標

min()、max()

>>>array.min(0) 返回乙個陣列,陣列中每個數都是它所在列的所有數的最小值

>>>array.min(1) 返回乙個陣列,陣列中每個數都是它所在行的所有數的最小值

split()切割字串

>>>string.split(『str』)以字元str為分隔符切片,返回list

2.2 實現「手寫識別

每乙個數字都預先被處理為32*32二進位制檔案。

1.將每乙個(即txt文字)轉化為乙個向量,即將32*32的陣列轉換為1 *1024的陣列。這個1*1024的陣列在ml中即乙個特徵向量。

2.訓練資料中一共有10*10個檔案,將其合併為10*1024的矩陣,每一行對應乙個。(這是為了方便計算,很多機器學習演算法在計算的時候採用矩陣運算,可以簡化**,有時還可以減少計算複雜度)。

3.測試樣本中有10*5個,我們要讓程式自動判斷每個所表示的數字。同樣的,對於測試,將其轉化為1*1024的向量,然後計算它與訓練樣本中各個的「距離」(這裡兩個向量的距離採用歐式距離),然後對距離排序,選出較小的前k個,因為這k個樣本來自訓練集,是已知其代表的數字的,所以被測試所代表的數字就可以確定為這k個中出現次數最多的那個數字。

2.3 **實現

第一步,轉化特徵向量

#輸入二進位制檔案

defimg2vector

(filename):

returnvect = zeros((1,1024))

with open(filename) as file:

for i in range(32):

line = file.readline()

for j in range(32):

returnvect[1,32*i+j] = int(line[j])

return returnvect

第二步,組合所有的訓練集,同時對測試集進行樣本分類。

def

handwritingclasstest

():#組合所有的訓練集

#所有已有的類別集合

handlabels =

#將每乙個檔案的檔名儲存在乙個列表中

trainingfilelist = listdir('traingdigits')

m = len(trainingfilelist)

trainingmat = zeros((m,1024))

#迴圈對每乙個數字檔案進行處理

for i in range(m):

filenamestr = trainingfilelist[i]

#切除字尾名

filename = filenamestr.split('.')[0]

#提取類別名

classnumstr = int(filename.split('_')[0])

#採用格式化引數

trainingmat[i,:] = img2vector('traindigits/%s' % filenamestr)

#對測試集進行分類

testfilelist = listdir('testdigits')

errorcount = 0.0

mtest = len(testfilelist)

for i in range(mtest):

filenamestr = testfilelist[i]

filename = filenamestr.split('.')[0]

classnumstr = int(filename.split('_')[0])

vectorundertest = img2vector('testdigits/%s' % filenamestr)

classifierresult = classify(vectorundertest, trainingmat, handlabels, 3)

print

"the classifier came back with: %d, and 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))

分類函式:

#testdata為測試向量;traindata為訓練資料;label為訓練資料對應的標籤;k為近鄰數

defclassify

(testdata, traindata, label, k):

#記錄訓練集資料個數

trainnum = traindata.shape[0]

#diffmat的每一行為該測試向量與訓練資料的差異值,每一行中的每乙個元素對應乙個維度上的差異

diffmat = tile(testdata,(trainnum,1)) - traindata

sqdiffmat = diffmat ** 2

#axis=1為按行累加,然後開方,即最終的歐式距離

sqdistances = sqdiffmat.sum(axis=1)

distances = sqdistances ** 0.5

#獲取排序後元素在原陣列中的下標列表,即sortdistindicies[0]為排序後第乙個元素在原來的序列中的下標

sortdistindicies = distances.argsort()

#統計k個相似值中的類別數

classcount = {}

for i in range(k):

getlabel = label(sortdistindicies[i])

classcount[getlabel] = classcount.get(getlabel,0)+1

sortedclasscount = sorted(classcount.iteritems(), key=operator.itemgetter(1), reverse=true)

#返回最多的label

return sortedclasscount[0][0]

機器學習實戰 knn 手寫識別

這個是 機器學習實戰 的第二個例項,用knn演算法實現手寫識別,識別0 9這幾個數字 要實現手寫識別功能,首先將影象資料轉換為矩陣或者向量形式,本例使用32 32的二值影象,轉化成1 1024的陣列,具體 如下 def img2vector filename returnvect zeros 1,1...

機器學習(二) kNN手寫數字識別

一 knn演算法 1 knn演算法是機器學習的入門演算法,其中不涉及訓練,主要思想是計算待測點和參照點的距離,選取距離較近的參照點的類別作為待測點的的類別。2,距離可以是歐式距離,夾角余弦距離等等。3,k值不能選擇太大或太小,k值含義,是最後選取距離最近的前k個參照點的類標,統計次數最多的記為待測點...

KNN演算法識別手寫數字

前言 從現在開始博主要開始學習機器學習了,歡迎有共同興趣的人一起學習。廢話不多說了,開始上 一 將資料集csv檔案匯入到python中,並將csv格式轉為list格式 def dataset 讀取訓練集檔案路徑 path trains1.csv os.path.abspath machinelear...