`

聚类算法学习笔记(四)——层次聚类

 
阅读更多
1.    层次聚类
层次聚类算法与之前所讲的顺序聚类有很大不同,它不再产生单一聚类,而是产生一个聚类层次。说白了就是一棵层次树。介绍层次聚类之前,要先介绍一个概念——嵌套聚类。讲的简单点,聚类的嵌套与程序的嵌套一样,一个聚类中R1包含了另一个R2,那这就是R2嵌套在R1中,或者说是R1嵌套了R2。具体说怎么算嵌套呢?聚类R1={{x1,x2},{x3},{x4,x5}嵌套在聚类R2={{x1,x2,x3},{x4,x5}}中,但并不嵌套在聚类R3={{x1,x4},{x3},{x2,x5}}中。

层次聚类算法产生一个嵌套聚类的层次,算法最多包含N步,在第t步,执行的操作就是在前t-1步的聚类基础上生成新聚类。主要有合并和分裂两种实现。我这里只讲合并,因为前一阶段正好课题用到,另外就是合并更容易理解和实现。当然分裂其实就是合并的相反过程。

令g(Ci,Cj)为所有可能的X聚类对的函数,此函数用于测量两个聚类之间的近邻性,用t表示当前聚类的层次级别。通用合并算法的伪码描述如下:

1.       初始化:

a)         选择Â0={{x1},…,{xN}}

b)        令t=0

2.       重复执行以下步骤:

a)         t=t+1

b)        在Ât-1中选择一组(Ci,Cj),满足

c)         定义Cq=CiÈCj,并且产生新聚类Ât=(Ât-1-{Ci,Cj})È{Cq}

直到所有向量全被加入到单一聚类中。

       这一方法在t层时将两个向量合并,那么这两个向量在以后的聚类过程中的后继聚类都是相同的,也就是说一旦它们走到一起,那么以后就不会再分离……(很专一哦O(∩_∩)O~)。这也就引出了这个算法的缺点,当在算法开始阶段,若出现聚类错误,那么这种错误将一直会被延续,无法修改。在层次t上,有N-t个聚类,为了确定t+1层上要合并的聚类对,必须考虑(N-t)(N-t-1)/2个聚类对。这样,聚类过程总共要考虑的聚类对数量就是(N-1)N(N+1)/6,也就是说整个算法的时间复杂度是O(N3)。

举例来说,如果令X={x1, x2, x3, x4, x5},其中x1=[1, 1]T, x2=[2, 1]T, x3=[5, 4]T, x4=[6, 5]T, x5=[6.5, 6]T。那么合并算法执行的过程可以用下面的图来表示。

              P(X)是不相似矩阵

该算法从核心过程上来讲,就是先计算出数据集中向量之间的距离,记为距离矩阵(也叫不相似矩阵)。接着通过不断的对矩阵更新,完成聚类。矩阵更新算法的伪码描述如下:

1.       初始化:

a)         Â0={{x1},…,{xN}}

b)        P0=P(X) (距离矩阵)

c)         t=0

2.       重复执行以下步骤:

a)         t=t+1

b)        合并Ci和Cj为Cq,这两个聚类满足d(Ci,Cj)=minr,s=1,…,N,r≠sd(Cr,Cs)

c)         删除第i和j行,第i和j列,同时插入新的行和列,新的行列为新合并的类Cq与所有其他聚类之间的距离值

直到将所有向量合并到一个聚类中

       大家可以看到,层次聚类算法的输出结果总是一个聚类,这往往不是我们想要的,我们总希望算法在得到我们期望的结果后就停止。那么我们如何控制呢?常用的做法就是为算法限制一个阈值,矩阵更新过程中,总是将两个距离最近的聚类合并,那么我们只要加入一个阈值判断,当这个距离大于阈值时,就说明不需要再合并了,此时算法结束。这样的阈值引入可以很好的控制算法结束时间,将层次截断在某一层上。

2. 算法实现
       MATLAB实现了层次聚类算法,基本语句如下:

1X = [1 2;2.5 4.5;2 2;4 1.5;4 2.5] ;
2Y = pdist(X,'euclid');
3Z = linkage(Y,'single');
4T = cluster(Z,'cutoff',cutoff);

MATLAB还有一个简化的层次聚类版本,一句话搞定

1T = clusterdata(X,cutoff)


Java实现的版本:



  1package util;
  2
  3import java.util.*;
  4
  5public class Clusterer {
  6    private List[] clusterList;
  7    DisjointSets ds;
  8    private static final int MAX = Integer.MAX_VALUE;
  9    private int n;
10    private int cc;
11
12    // private double ori[] = {1,2,5,7,9,10};
13
14    public Clusterer(int num) {
15        ds = new DisjointSets(num);
16        n = num;
17        cc = n;
18        clusterList = new ArrayList[num];
19        for (int i = 0; i < n; i++)
20            clusterList[i] = new ArrayList();
21    }
22
23    public List[] getClusterList() {
24        return clusterList;
25    }
26
27    public void setClusterList(List[] clusterList) {
28        this.clusterList = clusterList;
29    }
30
31    public void output() {
32        int ind = 1;
33        for (int i = 0; i < n; i++) {
34            clusterList[ds.find(i)].add(i);
35        }
36        for (int i = 0; i < n; i++) {
37            if (clusterList[i].size() != 0) {
38                System.out.print("cluster " + ind + " :");
39                for (int j = 0; j < clusterList[i].size(); j++) {
40                    System.out.print(clusterList[i].get(j) + " ");
41                }
42                System.out.println();
43                ind++;
44            }
45        }
46    }
47
48    /**
49     * this method provides a hierachical way for clustering data.
50     *
51     * @param r
52     *            denote the distance matrix
53     * @param n
54     *            denote the sample num(distance matrix's row number)
55     * @param dis
56     *            denote the threshold to stop clustering
57     */
58    public void cluster(double[][] r, int n, double dis) {
59        int mx = 0, my = 0;
60        double vmin = MAX;
61        for (int i = 0; i < n; i++) { // 寻找最小距离所在的行列
62            for (int j = 0; j < n; j++) {
63                if (j > i) {
64                    if (vmin > r[i][j]) {
65                        vmin = r[i][j];
66                        mx = i;
67                        my = j;
68                    }
69                }
70            }
71        }
72        if (vmin > dis) {
73            return;
74        }
75        ds.union(ds.find(mx), ds.find(my)); // 将最小距离所在的行列实例聚类合并
76        double o1[] = r[mx];
77        double o2[] = r[my];
78        double v[] = new double[n];
79        double vv[] = new double[n];
80        for (int i = 0; i < n; i++) {
81            double tm = Math.min(o1[i], o2[i]);
82            if (tm != 0)
83                v[i] = tm;
84            else
85                v[i] = MAX;
86            vv[i] = MAX;
87        }
88        r[mx] = v;
89        r[my] = vv;
90        for (int i = 0; i < n; i++) { // 更新距离矩阵
91            r[i][mx] = v[i];
92            r[i][my] = vv[i];
93        }
94        cluster(r, n, dis); // 继续聚类,递归直至所有簇之间距离小于dis值
95    }
96
97    /**
98     *
99     * @param r
100     * @param cnum
101     *            denote the number of final clusters
102     */
103    public void cluster(double[][] r, int cnum) {
104        /*if(cc< cnum)
105            System.err.println("聚类数大于实例数");*/
106        while (cc > cnum) {// 继续聚类,循环直至聚类个数等于cnum
107            int mx = 0, my = 0;
108            double vmin = MAX;
109            for (int i = 0; i < n; i++) { // 寻找最小距离所在的行列
110                for (int j = 0; j < n; j++) {
111                    if (j > i) {
112                        if (vmin > r[i][j]) {
113                            vmin = r[i][j];
114                            mx = i;
115                            my = j;
116                        }
117                    }
118                }
119            }
120            ds.union(ds.find(mx), ds.find(my)); // 将最小距离所在的行列实例聚类合并
121            double o1[] = r[mx];
122            double o2[] = r[my];
123            double v[] = new double[n];
124            double vv[] = new double[n];
125            for (int i = 0; i < n; i++) {
126                double tm = Math.min(o1[i], o2[i]);
127                if (tm != 0)
128                    v[i] = tm;
129                else
130                    v[i] = MAX;
131                vv[i] = MAX;
132            }
133            r[mx] = v;
134            r[my] = vv;
135            for (int i = 0; i < n; i++) { // 更新距离矩阵
136                r[i][mx] = v[i];
137                r[i][my] = vv[i];
138            }
139            cc--;
140        }
141    }
142
143    public static void main(String args[]) {
144        double[][] r = { { 0, 1, 4, 6, 8, 9 }, { 1, 0, 3, 5, 7, 8 },
145                { 4, 3, 0, 2, 4, 5 }, { 6, 5, 2, 0, 2, 3 },
146                { 8, 7, 4, 2, 0, 1 }, { 9, 8, 5, 3, 1, 0 } };
147        Clusterer cl = new Clusterer(6);
148        //cl.cluster(r, 6, 1);
149        cl.cluster(r, 3);
150        cl.output();
151    }
152
153}
154

3. 小结
       层次聚类算法是非常常用的聚类算法,同时也是被广泛研究的聚类算法。层次聚类本身分为合并和分裂两种实现,在合并算法中,又分基于矩阵理论的合并和基于图论的合并。本文只是初学聚类的一点体会,因此只实现了基于矩阵理论的算法,同时,用于大数据集合的层次算法如CURE,ROCK和Chameleon算法都没有涉及,这些算法如果以后有时间,会整理发布。还有截断点的选择,最佳聚类数的确定都是可以研究的问题。

4. 参考文献及推荐阅读
[1]Pattern Recognition Third Edition, Sergios Theodoridis, Konstantinos Koutroumbas

[2]模式识别第三版, Sergios Theodoridis, Konstantinos Koutroumbas著, 李晶皎, 王爱侠, 张广源等译





PS,第四第五节的内容的代码地址:

http://www.kuaipan.cn/index.php?ac=fileview&dirid=50160446308614332
分享到:
评论

相关推荐

    『ML』利用K-Means聚类算法对未标注数据分组——《机器学习实战》学习笔记(Ch10)

    K-Means聚类算法是机器学习领域中最基础且广泛应用的无监督学习方法之一,用于对未标注数据进行分组。它的核心思想是通过迭代优化,使得每个数据点尽可能地归属于与其最近的类中心(也称为质心)所在的簇。算法的...

    视频学习笔记——李宏毅机器学习——P1,2

    在无监督学习中,算法试图从数据中发现内在的结构或模式,如聚类分析,它可以帮助我们将相似的数据点归为一类,而无需知道具体的类别标签。 【强化学习】 强化学习是一种学习方式,它让机器通过与环境的交互来学习...

    数学建模算法模型——统计分析.zip

    首先,"K-Means算法研究及在文本聚类中的应用.doc"讲述了K-Means聚类算法,这是一种常见的无监督机器学习算法,用于将数据集分成K个不同的群组,每个群组内部的相似度较高,而群组间的相似度较低。在文本聚类中,K-...

    k-means同心圆的聚类代码

    ### K-Means聚类算法在同心圆数据集上的应用 ...此外,还可以进一步探索其他聚类算法如DBSCAN或层次聚类等是否能够更好地处理此类数据,以及如何优化现有的K-Means算法来应对更复杂的实际应用场景。

    [网盘]算法笔记-上机训练实战指南-胡凡 完整版

    根据提供的文件信息,我们可以推断出这是一本关于算法学习的书籍资料——《算法笔记-上机训练实战指南》,作者为胡凡。该书共有442页,内容全面覆盖了算法的基础理论与实践操作,适合希望提升算法能力的学习者使用。...

    MachineLearning_机器学习笔记_

    《机器学习笔记——深入探索与理解》 在当今数字化时代,机器学习作为人工智能的一个关键分支,已经在各个领域展现出强大的潜力和应用价值。本笔记旨在帮助读者深入理解和掌握机器学习的基本概念、理论框架以及实践...

    第二十一次报告1

    K-均值聚类(K-means)是无监督学习中一种广泛应用的聚类算法,它的目标是将数据集中的对象分成K个不同的簇,使得每个簇内的对象彼此相似,而不同簇之间的对象差异较大。聚类是数据分析的重要工具,尤其在数据挖掘、...

    Coursera-ML-AndrewNg-Notes-master

    《吴恩达机器学习笔记——深度解析与源码探索》 吴恩达,这位在人工智能领域具有深远影响力的科学家,以其亲授的Coursera在线课程《机器学习》闻名于世。他的课程深入浅出,引领无数学子步入了机器学习的大门。这份...

    傻瓜机器学习笔记,简单例子&手推题目

    "傻瓜机器学习笔记,简单例子&手推题目" 本文档总结了机器学习的重要算法、技术和概念,涵盖了线性回归、逻辑回归、决策树、集成学习、支持向量机、朴素贝叶斯、GDA、高斯判别分析、BP 误差逆传播算法、卷积神经...

    机器学习讲义.rar

    此外,笔记还可能包含聚类算法,如K-means、DBSCAN,以及降维技术,如主成分分析(PCA)和奇异值分解(SVD)。 接下来,"复习笔记1——复习笔记6"很可能是对关键知识点的总结和回顾,它们可能包含了各个主题的重点...

    人工智能导论笔记总结(知识图谱+机器学习部分)

    《人工智能导论笔记总结——知识图谱与机器学习》 一、知识图谱 知识图谱,作为一种将知识以图形形式展示的语义网络,它揭示了实体之间的复杂关系。知识图谱通常由多种类型的节点(代表实体)和边(表示关系)构成...

    cs224w 图神经网络 学习笔记(二)Properties of Networks and Random Graph Mode

    【图神经网络学习笔记(二)——网络属性与随机图模型】 在图神经网络的研究中,理解网络的特性至关重要。本笔记将深入探讨如何衡量一个网络的属性,并介绍几种常用的图模型,包括真实网络案例的属性计算以及小世界...

    斯坦福大学机器学习笔记(中文版)

    ### 斯坦福大学机器学习笔记(中文版)——核心知识点概述 #### 一、机器学习简介 **1.1 什么是机器学习?** 机器学习是计算机科学的一个分支,它研究如何让计算机从数据中自动“学习”并改进其性能。这种学习过程不...

    机器学习个人笔记完整版v5.24-A4打印版

    - **深学习笔记**:[GitHub](https://github.com/fengdu78/deeplearning_ai_books) - **知乎页面**:[知乎](https://www.zhihu.com/people/fengdu78/activities) 这些资源为学习者提供了丰富的参考资料和技术支持,...

    em 算法笔记

    在统计学和机器学习领域中,期望最大化算法(Expectation-Maximization Algorithm,简称EM算法)是一种广泛应用的算法,用于处理带有隐变量的数据集的最大似然估计问题。EM算法能够有效地处理不完全数据或涉及隐变量...

    数据分析-master笔记

    机器学习是数据分析中的高级部分,包括监督学习(如分类和回归)、无监督学习(如聚类和降维)和强化学习。Python的scikit-learn库是实现这些算法的首选工具。深度学习,尤其是神经网络,已经在图像识别、自然语言...

    斯坦福机器学习网页转pdf版本06-10.zip

    可能讲解了K-means算法、层次聚类以及DBSCAN等不同的聚类技术。这部分内容可能会强调无监督学习的特点,如何确定合适的簇数,以及如何评估聚类效果。 通过这些笔记,学习者可以全面理解神经网络的工作原理,掌握...

    加速属性网络嵌入——中南大学彭汪祺--论文研读笔记21

    【网络嵌入】是当前大数据分析领域中的一个重要技术,它旨在将复杂的网络结构转化为低维向量表示,以便于后续的分析任务,如节点分类、链接预测和网络聚类等。传统的网络嵌入方法主要关注网络的拓扑结构,但忽略了...

Global site tag (gtag.js) - Google Analytics