1、概述
最近鄰算法(KNN),是一種基本的分類與回歸方法,是數據挖掘技術中最簡單的技術之一。
所謂最近鄰,就是首先選取一個閾值為K,對在閾值范圍內離測試樣本最近的點進行投票,票數多的類別就是這個測試樣本的類別,這是分類問題。那么回歸問題也同理,對在閾值范圍內離測試樣本最近的點取均值,那么這個值就是這個樣本點的預測值。
它沒有訓練的過程,它的學習階段僅僅是把樣本保存起來,等收到測試集之后再進行處理,屬於“懶惰學習”。所以它本質上是衡量樣本之間的相似度。
2、KNN 算法三要素
1、K值的選擇
- K值的確定與樣本最終的判定結果有很大的關系;K 值太小會使得 KNN 算法容易過擬合。反之,太大則會欠擬合。因此,一般采用交叉驗證的方式選取 K 值。
2、距離的度量
- 通過什么樣的距離理論確定最近鄰的樣本數據。一般使用歐氏距離(歐幾里得距離);
- 閔可夫斯基距離本身不是一種距離,而是一類距離的定義。對於n維空間中的兩個點x(x1,x2,…,xn)和y(y1,y2,…,yn),x和y之間的閔可夫斯基距離可以表示為:

當p=1時,被稱為曼哈頓距離;
當p=2時,被稱為歐氏距離;
當p=\infty時,被稱為切比雪夫距離。
3、決策規則:以什么樣的決策規則來確定最終的輸出結果。
- 在分類預測時,一般采用“多數表決法”或“加權多數表決法”;
- 在回歸預測時,一般采用“平均值法”或“加權平均值法”,這也是KNN做分類與回歸最主要的區別。這里所說的加權一般情況下采用權重和距離成反比的方式來計算。
3、算法步驟
- 算距離:給定測試對象,計算它與訓練集中的每個對象的距離
- 找鄰居:對訓練集的每個對象根據距離排序,選取最近的K個
- 做分類:根據這k個近鄰歸屬的主要類別進行投票,以確定測試對象的分類
4、代碼示例
# -*- coding: utf-8 -*-
# 導入鳶尾花數據集
from sklearn.datasets import load_iris
# 導入knn算法
from sklearn import neighbors
# 加載數據
iris = load_iris()
# 提取數據
trainX = iris.data
trainY = iris.target
# 建立模型
clf = neighbors.KNeighborsClassifier(n_neighbors=6,
weights='uniform', algorithm='auto', metric='minkowski', metric_params=None, n_jobs=1)
'''
@param n_neighbors: 指定kNN的k值
@param weights:
'uniform': 本節點的所有鄰居節點的投票權重都相等
'distance': 本節點的所有鄰居節點的投票權重與距離成反比
@param algorithm:
'ball_tree': BallTree算法
'kd_tree': kd樹算法
'brute': 暴力搜索算法
'auto': 自動決定適合的算法
@param leaf_size: 指定ball_tree或kd_tree的葉節點規模。他影響樹的構建和查詢速度
@param p: p=1:曼哈頓距離; p=2:歐式距離
@param metric: 指定距離度量,默認為'minkowski'距離
@param n_jobs: 任務並行時指定使用的CPU數,-1表示使用所有可用的CPU
@method fit(X,y): 訓練模型
@method predict(X): 預測
@method score(X,y): 計算在(X,y)上的預測的准確率
@method predict_proba(X): 返回X預測為各類別的概率
@method kneighbors(X, n_neighbors, return_distance): 返回樣本點的k近鄰點。如果return_distance=True,則也會返回這些點的距離
@method kneighbors_graph(X, n_neighbors, mode): 返回樣本點的連接圖
'''
# 訓練模型
clf.fit(trainX, trainY)
# 打印准確率
print("訓練准確率:" + str(clf.score(trainX, trainY)))
print("測試准確率:" + str(clf.score(trainX, trainY)))
訓練准確率:0.9733333333333334
測試准確率:0.9733333333333334
4、算法優缺點
1、優點
- 簡單,易於理解,易於實現,無需估計參數,無需訓練
- 適合對稀有事件進行分類(例如當流失率很低時,比如低於0.5%,構造流失預測模型)
- 特別適合於多分類問題(multi-modal,對象具有多個類別標簽),例如根據基因特征來判斷其功能分類,kNN比SVM的表現要好
2、缺點
- 懶惰算法,對測試樣本分類時的計算量大,內存開銷大,評分慢
- 可解釋性較差,無法給出決策樹那樣的規則。