聚类算法:Hierarchical Clustering层次聚类
1. 層次聚類
1.1 層次聚類的原理及分類
1)層次法(Hierarchicalmethods):先計算樣本之間的距離。每次將距離最近的點合并到同一個類。然后,再計算類與類之間的距離,將距離最近的類合并為一個大類。不停的合并,直到合成了一個類。其中類與類的距離的計算方法有:最短距離法,最長距離法,中間距離法,類平均法等。比如最短距離法,將類與類的距離定義為類與類之間樣本的最短距離。
層次聚類算法根據層次分解的順序分為:自下向上和自上向下,即凝聚的層次聚類算法和分裂的層次聚類算法(agglomerative和divisive),也可以理解為自下而上法(bottom-up)和自上而下法(top-down)。
自下而上法:凝聚型層次聚類,就是一開始每個個體(object)都是一個類,然后根據linkage尋找同類,最后形成一個“類”。
自上而下法:分裂型層次聚類,就是反過來,一開始所有個體都屬于一個“類”,然后根據linkage排除異己,最后每個個體都成為一個“類”。
這兩種路方法沒有孰優孰劣之分,只是在實際應用的時候要根據數據特點以及你想要的“類”的個數,來考慮是自上而下更快還是自下而上更快。根據linkage判斷”類”的方法就是:最短距離法、最長距離法、中間距離法、類平均法等,其中類平均法往往被認為是最常用也最好用的方法,一方面因為其良好的單調性,另一方面因為其空間擴張/濃縮的程度適中。
為彌補分解與合并的不足,層次合并經常要與其它聚類方法相結合,如循環定位。
2)Hierarchical methods中比較新的算法有:
BIRCH(Balanced Iterative Reducingand Clustering Using Hierarchies利用層次方法的平衡迭代規約和聚類)主要是在數據量很大的時候使用,而且數據類型是numerical。首先利用樹的結構對對象集進行劃分,然后再利用其它聚類方法對這些聚類進行優化;
sklearn.cluster.BirchROCK(A Hierarchical ClusteringAlgorithm for Categorical Attributes)主要用在categorical的數據類型上;
Chameleon(A Hierarchical Clustering AlgorithmUsing Dynamic Modeling)里用到的linkage是kNN(k-nearest-neighbor)算法,并以此構建一個graph,Chameleon的聚類效果被認為非常強大,比BIRCH好用,但運算復雜度很高,O(n^2)。
1.2 層次聚類的流程
凝聚型層次聚類的策略是先將每個對象作為一個簇,然后合并這些原子簇為越來越大的簇,直到所有對象都在一個簇中,或者某個終結條件被滿足。絕大多數層次聚類屬于凝聚型層次聚類,它們只是在簇間相似度的定義上有所不同。 這里給出采用最小距離的凝聚層次聚類算法流程:
(1) 將每個對象看作一類,計算兩兩之間的最小距離;
(2) 將距離最小的兩個類合并成一個新類;
(3) 重新計算新類與所有類之間的距離;
(4) 重復(2)、(3),直到所有類最后合并成一類。
另外我們可以看出凝聚的層次聚類并沒有類似基本K均值的全局目標函數,沒有局部極小問題或是很難選擇初始點的問題。合并的操作往往是最終的,一旦合并兩個簇之后就不會撤銷。當然其計算存儲的代價是昂貴的。
1.3 層次聚類的優缺點、
優點:
1,距離和規則的相似度容易定義,限制少;
2,不需要預先制定聚類數;
3,可以發現類的層次關系;
4,可以聚類成其它形狀
缺點:
1,計算復雜度太高;
2,奇異值也能產生很大影響;
3,算法很可能聚類成鏈狀
1.4?聚類質量
聚類質量的評價方法,本質上,都是根據簇內和簇間的效果對比進行衡量。
(1)輪廓系數(Silhouette Coefficient)
使用輪廓系數評估聚類質量。 對于n個對象的數據集D,假設D被劃分為k個簇。對于D中的每個對象o,計算它和它所屬的簇的其他對象的平均距離a(o)。類似的,計算它和它不屬于的簇的最小平均距離b(o)。對數據集中的每個對象計算輪廓系數然后取平均值作為聚類的質量度量。輪廓系數的取值范圍是[-1,1],越靠近1代表聚類質量越好,越靠近-1代表聚類質量越差。
? ? ? ? ??
-
計算樣本i到同簇其他樣本的平均距離ai,ai越小,說明樣本i越應該被聚類到該簇。將ai 成為樣本i的簇內不相似度。
-
計算樣本i到其他某簇Cj的所有樣本的平均距離bij,稱為樣本i與簇cj的不相似度。定義為樣本i的簇間不相似度:bi=min{bi1,bi2,......bik}
-
si接近1,則說明樣本i聚類合理。
-
si接近-1,則說明樣本i更應該分類到另外的簇。
-
若si近似為0,則說明樣本i在兩個簇的邊界上。? ? ? ? ? ? ? ?
代碼:sklearn.metric庫的silhouette_score函數,silhouette_score的參數有:X、labels、metric,X為距離矩陣,labels為聚類結果,metric為度量方法。由于我們輸入的是距離矩陣,因此選擇"precomputed"。
from sklearn.metrics import silhouette_score import matplotlib.pyplot as plt silhouettteScore = [] for i in range(2,15):# 構建并訓練模型kmeans = KMeans(n_clusters = i,random_state=123).fit(iris_data)score = silhouette_score(iris_data,kmeans.labels_)silhouettteScore.append(score) plt.figure(figsize=(10,6)) plt.plot(range(2,15),silhouettteScore,linewidth=1.5, linestyle="-") plt.show()(2)Calinski-Harabasz指數
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ??
-
n:表示聚類的數目;
-
k:表示當前的類
-
trB(k):表示類間離差矩陣的跡
-
trW(k):表示類內離差矩陣的跡。
可以得出:CH越大代表著類自身越緊密,類與類之間越分散,即更優的聚類結果。
from sklearn.metrics import calinski_harabaz_score for i in range(2,7):# 構建并訓練模型kmeans = KMeans(n_clusters = i,random_state=123).fit(iris_data)score = calinski_harabaz_score(iris_data,kmeans.labels_)print('iris數據聚%d類calinski_harabaz指數為:%f'%(i,score))(3)FMI:需要真實值
from sklearn.metrics import fowlkes_mallows_score for i in range(2,7):##構建并訓練模型kmeans = KMeans(n_clusters = i,random_state=123).fit(iris_data)score = fowlkes_mallows_score(iris_target,kmeans.labels_)print('iris數據聚%d類FMI評價分值為:%f' %(i,score))2. python代碼實現
2.1 sklearn實現
參數詳解:
sklearn庫下的層次聚類是在sklearn.cluster的 AgglomerativeClustering中:
AgglomerativeClustering類的構造函數的參數有簇的個數n_clusters,連接方法linkage,連接度量選項affinity三個重要參數。下面就這三個參數進行描述。
-
簇的個數n_clusters:需要用戶指定的,按照常理來說,凝聚層次聚類是不需要指定簇的個數的,但是sklearn的這個類需要指定簇的個數。算法會根據簇的個數判斷最終的合并依據,這個參數會影響聚類質量。
-
連接方法linkage:指的是衡量簇與簇之間的遠近程度的方法。具體說來包括最小距離,最大距離和平均距離三種方式。對應于簇融合的方法,即簇間觀測點之間的最小距離作為簇的距離,簇間觀測點之間的最大距離作為簇的距離,以及簇間觀測點之間的平均距離作為簇的距離。一般說來,平均距離是一種折中的方法。
-
連接度量affinity:是一個簇間距離的計算方法,包括各種歐式空間的距離計算方法以及非歐式空間的距離計算方法。此外,該參數還可以設置為‘precomputed’,即用戶輸入計算好的距離矩陣。距離矩陣的生成方法:假設用戶有n個觀測點,那么先依次構造這n個點兩兩間的距離列表,即長度為n*(n-1)/2的距離列表,然后通過scipy.spatial.distance的dist庫的squareform函數就可以構造距離矩陣了。這種方式的好處是用戶可以使用自己定義的方法計算任意兩個觀測點的距離,然后再進行聚類。 聚類結束以后,需要對聚類質量進行評估。
實例:
from sklearn.cluster import AgglomerativeClustering import numpy as npX = [[1,2],[3,2],[4,4],[1,2],[1,3]] # 生成數據clustering = AgglomerativeClustering().fit(X) # 訓練模型clustering.labels_?
array([1, 0, 0, 1, 1])clustering.children_
array([[0, 3],[4, 5],[1, 2],[6, 7]])簡單解釋下(后面還會詳細說明):
X一共有5個樣本,那么在進行層次聚類是,這5個樣本各自一類,類別名稱是0、1、2、3、4
第一行:[0, 3]意思是類別0和類別3距離最近,首先聚成一類,并自動定義類別為5(=len(X)-1+1)
第二行:[4, 5]意思是類別4和上面聚類的新類別5距離為第二近,4、5聚成一類,類別為6(=len(X)-1+2)
第三行:[1, 2]意思是類別1、類別2距離為第三近,聚成一類,類別為7(=len(X)-1+3)
第四行:[6, 7]意思是類別6、7距離為第四近,聚成一類,類別為8(=len(X)-1+4)
因為類別5有兩個樣本,加上類別4形成類別6,有3個樣本;
類別7是類別1、2聚類形成,有兩個樣本;
類別6、7聚成一類后,類別8有5個樣本,這樣X全部樣本參與聚類,聚類完成。
這樣大家可能覺得優點亂,所以建議大家進行層次聚類是可以用下面的方法。
2.2 scipy實現
簡單介紹:
(1)linkage(y, method=’single’, metric=’euclidean’)
共包含3個參數: y是距離矩陣,可以是1維壓縮向量(距離向量),也可以是2維觀測向量(坐標矩陣)。若y是1維壓縮向量,則y必須是n個初始觀測值的組合,n是坐標矩陣中成對的觀測值。返回值:(n-1)*4的矩陣Z(后面會仔細的講解返回值各個字段的含義)
linkage方法用于計算兩個聚類簇s和t之間的距離d(s,t),這個方法的使用在層次聚類之前。當s和t形成一個新的聚類簇u時,s和t被從森林(已經形成的聚類簇群)中移除,而用新的聚類簇u來代替。當森林中只有一個聚類簇時算法停止。而這個聚類簇就成了聚類樹的根。 距離矩陣在每次迭代中都將被保存,d[i,j]對應于第i個聚類簇與第j個聚類簇之間的距離。每次迭代必須更新新形成的聚類簇之間的距離矩陣。 假定現在有|u|個初始觀測值u[0],...,u[|u|-1]在聚類簇u中,有|v|個初始對象v[0],...,v[|v|-1]在聚類簇v中。回憶s和t合并成u。讓v成為森林中的聚類簇,而不是u。
method是指計算類間距離的方法,比較常用的有3種: (1)single:最近鄰,把類與類間距離最近的作為類間距 (2)complete:最遠鄰,把類與類間距離最遠的作為類間距 (3)average:平均距離,類與類間所有pairs距離的平均 其他的method還有如weighted,centroid等等,具體可以參考:?
http://docs.scipy.org/doc/scipy/reference/generated/scipy.cluster.hierarchy.linkage.html#scipy.cluster.hierarchy.linkage
(2)fcluster(Z, t, criterion=’inconsistent’, depth=2, R=None, monocrit=None)
第一個參數Z是linkage得到的矩陣,記錄了層次聚類的層次信息; t是一個聚類的閾值-“The threshold to apply when forming flat clusters”,在實際中,感覺這個閾值的選取還是蠻重要的. 其他的參數我用的是默認的,具體可以參考:
http://docs.scipy.org/doc/scipy/reference/generated/scipy.cluster.hierarchy.fcluster.html#scipy.cluster.hierarchy.fcluster
為了跟前面sklearn進行對照,我們再來重新做一遍,順便詳細介紹下?
from scipy.cluster.hierarchy import dendrogram, linkage,fcluster from matplotlib import pyplot as plt X = [[1,2],[3,2],[4,4],[1,2],[1,3]] Z = linkage(X, 'ward') f = fcluster(Z,4,'distance') fig = plt.figure(figsize=(5, 3)) dn = dendrogram(Z) plt.show()? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ??
同時我們看下Z:numpy.ndarry。
層次聚類編碼為一個linkage矩陣。Z共有四列組成,第一字段與第二字段分別為聚類簇的編號,在初始距離前每個初始值被從0~n-1進行標識,每生成一個新的聚類簇就在此基礎上增加一對新的聚類簇進行標識,第三個字段表示前兩個聚類簇之間的距離,第四個字段表示新生成聚類簇所包含的元素的個數。
array([[0. , 3. , 0. , 2. ],[4. , 5. , 1.15470054, 3. ],[1. , 2. , 2.23606798, 2. ],[6. , 7. , 4.00832467, 5. ]])我們可以根據樹狀圖來進行分類,運用切割法進行:
樹狀圖分類判斷
想分兩類時,就從上往下數有兩根豎線時進行切割,那么所對應的豎線下面所連接的為一類
例如,左邊豎線下面鏈接的樣本有4、0、3,那么4、0、3就聚為一類,
右邊豎線相連的樣本有1、2,那么1、2就聚為一類。
想分三類時
?就從上往下數有三根豎線時進行切割,那么所對應的豎線下面所連接的為一類
例如,左邊豎線下面鏈接的樣本有4、0、3,那么4、0、3就聚為一類,
中間豎線相連的樣本有1,那么1就聚為一類,
右邊豎線相連的樣本有2,那么2就聚為一類。
?
?
?
總結
以上是生活随笔為你收集整理的聚类算法:Hierarchical Clustering层次聚类的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 五种常用的异常值检测方法(均方差、箱形图
- 下一篇: 混沌模型时间序列预测