聚類(Clustering)就是按照某個特定標準把一個數據集分割成不同的類或簇,使得同一個簇內的數據對象的相似性盡可能大,同時不在同一個簇中的數據對象的差異性也盡可能地大。即聚類后同一類的數據盡可能聚集到一起,不同類數據盡量分離。
主要的聚類方法可以劃分成如下幾類:劃分方法、層次方法、基于密度的方法、基于網絡的方法、基于模型的方法。
聚類和分類有什么區別
聚類(Clustering)
聚類,簡單地說就是把相似的東西分到一組,聚類的時候,我們并不關心某一類是什么,我們需要實現的目標只是把相似的東西聚到一起。一個聚類算法通常只需要知道如何計算相似度就可以開始工作了,因此聚類通常并不需要使用訓練數據進行學習,在機器學習中屬于無監督學習。
分類(Classifification)
分類,對于一個分類器,通常需要你告訴它“這個東西被分為某某類”。一般情況下,一個分類器會從它 得到的訓練集中進行學習,從而具備對未知數據進行分類的能力,在機器學習中屬于監督學習。
k-means算法
k-means是劃分方法中較經典的聚類算法之一。由于該算法的效率高,所以在對大規模數據進行聚類時被廣泛應用。目前,許多算法均圍繞著該算法進行擴展和改進。 k-means算法以k為參數,把n個對象分成k個簇,使簇內具有較高的相似度,而簇間的相似度較低。
k-means的算法流程
輸入:包含n個對象的數據和簇的數目k
(1) 隨機地選擇k個對象,它們初始地代表著k個簇的中心或者說平均值
(2) 對每個對象,根據其與各簇中心的距離,將它劃分給最近的簇
(3) 重新計算每個簇的平均值
(4) 重復步驟(2)、(3)知道簇中心不再變化
輸出:n個對象到k個簇,使平方誤差準則最小
平方誤差準則定義如下:
這里E是數據中所有對象的平方誤差的總和,p是對象,是簇的平均值,
是每個簇的對象集。該目標函數使生成的簇盡可能緊湊獨立,使用的距離度量是歐氏距離,當然也可以用其他距離度量。當平方誤差最小,簇中心不再變化,循環結束。
k-means算法的優缺點
優點:
? 簡單、速度快、適合發現球形聚類
缺點:
- k值不好選取,解決方案:可用GridSearch
- 對初始聚類中心敏感,解決方案:多初始化幾遍,選取損失函數小的
- 對噪音和異常值免疫能力差
- 不能解決非凸數據
DBSCAN
DBSCAN(Density-Based Spatial Clustering of Applications with Noise,具有噪聲的基于密度的聚類方法)是一種典型的基于密度的空間聚類算法。該算法將具有足夠密度的區域劃分為簇,并在具有噪聲的空間數據庫中發現任意形狀的簇,它將簇定義為密度相連的點的最大集合。
要理解DNSCAN算法的流程,首先要熟悉幾個概念:
-
算法需要給定兩個參數:鄰域半徑eps和密度閾值minPts。
這兩個算法參數實際可以刻畫什么叫密集——當鄰域半徑eps內的點的個數大于密度閾值minPts時,就是密集。
-
3種點的類別:核心點,邊界點和噪聲點。
鄰域半徑eps內樣本點的數量大于等于minPts的點叫做核心點。不屬于核心點但在某個核心點的鄰域內的點叫做邊界點。既不是核心點也不是邊界點的是噪聲點。
-
4種點的關系:密度直達,密度可達,密度相連,非密度相連。
如果P為核心點,Q在P的eps鄰域內,那么稱P到Q密度直達。任何核心點到其自身密度直達,密度直達不具有對稱性,如果P到Q密度直達,那么Q到P不一定密度直達。
如果存在核心點P2,P3,……,Pn,且P1到P2密度直達,P2到P3密度直達,……,P(n-1)到Pn密度直達,Pn到Q密度直達,則P1到Q密度可達。密度可達也不具有對稱性。
如果存在核心點S,使得S到P和Q都密度可達,則P和Q密度相連。密度相連具有對稱性,如果P和Q密度相連,那么Q和P也一定密度相連。密度相連的兩個點屬于同一個聚類簇。
如果兩個點不屬于密度相連關系,則兩個點非密度相連。非密度相連的兩個點屬于不同的聚類簇,或者其中存在噪聲點。
DBSCAN的算法流程
輸入:鄰域半徑eps,密度閾值minPts
(1) 掃描數據集中每點,如果某點p的eps鄰域半徑范圍內包含的點多于minPts個,則將其納入核心點列表,并將其密度直達的點形成對應的臨時聚類簇。
(2) 對于每一個臨時聚類簇,檢查其中的點是否為核心點,如果是,將該點對應的臨時聚類簇和當前臨時聚類簇合并,得到新的臨時聚類簇。重復此操作,直到當前臨時聚類簇中的每一個點要么不在核心點列表,要么其密度直達的點都已經在該臨時聚類簇,該臨時聚類簇升級成為聚類簇。最終所有臨時簇全部被處理為止。
輸出:簇的劃分結果
DBSCAN算法的優缺點
優點:
- 不需要指定簇的個數
- 可以發現任意形狀的簇
- 擅長找到離群點
缺點:
- 對于高維度數據不好處理
- 參數難以選擇
分層聚類
分層聚類(Hierarchical Clustering)是通過計算不同類別數據點間的相似度來創建一棵有層次的嵌套聚類樹。在聚類樹中,不同類別的原始數據點是樹的最低層,樹的頂層是一個聚類的根節點。創建聚類樹有自下而上合并(凝聚)和自上而下分裂兩種方法。
分層聚類的算法流程:
注:這里以自下而上凝聚的方法為例。
- 初始化,把每個樣本(假設一共N個樣本)各自歸為一類,計算每兩個類之間的距離,也就是樣本與樣本之間的相似度
- 尋找各個類之間最相近的兩個類,把他們歸為同一類
- 重新計算新生成的這個類與各個舊類之間的距離
- 重復(2)、(3)步驟,知道所有樣本都歸為一類,算法結束(當然,我們可以事先給定n_clusters參數,表示分成幾個聚類簇,當算法達到這個閾值時,迭代也會結束。)
通過這張gif圖,就能更加清楚地看出分層聚類的工作流程了。
關于如何判斷兩個類之間的距離,也就是相似度,有不少辦法,這里介紹三種:
-
Single Linkage
Single Linkage方法是將兩個組合數據點中距離最近的兩個數據點間的距離作為這兩個組合數據點的距離。這種方法容易受到極端值的影響。兩個很相似的組合數據點可能由于其中的某個極端的數據點距離較近而組合在一起。
-
Complete Linkage
complete Linkage的計算方法與Single Linkage相反,將兩個組合數據點中距離最遠的兩個數據點間的距離作為這兩個組合數據點的距離。Complete Linkage的問題也與Single Linkage相反,兩個不相似的組合數據點可能由于其中的極端值距離較遠而無法組合在一起。
-
Average Linkage
Average Linkage的計算方法是計算兩個組合數據點中的每個數據點與其他所有數據點的距離。將所有距離的均值作為兩個組合數據點間的距離。這種方法計算量比較大,但結果比前兩種方法更合理。
分層算法的優缺點
優點:
- 可以發現類的層次關系
- 能幫助解決k-means不能解決的非凸數據
缺點:
- 時間復雜度高
- 貪心算法,一步錯步步錯
聚類模型評估
評價聚類方法分簇的最佳數量和分簇效果。
1.輪廓系數(silhouette coefficient)
輪廓系數綜合考慮了內聚度和分離度兩種因素。
樣本i輪廓系數:
表示樣本i與其所在簇內其他樣本的平均距離,
表示樣本i與其他簇樣本的平均距離
聚類總的輪廓系數SC為:
輪廓系數取值范圍為[-1,1],取值越接近1則說明聚類性能越好,相反,取值越接近-1則說明聚類性能越差。輪廓系數最高的簇的數量表示簇的數量的最佳選擇。
輪廓系數使用案例
- 準備數據
# 導包
import numpy as np
from sklearn import datasets
from sklearn.cluster import KMeans
import matplotlib.pyplot as plt
from sklearn.metrics import silhouette_score
# 生成數據
X, y = datasets.make_blobs(random_state=100) # make_blobs 默認100樣本,2個特征
print(X.shape) # (100, 2)
plt.scatter(X[:, 0], X[:, 1], c=y)
生成的數據如下所示,從圖中可以看出分為3簇最好:
- 計算輪廓系數
score = []
for i in range(2, 7):
kmeans = KMeans(n_clusters = i)
kmeans.fit(X)
y_ = kmeans.predict(X) # 預測類別 == 標簽
print('當聚類類別數量是%d的時候,評價指標的輪廓系數是:'%i, silhouette_score(X, y_))
score.append(silhouette_score(X, y_))
plt.rcParams['font.sans-serif'] = ['KaiTi'] # 用來正常顯示中文標簽
plt.rcParams['axes.unicode_minus'] = False # 用來正常顯示負號
plt.rcParams['font.size'] = 18 # 設置字體大小
plt.plot(range(2,7), score)
plt.xlabel('K值')
plt.ylabel('輪廓系數')
得到如下結果:
當聚類類別數量是2的時候,評價指標的輪廓系數是: 0.6380785232724551
當聚類類別數量是3的時候,評價指標的輪廓系數是: 0.8353147343303
當聚類類別數量是4的時候,評價指標的輪廓系數是: 0.692708669793985
當聚類類別數量是5的時候,評價指標的輪廓系數是: 0.5318434130364085
當聚類類別數量是6的時候,評價指標的輪廓系數是: 0.3814586763403103
當k值為3時,輪廓系數最高,聚類效果最好。
2.蘭德系數(adjusted rand index)
如果 C 是一個真實簇的標簽分配, K 是簇的個數,我們定義a和b為:
- a,在 C 中的相同集合的與 K 中的相同集合中的元素對數
- b,在 C 中的不同集合與 K 中的不同集合中的元素對數
蘭德系數為:
其中是數據集中可能的數據對的總數。
取值范圍為[0,1],值越大意味著聚類結果與真實情況越吻合。
蘭德系數使用案例
- 準備數據
數據仍用上文輪廓系數的數據。
- 計算蘭德系數
from sklearn.metrics import adjusted_rand_score # 蘭德系數
score2 = []
for i in range(2, 7):
kmeans = KMeans(n_clusters = i)
kmeans.fit(X)
y_ = kmeans.predict(X) # 預測類別 == 標簽
print('當聚類類別數量是%d的時候,評價指標的蘭德系數是:'%i, adjusted_rand_score(y, y_))
score2.append(adjusted_rand_score(y, y_))
plt.plot(range(2,7), score2)
plt.xlabel('K值')
plt.ylabel('蘭德系數')
得到如下結果:
當聚類類別數量是2的時候,評價指標的蘭德系數是: 0.5628321618378193
當聚類類別數量是3的時候,評價指標的蘭德系數是: 1.0
當聚類類別數量是4的時候,評價指標的蘭德系數是: 0.8704389719572353
當聚類類別數量是5的時候,評價指標的蘭德系數是: 0.7187670100598754
當聚類類別數量是6的時候,評價指標的蘭德系數是: 0.5789975932695749
當k為3是,蘭德系數最大,聚類效果最好。
然而,得分不能保證隨機標簽分配(random label assignments)會獲得接近零的值(特別是如果簇的數量與樣本數量有著相同的規模排序)。
為了抵消這種影響,我們可以通過定義 adjusted Rand index 來低估(discount)隨機標簽的預期——
,如下所示: