K最近鄰演算法

2021-09-26 13:46:09 字數 3401 閱讀 5003

參考:
所謂k最近鄰,就是k個最近的鄰居的意思,說的是每個樣本都可以用它最接近的k個鄰居來代表。cover和hart在2023年提出了最初的鄰近演算法。knn是一種分類(classification)演算法,它輸入基於例項的學習(instance-based learning),屬於懶惰學習(lazy learning)即knn沒有顯式的學習過程,也就是說沒有訓練階段,資料集事先已有了分類和特徵值,待收到新樣本後直接進行處理。與急切學習(eager learning)相對應。

其基本做法是:給定測試例項,基於某種距離度量找出訓練集中與其最靠近的k個例項點,然後基於這k個最近鄰的資訊來進行**。

距離度量、k值的選擇及分類決策規則是k近鄰法的三個基本要素。根據選擇的距離度量(如曼哈頓距離或歐氏距離),可計算測試例項與訓練集中的每個例項點的距離,根據k值選擇k個最近鄰點,最後根據分類決策規則將測試例項分類。

如圖,根據歐氏距離,選擇k=4個離測試例項最近的訓練例項(紅圈處),再根據多數表決的分類決策規則,即這4個例項多數屬於「-類」,可推斷測試例項為「-類」。

1. 距離度量距離就是平面上兩個點的直線距離

關於距離的度量方法,常用的有:歐幾里得距離、余弦值(cos), 相關度 (correlation), 曼哈頓距離 (manhattan distance)或其他。

2. 關於k的取值

k值的選擇會對k近鄰法的結果產生重大影響。在應用中,k值一般取乙個比較小的數值,通常採用交叉驗證法來選取最優的k值。

如果當k的取值過小時,一旦有雜訊得成分存在們將會對**產生比較大影響,例如取k值為1時,一旦最近的乙個點是雜訊,那麼就會出現偏差,k值的減小就意味著整體模型變得複雜,容易發生過擬合;

如果k的值取的過大時,就相當於用較大鄰域中的訓練例項進行**,學習的近似誤差會增大。這時與輸入目標點較遠例項也會對**起作用,使**發生錯誤。k值的增大就意味著整體的模型變得簡單;

如果k==n的時候,那麼就是取全部的例項,即為取例項中某分類下最多的點,就對**沒有什麼實際的意義了;

k的取值盡量要取奇數,以保證在計算結果最後會產生乙個較多的類別,如果取偶數可能會產生相等的情況,不利於**。

我們很少將k近鄰用在影象上。因為:

測試速度非常慢,不符合需求,畫素上的距離度量不能提供有效資訊,有些影象可能進行一定的遮擋、變色等操作之後,其歐幾里得距離還是相等的,這樣就不能有效衡量兩張影象之間的距離;

維度災難:k近鄰等於把訓練集在樣本空間上進行分割,使得距離近的劃分為一類,為了使訓練集密集的分布在一起,就需要大量的訓練。從一維到二維到三維,我們所需要的訓練樣本呈指數倍增長。

- 交叉驗證:

通常用在小型資料集上,首先從資料集中分離出一部分作為測試集(test),然後將剩下分為5份。首先使用一組超引數,在前4份上進行訓練,在第5份上驗證。然後再訓練演算法,在1235份上進行訓練,在第4份上進行驗證。然後在1245份上訓練,在3份上驗證。以此類推。

**實現

#### 距離度量為歐氏距離,分類決策規則為多數表決。classify()函式有4個輸入引數:用於分類的輸入向量是in

#### x,輸入的訓練集為dataset,類別為labels,k表示用於選擇最近鄰的數目。

# -- coding: utf-8 --

import numpy as np

import operator

def createdataset():

# 建立訓練集

group = np.array([[1.0,1.1],[1.0,1.0],[0,0],[0,0.1]])

labels = ['a','a','b','b']

return group, labels

def classify0(inx, dataset, labels, k):

#numpy中shape[0]返回陣列的行數,shape[1]返回列數

datasetsize = dataset.shape[0]

# 根據歐式距離計算訓練集中每個樣本到測試點的距離

# np.tile()把陣列沿各個方向複製

# 將intx在沿y軸重複datasetsize次,沿x軸重複1次

# 例如intx=([1,2])--->([[1,2],[1,2],[1,2],[1,2]])便於後面計算

diffmat = np.tile(inx, (datasetsize,1)) - dataset

# 二維特徵相減後乘方

sqdiffmat = diffmat**2

# 計算距離

sqdistances = sqdiffmat.sum(axis=1)

# axis=0表示豎向相加,axis=1表示水平相加。

distances = sqdistances**0.5

# 計算完所有點的距離後,對資料按照從小到大的次序排序

sorteddistindicies = distances.argsort()

# 確定前k個距離最小的元素所在的主要分類,最後返回發生頻率最高的元素類別

classcount={}

for i in range(k):

voteilabel = labels[sorteddistindicies[i]]# k個值的標籤存入voteilabel

classcount[voteilabel] = classcount.get(voteilabel,0) + 1# ,對類別出現的次數進行計算,此處+1是為了計數

sortedclasscount = sorted(classcount.items(), key=operator.itemgetter(1), reverse=true) # 對label出現的次數從大到小進行排序

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

K最近鄰演算法

一 原理 k最近鄰演算法 k nearest neighbor,knn 是最基本的分類演算法,其基本原理是 從最近的k個鄰居 樣本 中,選擇出現次數最多的類別作為判定類別。k最近鄰演算法可以理解為是乙個分類演算法,常用於標籤的 如性別。實現knn演算法核心的一般思路 相似度計算 計算未知樣本和每個訓...

K最近鄰演算法(介紹)

問題 用k最近鄰演算法建立分類系統 學習特徵抽取 學習回歸,即 數值 學習k最近鄰演算法的應用案例和侷限性k最近鄰 k nearest neighbours,knn 演算法 k最近鄰演算法是指在乙個座標系中 前提是把元素放入座標系 so,問題來了,怎麼把他們放入座標系?他們在座標系的位置怎麼確定?其...

最近鄰與K近鄰演算法思想

在關於徑向基神經網路的一篇博文機器學習之徑向基神經網路 rbf nn 中已經對最近鄰思想進行過描述,但是寫到了rbf中有些重點不夠突出,所以,這裡重新對最近鄰和k近鄰的基本思想進行介紹,簡潔扼要的加以總結。最近鄰的基本思想 儲存所有觀察到的有標籤的樣本,然後對新來的測試樣本,在標籤樣本集中找到與測試...