一文读懂层次聚类(Python代码)

Posted Python数据科学

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了一文读懂层次聚类(Python代码)相关的知识,希望对你有一定的参考价值。

大家好,我是东哥。

本篇想和大家介绍下层次聚类,先通过一个简单的例子介绍它的基本理论,然后再用一个实战案例Python代码实现聚类效果。

首先要说,聚类属于机器学习的无监督学习,而且也分很多种方法,比如大家熟知的有K-means。层次聚类也是聚类中的一种,也很常用。下面我先简单回顾一下K-means的基本原理,然后慢慢引出层次聚类的定义和分层步骤,这样更有助于大家理解。

层次聚类和K-means有什么不同?

K-means 工作原理可以简要概述为:

  • 决定簇数(k)
  • 从数据中随机选取 k 个点作为质心
  • 将所有点分配到最近的聚类质心
  • 计算新形成的簇的质心
  • 重复步骤 3 和 4
  • 这是一个迭代过程,直到新形成的簇的质心不变,或者达到最大迭代次数。

    但是 K-means 是存在一些缺点的,我们必须在算法开始前就决定簇数 K 的数量,但实际我们并不知道应该有多少个簇,所以一般都是根据自己的理解先设定一个值,这就可能导致我们的理解和实际情况存在一些偏差。

    层次聚类完全不同,它不需要我们开始的时候指定簇数,而是先完整的形成整个层次聚类后,通过决定合适的距离,自动就可以找到对应的簇数和聚类。

    什么是层次聚类?

    下面我们由浅及深的介绍什么是层次聚类,先来一个简单的例子。

    假设我们有以下几点,我们想将它们分组:

    我们可以将这些点中的每一个分配给一个单独的簇,就是4个簇(4种颜色):

    然后基于这些簇的相似性(距离),将最相似的(距离最近的)点组合在一起并重复这个过程,直到只剩下一个集群:

    上面本质上就是在构建一个层次结构。先了解到这里,后面我们详细介绍它的分层步骤。

    层次聚类的类型

    主要有两种类型的层次聚类:

  • 凝聚层次聚类
  • 分裂层次聚类
  • 凝聚层次聚类

    先让所有点分别成为一个单独的簇,然后通过相似性不断组合,直到最后只有一个簇为止,这就是凝聚层次聚类的过程,和我们上面刚刚说的一致。

    分裂层次聚类

    分裂层次聚类正好反过来,它是从单个集群开始逐步分裂,直到无法分裂,即每个点都是一个簇。

    所以无论是 10、100、1000 个数据点都不重要,这些点在开始的时候都属于同一个簇:

    现在,在每次迭代中拆分簇中相隔最远的两点,并重复这个过程,直到每个簇只包含一个点:

    上面的过程就是分裂层次聚类

    执行层次聚类的步骤

    上面已经说了层次聚类的大概过程,那关键的来了,如何确定点和点的相似性呢?

    这是聚类中最重要的问题之一了,一般计算相似度的方法是:计算这些簇的质心之间的距离。距离最小的点称为相似点,我们可以合并它们,也可以将其称为基于距离的算法

    另外在层次聚类中,还有一个称为邻近矩阵的概念,它存储了每个点之间的距离。下面我们通过一个例子来理解如何计算相似度、邻近矩阵、以及层次聚类的具体步骤。

    案例介绍

    假设一位老师想要将学生分成不同的组。现在有每个学生在作业中的分数,想根据这些分数将他们分成几组。关于拥有多少组,这里没有固定的目标。由于老师不知道应该将哪种类型的学生分配到哪个组,因此不能作为监督学习问题来解决。下面,我们将尝试应用层次聚类将学生分成不同的组。

    下面是个5名学生的成绩:

    创建邻近矩阵

    首先,我们要创建一个邻近矩阵,它储存了每个点两两之间的距离,因此可以得到一个形状为 n X n 的方阵。

    这个案例中,可以得到以下 5 x 5 的邻近矩阵:

    矩阵里有两点需要注意下:

  • 矩阵的对角元素始终为 0,因为点与其自身的距离始终为 0
  • 使用欧几里得距离公式来计算非对角元素的距离
  • 比如,我们要计算点 1 和 2 之间的距离,计算公式为:

    同理,按此计算方法完成后填充邻近矩阵其余元素。

    执行层次聚类

    这里使用凝聚层次聚类来实现。

    步骤 1:首先,我们将所有点分配成单个簇:

    这里不同的颜色代表不同的簇,我们数据中的 5 个点,即有 5 个不同的簇。

    步骤2:接下来,我们需要查找邻近矩阵中的最小距离并合并距离最小的点。然后我们更新邻近矩阵:最小距离是 3,因此我们将合并点 1 和 2:让我们看看更新的集群并相应地更新邻近矩阵:

    更新之后,我们取了1、2 两个点中值 (7, 10) 最大的来替换这个簇的值。当然除了最大值之外,我们还可以取最小值或平均值。然后,我们将再次计算这些簇的邻近矩阵:第 3 步:重复第 2 步,直到只剩下一个簇。

    重复所有的步骤后,我们将得到如下所示的合并的聚类:

    这就是凝聚层次聚类的工作原理。但问题是我们仍然不知道该分几组?是2、3、还是4组呢?

    下面开始介绍如何选择聚类数。

    如何选择聚类数?

    为了获得层次聚类的簇数,我们使用了一个概念,叫作树状图

    通过树状图,我们可以更方便的选出聚类的簇数。

    回到上面的例子。当我们合并两个簇时,树状图会相应地记录这些簇之间的距离并以图形形式表示。下面这个是树状图的原始状态,横坐标记录了每个点的标记,纵轴记录了点和点之间的距离:

    当合并两个簇时,将会在树状图中连接起来,连接的高度就是点之间的距离。下面是我们刚刚层次聚类的过程。

    然后开始对上面的过程进行树状图的绘制。从合并样本 1 和 2 开始,这两个样本之间的距离为 3。

    可以看到已经合并了 1 和 2。垂直线代表 1 和 2 的距离。同理,按照层次聚类过程绘制合并簇类的所有步骤,最后得到了这样的树状图:

    通过树状图,我们可以清楚地形象化层次聚类的步骤。树状图中垂直线的距离越远代表簇之间的距离越大。

    有了这个树状图,我们决定簇类数就方便多了。

    现在我们可以设置一个阈值距离,绘制一条水平线。比如我们将阈值设置为 12,并绘制一条水平线,如下:

    从交点中可以看到,聚类的数量就是与阈值水平线与垂直线相交的数量(红线与 2 条垂直线相交,我们将有 2 个簇)。与横坐标相对应的,一个簇将有一个样本集合为 (1,2,4),另一个集群将有一个样本集合 (3,5)。

    这样,我们就通过树状图解决了分层聚类中要决定聚类的数量。

    Python代码实战案例

    上面是理论基础,有点数学基础都能看懂。下面介绍下在如何用代码Python来实现这一过程。这里拿一个客户细分的数据来展示一下。

    数据集和代码在我的GitHub里,欢迎star!

    https://github.com/xiaoyusmd/PythonDataScience

    这个数据来源于UCI 机器学习库。我们的目的是根据批发分销商的客户在不同产品类别(如牛奶、杂货、地区等)上的年度支出,对他们进行细分。

    首先对数据进行一个标准化,为了让所有数据在同一个维度便于计算,然后应用层次聚类来细分客户。

    from sklearn.preprocessing import normalize
    data_scaled = normalize(data)
    data_scaled = pd.DataFrame(data_scaled, columns=data.columns)

    import scipy.cluster.hierarchy as shc
    plt.figure(figsize=(107))  
    plt.title("Dendrograms")  
    dend = shc.dendrogram(shc.linkage(data_scaled, method=\'ward\'))

    x 轴包含了所有样本,y 轴代表这些样本之间的距离。距离最大的垂直线是蓝线,假如我们决定要以阈值 6 切割树状图:

    plt.figure(figsize=(107))  
    plt.title("Dendrograms")  
    dend = shc.dendrogram(shc.linkage(data_scaled, method=\'ward\'))
    plt.axhline(y=6, color=\'r\', linestyle=\'--\')

    现在我们有两个簇了,我们要对这 2 个簇应用层次聚类:

    from sklearn.cluster import AgglomerativeClustering
    cluster = AgglomerativeClustering(n_clusters=2, affinity=\'euclidean\', linkage=\'ward\')  
    cluster.fit_predict(data_scaled)

    由于我们定义了 2 个簇,因此我们可以在输出中看到 0 和 1 的值。0 代表属于第一个簇的点,1 代表属于第二个簇的点。

    plt.figure(figsize=(107))  
    plt.scatter(data_scaled[\'Milk\'], data_scaled[\'Grocery\'], c=cluster.labels_) 

    到这里我们就成功的完成了聚类。

    参考:https://www.analyticsvidhya.com/blog/2019/05/beginners-guide-hierarchical-clustering/

    推荐阅读
    1. pandas100个骚操作
    2. pandas数据清洗
    机器学习原创系列
    4. 数据科学干货下载

    一文读懂聚类算法


    一文读懂聚类算法

    1.基本概念

    聚类是数据挖掘中的概念,就是按照某个特定标准(如距离)把一个数据集分割成不同的类或簇,使得同一个簇内的数据对象的相似性尽可能大,同时不在同一个簇中的数据对象的差异性也尽可能地大。聚类后同一类的数据尽可能聚集到一起,不同类的数据尽量分离。

     

    聚类与分类的区别

    Clustering (聚类),简单地说就是把相似的东西分到一组,聚类的时候,我们并不关心某一类是什么,我们需要实现的目标只是把相似的东西聚到一起。因此,一个聚类算法通常只需要知道如何计算相似度就可以开始工作了,因此 clustering 通常并不需要使用训练数据进行学习,这在Machine Learning中被称作unsupervisedlearning (无监督学习)

    Classification (分类),对于一个classifier,通常需要你告诉它“这个东西被分为某某类”这样一些例子,理想情况下,一个classifier 会从它得到的训练集中进行“学习”,从而具备对未知数据进行分类的能力,这种提供训练数据的过程通常叫做supervised learning (监督学习)

     

    聚类过程

    数据准备:包括特征标准化和降维;

    特征选择:从最初的特征中选择最有效的特征并将其存储于向量中;

    特征提取:通过对所选择的特征进行转换形成新的突出特征;

    聚类(或分组):首先选择合适特征类型的某种距离函数(或构造新的距离函数)进行接近程度的度量,而后执行聚类或分组;

    聚类结果评估:是指对聚类结果进行评估,评估主要有3种:外部有效性评估、内部有效性评估和相关性测试评估。

     

    衡量聚类算法优劣的标准

    处理大的数据集的能力;

    处理任意形状,包括有间隙的嵌套的数据的能力;

    算法处理的结果与数据输入的顺序是否相关,也就是说算法是否独立于数据输入顺序;

    处理数据噪声的能力;

    是否需要预先知道聚类个数,是否需要用户给出领域知识;

    算法处理有很多属性数据的能力,也就是对数据维数是否敏感。

     

    2.分类

    主要分为层次化聚类算法,划分式聚类算法,基于密度的聚类算法,基于网格的聚类算法,基于模型的聚类算法等。

     

    层次化聚类算法

    又称树聚类算法,透过一种层次架构方式,反复将数据进行分裂或聚合。

    典型的有BIRCH算法,CURE算法,CHAMELEON算法,Sequencedata rough clustering算法, Betweengroups average算法, Furthest neighbor算法, Neares neighbor算法等。

    典型凝聚型层次聚类:

    先将每个对象作为一个簇,然后合并这些原子簇为越来越大的簇,直到所有对象都在一个簇中,或者某个终结条件被满足。

    算法流程:

    将每个对象看作一类,计算两两之间的最小距离;将距离最小的两个类合并成一个新类;重新计算新类与所有类之间的距离;重复12,直到所有类最后合并成一类。

     

    划分式聚类算法

    预先指定聚类数目或聚类中心,反复迭代逐步降低目标函数误差值直至收敛,得到最终结果。

    经典K-means算法流程:

    随机地选择k个对象,每个对象初始地代表了一个簇的中心;对剩余的每个对象,根据其与各簇中心的距离,将它赋给最近的簇;重新计算每个簇的平均值,更新为新的簇中心;不断重复23,直到准则函数收敛。

     

    基于模型的聚类算法

    为每簇假定了一个模型,寻找数据对给定模型的最佳拟合,同一”类“的数据属于同一种概率分布,即假设数据是根据潜在的概率分布生成的。主要有基于统计学模型的方法和基于神经网络模型的方法,尤其以基于概率模型的方法居多。一个基于模型的算法可能通过构建反应数据点空间分布的密度函数来定位聚类。基于模型的聚类试图优化给定的数据和某些数据模型之间的适应性。

    SOM神经网络算法:

    该算法假设在输入对象中存在一些拓扑结构或顺序,可以实现从输入空间(n)到输出平面(2)的降维映射,其映射具有拓扑特征保持性质,与实际的大脑处理有很强的理论联系。

    SOM网络包含输入层和输出层。输入层对应一个高维的输入向量,输出层由一系列组织在2维网格上的有序节点构成,输入节点与输出节点通过权重向量连接。学习过程中,找到与之距离最短的输出层单元,即获胜单元,对其更新。同时,将邻近区域的权值更新,使输出节点保持输入向量的拓扑特征。

    算法流程:

    网络初始化,对输出层每个节点权重赋初值;将输入样本中随机选取输入向量,找到与输入向量距离最小的权重向量;定义获胜单元,在获胜单元的邻近区域调整权重使其向输入向量靠拢;提供新样本、进行训练;收缩邻域半径、减小学习率、重复,直到小于允许值,输出聚类结果。

     

    基于密度聚类算法

    主要思想:

    只要邻近区域的密度(对象或数据点的数目)超过某个阈值,就继续聚类。

    擅于解决不规则形状的聚类问题,广泛应用于空间信息处理,SGC,GCHLDBSCAN算法、OPTICS算法、DENCLUE算法。

    DBSCAN

    对于集中区域效果较好,为了发现任意形状的簇,这类方法将簇看做是数据空间中被低密度区域分割开的稠密对象区域;一种基于高密度连通区域的基于密度的聚类方法,该算法将具有足够高密度的区域划分为簇,并在具有噪声的空间数据中发现任意形状的簇。

     

    基于网格的聚类算法

    基于网格的方法把对象空间量化为有限数目的单元,形成一个网格结构。所有的聚类操作都在这个网格结构(即量化空间)上进行。这种方法的主要优点是它的处理速度很快,其处理速度独立于数据对象的数目,只与量化空间中每一维的单元数目有关。但这种算法效率的提高是以聚类结果的精确性为代价的。经常与基于密度的算法结合使用。

    代表算法有STING算法、CLIQUE算法、WAVE-CLUSTER算法等。

     

    2.新发展的方法

    基于约束的方法:

    真实世界中的聚类问题往往是具备多种约束条件的 , 然而由于在处理过程中不能准确表达相应的约束条件、不能很好地利用约束知识进行推理以及不能有效利用动态的约束条件 , 使得这一方法无法得到广泛的推广和应用。这里的约束可以是对个体对象的约束, 也可以是对聚类参数的约束 , 它们均来自相关领域的经验知识。该方法的一个重要应用在于对存在障碍数据的二维空间数据进行聚类。COD (Clustering with Ob2structed Distance) 就是处理这类问题的典型算法 , 其主要思想是用两点之间的障碍距离取代了一般的欧氏距离来计算其间的最小距离。


    基于模糊的聚类方法:

    基于模糊集理论的聚类方法,样本以一定的概率属于某个类。比较典型的有基于目标函数的模糊聚类方法、基于相似性关系和模糊关系的方法、基于模糊等价关系的传递闭包方法、基于模糊图论的最小支撑树方法,以及基于数据集的凸分解、动态规划和难以辨别关系等方法。

    FCM模糊聚类算法流程:

    标准化数据矩阵;

    建立模糊相似矩阵,初始化隶属矩阵;

    算法开始迭代,直到目标函数收敛到极小值;

    根据迭代结果,由最后的隶属矩阵确定数据所属的类,显示最后的聚类结果。


    基于粒度的聚类方法:

    基于粒度原理,研究还不完善。

    量子聚类:

    受物理学中量子机理和特性启发,可以用量子理论解决聚类记过依赖于初值和需要指定类别数的问题。一个很好的例子就是基于相关点的 Pott自旋和统计机理提出的量子聚类模型。它把聚类问题看做一个物理系统。许多算例表明,对于传统聚类算法无能为力的几种聚类问题,该算法都得到了比较满意的结果。

    核聚类:

    核聚类方法增加了对样本特征的优化过程,利用 Mercer核把输入空间的样本映射到高维特征空间,并在特征空间中进行聚类。核聚类方法是普适的,并在性能上优于经典的聚类算法,它通过非线性映射能够较好地分辨、提取并放大有用的特征,从而实现更为准确的聚类;同时,算法的收敛速度也较快。在经典聚类算法失效的情况下,核聚类算法仍能够得到正确的聚类。代表算法有SVDD算法,SVC算法。

    谱聚类:

    首先根据给定的样本数据集定义一个描述成对数据点相似度的亲合矩阵,并计算矩阵的特征值和特征向量,然后选择合适的特征向量聚类不同的数据点。谱聚类算法最初用于计算机视觉、VLSI设计等领域,最近才开始用于机器学习中,并迅速成为国际上机器学习领域的研究热点。

    谱聚类算法建立在图论中的谱图理论基础上,其本质是将聚类问题转化为图的最优划分问题,是一种点对聚类算法。

     



    以上是关于一文读懂层次聚类(Python代码)的主要内容,如果未能解决你的问题,请参考以下文章

    一文读懂聚类算法

    如何在 python Scikit-learn 中获得凝聚聚类“质心”

    独家一文读懂聚类算法

    技术工具一文读懂聚类算法

    转发技术贴:一文读懂聚类算法

    算法笔记 | 一文读懂K-means聚类算法