python实现层次聚类

python实现层次聚类 | 沙湖王

python实现层次聚类

    昨晚到现在一直在研究层次聚类的问题。scipy包含了一些层次聚类的包和函数,但是它的文档实在太坑爹了,http://docs.scipy.org/doc/scipy/reference/cluster.hierarchy.html 这个就是scipy实现层次聚类的包。我感觉还没有完全弄明白它的意思。http://math.stanford.edu/~muellner/fastcluster.html fastcluster 则好多了,它提供的东西没有scipy多,但是它做层次聚类已经够了,而且它的速度也比scipy快,还和scipy是兼容的。http://www2.warwick.ac.uk/fac/sci/sbdtc/people/students/2010/jason_piper/code/ 这篇文章提到的例子就是fastcluster的使用。

 

   http://home.dei.polimi.it/matteucc/Clustering/tutorial_html/hierarchical.html 这篇文章是很好的层次聚类例子。文章中的

 
BA
FI
MI
NA
RM
TO
BA
0
662
877
255
412
996
FI
662
0
295
468
268
400
MI
877
295
0
754
564
138
NA
255
468
754
0
219
869
RM
412
268
564
219
0
669
TO
996
400
138
869
669
0
 

这是一个距离矩阵。不管是scipy还是fastcluster,都有一个计算距离矩阵的步骤(也可以不用)。距离矩阵是冗余的,因为它是对称的。scipy里面的文档好多的关于数学上的英文,让我都搞糊涂了。distance = spatial.distance.pdist(data),这段代码里,data是一个矩阵,但不是距离矩阵,而是如http://www.shahuwang.com/?p=952 这篇文章中用到的数据形式,而最后算出来的distance只是一个数组,并不是矩阵,而且是一维数组,这是为什么呢?仔细看上面的那个矩阵,就知道我们只需要记录对角线上或者下面的一部分就可以了。废话不说,来看最简单的一个层次聚类实现(我现在主要将scipy的,fastcluster的使用几乎一样):

1
2
from scipy.cluster.hierarchy import fclusterdata
fclusterdata(matData,t=0.99,criterion='inconsistent',metric='euclidean',method='average',R=None)#这个不需要计算linkage就能直接出结果了

这里用到的matData来自于:http://www.shahuwang.com/?p=952 用到的数据,是矩阵形式的。输出的结果如下:

array([15, 19, 20, 26, 23, 10, 26, 23, 18, 21, 20, 22, 10, 20,  1, 18, 11,
        8,  4, 18, 21, 29, 25, 17, 18, 20, 24, 23,  3, 19, 12, 13, 15,  9,
       18, 25, 16, 28,  5, 17, 25, 17,  1, 15,  7,  4, 14,  6, 20,  2,  4,
        3,  9,  5,  2, 23,  1,  9, 25, 15, 23, 27, 16, 11, 22, 20, 12])

结果的意思,就是说我的矩阵的第一个数据现在被分到了第15个类中,后面的也都是这个意思,自己再整理一下,就能输出美观直观的结果了。下面主要来讲一下fclusterdata里面的参数的意思:

matData,这是要聚类的数据,t是一个阈值,小于1大于0,你可以根据输出结果来设置这个阈值。criterion,是一个标准,它主要是确定形成最后结果(如上面的那个array)需要满足什么条件,这个主要和 t 这个阈值进行合作。

http://docs.scipy.org/doc/scipy/reference/generated/scipy.cluster.hierarchy.fcluster.html#scipy.cluster.hierarchy.fcluster 这里有比较详细的说明,不过貌似我这里就inconsistent能有比较好的结果。metric则是设置两个点之间的距离用什么方式计算,我这里的是欧几里得距离,详细可看维基百科的内容:http://en.wikipedia.org/wiki/Hierarchical_clustering  method则是计算两个簇直接满足什么条件就能合并。http://docs.scipy.org/doc/scipy/reference/generated/scipy.cluster.hierarchy.linkage.html#scipy.cluster.hierarchy.linkage 这里对method有详细的叙述。fclusterdata还有其他几个参数,我还没有搞明白,不过它们不提供的话,会有默认的。

1
2
3
4
5
6
7
8
from scipy.cluster.hierarchy import linkage ,fcluster,fclusterdata
import pandas as pd
data = pd.read_csv('/home/rickey/文档/学习/数据挖掘与数据仓库/数据挖掘作业/三围数据',sep='t',index_col=0)
matData = data.as_matrix()
distance = spatial.distance.pdist(matData)
linkresult = linkage(distance,method='average',metric='euclidean')
fcluster(linkresult,t=0.99,criterion='inconsistent',depth=2,R=None,monocrit=None)#这个需要先计算linkage,再出结果
dendrogram(linkresult,get_leaves=False,show_leaf_counts=False)#这个可以绘制出树形图

这是更复杂一些的实现形式,主要有四个函数要注意,分别是pdist,linkage,fcluster,dendrogram。

这段代码用的数据和前面那段是一样的,结果也是一样的。distance是一个距离数组(距离矩阵的一边角),之前已经说明了pdist的作用了。linkage返回的是一个4×(n-1)的矩阵。比如我的数据是67个,返回的则是一个4×66的矩阵。这个矩阵的意思,scipy文档上用的是这段话:“A 4 by (n-1) matrix Z is returned. At the i-th iteration, clusters with indices Z[i, 0] and Z[i, 1] are combined to form cluster n + i. A cluster with an index less than n corresponds to one of the n original observations. The distance between clusters Z[i, 0] and Z[i, 1] is given by Z[i, 2]. The fourth value Z[i, 3] represents the number of original observations in the newly formed cluster.”

英语不济,不是很看得明白。大概是说Z[i,0],Z[i,1]是组成n+i簇的之类的吧。

http://docs.scipy.org/doc/scipy/reference/generated/scipy.cluster.hierarchy.linkage.html#scipy.cluster.hierarchy.linkage linkage的用法还是要仔细看文档才行。

fcluster这个函数,则是把linkage算出的结果,形成一个平面数组,形成最后的聚类结果呈现出来。里面的参数和fclusterdata里面的意思是一样的。

fcluster的这段代码和fclusterdata的代码相比,多了一些,不过,好处就是能设置更多的参数。

dendrogram的参数设置非常多,没有完全搞明白,不过它会输出一个字典,和一幅图。字典里面有四个key,而图则是树形图,如下:

不过,我觉得这个图的用途不是很大,数据量一多,就什么都看不到了。

scipy里面关于层次聚类的函数还有不少,我也没有搞懂,这里就不多说了。

原文地址:https://www.cnblogs.com/lexus/p/2815785.html