層次聚類關鍵方法
#coding:UTF-8
#Hierarchical clustering 層次聚類
from E_distance import Euclidean_distance from yezi import yezi class bicluster: def __init__(self, vec, left=None,right=None,distance=0.0,id=None): self.left = left self.right = right #每次聚類都是一對數據,left保存其中一個數據,right保存另一個 self.vec = vec #保存兩個數據聚類后形成新的中心 self.id = id self.distance = distance def hcluster(blogwords,n) : biclusters = [ bicluster(vec = blogwords[i], id = i ) for i in range(len(blogwords)) ] distances = {} flag = None; currentclusted = -1 while(len(biclusters) > n) : #假設聚成n個類 min_val = 999999999999; #Python的無窮大應該是inf biclusters_len = len(biclusters) for i in range(biclusters_len-1) : for j in range(i + 1, biclusters_len) : if distances.get((biclusters[i].id,biclusters[j].id)) == None: distances[(biclusters[i].id,biclusters[j].id)] = Euclidean_distance(biclusters[i].vec,biclusters[j].vec) d = distances[(biclusters[i].id,biclusters[j].id)] if d < min_val : min_val = d flag = (i,j) bic1,bic2 = flag #解包bic1 = i , bic2 = j newvec = [(biclusters[bic1].vec[i] + biclusters[bic2].vec[i])/2 for i in range(len(biclusters[bic1].vec))] #形成新的類中心,平均 newbic = bicluster(newvec, left=biclusters[bic1], right=biclusters[bic2], distance=min_val, id = currentclusted) #二合一 currentclusted -= 1 del biclusters[bic2] #刪除聚成一起的兩個數據,由於這兩個數據要聚成一起 del biclusters[bic1] biclusters.append(newbic)#補回新聚類中心 clusters = [yezi(biclusters[i]) for i in range(len(biclusters))] #深度優先搜索葉子節點,用於輸出顯示 return biclusters,clusters
深度優先顯示:
def yezi(clust): if clust.left == None and clust.right == None : return [clust.id] return yezi(clust.left) + yezi(clust.right)
歐氏距離:
#Euclidean_distance from math import sqrt def Euclidean_distance(vector1,vector2): length = len(vector1) TSum = sum([pow((vector1[i] - vector2[i]),2) for i in range(len(vector1))]) SSum = sqrt(TSum) return SSum
層次聚類算法:
給定要聚類的N的對象以及N*N的距離矩陣(或者是相似性矩陣), 層次式聚類方法的基本步驟(參看S.C. Johnson in 1967)如下:
-
將每個對象歸為一類, 共得到N類, 每類僅包含一個對象. 類與類之間的距離就是它們所包含的對象之間的距離.
-
找到最接近的兩個類並合並成一類, 於是總的類數少了一個.
-
重新計算新的類與所有舊類之間的距離.
-
重復第2步和第3步, 直到最后合並成一個類為止(此類包含了N個對象).
由於層次聚類計算量巨大,所以通常不用來計算大量的數據,不過可以用層次聚類來選取K-means算法的初始類中心。
例子(不規范,只是用來顯示輸入和輸出的格式):
參考:http://www.cnblogs.com/coser/archive/2013/04/10/3013044.html