凝聚式层次聚类算法的初步理解

凝聚式层次聚类算法的初步理解

层次聚类

层次聚类,是一种很直观的算法。顾名思义就是要一层一层地进行聚类,可以从下而上地把小的cluster合并聚集,也可以从上而下地将大的cluster进行分割。自下而上地进行聚类称为凝聚式层次聚类,自上而下地进行聚类称为分裂式层次聚类。似乎一般用得比较多的是从下而上地聚集。

凝聚式:从点作为个体簇开始,每一步合并两个最接近的簇。

分裂式:从包含所有点的某个簇开始,每一步分裂一个簇,直到仅剩下单点簇。

基本凝聚层次聚类算法步骤

1:如果需要,计算邻近度矩阵

2:repeat

3: 合并最接近的两个簇

4: 更新邻近度矩阵,以反映新的簇与原来的簇之间的邻近性

5:until 仅剩下一个簇/达到某个终止条件


在这个算法中,有几个重要的地方要拎出来点一下。

  • 邻近度矩阵

邻近度有许多种定义方式,比如欧氏距离,曼哈顿距离,马氏距离,余弦相似度,Jaccard系数,Bregman散度等等。种类丰富,样品奇多,根据不同的需求来选择最适合的邻近度,计算得到相应的邻近度矩阵。

  • 簇与簇之间邻近度的定义

每个簇中的点数不一定相等,如何计算两个不同簇之间的邻近度呢?

常用的有三种方法:单链(MIN准则),全链(MAX准则),组平均技术。

单链

单链(MIN)定义簇的邻近度为不同簇的两个最近的点之间的邻近度。在图中,即不同结点子集中两个节点之间的最短边。下图中的虚线,就是左右两个簇的邻近度。

全链

全链(MAX)定义簇的邻近度为不同簇中两个最远的点之间的邻近度作为簇的邻近度。在图中,即不同结点子集中两个结点之间的最长边。下图中的虚线,就是左右两个簇的邻近度。

组平均

组平均是一种基于图的方法。它定义簇邻近度为取自不同簇的所有点对邻近度的平均值(平均长度)。它的计算公式为proximity(C_{i} ,C_{j})=\frac{\sum_{x\epsilon C_{i},y\epsilon C_{j}}^{}{proximity(x,y)} }{m_{i}*m_{j}}

举个例子

如图的6个样本点,它们的坐标按标记依次如下

它们各点到其他点的邻近度矩阵如下


使用单链计算邻近度如下:

Dist({3,6},{2,5})=min(Dist(3,2),Dist(6,2),Dist(3,5),Dist(6,5))=min(0.1483,0.2540,0.2843,0.3921)=0.1483

使用单链的层次聚类如下:

(在代码中,需要将每次形成的新簇做上新的标记,比如例中6个点,某两个点合并后就给合并后的簇标记为7,依次为每个合并后的新簇做上标记。标记结果如下,前两列表示的是合并的簇的标记数,第三列是合并后形成的新簇的标记数。)

于是单链的最后结果为

树状结构图显示为

如上图,首先是红色圈圈合并,再是蓝色圈圈合并,再是紫色圈圈合并,最后是黑色圈圈合并。


使用全链计算邻近度如下:

Dist({3,6},{2,5})=max(Dist(3,2),Dist(6,2),Dist(3,5),Dist(6,5))=max(0.1513,0.2540,0.2843,0.3921)=0.3921;

Dist({3,6},{4})=max(Dist(3,4),Dist(6,4))=max(0.1513,0.2216)=0.2216;

Dist({3,6},{1})=max(Dist(3,1),Dist(6,1))=max(0.2219,0.2348)=0.2348;

所以簇{3,6}与{4}合并,而不是和单链一样与{2,5}合并。

使用全链的层次聚类如下:

形成新簇的标记数如下:

全链聚类的顺序为:

树状结构图如下:

首先点3和点6合并,其次点5和点2合并,接着{3,6}和点4合并,{{3,6},4}和点1合并,最后与{2,5}合并为一个大簇。

以上是我写的代码的输出结果,然而书上包括matlab自带的凝聚式层次聚类的输出结果是酱婶儿的:

他的聚类顺序是:

目前我还没有看出是哪里的问题,我得好好想想,希望我能够早点想通……不,希望我能先早点复习完概率论……


使用组平均计算邻近度

这里偷了个小懒,还没有写组平均计算邻近度的代码,因为下周二有个概率论的考试,大二这一年过的太混账,没好好学,导致要在最后几天突击一波,在过的基础上争取保80+望90+。到假期我再把组平均的代码补上吧。(下周日之前一定补上)

Dist({2,5},{1})=(Dist(2,1)+Dist(5,1))/(2*1)=(0.2357+0.3421)/(2*1)=0.2889;

Dist({3,6,4},{1})=(Dist(3,1)+Dist(6,1)+Dist(4,1))/(3*1)=(0.2357+0.3421)/(3*1)=0.2889;

Dist({3,6,4},{2,5})=(Dist(3,2)+Dist(6,2)+Dist(4,2)+Dist(3,5)+Dist(6,5)+Dist(4,5))/(3*2)=(0.1483+0.1100+0.1513+0.2843+0.3921+0.2932)/(3*2)=0.2300;

用了一下matlab自带的凝聚式层次聚类

y=pdist(x,'euclidean');%计算邻近度矩阵
z=linkage(y,'average');%选择组平均技术进行聚类
[H,T]=dendrogram(z);%绘制树状结构图
set(H,'LineWidth',2);%加粗图中线条

组平均的聚类顺序为:

按照这个顺序,新簇的标记依次为{3,6}-7;{2,5}-8;{4,7}-9;{8,9}-10;{1,10}-11

组平均聚类的树状结构图为:

定义两簇之间的邻近度还有其他方法,比如ward法和质心方法

ward方法就是把两个簇的邻近度定义为两个簇合并时导致的平方误差的增量。该方法使用的目标函数与K均值相同,且当两点之间的邻近度取它们之间距离的平方时,Ward方法与组平均非常相似。

而质心方法,是通过计算簇质心之间的距离来计算两个簇之间的邻近度。看上去与K均值也类似。而且质心方法有可能导致倒置的可能,也就是合并的两个簇可能比前一步合并的簇对更加相似。

Lance-Williams公式

上面提到的五种定义簇与簇之间邻近度的方式其实可以规整到一个公式里来,然后通过不同的系数来体现他们的不同,这个公式就是Lance-Williams公式。

p(R,Q)=\alpha _{A} p(A,Q)+\alpha _{B} p(B,Q)+\beta p(A,B)+\gamma |p(A,Q)-P(B,Q)|

式中,p(·,·)表示为邻近度函数,簇R是通过合并簇A和B形成的,Q是A、B以外的原簇,m_{A},m_{B},m_{Q}分别是原簇A、B和Q的大小(点数)。

我们可以看到,合并簇A和B形成新簇R之后,新簇R与原簇Q的邻近度是Q与原来的簇A和B的邻近度的线性函数。


凝聚式层次聚类的主要问题

1、缺乏全局目标函数

凝聚层次聚类不能视为全局优化目标函数,因为在每一步合并时仅仅局部地确定哪些簇应当合并(或分裂,对于分裂式)。但是避开了解决困难的组合优化问题,并且这样的方法没有局部极小问题或难选择初始点的问题。

2、处理不同大小簇的能力

关于如何处理待合并的簇对的相对大小这个问题,解决的方法有两种:一是加权,就是不同簇中的点具有不同的权值;二是非加权,需要考虑每个簇的点数。

比如组平均技术,上面说的组平均实际上是组平均技术的非加权版,全称为“使用算术平均的非加权的对组方法”(UPGMA),Lance-Williams公式的系数也涉及每个被合并簇的大小。而对于加权版本(WPGMA),它的系数是常数:\alpha _{A}=1/2,\alpha _{B}=1/2,β=0,γ=0。通常非加权方法更可取,除非出于某种原因个体点具有不同的权值,如对象类非均匀的抽样。

3、合并决策是最终的

对于合并两个簇,凝聚层次聚类可以使用所有点的逐对相似度信息趋向于作出好的局部决策。然而,一旦做出合并两个簇的决策,以后就不能撤销,这阻碍了局部最优标准变成全局最优标准。

一些方法试图克服“合并是最终的”这一限制,如移动树的分支以改善全局目标;使用划分聚类方法(K均值)来创建许多小簇,然后从这些小簇出发进行层次聚类。

优点与缺点

层次聚类能产生较高质量的聚类;有些使用这种算法是因为基本应用需要层次结构。但就计算量和存储需求而言,凝聚式层次聚类算法是昂贵的。

基本凝聚式层次聚类算法使用邻近度矩阵,这需要存储\frac{m^{2} }{2} 个邻近度(假定邻近度矩阵式对称的),其中m是数据点的个数。记录簇所需要的空间正比于簇的个数为m-1,不包括单点簇。因此总的空间复杂度为O(m^{2}) 。层次聚类所需要的总时间为O(m_{2}log m)


以上的知识点大部分来自于《数据挖掘导论》的学习,还包括网上查阅的一些博客,初步总结一些东西。

代码都是自己琢磨敲出来的,因为找代码的能力实在是有限,我想关键还是英语水平不高,高中把老本吃完了= =,英语还是很重要的能力啊。不过我的代码比较粗糙,我觉得假期需要尝试着优化它,让它的可读性变高一些,等成熟了我再发到知乎上来,希望路过的大牛不要喷的太狠……

大致的基本凝聚式层次聚类算法的初步介绍就到这里结束。我就静静地等待概率论考完,容纳后开始新一轮的学习了!不要浪费自己的时间啊!想想人工智能的冲击就后怕,我不想成为被淘汰掉的那一个。

编辑于 2017-07-02