这个算法。我个人感觉有点鸡肋。最终的表达也不是特别清楚。
原理很简单,从所有的样本中选取Euclidean distance最近的两个样本,归为一类,取其平均值组成一个新样本,总样本数少1;不断的重复,最终样本数为1。这样的话就形成了一个树,每个节点要不有两个子节点,要不没有子节点。
这个算法也大概能分出来类,但是实用性我觉得不是很强。
源代码
1 from numpy import * 2 3 4 class cluster_node: 5 def __init__(self,vec,left=None,right=None,distance=0.0,id=None,count=1): 6 self.left=left 7 self.right = right 8 self.vec = vec 9 self.distance = distance 10 self.id = id 11 self.count = count 12 def L2dist(v1,v2): 13 return sqrt(sum(v1-v2)**2) 14 def L1dist(v1,v2): 15 return sum(abs(v1-v2)) 16 17 def hcluster(features,distance=L2dist): 18 distances={} 19 currentclustid=-1 20 21 clust=[cluster_node(array(features[i],id=i) for i in range(len(features)))] 22 23 while len(clust)>1: 24 lowstpiar=(0,1) 25 closest=distance(clust[0].vec,clust[1].vec) 26 27 for i in range(len(clust)): 28 for j in range(i+1,len(clust)): 29 if(clust[i].id,clust[j].id) not in distances: 30 distances[(clust[i].id,clust[j].id)]=distance(clust[i].vec,clust[j].vec) 31 d=distances[(clust[i].id,clust[j].id)] 32 if d<closest: 33 closest=d 34 lowstpiar=(i,j) 35 mergeve=[(clust[lowstpiar[0]].vec[i]+clust[lowstpiar[1]].vec[i])/2.0 for i in range(len(clust[lowstpiar[1]].vec))] 36 newcluster=cluster_node(array(mergeve),left=clust[lowstpiar[0]],right=clust[lowstpiar[1]],distance=closest,id=currentclustid) 37 currentclustid-=1 38 del clust[lowstpiar[1]] 39 del clust[lowstpiar[0]] 40 clust.append(newcluster) 41 return clust[0] 42 43 def extract_clusters(clust,dist): 44 clusters={} 45 if clust.distance<dist: 46 return [clust] 47 else: 48 cl=[] 49 cr=[] 50 if clust.left!=None: 51 cl=extract_clusters(clust.left,dist=dist) 52 if clust.right != None: 53 cr=extract_clusters(clust.right,dist=dist) 54 return cl+cr 55 56 def get_cluster_element(clust): 57 if clust.id>=0: 58 return [clust.id] 59 else: 60 cl=[] 61 cr=[] 62 if clust.left!=None: 63 cl=get_cluster_element(clust.left) 64 if clust.right != None: 65 cr=get_cluster_element(clust.right) 66 return cl+cr 67 def printclust(clust,labels=None,n=0): 68 for i in range(n):print(' ') 69 if clust.id<0: 70 print('-') 71 else: 72 if labels==None:print(clust.id) 73 else:print(labels[clust.id]) 74 75 if clust.left !=None:printclust(clust.left,labels=labels,n=n+1) 76 if clust.right != None: printclust(clust.right, labels=labels, n=n + 1) 77 78 def getheight(clust): 79 if clust.left==None and clust.right==None:return 1 80 return getheight(clust.left)+getheight(clust.right) 81 def getdepth(clust): 82 if clust.left==None and clust.right==None:return 0 83 return max(getheight(clust.left),getheight(clust.right))+clust.distance
为了节约时间,我只写了算法部分,实际应用的没写。
这个当中的递归用的不错。还有对每个节点类的定义
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:菜鸟之路——机器学习之HierarchicalClustering层次分析及个人理解 - Python技术站