關於聚類演算法的前面兩篇文章,已經介紹過了常用的原型聚類演算法k-measn演算法和層次聚類中的凝聚演算法,這篇文章介紹一些密度聚類演算法DBSCAN。k-means演算法需要事先指定簇的個數,而凝聚不需要指定簇的個數,這兩個演算法會將所有的樣本的劃分到簇中,無法區分出雜訊,k-means演算法的簇空間是球狀的,它們都無法很好的區分出高密度的地區。這篇文章主要介紹聚類演算法中的DBSCAN演算法,它劃分出來的簇空間可以是任意形狀的。通過這篇文章你能夠瞭解到:
1、什麼是密度聚類
2、DBSCAN演算法
3、使用DBSCAN來劃分高密度地區 一、密度聚類
密度聚類也稱"基於密度的聚類"(density-based clustering),演算法是假設聚類結果能夠通過樣本分布的緊密程度來進行簇的劃分的。密度聚類演算法是從樣本密度的角度來考慮樣本之間的可串連性,並基於可串連性不斷擴充聚類簇來獲得最終的聚類結果。 二、DBSCAN演算法
DBSCAN是一種常用的密度聚類演算法,密度被定義為指定半徑ε範圍內樣本點的數量。在DBSCAN中,每個樣本點都被賦予了一個標籤:
核心點(core point):如果在一個點周邊的指定半徑ε內,其它樣本點的數量不小於指定數量(MinPts),則稱這個點為核心點。
邊界點(border point):在一個指定半徑ε內,如果一個點的鄰居點小於MinPts,但是卻包含一個核心點,則稱這個點為邊界點。
雜訊點(noise point):除核心點和邊界點以外的點,都被稱為雜訊點。
DBSCAN演算法主要包括兩個步驟:
1、基於每個核心點或者一組相連的核心點(如果核心點的距離很近,則將其看作是相連的)形成一個單獨的簇。
2、將每個邊界點劃分到其對應核心點的簇中。
與k-means演算法相比,DBSCAN的簇空間不一定是球狀,這是DBSCAN演算法的優點之一。而且,DBSCAN聚類還可以識別並移除雜訊點,所以它不一定會將所有的樣本點都劃分到某一簇中。下面我們通過一個半月形的資料集來對比k-means聚類以及凝聚聚類和DBSCAN的聚類結果 三、使用DBSCAN來劃分高密度的資料 1、擷取資料集
使用sklearn的dataset擷取一個高密度的半月形資料集,包含2類樣本一共200個樣本點,並加入一些雜訊。
from sklearn.datasets import make_moonsimport matplotlib.pyplot as pltif __name__ == "__main__": #擷取半月形資料 #擷取200個點,並向資料中加入一些高斯雜訊 x,y = make_moons(n_samples=200,noise=0.09,random_state=0) plt.scatter(x[:,0],x[:,1],c="blue",marker="o") plt.show()
2、使用k-means演算法進行聚類
#使用k-means演算法來進行聚類 from sklearn.cluster import KMeans #初始化一個KMeans對象 km = KMeans(n_clusters=2,init="k-means++",n_init=10,max_iter=300) #訓練和預測 y_km = km.fit_predict(x) #繪製屬於1類的點 plt.scatter(x[y_km==0,0],x[y_km==0,1],c="green",marker="o",label="簇1") #繪製屬於2類的點 plt.scatter(x[y_km==1,0],x[y_km==1,1],c="red",marker="s",label="簇2") #設定標題 plt.title("K-Means聚類") plt.legend() plt.show()
通過上圖可以發現,k-means演算法並不能很好的將半月形資料分開。 3、使用凝聚聚類進行
#使用凝聚聚類 from sklearn.cluster import AgglomerativeClustering #初始化一個凝聚聚類對象,使用全串連的方式 ac = AgglomerativeClustering(n_clusters=2,affinity="euclidean",linkage="complete") #訓練和預測 ac_y = ac.fit_predict(x) # 繪製屬於1類的點 plt.scatter(x[ac_y==0,0],x[ac_y==0,1],c="green",marker="o",label="簇1") # 繪製屬於2類的點 plt.scatter(x[ac_y==1,0],x[ac_y==1,1],c="red",marker="s",label="簇2") # 設定標題 plt.title("凝聚聚類") plt.legend() plt.show()
通過結果發現,凝聚聚類也不能很好的將兩個簇進行分割。 4、使用DBSCAN演算法進行聚類
在使用DBSCAN演算法的時候,需要設定好半徑和MinPts兩個參數
#使用DBSCAN聚類 from sklearn.cluster import DBSCAN #初始化一個DBSCAN對象 ''' eps:設定半徑大小 min_samples:設定MinPts的個數 ''' dbscan = DBSCAN(eps=0.2,min_samples=5,metric="euclidean") #訓練預測 dbscan_y = dbscan.fit_predict(x) # 繪製屬於1類的點 plt.scatter(x[dbscan_y==0,0],x[dbscan_y==0,1],c="green",marker="o",label="簇1") # 繪製屬於2類的點 plt.scatter(x[dbscan_y==1,0],x[dbscan_y==1,1],c="red",marker="s",label="簇2") # 繪製雜訊點 plt.scatter(x[dbscan_y==-1,0],x[dbscan_y==-1,1],c="blue",marker="^",label="雜訊點") # 設定標題 plt.title("DBSCAN聚類") plt.legend() plt.show()
通過DBSCAN的結果可以發現,它能夠將這種高密度的資料集很好的進行劃分,相對於k-means演算法和凝聚聚類而言,它還能夠標記出雜訊點,雜訊所對應的類標是-1。
總結:在使用聚類演算法對資料進行群集的時候,隨著樣本特徵數量的增加,維度災難也會隨之遞增。特別是在使用歐式距離作為度量標準的時候。在使用DBSCAN演算法的時候,需要對兩個超參MinPts和半徑進行最佳化,如果資料集中的密度差異相對較大,找到合適的半徑和MinPts相對較難。DBSCAN除了用於群集之外,還可以通過去除雜訊。在實際應用中,對於一個給定的資料集,很難確定應該選擇哪種演算法,特別是資料的維度較高或者難以進行可視化分析的時候。一個好的聚類演算法,除了依賴演算法和其超參之外,對於選擇合適的度量標準也很重要。