python实现一个层次聚类方法

层次聚类(Hierarchical Clustering)

一.概念

  层次聚类不需要指定聚类的数目,首先它是将数据中的每个实例看作一个类,然后将最相似的两个类合并,该过程迭代计算只到剩下一个类为止,类由两个子类构成,每个子类又由更小的两个子类构成。如下图所示:

二.合并方法

在聚类中每次迭代都将两个最近的类进行合并,这个类间的距离计算方法常用的有三种:

1.单连接聚类(Single-linkage clustering)

  在单连接聚类中,两个类间的距离定义为一个类的所有实例到另一个类的所有实例之间最短的那个距离。如上图中类A(A1,A2),B(B1,B2),C(C1,C2),A类和B类间的最短距离是A1到B1,所以A类与B类更近,所有A和B合并。

2.全连接聚类(Complete-linkage clustering)

  在全连接聚类中,两个类间的距离定义为一个类的所有实例到另一个类的所有实例之间最长的那个距离。图中A类和B类间最长距离是A2到B2,B类和C类最长距离是B1到C1,distance(B1-C1)<distance(A2-B2),所以B类和C类合并在一起。

3.平均连接聚类(Average-linkage clustering)

  在平均连接聚类中,类间的距离为一个类的所有实例到另一个类的所有实例的平均距离。

三.python实现(单连接)

  1 #!/usr/bin/python
  2 # -*- coding: utf-8 -*-
  3
  4 from queue import PriorityQueue
  5 import math
  6 import codecs
  7
  8
  9 """
 10 层次聚类
 11 """
 12 class HCluster:
 13
 14     #一列的中位数
 15     def getMedian(self,alist):
 16         tmp = list(alist)
 17         tmp.sort()
 18         alen = len(tmp)
 19         if alen % 2 == 1:
 20             return tmp[alen // 2]
 21         else:
 22             return (tmp[alen // 2] + tmp[(alen // 2) - 1]) / 2
 23
 24     #对数值型数据进行归一化,使用绝对标准分[绝对标准差->asd=sum(x-u)/len(x),x的标准分->(x-u)/绝对标准差,u是中位数]
 25     def normalize(self,column):
 26         median = self.getMedian(column)
 27         asd = sum([abs(x - median) for x in column]) / len(column)
 28         result = [(x - median) / asd for x in column]
 29         return result
 30
 31     def __init__(self,filepath):
 32         self.data={}
 33         self.counter=0
 34         self.queue=PriorityQueue()
 35         line_1=True#开头第一行
 36         with codecs.open(filepath,‘r‘,‘utf-8‘) as f:
 37             for line in f:
 38                 #第一行为描述信息
 39                 if line_1:
 40                     line_1=False
 41                     header=line.split(‘,‘)
 42                     self.cols=len(header)
 43                     self.data=[[] for i in range(self.cols)]
 44                 else:
 45                     instances=line.split(‘,‘)
 46                     toggle=0
 47                     for instance in range(self.cols):
 48                         if toggle==0:
 49                             self.data[instance].append(instances[instance])
 50                             toggle=1
 51                         else:
 52                             self.data[instance].append(float(instances[instance]))
 53         #归一化数值列
 54         for i in range(1,self.cols):
 55             self.data[i]=self.normalize(self.data[i])
 56
 57         #欧氏距离计算元素i到所有其它元素的距离,放到邻居字典中,比如i=1,j=2...,结构如i=1的邻居-》{2: ((1,2), 1.23),  3: ((1, 3), 2.3)... }
 58         #找到最近邻
 59         #基于最近邻将元素放到优先队列中
 60         #data[0]放的是label标签,data[1]和data[2]是数值型属性
 61         rows=len(self.data[0])
 62         for i in range(rows):
 63             minDistance=10000
 64             nearestNeighbor=0
 65             neighbors={}
 66             for j in range(rows):
 67                 if i!=j:
 68                     dist=self.distance(i,j)
 69                     if i<j:
 70                         pair=(i,j)
 71                     else:
 72                         pair=(j,i)
 73                     neighbors[j]=(pair,dist)
 74                     if dist<minDistance:
 75                         minDistance=dist
 76                         nearestNeighbor=j
 77             #创建最近邻对
 78             if i<nearestNeighbor:
 79                 nearestPair=(i,nearestNeighbor)
 80             else:
 81                 nearestPair=(nearestNeighbor,i)
 82             #放入优先对列中,(最近邻距离,counter,[label标签名,最近邻元组,所有邻居])
 83             self.queue.put((minDistance,self.counter,[[self.data[0][i]],nearestPair,neighbors]))
 84             self.counter+=1
 85
 86     #欧氏距离,d(x,y)=math.sqrt(sum((x-y)*(x-y)))
 87     def distance(self,i,j):
 88         sumSquares=0
 89         for k in range(1,self.cols):
 90             sumSquares+=(self.data[k][i]-self.data[k][j])**2
 91         return math.sqrt(sumSquares)
 92
 93     #聚类
 94     def cluster(self):
 95         done=False
 96         while not done:
 97             topOne=self.queue.get()
 98             nearestPair=topOne[2][1]
 99             if not self.queue.empty():
100                 nextOne=self.queue.get()
101                 nearPair=nextOne[2][1]
102                 tmp=[]
103                 #nextOne是否是topOne的最近邻,如不是继续找
104                 while nearPair!=nearestPair:
105                     tmp.append((nextOne[0],self.counter,nextOne[2]))
106                     self.counter+=1
107                     nextOne=self.queue.get()
108                     nearPair=nextOne[2][1]
109                 #重新加回Pop出的不相等最近邻的元素
110                 for item in tmp:
111                     self.queue.put(item)
112
113                 if len(topOne[2][0])==1:
114                     item1=topOne[2][0][0]
115                 else:
116                     item1=topOne[2][0]
117                 if len(nextOne[2][0])==1:
118                     item2=nextOne[2][0][0]
119                 else:
120                     item2=nextOne[2][0]
121                 #联合两个最近邻族成一个新族
122                 curCluster=(item1,item2)
123                 #下面使用单连接方法建立新族中的邻居距离元素,一:计算上面新族的最近邻。二:建立新的邻居。如果 item1和item3距离是2,item2和item3距离是4,则在新族中的距离是2
124                 minDistance=10000
125                 nearestPair=()
126                 nearestNeighbor=‘‘
127                 merged={}
128                 nNeighbors=nextOne[2][2]
129                 for key,value in topOne[2][2].items():
130                     if key in nNeighbors:
131                         if nNeighbors[key][1]<value[1]:
132                             dist=nNeighbors[key]
133                         else:
134                             dist=value
135                         if dist[1]<minDistance:
136                             minDistance=dist[1]
137                             nearestPair=dist[0]
138                             nearestNeighbor=key
139                         merged[key]=dist
140                 if merged=={}:
141                     return curCluster
142                 else:
143                     self.queue.put((minDistance,self.counter,[curCluster,nearestPair,merged]))
144                     self.counter+=1
145
146 if __name__==‘__main__‘:
147     hcluser=HCluster(‘filePath‘)
148     cluser=hcluser.cluster()
149     print(cluser)

参考:1.machine.learning.an.algorithmic.perspective.2nd.edition.

    2.a programmer‘s guide to data mining

时间: 2024-11-08 23:06:34

python实现一个层次聚类方法的相关文章

Python机器学习——Agglomerative层次聚类

层次聚类(hierarchical clustering)可在不同层次上对数据集进行划分,形成树状的聚类结构.AggregativeClustering是一种常用的层次聚类算法. ??其原理是:最初将每个对象看成一个簇,然后将这些簇根据某种规则被一步步合并,就这样不断合并直到达到预设的簇类个数.这里的关键在于:如何计算聚类簇之间的距离? ??由于每个簇就是一个集合,因此需要给出集合之间的距离.给定聚类簇Ci,CjCi,Cj,有如下三种距离: 最小距离: dmin(Ci,Cj)=minx? i∈C

挑子学习笔记:BIRCH层次聚类

转载请标明出处:http://www.cnblogs.com/tiaozistudy/p/6129425.html 本文是“挑子”在学习BIRCH算法过程中的笔记摘录,文中不乏一些个人理解,不当之处望多加指正.本人邮箱:[email protected] BIRCH(Balanced Iterative Reducing and Clustering using Hierarchies,利用层次结构的平衡迭代归约和聚类)是由T. Zhang等人[1]于1996年为大量聚类设计的一种层次聚类方法.

聚类算法:K均值、凝聚层次聚类和DBSCAN

聚类分析就仅根据在数据中发现的描述对象及其关系的信息,将数据对象分组(簇).其目标是,组内的对象相互之间是相似的,而不同组中的对象是不同的.组内相似性越大,组间差别越大,聚类就越好. 先介绍下聚类的不同类型,通常有以下几种: (1)层次的与划分的:如果允许簇具有子簇,则我们得到一个层次聚类.层次聚类是嵌套簇的集族,组织成一棵树.划分聚类简单地将数据对象划分成不重叠的子集(簇),使得每个数据对象恰在一个子集中. (2)互斥的.重叠的与模糊的:互斥的指每个对象都指派到单个簇.重叠的或是模糊聚类用来反

聚类方法简介

将物理或抽象对象的集合分组成为有类似的对象组成的多个簇的过程被称为聚类.由聚类所生成的簇是一组数据对象的集合,这些对象与同一个簇中的对象彼此相似,与其它簇中的对象相异.在许多应用中,可以将一个簇中的数据对象作为一个整体来对待. 目前在文献中存在大量的聚类算法.算法的选择取决于数据的类型.聚类的目的和应用.如果聚类分析备用作描述或探查的工具,可以对同样的数据尝试多种算法,以发现数据可能揭示的结果. 大体上,主要的聚类技术可以划分为如下几类: 1.划分方法 给定一个个对象或元组的数据库,一个划分方法

【机器学习】--层次聚类从初识到应用

一.前述 聚类就是对大量未知标注的数据集,按数据的内在相似性将数据集划分为多个类别,使类别内的数据相似度较大而类别间的数据相似度较小. 数据聚类算法可以分为结构性或者分散性,许多聚类算法在执行之前,需要指定从输入数据集中产生的分类个数. 1.分散式聚类算法,是一次性确定要产生的类别,这种算法也已应用于从下至上聚类算法. 2.结构性算法利用以前成功使用过的聚类器进行分类,而分散型算法则是一次确定所有分类. 结构性算法可以从上至下或者从下至上双向进行计算.从下至上算法从每个对象作为单独分类开始,不断

机器学习-层次聚类(划分聚类)

层次聚类(划分聚类) 聚类就是对大量未知标注的数据集,按照数据内部存在的数据特征将数据集划分为多个不同的类别,使类别内的数据比较相似,类别之间的数据相似度比较小:属于无监督学习. 算法步骤 1.初始化的k个中心点 2.为每个样本根据距离分配类别 3.更新每个类别的中心点(更新为该类别的所有样本的均值) 4.重复上面两步操作,直到达到某个中止条件 层次聚类方法对给定的数据集进行层次的分解,直到满足某种条件为止,传统的层次聚类算法主要分为两大类算法: 凝聚的层次聚类 AGNES算法==>采用自底向上

机器学习(6)之聚类算法(k-means\Canopy\层次聚类\谱聚类)

目录 1 聚类的定义 1.1 距离公式(相似度) 1.2 聚类的思想 2 K-means算法 2.1 K-means算法的思考 2.2 总结 3 二分K-Means算法 4 K-Means++算法 4.1 K-Means||算法 5 Canopy算法 5.1 应用场景 6 Mini Batch K-Means算法 7 层次聚类方法 7.1 AGNES算法中簇间距离 7.2 层次聚类优化算法 8 密度聚类 8.1 DBSCAN算法 8.1.1 基本概念 8.1.2 算法流程 8.1.3 DBSCA

初识聚类算法:K均值、凝聚层次聚类和DBSCAN

原文地址http://blog.sina.com.cn/s/blog_62186b460101ard2.html 这里只是将比较重要的部分转一下 另外还有一篇关于层次聚类的 http://blog.csdn.net/jwh_bupt/article/details/7685809 聚类分析就仅根据在数据中发现的描述对象及其关系的信息,将数据对象分组(簇).其目标是,组内的对象相互之间是相似的,而不同组中的对象是不同的.组内相似性越大,组间差别越大,聚类就越好. 先介绍下聚类的不同类型,通常有以下

Python使用MySQL数据库的方法以及一个实例

使用环境:Windows+python3.4+MySQL5.5+Navicat 一.创建连接 1.准备工作,想要使用Python操作MySQL,首先需要安装MySQL-Python的包,在Python 3.x下,该包已经改名为MySQLClient.可以使用pip方式安装: pip install MySQLClient 或者下载包文件,进行安装也可以. 2.Python使用MySQL的流程: 3.启动MySQL服务器:以管理员身份启动“cmd”,输入命令:’net start mysql‘ P