kNN演算法及python實現

2021-10-07 05:25:45 字數 3305 閱讀 6606

knn演算法又稱為k近鄰分類(k-nearest neighbor classification)演算法,可以解決分類和回歸的問題。knn演算法主要是通過距離判定出訓練集中離待測樣本最近的k個樣本,然後統計這k個樣本的類別,次數最多的類別或加權後距離最小的點的類別為新資料的類別。距離越近,類別判定的準確度越高。

knn演算法有3個主要因素:訓練集、距離衡量、k值。

訓練集少且種類少的時候演算法有效,訓練集大的時候要使用kd樹和球樹的方法建立模型。

距離衡量的方法有多種,目的都是搜尋最近鄰,最常用的是歐氏距離。

k值決定了最後確定類別時所參考的樣本數量,k值過大則訓練誤差增大,選取的臨近點中包含錯誤種類的可能性增大,導致結果不準確;k值過小則泛化誤差增大,模型容易受到雜訊干擾,容易過度擬合。因此k值的選取非常重要,一般先選取乙個很小的值,再使用交叉檢驗確定最優的k值,一般都低於訓練樣本的平方根。

演算法步驟如下所示:

找k個最近樣本:給定k值,根據求出的距離選定距離最近的k個樣本

利用交叉檢驗確定最優的k值,即將資料臨時分為訓練集和測試集,從k=1開始測試,最大不能超過樣本資料的平方根,從中選出效果最好的k值。

定類別:根據最近的k個樣本的類別,確定待測樣本的類別

一般有兩種方法確定類別:第一,類別定為k個樣本**現次數最多的類別;第二,距離加權法,在k個樣本中,權重為距離平方的倒數,每個點都賦值為1,對相同種類的點進行加權求和,最後值最大的種類為待測樣本的種類。

當資料量非常大或特徵特別多時,一般使用kd樹或球樹法建模。

1、 優點

簡單易懂,易於實現,無需估計引數和反腐訓練;適合對稀有事件進行分類;

特別適合於多分類問題(multi-modal,物件具有多個類別標籤),例如根據基因特徵來判斷其功能分類,knn比svm的表現要好

2、缺點

knn是懶惰演算法,沒有提前訓練,輸入待測樣本時才選定k個最近樣本,對測試樣本分類時的計算量大,要從頭開始計算每個樣本離待測樣本的距離,速度慢;可解釋性較差,無法給出決策樹那樣的規則。

在檔案data111.txt中我們有40個點的座標,其分別屬於0,1,2,3類,類別資料儲存在檔案data2.txt中,先利用互動檢驗的方法,取其中三十組資料為訓練集,十組資料為測試集,比較結果的精確度,選出效果最好的k值,再對待測資料進行分析歸類。

使用程式如下所示:

# -

*- coding: utf-8-

*-import numpy as np

import operator as opt

def loaddata

(infile)

: dataset= np.

loadtxt

(infile)

return dataset

def loadtxt

(filename)

: labels= np.

loadtxt

(filename)

return labels

def normdata

(dataset)

: maxvals = dataset.

max(axis=0)

minvals = dataset.

min(axis=0)

ranges = maxvals - minvals

retdata =

(dataset - minvals)

/ ranges

return retdata, ranges, maxvals, minvals

def knn

(dataset, labels, testdata, k)

: #計算歐氏距離

distsquaremat =

(dataset - testdata)

**2 # 計算差值的平方

distsquaresums = distsquaremat.

sum(axis=

1) # 求每一行的差值平方和

distances = distsquaresums **

0.5 # 開根號,得出每個樣本到測試點的距離

#找最近鄰

sortedindices = distances.

argsort

() # 排序,得到排序後的下標

indices = sortedindices[

:k] # 取最小的k個 #sorted臨時排序

labelcount =

# 儲存每個label的出現次數 #count出現次數

for i in indices:

label = labels[i]

labelcount[label]

= labelcount.

get(label,0)

+1 # 次數加一

sortedcount =

sorted

(labelcount.

items()

, key=opt.

itemgetter(1

), reverse=true) # 對label出現的次數從大到小進行排序

return sortedcount[0]

[0] # 返回出現次數最大的label

if __name__ ==

"__main__"

: infile=

'c:/users/administrator/desktop'

dataset=np.

array

(loaddata

(infile)

) normdataset, retdata, ranges, minvals =

normdata

(dataset)

filename=

'c:/users/administrator/desktop'

labels= np.

loadtxt

(filename)

testdata = np.

array([

3.9,

5.5]

) normtestdata =

(testdata - minvals)

/ ranges

result =

knn(normdataset, labels, normtestdata,4)

print

('dataset='

,infile)

print

(dataset)

print

('類別:'

,result)

輸出結果:
類別:3

Python實現KNN演算法

from numpy import import operator def creatdataset group array 1.0,1.1 1.0,1.0 0,0 0,0.1 lables a a b b return group,lables def classify0 inx,dataset,...

python實現knn演算法

importnumpyasnp importoperator defcreatedataset group np.array 1.0 1.1 1.0 1.0 0.0 0.0 0.0 0.1 labels a a b b returngroup,labels 分類演算法 inx待分類的點 defcla...

python實現KNN演算法

具體 如下 import numpy as np import matplotlib.pyplot as plt class myknn def init self,k self.k k def compute self,x train,y train,x test dist i 0 計算歐式距離 ...