什麼是knn
kNN(k-NearestNeighbor),也就是k最近鄰算法。顧名思義,所謂K最近鄰,就是k個最近的鄰居的意思。也就是在數據集中,認爲每個樣本可以用離他最距離近的k個鄰居來代表。
它是一種常用的監督學習方法,在分類任務中可以採用“投票法”,在迴歸任務中可以採用“平均法”,以及基於距離遠近進行加權平均或加權投票,距離越近的樣本權重越大。
簡單來說就是“近朱者赤近墨者黑”思想的直觀體現。
注:這裏的距離可能是歐式距離或曼哈頓距離
kNN算法流程
通過理解算法思想,可以將其簡化爲“找鄰居+投票”。K近鄰法使用的模型,實際上是特徵空間的劃分。模型由三個基本要素決定:
- 距離度量
- k值
- 分類決策規則
其中兩個實例點之間的距離反映了相似程度。一般來說使用歐氏距離來計算。
梳理kNN算法流程如下:
-
計算測試對象到訓練集中每個對象的距離
-
按照距離的遠近排序
-
選取與當前測試對象最近的k的訓練對象,作爲該測試對象的鄰居
-
統計這k個鄰居的類別頻次
-
k個鄰居里頻次最高的類別,即爲測試對象的類別
簡單來說,如下圖,當k=3,那麼數據樣本應該是屬於classB,當k=6時,那麼數據樣本應該是屬於classA,當然,如果k=1的話,那麼就能確定唯一隻,但是這樣的話很容易變成異常值干擾,所以,只要距離類別選擇合適,數據樣本越大,準確度應該是增高的
KNN算法在python的中實現
python中關於knn的算法實在sklearn包下的neighbors下的KNeighborsClassifier,具體的使用案例如下:
import numpy as np
from sklearn.neighbors import KNeighborsClassifier
# 創建kNN_classifier實例
kNN_classifier = KNeighborsClassifier(n_neighbors=6)
# raw_data_x是特徵(x,y 座標),raw_data_y是標籤,0爲良性,1爲惡性
raw_data_x = [[3.393533211, 2.331273381], [3.110073483, 1.781539638], [1.343853454, 3.368312451],
[3.582294121, 4.679917921], [2.280362211, 2.866990212], [7.423436752, 4.685324231],
[5.745231231, 3.532131321], [9.172112222, 2.511113104], [7.927841231, 3.421455345],
[7.939831414, 0.791631213]]
raw_data_y = [0, 0, 0, 0, 0, 1, 1, 1, 1,1]
# 設置訓練組
X_train = np.array(raw_data_x)
y_train = np.array(raw_data_y)
# kNN_classifier做一遍fit(擬合)的過程,沒有返回值,模型就存儲在kNN_classifier實例中
fit = kNN_classifier.fit(X_train, y_train)
# KNeighborsClassifier(algorithm='auto', leaf_size=30, metric='minkowski',
# metric_params=None, n_jobs=None, n_neighbors=6, p=2,
# weights='uniform')
print(fit)
x = [8.90933607318, 3.365731514]
# kNN進行預測predict,需要傳入一個矩陣,而不能是一個數組。reshape()成一個二維數組,
# 第一個參數是1表示只有一個數據,第二個參數-1,numpy自動決定第二維度有多少
y_predict = kNN_classifier.predict(x.reshape(1,-1))
print(y_predict)
關於KNeighborsClassifier的構造方法
對於KNeighborsClassifier的方法:
# weights(權重): str or callable(自定義類型), 可選參數(默認爲 ‘uniform’)。用於預測的權重參數,可選參數如下:
#
# uniform : 統一的權重. 在每一個鄰居區域裏的點的權重都是一樣的。
# distance : 權重點等於他們距離的倒數。使用此函數,更近的鄰居對於所預測的點的影響更大。
# [callable] : 一個用戶自定義的方法,此方法接收一個距離的數組,然後返回一個相同形狀並且包含權重的數組。
# algorithm(算法): {‘auto’, ‘ball_tree’, ‘kd_tree’, ‘brute’}, 可選參數(默認爲 'auto')。計算最近鄰居用的算法:
#
# ball_tree 使用算法BallTree
# kd_tree 使用算法KDTree
# brute 使用暴力搜索
# auto 會基於傳入fit方法的內容,選擇最合適的算法。注意 : 如果傳入fit方法的輸入是稀疏的,將會重載參數設置,直接使用暴力搜索。
# leaf_size(葉子數量): int, 可選參數(默認爲 30)。傳入BallTree或者KDTree算法的葉子數量。此參數會影響構建、查詢BallTree或者KDTree的速度,以及存儲BallTree或者KDTree所需要的內存大小。此可選參數根據是否是問題所需選擇性使用。
#
# p: integer, 可選參數(默認爲 2)。用於Minkowski metric(閔可夫斯基空間)的超參數。p = 1, 相當於使用曼哈頓距離,p = 2, 相當於使用歐幾里得距離],對於任何 p ,使用的是閔可夫斯基空間。
#
# metric(矩陣): string or callable, 默認爲 ‘minkowski’。用於樹的距離矩陣。默認爲閔可夫斯基空間,如果和p=2一塊使用相當於使用標準歐幾里得矩陣. 所有可用的矩陣列表請查詢 DistanceMetric 的文檔。
#
# metric_params(矩陣參數): dict, 可選參數(默認爲 None)。給矩陣方法使用的其他的關鍵詞參數。
#
# n_jobs: int, 可選參數(默認爲 1)。用於搜索鄰居的,可並行運行的任務數量。如果爲-1, 任務數量設置爲CPU核的數量。不會影響fit
def __init__(self, n_neighbors=5,
weights='uniform', algorithm='auto', leaf_size=30,
p=2, metric='minkowski', metric_params=None, n_jobs=None,
**kwargs):
super().__init__(
n_neighbors=n_neighbors,
algorithm=algorithm,
leaf_size=leaf_size, metric=metric, p=p,
metric_params=metric_params,
n_jobs=n_jobs, **kwargs)
self.weights = _check_weights(weights)
n_neighbors: int, 可選參數(默認爲 5)。用於kneighbors查詢的默認鄰居的數量
方法 | 含義 |
---|---|
fit(X, y) | 使用X作爲訓練數據,y作爲目標值(類似於標籤)來擬合模型。 |
get_params([deep]) | 獲取估值器的參數。 |
neighbors([X, n_neighbors, return_distance]) | 查找一個或幾個點的K個鄰居。 |
kneighbors_graph([X, n_neighbors, mode]) | 計算在X數組中每個點的k鄰居的(權重)圖。 |
predict(X) | 給提供的數據預測對應的標籤。 |
predict_proba(X) | 返回測試數據X的概率估值。 |
score(X, y[, sample_weight]) | 返回給定測試數據和標籤的平均準確值。 |
set_params(**params) | 設置估值器的參數。 |