【Scikit-Learn 中文文檔】最近鄰 - 監督學習 - 用戶指南 | ApacheCN

中文文檔: http://sklearn.apachecn.org/cn/stable/modules/neighbors.html

英文文檔: http://sklearn.apachecn.org/en/stable/modules/neighbors.html

官方文檔: http://scikit-learn.org/stable/

GitHub: https://github.com/apachecn/scikit-learn-doc-zh(覺得不錯麻煩給個 Star,我們一直在努力)

貢獻者: https://github.com/apachecn/scikit-learn-doc-zh#貢獻者

關於我們: http://www.apachecn.org/organization/209.html




1.6. 最近鄰

sklearn.neighbors 提供了 neighbors-based (基於鄰居的) 無監督學習以及監督學習方法的功能。 無監督的最近鄰是許多其它學習方法的基礎,尤其是 manifold learning (流行學習) 和 spectral clustering (譜聚類)。 受監督的 neighbors-based (基於鄰居的) 學習分爲兩種: classification (分類)針對的是具有離散標籤的數據,regression (迴歸)針對的是具有連續標籤的數據。

最近鄰方法的原理是從訓練樣本中找到與新點在距離上最近的預定數量的幾個點,並從這些點中預測標籤。 這些點的數量可以是用戶自定義的常量(K-最近鄰學習), 或是基於當前點的局部密度(基於半徑的最近鄰學習)。距離通常可以通過任何方式來度量: standard Euclidean distance(標準歐式距離)是最常見的選擇。Neighbors-based(基於鄰居的)方法被稱爲 非泛化 機器學習方法, 因爲它們只是簡單地”考慮”其所有的訓練數據(正因如此可能需要加速, 將其轉換爲一個快速索引結構,如 Ball Tree 或 KD Tree)。

儘管它很簡單,但最近鄰算法已經成功地適用於很多的分類和迴歸問題,例如手寫數字或衛星圖像的場景。 作爲一個 non-parametric(非參數化)方法,它經常成功地應用於決策邊界非常不規則的情景下。

sklearn.neighbors 可以處理 Numpy 數組或 scipy.sparse 矩陣作爲其輸入。 對於密集矩陣,大多數可能距離的矩陣都是支持的。對於稀疏矩陣,任何 Minkowski 矩陣都支持被搜索。

許多學習方法都是依賴最近鄰作爲核心。 一個例子是 核密度估計 , 在 密度估計 章節中有更深入的討論。

1.6.1. 無監督最近鄰

NearestNeighbors (最近鄰)實現了 unsupervised nearest neighbors learning(無監督的最近鄰學習)。 它爲三種不同的最近鄰算法提供統一的接口:BallTreeKDTree, 還有基於 sklearn.metrics.pairwise 的 brute-force 算法。選擇算法時可通過關鍵字 'algorithm' 來控制, 並指定爲 ['auto', 'ball_tree', 'kd_tree', 'brute'] 其中的一個即可。當默認值設置爲 'auto' 時,算法會嘗試從訓練數據中確定最佳方法。有關上述每個選項的優缺點,參見 `Nearest Neighbor Algorithms`_ 。

Warning

   

關於最近鄰算法,如果鄰居 k+1 和鄰居 k 具有相同的距離,但具有不同的標籤, 結果將取決於訓練數據的順序。

1.6.1.1. 找到最近鄰

爲了完成找到兩組數據集中最近鄰點的簡單任務, 可以使用 sklearn.neighbors 中的無監督算法:

>>>
>>> from sklearn.neighbors import NearestNeighbors
>>> import numpy as np
>>> X = np.array([[-1, -1], [-2, -1], [-3, -2], [1, 1], [2, 1], [3, 2]])
>>> nbrs = NearestNeighbors(n_neighbors=2, algorithm='ball_tree').fit(X)
>>> distances, indices = nbrs.kneighbors(X)
>>> indices                                           
array([[0, 1],
       [1, 0],
       [2, 1],
       [3, 4],
       [4, 3],
       [5, 4]]...)
>>> distances
array([[ 0.        ,  1.        ],
       [ 0.        ,  1.        ],
       [ 0.        ,  1.41421356],
       [ 0.        ,  1.        ],
       [ 0.        ,  1.        ],
       [ 0.        ,  1.41421356]])

因爲查詢集匹配訓練集,每個點的最近鄰點是其自身,距離爲0。

還可以有效地生成一個稀疏圖來標識相連點之間的連接情況:

>>>
>>> nbrs.kneighbors_graph(X).toarray()
array([[ 1.,  1.,  0.,  0.,  0.,  0.],
       [ 1.,  1.,  0.,  0.,  0.,  0.],
       [ 0.,  1.,  1.,  0.,  0.,  0.],
       [ 0.,  0.,  0.,  1.,  1.,  0.],
       [ 0.,  0.,  0.,  1.,  1.,  0.],
       [ 0.,  0.,  0.,  0.,  1.,  1.]])

我們的數據集是結構化的,因此附近索引順序的點就在參數空間附近,從而生成了近似 K-nearest neighbors(K-近鄰)的塊對角矩陣。 這種稀疏圖在各種情況下都很有用,它利用點之間的空間關係進行無監督學習:特別地可參見 sklearn.manifold.Isomapsklearn.manifold.LocallyLinearEmbedding, 和 sklearn.cluster.SpectralClustering

1.6.1.2. KDTree 和 BallTree 類

我們可以使用 KDTree 或 BallTree 其中一個類來找最近鄰。 這是上文使用過的 NearestNeighbors 類所包含的功能。KDTree 和 BallTree 具有相同的接口; 我們將在這裏展示使用 KDTree 的例子:

>>>
>>> from sklearn.neighbors import KDTree
>>> import numpy as np
>>> X = np.array([[-1, -1], [-2, -1], [-3, -2], [1, 1], [2, 1], [3, 2]])
>>> kdt = KDTree(X, leaf_size=30, metric='euclidean')
>>> kdt.query(X, k=2, return_distance=False)          
array([[0, 1],
       [1, 0],
       [2, 1],
       [3, 4],
       [4, 3],
       [5, 4]]...)

對於近鄰搜索中選項的更多信息,包括各種度量距離的查詢策略的說明等,請參閱 KDTree 和 BallTree 類文檔。 關於可用度量距離的列表,請參閱 DistanceMetric 類。

1.6.2. 最近鄰分類

最近鄰分類屬於基於樣本的學習或非泛化學習:它不會去構造一個泛化的內部模型,而是簡單地存儲訓練數據的實例。 分類是由每個點的最近鄰的簡單多數投票中計算得到的:一個查詢點的數據類型是由它最近鄰點中最具代表性的數據類型來決定的。

scikit-learn 實現了兩種不同的最近鄰分類器:KNeighborsClassifier 基於每個查詢點的 k 個最近鄰實現,
其中 k 是用戶指定的整數值。RadiusNeighborsClassifier 基於每個查詢點的固定半徑 r 內的鄰居數量實現, 其中 r 是用戶指定的浮點數值。
k -鄰居分類是 KNeighborsClassifier 下的兩種技術中比較常用的一種。k 值的最佳選擇是高度數據依賴的:

通常較大的 k 是會抑制噪聲的影響,但是使得分類界限不明顯。

如果數據是不均勻採樣的,那麼 RadiusNeighborsClassifier 中的基於半徑的近鄰分類可能是更好的選擇。

用戶指定一個固定半徑 r,使得稀疏鄰居中的點使用較少的最近鄰來分類。

對於高維參數空間,這個方法會由於所謂的“維度懲罰”而變得不那麼有效。

基本的最近鄰分類使用統一的權重:分配給查詢點的值是從最近鄰的簡單多數投票中計算出來的。 在某些環境下,最好對鄰居進行加權,使得近鄰更有利於擬合。可以通過 weights 關鍵字來實現。

默認值 weights = 'uniform' 爲每個近鄰分配統一的權重。而 weights = 'distance' 分配權重與查詢點的距離成反比。 或者,用戶可以自定義一個距離函數用來計算權重。

target: ../auto_examples/neighbors/plot_classification.html
scale: 50
target: ../auto_examples/neighbors/plot_classification.html
scale: 50

classification_1 classification_2

示例:

1.6.3. 最近鄰迴歸

最近鄰迴歸是用在數據標籤爲連續變量,而不是離散變量的情況下。分配給查詢點的標籤是由它的最近鄰標籤的均值計算而來的。

scikit-learn 實現了兩種不同的最近鄰迴歸:KNeighborsRegressor 基於每個查詢點的 k 個最近鄰實現,

其中 k 是用戶指定的整數值。RadiusNeighborsRegressor 基於每個查詢點的固定半徑 r 內的鄰居數量實現, 其中 r 是用戶指定的浮點數值。

在某些環境下,增加權重可能是有利的,使得附近點對於迴歸所作出的貢獻多於遠處點。 這可以通過 weights 關鍵字來實現。默認值 weights = 'uniform' 爲所有點分配同等權重。

而 weights = 'distance' 分配的權重與查詢點距離呈反比。 或者,用戶可以自定義一個距離函數用來計算權重。

../_images/sphx_glr_plot_regression_0011.png
target:

../auto_examples/neighbors/plot_regression.html :align: center

scale: 75

使用多輸出的最近鄰進行迴歸分析 Face completion with a multi-output estimators

在這個示例中,輸入 X 是臉上半部分像素,輸出 Y 是臉下半部分像素。

modules/../auto_examples/images/sphx_glr_plot_multioutput_face_completion_001.png
target:

../auto_examples/plot_multioutput_face_completion.html :scale: 75

align: center

示例:

1.6.4. 最近鄰算法

1.6.4.1. 暴力計算

最近鄰的快速計算是機器學習中一個活躍的研究領域。最簡單的近鄰搜索涉及數據集中所有成對點之間距離的暴力計算: 對於 D 維度中的 N 個樣本來說, 這個方法的範圍是 O[D N^2]。 對於小數據樣本,高效的暴力近鄰搜索是非常有競爭力的。 然而,隨着樣本數 N 的增長,暴力方法很快變得不行了。在 sklearn.neighbors 類中, 暴力近鄰搜索通過關鍵字 algorithm = 'brute' 來指定,並通過 sklearn.metrics.pairwise 中的例程來進行計算。

1.6.4.2. K-D 樹

爲了解決效率低下的暴力計算方法,已經發明瞭大量的基於樹的數據結構。總的來說, 這些結構試圖通過有效地編碼樣本的 aggregate distance (聚合距離) 信息來減少所需的距離計算量。 基本思想是,若 A 點距離 B 點非常遠,B 點距離 C 點非常近,

可知 A 點與 C 點很遙遠,不需要明確計算它們的距離

通過這樣的方式,近鄰搜索的計算成本可以降低爲 O[D N \log(N)] 或更低。 這是對於暴力搜索在大樣本數 large N 中表現的顯著改善。

利用這種聚合信息的早期方法是 KD tree 數據結構(* K-dimensional tree* 的簡寫),

它將二維 Quad-trees 和三維 *Oct-trees 推廣到任意數量的維度. KD 樹是二叉樹結構, 它沿着數據軸遞歸地劃分參數空間, 將其劃分成嵌套的原點區域, 數據點被歸檔到其中. KD 樹的構造非常快:因爲只能沿數據軸執行分區, 無需計算 D-dimensional 距離.

一旦構建完成, 查詢點的最近鄰可以僅使用 O[\log(N)] 距離計算來確定.
雖然 KD 樹的方法對於低維度 (D < 20) 近鄰搜索非常快, 當 D 增長到很大時,
效率開始降低: 這就是所謂的 “維度災難” 的一種體現. 在 scikit-learn 中, KD 樹近鄰搜索可以使用關鍵字 algorithm = 'kd_tree' 來指定,

並且使用類 KDTree 來計算.

References:

1.6.4.3. Ball 樹

爲了解決 KD 樹在高維上效率低下的問題, 開發了 ball 樹 數據結構. 其中 KD 樹沿笛卡爾軸分割數據, ball 樹在沿着一系列的 hyper-spheres 來分割數據. 通過這種方法構建的樹要比 KD 樹消耗更多的時間, 但是這種數據結構對於高結構化的數據是非常有效的, 即使在高緯度上也是一樣.

ball 樹將數據遞歸地劃分爲由質心 C 和半徑 r 定義的節點,
使得節點中的每個點位於由 r 和 C 定義的 hyper-sphere 內. 通過使用 triangle inequality(三角不等式) 減少近鄰搜索的候選點數:

|x+y| \leq |x| + |y|

通過這種設置, 測試點和質心之間的單一距離計算足以確定距節點內所有點的距離的下限和上限. 由於 ball 樹節點的球形幾何, 它可以在高維度上執行 KD-tree, 儘管實際的性能高度依賴於訓練數據的結構. 在 scikit-learn 中, 基於 ball 樹的近鄰搜索可以使用關鍵字 algorithm = 'ball_tree' 來指定, 並且使用類 sklearn.neighbors.BallTree 來計算. 或者, 用戶可以直接使用 BallTree 類.

參考:

1.6.4.4. 最近鄰算法的選擇

對於給定數據集的最優算法是一個複雜的選擇, 並且取決於多個因素:

  • 樣本數量 N (i.e. n_samples) 和維度 D (例如. n_features).

    • Brute force 查詢時間增長爲 O[D N]

    • Ball tree 查詢時間大約增長 O[D \log(N)]

    • KD tree 查詢時間 D 的變化是很難精確描述的.

      對於較小的 D (小於20) 的成本大約是 O[D\log(N)], 並且 KD 樹更加有效.

      對於較大的 D 成本的增加接近 O[DN], 由於樹結構引起的開銷會導致查詢效率比暴力還要低.

    對於小數據集 (N 小於30), \log(N) 相當於 N, 暴力算法比基於樹的算法更加有效.

    KDTree 和 BallTree 通過提供一個 leaf size 參數來解決這個問題:

    這控制了查詢切換到暴力計算樣本數量. 使得兩種算法的效率都能接近於對較小的 N 的暴力計算的效率.

    • 數據結構: 數據的 intrinsic dimensionality (本徵維數) 和/或數據的 sparsity (稀疏度).

    本徵維數是指數據所在的流形的維數 d \le D, 在參數空間可以是線性或非線性的. 稀疏度指的是數據填充參數空間的程度(這與“稀疏”矩陣中使用的概念不同, 數據矩陣可能沒有零項, 但是從這個意義上來講,它的 structure 仍然是 “稀疏” 的)。

    • Brute force 查詢時間與數據結構保持一致。
    • Ball tree 和 KD tree 的數據結構對查詢時間影響很大. 一般地, 小維度的 sparser (稀疏) 數據會使查詢更快. 因爲 KD 樹的內部表現形式是與參數軸對齊的, 對於任意的結構化數據它通常不會表現的像 ball tree 那樣好.

    在機器學習中往往使用的數據集是非機構化的, 而且非常適合基於樹結構的查詢。

  • 近鄰數 k 請求 query point(查詢點).

    • Brute force 查詢時間幾乎不受 k 值的影響.
    • Ball tree 和 KD tree 的查詢時間會隨着 k 的增加而變慢. 這是由於兩個影響: 首先, k 的值越大在參數空間中搜索的部分就越大. 其次, 使用 k > 1 進行樹的遍歷時, 需要對內部進行排序.

    當 k 大於 N, 在基於樹的查詢中修剪樹枝的能力是減弱的. 在這種情況下, 暴力查詢會更加有效.

    • query points(查詢點)數. ball tree 和 KD Tree 都需要一個構建階段. 在許多查詢中,這種結構的成本可以忽略不計。 如果只執行少量的查詢, 可是構建成本卻佔總成本的很大一部分. 如果僅需查詢很少的點, 暴力方法會比基於樹的方法更好.

    一般地, algorithm = 'auto' 選擇 'kd_tree' 如果 k < N/2

並且 'effective_metric_' 在 'kd_tree' 的列表 'VALID_METRICS' 中. 它選擇 'ball_tree' 如果 k < N/2 並且'effective_metric_' 在 'ball_tree' 的列表 'VALID_METRICS' 中. 它選擇 'brute' 如果 k < N/2 並且'effective_metric_' 不在 'kd_tree' 或 'ball_tree' 的列表 'VALID_METRICS' 中. 它選擇 'brute' 如果 k >= N/2.

這種選擇基於以下假設: 查詢點的數量與訓練點的數量至少相同, 並且 leaf_size 接近其默認值 30.

1.6.4.5. leaf_size 的影響

如上所述, 對於小樣本暴力搜索是比基於數的搜索更有效的方法. 這一事實在 ball 樹和 KD 樹中被解釋爲在葉節點內部切換到蠻力搜索. 該開關的級別可以使用參數 leaf_size 來指定. 這個參數選擇有很多的效果:

構造時間
更大的 leaf_size 會導致更快的樹構建時間, 因爲需要創建更少的節點.
查詢時間
一個大或小的 leaf_size 可能會導致次優查詢成本. 當 leaf_size 接近 1 時, 遍歷節點所涉及的開銷大大減慢了查詢時間. 當 leaf_size, 接近訓練集的大小,查詢變得本質上是暴力的. 這些之間的一個很好的妥協是 leaf_size = 30, 這是該參數的默認值.
內存
針對 BallTree 所需的存儲空間近似於 1 / leaf_size 乘以訓練集的大小.

leaf_size 不被 brute force queries(暴力查詢)所引用.

1.6.5. 最近質心分類

該 NearestCentroid 分類器是一個簡單的算法, 它表示每個類都通過其成員的質心組成. 實際上, 這使得它類似於 sklearn.KMeans 算法的標籤更新階段. 它也沒有參數選擇, 使其成爲良好的基準分類器. 然而,它確實受到非凸類的影響,而且當類有顯著不同的方差時,假設所有維度的方差都是相等的。 對於沒有做出這個假設的更復雜的方法, 請參閱線性判別分析 (sklearn.discriminant_analysis.LinearDiscriminantAnalysis) 和二次判別分析 (sklearn.discriminant_analysis.QuadraticDiscriminantAnalysis). 默認的 NearestCentroid 用法示例如下:

>>>
>>> from sklearn.neighbors.nearest_centroid import NearestCentroid
>>> import numpy as np
>>> X = np.array([[-1, -1], [-2, -1], [-3, -2], [1, 1], [2, 1], [3, 2]])
>>> y = np.array([1, 1, 1, 2, 2, 2])
>>> clf = NearestCentroid()
>>> clf.fit(X, y)
NearestCentroid(metric='euclidean', shrink_threshold=None)
>>> print(clf.predict([[-0.8, -1]]))
[1]

1.6.5.1. 最近縮小質心

該 NearestCentroid 分類器有一個 shrink_threshold 參數, 它實現了 nearest shrunken centroid 分類器. 實際上, 每個質心的每個特徵的值除以該特徵的類中的方差. 然後通過 shrink_threshold 來減小特徵值. 最值得注意的是, 如果特定特徵值與零相交, 則將其設置爲零. 實際上, 這將從影響的分類上刪除該特徵. 這是有用的, 例如, 去除噪聲特徵.

在以下例子中, 使用一個較小的 shrink 閥值將模型的準確度從 0.81 提高到 0.82.

target: ../auto_examples/neighbors/plot_nearest_centroid.html
scale: 50
target: ../auto_examples/neighbors/plot_nearest_centroid.html
scale: 50

nearest_centroid_1 nearest_centroid_2

例子:




中文文檔: http://sklearn.apachecn.org/cn/stable/modules/neighbors.html

英文文檔: http://sklearn.apachecn.org/en/stable/modules/neighbors.html

官方文檔: http://scikit-learn.org/stable/

GitHub: https://github.com/apachecn/scikit-learn-doc-zh(覺得不錯麻煩給個 Star,我們一直在努力)

貢獻者: https://github.com/apachecn/scikit-learn-doc-zh#貢獻者

關於我們: http://www.apachecn.org/organization/209.html

有興趣的們也可以和我們一起來維護,持續更新中 。。。

機器學習交流羣: 629470233

發佈了34 篇原創文章 · 獲贊 5 · 訪問量 3萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章