k最鄰近演算法 使用kNN進行手寫識別

2021-08-07 21:54:19 字數 2826 閱讀 9567

上篇文章中提到了使用pillow對手寫文字進行預處理,本文介紹如何使用knn演算法對文字進行識別。

k最鄰近演算法(k-nearest neighbor, knn),是機器學習分類演算法中最簡單的一類。假設乙個樣本空間被分為幾類,然後給定乙個待分類的特徵資料,通過計算距離該資料的最近的k個樣本來判斷這個資料屬於哪一類。如果距離待分類屬性最近的k個類大多數都屬於某乙個特定的類,那麼這個待分類的資料也就屬於這個類。所謂k最近鄰,就是k個最近的鄰居的意思,說的是每個樣本都可以用它最接近的k個鄰居來代表。knn在確定分類決策上只依據最鄰近的乙個或者幾個樣本的類別來決定待分樣本所屬的類別,在決策時,只與極少量的相鄰樣本有關。通常,k是不大於20的整數。

下圖所示,綠色圓要被決定賦予哪個類,是紅色三角形還是藍色四方形?如果k=3,由於紅色三角形所佔比例為2/3,綠色圓將被賦予紅色三角形那個類,如果k=5,由於藍色四方形比例為3/5,因此綠色圓被賦予藍色四方形類。

在理想情況下,k值選擇1,即只選擇最近的鄰居。在現實生活中往往沒這麼理想,比如對於**來說,有些顧客訊息閉塞,可能會為 「最近的鄰居」多付很多錢,所以應當貨比三家,多選擇一些鄰居,取均值來減少雜訊。實際上,k值過大或過小都將影響結果。

過程如下:

計算訓練集中的點與當前點之間的距離;

按距離降序排序;

選取與當前點距離最小的k個點;

如果是數值型資料,計算前k個點的均值;如果是離散資料,計算前k個點所在類別出現的頻率;

如果是數值型資料,返回前k個點的均值作為**數值;如果是離散資料,返回前k個點出現頻率最高的類別作為**分類。

**如下:

from os import  listdir

#將檔案轉換為向量

def img2vector(filename):

with open(filename) as fobj:

arr = fobj.readlines()

vec, demension = , len(arr)

for i in range(demension):

line = arr[i].strip()

for j in range(demension):

return vec

#讀取訓練資料

def createdataset(dir):

dataset, labels = ,

files = listdir(dir)

for filename in files:

label = int(filename[0])

return dataset, labels

#計算谷本係數

def tanimoto(vec1, vec2):

c1, c2, c3 = 0, 0, 0

for i in range(len(vec1)):

if vec1[i] == 1: c1 += 1

if vec2[i] == 1: c2 += 1

if vec1[i] == 1 and vec2[i] == 1: c3 += 1

return c3 / (c1 + c2 - c3)

def classify(dataset, labels, testdata, k=20):

distances =

for i in range(len(labels)):

d = tanimoto(dataset[i], testdata)

distances.sort(reverse=true)

#key label, value count of the label

klabeldict = {}

for i in range(k):

klabeldict.setdefault(distances[i][1], 0)

klabeldict[distances[i][1]] += 1 / k

#按value降序排序

preddict = sorted(klabeldict.items(), key=lambda item: item[1], reverse=true)

return preddic

dataset, labels = createdataset('trainingdigits')

testdata = img2vector('testdigits/8_19.txt')

print(classify(dataset, labels, testdata))

我們事先使用pillow對手寫數字進行了二值化處理,形成乙個32*32的矩陣,並將每個訓練樣本儲存到乙個txt檔案,檔名以數字開頭,這個數字就是手寫數字的label,如3_1.txt,其中的內容是:

在上述手寫識別的例子中,供使用了900個測試樣本,其中34個產生了誤判,下圖是乙個誤判的例子:

圖中是手寫數字1,程式判斷為7,其原因是

**所用的方法有可能會選擇很遠的近鄰:

y點肉眼去看因為在紅色區域內很容易判斷出多半屬於紅色一類,但因為藍色過多,若k值選取稍大則很容易將其歸為藍色一類。為了改進這一點,可以為每個點的距離增加乙個權重,這樣距離近的點可以得到更大的權重。

k最鄰近演算法 加權kNN

上篇文章中提到為每個點的距離增加乙個權重,使得距離近的點可以得到更大的權重,在此描述如何加權。該方法最簡單的形式是返回距離的倒數,比如距離d,權重1 d。有時候,完全一樣或非常接近的商品權重會很大甚至無窮大。基於這樣的原因,在距離求倒數時,在距離上加乙個常量 weight 1 distance co...

K鄰近演算法 KNN

k nearest neighbor knn演算法 如果乙個樣本在特徵空間中的k個最相似 即特徵空間中最鄰近 的樣本中的大多數屬於某乙個類別,則該樣本也屬於這個類別。所選擇的鄰居都是已經正確分類的物件。如果k 3,則綠色圓形的類別與紅色三角形相同 如果k 5,則綠色圓形的類別與藍色正方形相同 the...

K 最鄰近演算法總結

1.基本介紹 k最近鄰 k nearest neighbor,knn 分類演算法,是乙個理論上比較成熟的方法,也是最簡單的機器學習演算法之一。該方法的思路是 如果乙個樣本在特徵空間中的k個最相似 即特徵空間中最鄰近 的樣本中的大多數屬於某乙個類別,則該樣本也屬於這個類別。knn演算法中,所選擇的鄰居...