首先,聚类属于机器学习的无监督学习,方法有很多,比如大家熟知的K-means。层次聚类也是聚类的一种,也是很常用的。先简单回顾一下K-means的基本原理,再慢慢介绍层次聚类的定义和层次步骤,这样会更有利于大家的理解。层次聚类与K均值有何不同?K-means的工作原理可以简单概括如下:确定簇的个数(k)从数据中随机选取k个点作为质心将所有点分配给最近的簇质心计算新形成的簇的质心重复步骤3而4这是一个迭代过程,直到新形成的簇的质心不变,或者达到最大迭代次数。然而,K-means有一些缺点。我们必须在算法开始前确定簇的个数K,但实际上我们并不知道应该有多少个簇,所以一般根据自己的理解来定一个值。这可能导致我们的理解与实际情况存在一些偏差。层次聚类则完全不同。它不需要我们一开始就指定簇的个数,而是在整个层次聚类先形成之后,通过确定合适的距离,就可以自动找到对应的簇数和簇数。什么是层次聚类?下面由浅入深介绍一下什么是层次聚类。让我们从一个简单的例子开始。假设我们有以下几个点,我们想对它们进行分组:我们可以将这些点中的每一个分配到一个单独的簇中,即4个簇(4种颜色):然后根据这些簇的相似性(距离),将最相似的分组(最近的)点在一起并重复该过程,直到只剩下一个集群:以上本质上是在构建层次结构。先了解这个,后面会详细介绍它的分层步骤。层次聚类的类型层次聚类主要有两种类型:AgglomerativeHierarchicalClusteringSplitHierarchicalClusteringAgglomerativeHierarchicalClustering首先让所有的点成为一个单独的簇,然后继续通过相似性将它们组合起来,直到最后只有一个簇为止,这就是凝聚层次聚类的过程,和我们刚才说的一致。拆分层次聚类拆分层次聚类正好相反。它从单个簇开始,逐渐分裂,直到不能分裂为止,即每个点都是一个簇。所以无论是10、100、1000个数据点都无所谓,一开始这些点都属于同一个簇:现在,在每次迭代中,拆分簇中距离最远的两个点,重复这个过程,直到每个聚类只包含一个点:以上过程就是分裂层次聚类。进行层次聚类的步骤上面已经讲了层次聚类的大致过程,关键是,如何判断点之间的相似度呢?这是聚类中最重要的问题之一。计算相似度的一般方法是计算这些聚类的质心之间的距离。距离最小的点称为相似点,我们可以合并它们,或者我们可以将其称为基于距离的算法。同样在hierarchicalclustering中,有一个概念叫做proximitymatrix,它存储了每个点之间的距离。下面我们通过一个例子来了解如何计算相似度、邻近矩阵以及层次聚类的具体步骤。示例介绍假设一位老师要将学生分成不同的组。现在我有了作业中每个学生的分数,想根据这些分数将他们分组。关于拥有多少组,这里没有设定目标。由于老师不知道应该将哪种类型的学生分配到哪个组,因此无法将其作为监督学习问题来解决。接下来,我们将尝试应用层次聚类将学生分为不同的组。下面是5个同学的结果:创建一个邻近矩阵首先,我们需要创建一个邻近矩阵,存储每个点对之间的距离,所以我们可以得到一个形状为nXn的方阵。在这种情况下,可以得到如下5×5的邻近矩阵:矩阵中有两点需要注意:矩阵的对角线元素始终为0,因为点与自身的距离始终为0。使用欧几里德distance公式来计算非对角线元素的距离例如我们要计算点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仓库:https://github.com/xiaoyusmd/PythonDataScience,如果觉得有帮助请给个star吧!此数据来自UCI机器学习存储库。我们的目标是根据批发商的客户每年在不同产品类别(如牛奶、杂货、地区等)上的支出来细分客户。首先,对数据进行标准化,以使所有数据都在同一维度上,以便于计算,以及然后应用层次聚类来细分客户。fromsklearn.preprocessingimportnormalizedata_scaled=normalize(data)data_scaled=pd.DataFrame(data_scaled,columns=data.columns)importscipy.cluster.hierarchyasshcplt.figure(figsize=(10,7))plt.title("树状图")dend=shc.dendrogram(shc.linkage(data_scaled,method='ward'))x轴包含所有样本,y轴表示这些样本之间的距离。距离最大的垂直线是蓝线。假设我们决定用6的阈值切割树状图:plt.figure(figsize=(10,7))plt.title("Dendrograms")dend=shc.dendrogram(shc.linkage(data_scaled,method='ward'))plt.axhline(y=6,color='r',linestyle='--')现在我们有两个集群,我们想对这两个集群应用层次聚类:fromsklearn.clusterimportAgglomerativeClusteringcluster=AgglomerativeClustering(n_clusters=2,affinity='euclidean',linkage='ward')cluster.fit_predict(data_scaled)由于我们定义了2个集群,因此我们可以看到0和1值。0表示属于第一个聚类的点,1表示属于第二个聚类的点。plt.figure(figsize=(10,7))plt.scatter(data_scaled['Milk'],data_scaled['Grocery'],c=cluster.labels_)到这里我们就成功的完成了聚类。
