1 层次聚类概述
层次法(Hierarchical methods):先计算样本之间的距离。每次将距离最近的点合并到同一个类。然后,再计算类与类之间的距离,将距离最近的类合并为一个大类。不停的合并,直到合成了一个类。其中类与类的距离的计算方法有:最短距离法,最长距离法,中间距离法,类平均法等。比如最短距离法,将类与类的距离定义为类与类之间样本的最短距离。
层次聚类算法根据层次分解的顺序分为:自下向上和自上向下,即凝聚的层次聚类算法和分裂的层次聚类算法(agglomerative NESting和divisive ANALysis),也可以理解为自下而上法(bottom-up)和自上而下法(top-down)。
- 自下而上法:凝聚型层次聚类,就是一开始每个个体(object)都是一个类,然后根据linkage寻找同类,最后形成一个“类”。
- 自上而下法:分裂型层次聚类,就是反过来,一开始所有个体都属于一个“类”,然后根据linkage排除异己,最后每个个体都成为一个“类”。
这两种路方法没有孰优孰劣之分,只是在实际应用的时候要根据数据特点以及你想要的“类”的个数,来考虑是自上而下更快还是自下而上更快。根据linkage判断”类”的方法就是:最短距离法、最长距离法、中间距离法、类平均法等,其中类平均法往往被认为是最常用也最好用的方法,一方面因为其良好的单调性,另一方面因为其空间扩张/浓缩的程度适中。
为弥补分解与合并的不足,层次合并经常要与其它聚类方法相结合,如循环定位。
2 层次聚类的流程
凝聚型层次聚类的策略是先将每个对象作为一个簇,然后合并这些原子簇为越来越大的簇,直到所有对象都在一个簇中,或者某个终结条件被满足。绝大多数层次聚类属于凝聚型层次聚类,它们只是在簇间相似度的定义上有所不同。 这里给出采用最小距离的凝聚层次聚类算法流程:
- (1) 将每个对象看作一类,计算两两之间的最小距离;
- (2) 将距离最小的两个类合并成一个新类;
- (3) 重新计算新类与所有类之间的距离;
- (4) 重复(2)、(3),直到所有类最后合并成一类。
另外我们可以看出凝聚的层次聚类并没有类似基本K均值的全局目标函数,没有局部极小问题或是很难选择初始点的问题。合并的操作往往是最终的,一旦合并两个簇之后就不会撤销。当然其计算存储的代价是昂贵的。
距离计算方式
-
Single Linkage
Single Linkage的计算方法是将两个组合数据点中距离最近的两个数据点间的距离作为这两个组合数据点的距离。这种方法容易受到极端值的影响,两个很相似的组合数据点可能由于其中的某个极端的数据点距离较近而组合在一起。
-
Complete Linkage
Complete Linkage的计算方法与Single Linkage相反,将两个组合数据点中距离最远的两个数据点间的距离作为这两个组合数据点的距离。Complete Linkage的问题也与Single Linkage相反,两个不相似的组合数据点可能由于其中的极端值距离较远而无法组合在一起。
-
Average Linkage
Average Linkage的计算方法是计算两个组合数据点中的每个数据点与其他所有数据点的距离,将所有距离的均值作为两个组合数据点间的距离。这种方法计算量比较大,但结果比前两种方法更合理。
3 案例详解
下面运用凝聚型层次聚类,通过欧氏距离计算下面A到G的欧式距离矩阵,并通过合并的方法将相似度最高的数据点进行组合,并创建聚类树。
(1)计算每两个点间距离
(2)计算数据点与组合数据点间的距离
(3)将最近数据点合并
(4)后续合并
4 优缺点
优点:
- 距离和规则的相似度容易定义,限制少;
- 不需要预先制定聚类数;
- 可以发现类的层次关系;
- 可以聚类成其它形状
缺点:
- 计算复杂度太高, O ( t ∗ n 2 ) O(t*n^2) O(t∗n2), t t t为迭代次数, n n n为样本点数 ;
- 奇异值也能产生很大影响;
- 算法很可能聚类成链状
- 大数据集不太适合
5 sklearn中的层次聚类
(1)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 np
X = [[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)scipy下cluster.hierarchy
(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
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. ]])
6 优化算法
6.1 BIRCH算法
BIRCH(Balanced Iterative Reducingand Clustering Using Hierarchies,利用层次方法的平衡迭代规约和聚类)主要是在数据量很大的时候使用,而且数据类型是numerical。首先利用树的结构对对象集进行划分,然后再利用其它聚类方法对这些聚类进行优化;
聚类特征使用3元组进行一个簇的相关信息,通过构建满足分枝因子和簇直径限制的聚类特征树来求聚类,聚类特征树其实是一个具有两个参数分枝因子和类直径的高度平衡树;分枝因子规定了树的每个节点的子女的最多个数,而类直径体现了对这一类点的距离范围;非叶子节点为它子女的最大特征值;聚类特征树的构建可以是动态过程的,可以随时根据数据对模型进行更新操作。
sklearn.cluster.Birch
优缺点
- 适合大规模数据集,线性效率;
- 只适合分布呈凸形或者球形的数据集、需要给定聚类个数和簇之间的相关参数;
6.2 CURE算法
CURE算法(Clustering Using Representative 使用代表点的聚类法):该算法先把每个数据点看成一类,然后合并距离最近的类直至类个数为所要求的个数为止。但是和AGNES算法的区别是:取消了使用所有点或用中心点+距离来表示一个类,而是从每个类中抽取固定数量、分布较好的点作为此类的代表点,并将这些代表点乘以一个适当的收缩因子,使它们更加靠近类中心点。代表点的收缩特性可以调整模型可以匹配那些非球形的场景,而且收缩因子的使用可以减少噪音对聚类的影响
算法步骤:
- 从源数据对象中抽取一个随机样本S;
- 将样本S分割成一组划分;
- 对每个划分局部的聚类;
- 通过随机样本剔除孤立点。如果一个类增长缓慢就去除它;
- 对局部的类进行聚类,落在每个新形成的类中的代表点根据用户定义的一个收缩因子收缩或向类中心移动。这些点代表和捕捉到了类的形状。
- 用相应的类标签来标记数据。
CURE算法特点:
- 属于凝聚层次聚类
- 适应非球形的几何形状
- 对孤立点的处理更加健壮
- 识别异常值/离群点
- 适应大规模数据
优点:
-
可以发现复杂空间的簇
-
受噪点影响小
缺点:
-
参数较多,包括采样的大小、聚类的个数、收缩的比例等;
-
抽样有误差;
-
难以发现形状非常复杂的空间簇(如中空形状),对空间数据密度差异敏感
-
虽然 CURE 聚类是针对大规模数据库设计的算法,但是当数据量剧增时,效率仍然不能满足需求
6.3 ROCK算法
ROCK(A Hierarchical ClusteringAlgorithm for Categorical Attributes)主要用在categorical的数据类型上;
6.4 Chameleon算法
Chameleon(A Hierarchical Clustering AlgorithmUsing Dynamic Modeling)里用到的linkage是kNN(k-nearest-neighbor)算法,并以此构建一个graph,Chameleon的聚类效果被认为非常强大,比BIRCH好用,但运算复杂度很高,O(n^2)。