用scikit learn學習DBSCAN聚類

2022-03-17 06:25:24 字數 4353 閱讀 3341

在dbscan密度聚類演算法中,我們對dbscan聚類演算法的原理做了總結,本文就對如何用scikit-learn來學習dbscan聚類做乙個總結,重點講述引數的意義和需要調參的引數。

在scikit-learn中,dbscan演算法類為sklearn.cluster.dbscan。要熟練的掌握用dbscan類來聚類,除了對dbscan本身的原理有較深的理解以外,還要對最近鄰的思想有一定的理解。集合這兩者,就可以玩轉dbscan了。

dbscan類的重要引數也分為兩類,一類是dbscan演算法本身的引數,一類是最近鄰度量的引數,下面我們對這些引數做乙個總結。

1)eps: dbscan演算法引數,即我們的$\epsilon$-鄰域的距離閾值,和樣本距離超過$\epsilon$的樣本點不在$\epsilon$-鄰域內。預設值是0.5.一般需要通過在多組值裡面選擇乙個合適的閾值。eps過大,則更多的點會落在核心物件的$\epsilon$-鄰域,此時我們的類別數可能會減少, 本來不應該是一類的樣本也會被劃為一類。反之則類別數可能會增大,本來是一類的樣本卻被劃分開。

2)min_samples: dbscan演算法引數,即樣本點要成為核心物件所需要的$\epsilon$-鄰域的樣本數閾值。預設值是5. 一般需要通過在多組值裡面選擇乙個合適的閾值。通常和eps一起調參。在eps一定的情況下,min_samples過大,則核心物件會過少,此時簇內部分本來是一類的樣本可能會被標為噪音點,類別數也會變多。反之min_samples過小的話,則會產生大量的核心物件,可能會導致類別數過少。

3)metric:最近鄰距離度量引數。可以使用的距離度量較多,一般來說dbscan使用預設的歐式距離(即p=2的閔可夫斯基距離)就可以滿足我們的需求。可以使用的距離度量引數有:

a) 歐式距離 「euclidean」: $ \sqrt^(x_i-y_i)^2} $

b) 曼哈頓距離 「manhattan」: $ \sum\limits_^|x_i-y_i| $

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

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

e) 帶權重閔可夫斯基距離 「wminkowski」: $ \sqrt[p]^(w*|x_i-y_i|)^p} $ 其中w為特徵權重

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

g) 馬氏距離「mahalanobis」:$\sqrt(x-y)}$ 其中,$s^$為樣本協方差矩陣的逆矩陣。當樣本分佈獨立時, 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,這兩個值的組合對最終的聚類效果有很大的影響。

完整**參見我的github:

首先,我們生成一組隨機資料,為了體現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()

輸出的效果圖如下:

可見現在聚類效果基本已經可以讓我們滿意了。

ϵ ϵ-鄰域

ϵ ϵ-鄰域

用scikit learn學習DBSCAN聚類

在dbscan密度聚類演算法中,我們對dbscan聚類演算法的原理做了總結,本文就對如何用scikit learn來學習dbscan聚類做乙個總結,重點講述引數的意義和需要調參的引數。在scikit learn中,dbscan演算法類為sklearn.cluster.dbscan。要熟練的掌握用db...

Scikit Learn學習筆記系列

關於python中的機器學習模組scikit learn模組的學習 使用筆記,我要整理成乙個系列。每一篇學習筆記包括原始碼解析和例項展示。這個既敦促自己不斷的學習下去,也方便日後複習。1 scikit learn學習筆記 開啟旅行 2 scikit learn學習筆記 ordinary least ...

scikit learn文件學習筆記

一 獲取資料,處理資料 coding utf 8 一 載入資料 import numpy as np import urllib url raw data urllib.urlopen url dataset np.loadtxt raw data,delimiter 讀入資料,用逗號分隔 x da...