scikit-learn K近鄰法類庫使用小結

K近鄰法(KNN)原理小結這篇文章,咱們討論了KNN的原理和優缺點,這裏咱們就從實踐出發,對scikit-learn 中KNN相關的類庫使用作一個小結。主要關注於類庫調參時的一個經驗總結。javascript

1、1. scikit-learn 中KNN相關的類庫概述

    在scikit-learn 中,與近鄰法這一大類相關的類庫都在sklearn.neighbors包之中。KNN分類樹的類是KNeighborsClassifier,KNN迴歸樹的類是KNeighborsRegressor。除此以外,還有KNN的擴展,即限定半徑最近鄰分類樹的類RadiusNeighborsClassifier和限定半徑最近鄰迴歸樹的類RadiusNeighborsRegressor, 以及最近質心分類算法NearestCentroid。css

    在這些算法中,KNN分類和迴歸的類參數徹底同樣。限定半徑最近鄰法分類和迴歸的類的主要參數也和KNN基本同樣。html

    比較特別是的最近質心分類算法,因爲它是直接選擇最近質心來分類,因此僅有兩個參數,距離度量和特徵選擇距離閾值,比較簡單,所以後面就再也不專門講述最近質心分類算法的參數。java

    另外幾個在sklearn.neighbors包中但不是作分類迴歸預測的類也值得關注。kneighbors_graph類返回用KNN時和每一個樣本最近的K個訓練集樣本的位置。radius_neighbors_graph返回用限定半徑最近鄰法時和每一個樣本在限定半徑內的訓練集樣本的位置。NearestNeighbors是個大雜燴,它便可以返回用KNN時和每一個樣本最近的K個訓練集樣本的位置,也能夠返回用限定半徑最近鄰法時和每一個樣本最近的訓練集樣本的位置,經常用在聚類模型中。python

2、K近鄰法和限定半徑最近鄰法類庫參數小結

    本節對K近鄰法和限定半徑最近鄰法類庫參數作一個總結。包括KNN分類樹的類KNeighborsClassifier,KNN迴歸樹的類KNeighborsRegressor, 限定半徑最近鄰分類樹的類RadiusNeighborsClassifier和限定半徑最近鄰迴歸樹的類RadiusNeighborsRegressor。這些類的重要參數基本相同,所以咱們放到一塊兒講。git

參數
github

KNeighborsClassifier
KNeighborsRegressor
RadiusNeighborsClassifier
RadiusNeighborsRegressor

KNN中的K值n_neighbors 
K值的選擇與樣本分佈有關,通常選擇一個較小的K值,能夠經過交叉驗證來選擇一個比較優的K值,默認值是5。若是數據是三維一下的,若是數據是三維或者三維如下的,能夠經過可視化觀察來調參。 不適用於限定半徑最近鄰法

限定半徑最近鄰法中的半radius 
不適用於KNN 半徑的選擇與樣本分佈有關,能夠經過交叉驗證來選擇一個較小的半徑,儘可能保證每類訓練樣本其餘類別樣本的距離較遠,默認值是1.0。若是數據是三維或者三維如下的,能夠經過可視化觀察來調參。

近鄰權weights 

主要用於標識每一個樣本的近鄰樣本的權重,若是是KNN,就是K個近鄰樣本的權重,若是是限定半徑最近鄰,就是在距離在半徑之內的近鄰樣本的權重。能夠選擇"uniform","distance" 或者自定義權重。選擇默認的"uniform",意味着全部最近鄰樣本權重都同樣,在作預測時一視同仁。若是是"distance",則權重和距離成反比例,即距離預測目標更近的近鄰具備更高的權重,這樣在預測類別或者作迴歸時,更近的近鄰所佔的影響因子會更加大。固然,咱們也能夠自定義權重,即自定義一個函數,輸入是距離值,輸出是權重值。這樣咱們能夠本身控制不一樣的距離所對應的權重。
通常來講,若是樣本的分佈是比較成簇的,即各種樣本都在相對分開的簇中時,咱們用默認的"uniform"就能夠了,若是樣本的分佈比較亂,規律很差尋找,選擇"distance"是一個比較好的選擇。若是用"distance"發現預測的效果的仍是很差,能夠考慮自定義距離權重來調優這個參數。

KNN和限定半徑最近鄰法使用的算法algorithm 

算法一共有三種,第一種是蠻力實現,第二種是KD樹實現,第三種是球樹實現。這三種方法在K近鄰法(KNN)原理小結中都有講述,若是不熟悉能夠去複習下。對於這個參數,一共有4種可選輸入,‘brute’對應第一種蠻力實現,‘kd_tree’對應第二種KD樹實現,‘ball_tree’對應第三種的球樹實現, ‘auto’則會在上面三種算法中作權衡,選擇一個擬合最好的最優算法。須要注意的是,若是輸入樣本特徵是稀疏的時候,不管咱們選擇哪一種算法,最後scikit-learn都會去用蠻力實現‘brute’。
我的的經驗,若是樣本少特徵也少,使用默認的 ‘auto’就夠了。 若是數據量很大或者特徵也不少,用"auto"建樹時間會很長,效率不高,建議選擇KD樹實現‘kd_tree’,此時若是發現‘kd_tree’速度比較慢或者已經知道樣本分佈不是很均勻時,能夠嘗試用‘ball_tree’。而若是輸入樣本是稀疏的,不管你選擇哪一個算法最後實際運行的都是‘brute’。

中止建子樹的葉子節點閾值leaf_size

這個值控制了使用KD樹或者球樹時, 中止建子樹的葉子節點數量的閾值。這個值越小,則生成的KD樹或者球樹就越大,層數越深,建樹時間越長,反之,則生成的KD樹或者球樹會小,層數較淺,建樹時間較短。默認是30. 這個值通常依賴於樣本的數量,隨着樣本數量的增長,這個值必需要增長,不然不光建樹預測的時間長,還容易過擬合。能夠經過交叉驗證來選擇一個適中的值。
若是使用的算法是蠻力實現,則這個參數能夠忽略。

距離度量metric 

 K近鄰法和限定半徑最近鄰法類可使用的距離度量較多,通常來講默認的歐式距離(即p=2的閔可夫斯基距離)就能夠知足咱們的需求。可使用的距離度量參數有:

a) 歐式距離 「euclidean」: $ \sqrt{\sum\limits_{i=1}^{n}(x_i-y_i)^2} $算法

b) 曼哈頓距離 「manhattan」: $ \sum\limits_{i=1}^{n}|x_i-y_i| $瀏覽器

c) 切比雪夫距離「chebyshev」: $ max|x_i-y_i|  (i = 1,2,...n)$
d) 閔可夫斯基距離 「minkowski」(默認參數): $ \sqrt[p]{\sum\limits_{i=1}^{n}(|x_i-y_i|)^p} $ p=1爲曼哈頓距離, p=2爲歐式距離。微信

e) 帶權重閔可夫斯基距離 「wminkowski」: $ \sqrt[p]{\sum\limits_{i=1}^{n}(w*|x_i-y_i|)^p} $ 其中w爲特徵權重

f) 標準化歐式距離 「seuclidean」: 即對於各特徵維度作了歸一化之後的歐式距離。此時各樣本特徵維度的均值爲0,方差爲1.

g) 馬氏距離「mahalanobis」:\(\sqrt{(x-y)^TS^{-1}(x-y)}\) 其中,\(S^{-1}\)爲樣本協方差矩陣的逆矩陣。當樣本分佈獨立時, S爲單位矩陣,此時馬氏距離等同於歐式距離
還有一些其餘不是實數的距離度量,通常在KNN之類的算法用不上,這裏也就不列了。


距離度量附屬參數p
p是使用距離度量參數 metric 附屬參數,只用於閔可夫斯基距離和帶權重閔可夫斯基距離中p值的選擇,p=1爲曼哈頓距離, p=2爲歐式距離。默認爲2

距離度量其餘附屬參數metric_params
 通常都用不上,主要是用於帶權重閔可夫斯基距離的權重,以及其餘一些比較複雜的距離度量的參數。

並行處理任務數n_jobs
主要用於多核CPU時的並行處理,加快創建KNN樹和預測搜索的速度。通常用默認的-1就能夠了,即全部的CPU核都參與計算。   不適用於限定半徑最近鄰法
異常點類別選擇outlier_label 不適用於KNN  主要用於預測時,若是目標點半徑內沒有任何訓練集的樣本點時,應該標記的類別,不建議選擇默認值 none,由於這樣遇到異常點會報錯。通常設置爲訓練集裏最多樣本的類別。   不適用於限定半徑最近鄰迴歸

 

3、使用KNeighborsClassifier作分類的實例

    完整代碼見個人github: https://github.com/nickchen121/machinelearning/blob/master/classic-machine-learning/knn_classifier.ipynb

3.1 生成隨機數據

    首先,咱們生成咱們分類的數據,代碼以下:

import numpy as np
import matplotlib.pyplot as plt
%matplotlib inline
from sklearn.datasets.samples_generator import make_classification
# X爲樣本特徵,Y爲樣本類別輸出, 共1000個樣本,每一個樣本2個特徵,輸出有3個類別,沒有冗餘特徵,每一個類別一個簇
X, Y = make_classification(n_samples=1000, n_features=2, n_redundant=0,
                             n_clusters_per_class=1, n_classes=3)
plt.scatter(X[:, 0], X[:, 1], marker='o', c=Y)
plt.show()

    先看看咱們生成的數據圖以下。因爲是隨機生成,若是你也跑這段代碼,生成的隨機數據分佈會不同。下面是我某次跑出的原始數據圖。

    接着咱們用KNN來擬合模型,咱們選擇K=15,權重爲距離遠近。代碼以下:

from sklearn import neighbors
clf = neighbors.KNeighborsClassifier(n_neighbors = 15 , weights='distance')
clf.fit(X, Y)

    最後,咱們可視化一下看看咱們預測的效果如何,代碼以下:

from matplotlib.colors import ListedColormap
cmap_light = ListedColormap(['#FFAAAA', '#AAFFAA', '#AAAAFF'])
cmap_bold = ListedColormap(['#FF0000', '#00FF00', '#0000FF'])

#確認訓練集的邊界
x_min, x_max = X[:, 0].min() - 1, X[:, 0].max() + 1
y_min, y_max = X[:, 1].min() - 1, X[:, 1].max() + 1
#生成隨機數據來作測試集,而後做預測
xx, yy = np.meshgrid(np.arange(x_min, x_max, 0.02),
                         np.arange(y_min, y_max, 0.02))
Z = clf.predict(np.c_[xx.ravel(), yy.ravel()])

# 畫出測試集數據
Z = Z.reshape(xx.shape)
plt.figure()
plt.pcolormesh(xx, yy, Z, cmap=cmap_light)

# 也畫出全部的訓練集數據
plt.scatter(X[:, 0], X[:, 1], c=Y, cmap=cmap_bold)
plt.xlim(xx.min(), xx.max())
plt.ylim(yy.min(), yy.max())
plt.title("3-Class classification (k = 15, weights = 'distance')" )

    生成的圖以下,能夠看到大多數數據擬合不錯,僅有少許的異常點不在範圍內。

    以上就是使用scikit-learn的KNN相關類庫的一個總結,但願能夠幫到朋友們。

 

(歡迎轉載,轉載請註明出處。歡迎溝通交流: 微信:nickchen121)

posted @ 2019-07-19 17:57  十七歲的有德 閱讀( ...) 評論( ...) 編輯 收藏
相關文章
相關標籤/搜索