用scikit-learn學習DBSCAN聚類

DBSCAN密度聚類算法中,咱們對DBSCAN聚類算法的原理作了總結,本文就對如何用scikit-learn來學習DBSCAN聚類作一個總結,重點講述參數的意義和須要調參的參數。html

1、scikit-learn中的DBSCAN類

    在scikit-learn中,DBSCAN算法類爲sklearn.cluster.DBSCAN。要熟練的掌握用DBSCAN類來聚類,除了對DBSCAN自己的原理有較深的理解之外,還要對最近鄰的思想有必定的理解。集合這二者,就能夠玩轉DBSCAN了。python

2、DBSCAN類重要參數

    DBSCAN類的重要參數也分爲兩類,一類是DBSCAN算法自己的參數,一類是最近鄰度量的參數,下面咱們對這些參數作一個總結。git

    1)eps: DBSCAN算法參數,即咱們的\(\epsilon\)-鄰域的距離閾值,和樣本距離超過\(\epsilon\)的樣本點不在\(\epsilon\)-鄰域內。默認值是0.5.通常須要經過在多組值裏面選擇一個合適的閾值。eps過大,則更多的點會落在覈心對象的\(\epsilon\)-鄰域,此時咱們的類別數可能會減小, 原本不該該是一類的樣本也會被劃爲一類。反之則類別數可能會增大,原本是一類的樣本卻被劃分開。github

    2)min_samples: DBSCAN算法參數,即樣本點要成爲核心對象所須要的\(\epsilon\)-鄰域的樣本數閾值。默認值是5. 通常須要經過在多組值裏面選擇一個合適的閾值。一般和eps一塊兒調參。在eps必定的狀況下,min_samples過大,則核心對象會過少,此時簇內部分原本是一類的樣本可能會被標爲噪音點,類別數也會變多。反之min_samples太小的話,則會產生大量的核心對象,可能會致使類別數過少。算法

    3)metric:最近鄰距離度量參數。可使用的距離度量較多,通常來講DBSCAN使用默認的歐式距離(即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| $dom

    c) 切比雪夫距離「chebyshev」: $ max|x_i-y_i|  (i = 1,2,...n)$ide

    d) 閔可夫斯基距離 「minkowski」: $ \sqrt[p]{\sum\limits_{i=1}^{n}(|x_i-y_i|)^p} $ p=1爲曼哈頓距離, p=2爲歐式距離。post

    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爲單位矩陣,此時馬氏距離等同於歐式距離。

  還有一些其餘不是實數的距離度量,通常在DBSCAN算法用不上,這裏也就不列了。

    4)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’。

    5)leaf_size:最近鄰搜索算法參數,爲使用KD樹或者球樹時, 中止建子樹的葉子節點數量的閾值。這個值越小,則生成的KD樹或者球樹就越大,層數越深,建樹時間越長,反之,則生成的KD樹或者球樹會小,層數較淺,建樹時間較短。默認是30. 由於這個值通常隻影響算法的運行速度和使用內存大小,所以通常狀況下能夠無論它。

    6) p: 最近鄰距離度量參數。只用於閔可夫斯基距離和帶權重閔可夫斯基距離中p值的選擇,p=1爲曼哈頓距離, p=2爲歐式距離。若是使用默認的歐式距離不須要管這個參數。

    以上就是DBSCAN類的主要參數介紹,其實須要調參的就是兩個參數eps和min_samples,這兩個值的組合對最終的聚類效果有很大的影響。

3、scikit-learn DBSCAN聚類實例

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

    首先,咱們生成一組隨機數據,爲了體現DBSCAN在非凸數據的聚類優勢,咱們生成了三簇數據,兩組是非凸的。代碼以下:

import numpy as np
import matplotlib.pyplot as plt
from sklearn import datasets
%matplotlib inline
X1, y1=datasets.make_circles(n_samples=5000, factor=.6,
                                      noise=.05)
X2, y2 = datasets.make_blobs(n_samples=1000, n_features=2, centers=[[1.2,1.2]], cluster_std=[[.1]],
               random_state=9)

X = np.concatenate((X1, X2))
plt.scatter(X[:, 0], X[:, 1], marker='o')
plt.show()

    能夠直觀看看咱們的樣本數據分佈輸出:

    首先咱們看看K-Means的聚類效果,代碼以下:

from sklearn.cluster import KMeans
y_pred = KMeans(n_clusters=3, random_state=9).fit_predict(X)
plt.scatter(X[:, 0], X[:, 1], c=y_pred)
plt.show()

    K-Means對於非凸數據集的聚類表現很差,從上面代碼輸出的聚類效果圖能夠明顯看出,輸出圖以下:

    那麼若是使用DBSCAN效果如何呢?咱們先不調參,直接用默認參數,看看聚類效果,代碼以下:

from sklearn.cluster import DBSCAN
y_pred = DBSCAN().fit_predict(X)
plt.scatter(X[:, 0], X[:, 1], c=y_pred)
plt.show()

    發現輸出讓咱們很不滿意,DBSCAN竟然認爲全部的數據都是一類!輸出效果圖以下:

    怎麼辦?看來咱們須要對DBSCAN的兩個關鍵的參數eps和min_samples進行調參!從上圖咱們能夠發現,類別數太少,咱們須要增長類別數,那麼咱們能夠減小\(\epsilon\)-鄰域的大小,默認是0.5,咱們減到0.1看看效果。代碼以下:

y_pred = DBSCAN(eps = 0.1).fit_predict(X)
plt.scatter(X[:, 0], X[:, 1], c=y_pred)
plt.show()

    對應的聚類效果圖以下:

 

    能夠看到聚類效果有了改進,至少邊上的那個簇已經被發現出來了。此時咱們須要繼續調參增長類別,有兩個方向都是能夠的,一個是繼續減小eps,另外一個是增長min_samples。咱們如今將min_samples從默認的5增長到10,代碼以下:

y_pred = DBSCAN(eps = 0.1, min_samples = 10).fit_predict(X)
plt.scatter(X[:, 0], X[:, 1], c=y_pred)
plt.show()

    輸出的效果圖以下:

 

    可見如今聚類效果基本已經可讓咱們滿意了。

    上面這個例子只是幫你們理解DBSCAN調參的一個基本思路,在實際運用中可能要考慮不少問題,以及更多的參數組合,但願這個例子能夠給你們一些啓發。

 

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

    ϵ  ϵ -鄰域ϵ  ϵ -鄰域

相關文章
相關標籤/搜索