1. 程式人生 > >聚類演算法(三)——基於密度的聚類演算法(以 DBSCAN 為例)

聚類演算法(三)——基於密度的聚類演算法(以 DBSCAN 為例)

      上一篇部落格提到 K-kmeans 演算法存在好幾個缺陷,其中之一就是該演算法無法聚類哪些非凸的資料集,也就是說,K-means 聚類的形狀一般只能是球狀的,不能推廣到任意的形狀。本文介紹一種基於密度的聚類方法,可以聚類任意的形狀。

      基於密度的聚類是根據樣本的密度分佈來進行聚類。通常情況下,密度聚類從樣本密度的角度出來,來考查樣本之間的可連線性,並基於可連線樣本不斷擴充套件聚類簇,以獲得最終的聚類結果。其中最著名的演算法就是 DBSCAN 演算法

DBSCAN 演算法有兩個引數:半徑 eps 和密度閾值 MinPts,具體步驟為:

1、以每一個數據點 xi 為圓心,以 eps 為半徑畫一個圓圈。這個圓圈被稱為 xi 的 eps 鄰域

2、對這個圓圈內包含的點進行計數。如果一個圓圈裡面的點的數目超過了密度閾值 MinPts,那麼將該圓圈的圓心記為核心點,又稱核心物件。如果某個點的 eps 鄰域內點的個數小於密度閾值但是落在核心點的鄰域內,則稱該點為邊界點。既不是核心點也不是邊界點的點,就是噪聲點。

3、核心點 xi 的 eps 鄰域內的所有的點,都是 xi 的直接密度直達。如果 xj 由 xi 密度直達,xk 由 xj 密度直達。。。xn 由 xk 密度直達,那麼,xn 由 xi 密度可達。這個性質說明了由密度直達的傳遞性,可以推匯出密度可達。

4、如果對於 xk,使 xi 和 xj 都可以由 xk 密度可達,那麼,就稱 xi 和 xj 密度相連。將密度相連的點連線在一起,就形成了我們的聚類簇。

      用更通俗易懂的話描述就是如果一個點的 eps 鄰域內的點的總數小於閾值,那麼該點就是低密度點。如果大於閾值,就是低密度點。如果一個高密度點在另外一個高密度點的鄰域內,就直接把這兩個高密度點相連,這是核心點。如果一個低密度點在高密度點的鄰域內,就將低密度點連在距離它最近的高密度點上,這是邊界點。不在任何高密度點的 eps  鄰域內的低密度點,就是異常點。

      周志華《機器學習》書上給的虛擬碼如下。

公式性有點強,用語義表達演算法的偽碼如下:

1、根據 eps 鄰域和密度閾值 MinPts ,判斷一個點是核心點、邊界點或者離群點。並將離群點刪除

2、如果核心點之間的距離小於 MinPts ,就將兩個核心點連線在一起。這樣就形成了若干組簇

3、將邊界點分配到距離它最近的核心點範圍內

4、形成最終的聚類結果

DBSCAN 演算法評價及改進

DBSCAN優點:

1、對噪聲不敏感。這是因為該演算法能夠較好地判斷離群點,並且即使錯判離群點,對最終的聚類結果也沒什麼影響

2、能發現任意形狀的簇。這是因為DBSCAN 是靠不斷連線鄰域呢高密度點來發現簇的,只需要定義鄰域大小和密度閾值,因此可以發現不同形狀,不同大小的簇

DBSCAN 缺點:

1、對兩個引數的設定敏感,即圈的半徑 eps 、閾值 MinPts。

2、DBSCAN 使用固定的引數識別聚類。顯然,當聚類的稀疏程度不同,聚類效果也有很大不同。即資料密度不均勻時,很難使用該演算法

3、如果資料樣本集越大,收斂時間越長。此時可以使用 KD 樹優化

Python  程式碼:


from sklearn.datasets.samples_generator import make_circles
import matplotlib.pyplot as plt
 
import time
from sklearn.cluster import KMeans
 
from sklearn.cluster import DBSCAN
 
X,y_true = make_circles(n_samples=1000,noise=0.15) #這是一個圓環形狀的
 
plt.scatter(X[:,0],X[:,1],c=y_true)
plt.show()
 

#DBSCAN 演算法
t0 = time.time()
dbscan = DBSCAN(eps=.1,min_samples=6).fit(X)  # 該演算法對應的兩個引數
t = time.time()-t0
plt.scatter(X[:, 0], X[:, 1], c=dbscan.labels_)
plt.title('time : %f'%t)
plt.show()

初始資料點分佈是這樣的:

密度閾值均取 6,eps 分別為 0.01,0.05,0.2,0.8時的聚類效果

來來來,你再看看 K-means 的聚類效果,對於非凸的資料聚類效果就是這個樣子。。。

du

拓展閱讀:

1、為了解決 DBSCAN 很難聚類不同密度的簇,目前已經有很多新的方法被髮明出來,比如OPTICS(Ordering points to identify the clustering structure)將鄰域點按照密度大小進行排序,再用視覺化的方法來發現不同密度的簇

2、2014年Science雜誌刊登了一種基於密度峰值的演算法DP(Clustering by fast search and find of density peaks),也是採用視覺化的方法來幫助查詢不同密度的簇。其思想為每個簇都有個最大密度點為簇中心,每個簇中心都吸引並連線其周圍密度較低的點,且不同的簇中心點都相對較遠。為實現這個思想,它首先計算每個點的密度大小(也是數多少點在鄰域eps-neigbourhood內),然後再計算每個點到其最近的且比它密度高的點的距離。這樣對每個點我們都有兩個屬性值,一個是其本身密度值,一個是其到比它密度高的最近點的距離值。對這兩個屬性我們可以生成一個2維圖表(決策圖),那麼在右上角的幾個點就可以代表不同的簇的中心了,即密度高且離其他簇中心較遠。然後我們可以把其他的點逐步連線到離其最近的且比它密度高的點,直到最後連到某個簇中心點為止。這樣所有共享一個簇中心的點都屬於一個簇,而離其他點較遠且密度很低的點就是異常點了。由於這個方法是基於相對距離和相對密度來連線點的,所以其可以發現不同密度的簇。DP的缺陷就在於每個簇必須有個最大密度點作為簇中心點,如果一個簇的密度分佈均與或者一個簇有多個密度高的點,其就會把某些簇分開成幾個子簇。另外DP需要使用者指定有多少個簇,在實際操作的時候需要不斷嘗試調整。

話說,一個聚類演算法就可以發 Science 了嗎????哪位大佬幫我解釋下