機器學習_ML_KNN_最近鄰居
tags: ML
KNN
官方連結KNN是一種惰式學習器,它不會從訓練資料集中學出判別函數,而是把訓練資料集記憶起來。
在學習過程中是沒有成本的!
三步驟:
- 選定k值和一個距離度量
- 找出k個想要分類的最相近的鄰近樣本
- 以多數決方式來指定類別標籤
根據選定的距離度量來針對某個新分類的點做判斷,多數決!
還有一種為『RadiusNeighborsClassifier』,可以設置相鄰範圍,這對數據分佈不均的資料集有較好的效果,這部份我們另篇說明。
Warning
Regarding the Nearest Neighbors algorithms, if it is found that two neighbors, neighbor k+1 and k, have identical distances but different labels, the results will depend on the ordering of the training data.
官方說明到,如果兩個鄰居具有相同權重,具相同距離但不同label的話,其結果取決於訓練資料集的順序。
Regarding the Nearest Neighbors algorithms, if it is found that two neighbors, neighbor k+1 and k, have identical distances but different labels, the results will depend on the ordering of the training data.
官方說明到,如果兩個鄰居具有相同權重,具相同距離但不同label的話,其結果取決於訓練資料集的順序。
IMPORT
from sklearn.neighbors import KNeighborsClassifier
CLASS
sklearn.neighbors.KNeighborsClassifier(n_neighbors=5,
weights='uniform', algorithm='auto',
leaf_size=30, p=2, metric='minkowski',
metric_params=None, n_jobs=1, **kwargs)
參數說明
n_neighbors
int, optional (default = 5)K值,以幾個點來決定預測點。
weights
str or callable, optional (default = ‘uniform’)uniform:預設置,相同權重
distance:愈接近的權重愈高
也可以自定義
algorithm
{‘auto’, ‘ball_tree’, ‘kd_tree’, ‘brute’}, optional計算最近鄰居的演算法
auto:學習的時候會自動選擇(一般選擇此項)
brute:暴力解
leaf_size
int, optional (default = 30)葉節點的大小,不影響結果,但影響速度以及結構樹的存儲空間。
結構樹的存儲空間需求記憶體用量為n_samples / leaf_size
一般取預設值即可。
p
integer, optional (default = 2)default 2
1_曼哈頓距離(只能直角)
2_歐氏距離
metric
string or callable, default ‘minkowski’『the distance metric to use for the tree』,樹的距離度量。
一般來說取預設值即可,如果有其它需求的話可以參考官方Distance metric
minkowski=sum(|x - y|^p)^(1/p)
metric_params
dict, optional (default = None)如果有使用其它的Distance metric,相關特殊參數可由此設置。
更多情況使用預設值即可滿足。
n_jobs
int, optional (default = 1)訓練時的cpu使用數
設置-1則火力全開
方法說明
fit(X, y)
擬合、訓練get_params([deep])
取得模型參數kneighbors([X, n_neighbors, return_distance])
找出輸入X的鄰居與距離,如果沒有給值的話會回傳訓練模型的資料。每個點的最近鄰居都是自己,所以距離都為0。
kneighbors_graph([X, n_neighbors, mode])
回傳最近鄰居的矩陣圖,1是最近點,0非最近點。predict(X)
回傳預測類別predict_proba(X)
回傳機率score(X, y[, sample_weight])
取得平均精準度(mean accuracy)set_params(**params)
設置模型參數範例
透過簡單的範例來了解部份method所產生的結果X = [[0], [1], [3], [15], [7]]
from sklearn.neighbors import NearestNeighbors
nn = NearestNeighbors(n_neighbors=2)
nn.fit(X)
a = nn.kneighbors_graph(X)
a.toarray()
第1行:建置一個資料集第2行:import套件,借用無監督式演算法
第3行:實作
第4行:擬合、訓練
第5行:回傳矩陣圖
第6行:將圖轉陣列
array([[ 1., 1., 0., 0., 0.],
[ 1., 1., 0., 0., 0.],
[ 0., 1., 1., 0., 0.],
[ 0., 0., 0., 1., 1.],
[ 0., 0., 1., 0., 1.]])
1是鄰居,0不是鄰居,自己跟自己一定是鄰居,n_neighbors設置為2,故有兩個1。最後一維來看,7跟3比跟15還要近,故7、3為1中間空了一個0。nn.kneighbors(X)
第1行:回傳兩個資料,與鄰居距離與鄰居索引(array([[ 0., 1.],
[ 0., 1.],
[ 0., 2.],
[ 0., 8.],
[ 0., 4.]]), array([[0, 1],
[1, 0],
[2, 1],
[3, 4],
[4, 2]], dtype=int64))
第一部份是鄰居間的距離,自己最近的鄰居是自己,所以第一個值是0,第二個值是距離。第二部份是自己跟鄰居的索引值,索引從0開始。
接下來,我們就可以來實作一個KNN的範例。
- 手動自己產生資料集
# 產生資料集
from sklearn.datasets.samples_generator import make_blobs
centers = [[-1, -1], [0.5, 0.5], [2, 2]]
X,y = make_blobs(n_samples=60, centers=centers, random_state=0, cluster_std=0.5)
n_samples:樣本數centers:中心點,數值會依中心點分佈
cluster_std:樣本的標準差,這影響到數值
- 資料集設置完畢之後,記得先利用可視化方式確認資料集
# 查看資料集的分佈
%matplotlib inline
import matplotlib.pyplot as plt
import numpy as np
cen = np.array(centers)
# 設置圖框大小
plt.figure(figsize=(16,9), dpi=100)
# 產生資料集散佈圖
plt.scatter(X[:, 0], X[:, 1], c=y)
# 繪製中心點
plt.scatter(cen[:, 0], cen[:, 1], s=100, marker='^', c='orange')
plt.show()
- 訓練模型
# 在沒有特殊需求情況下,預設參數就可以有不錯的效果,我們單純的設置k
from sklearn.neighbors import KNeighborsClassifier
knn = KNeighborsClassifier(n_neighbors=5)
knn.fit(X,y)
- 預測
# 自己增加一個範本
X_test = [[1.5, 1]]
y_test = knn.predict(X_test)
# 單純回傳鄰居索引,不回傳距離
neighbors = knn.kneighbors(X_test, return_distance=False)
- 查看y_test
array([1])
範本點被歸於1- 查看範本的各類別機率
array([[ 0. , 0.6, 0.4]])
有三個中心點,所以有三類,y=1的機率最高。- 可視化
%matplotlib inline
import matplotlib.pyplot as plt
import numpy as np
cen = np.array(centers)
plt.figure(figsize=(16,9), dpi=100)
plt.scatter(X[:, 0], X[:, 1], c=y)
plt.scatter(cen[:, 0], cen[:, 1], s=100, marker='^', c='orange')
# 加入預測點x
plt.scatter(X_test[0][0], X_test[0][1], marker='x', c=y_test, s=200)
# 產生於測點與鄰居的連接線
for i in neighbors[0]:
plt.plot([X[i][0], X_test[0][0]], [X[i][1], X_test[0][1]], 'k--', linewidth=0.5)
plt.show()