Python中的分层聚类技术入门
分层聚类是流行的无监督学习算法之一。分层聚类的名字来自于层次结构这个词,这个词意味着根据事物的重要性进行排序。
这就是分层聚类的作用。它在数据集中找到具有类似属性的元素,并将它们归入一个聚类。
最后,我们得到一个单一的大聚类,其主要元素是数据点的聚类或其他聚类的聚类。层次聚类以两种方式处理聚类问题。让我们来看看这两种分层聚类的方法。
前提条件
要继续学习,你需要具备以下条件
- 在你的电脑上安装了Python 3.6或以上版本。
- 具有Python编程语言的知识。
分层聚类的类型
聚合式聚类
在这种聚类方法中,我们从聚类的叶子开始,然后向上移动,直到最后得到聚类的根。最初,这种方法假设数据集中的每个数据点都是一个独立的聚类。
在开始时,每个数据点都被认为是一个单元素的聚类(叶子)。由于每一步都会将两个最相似的聚类合并,因此我们在每次迭代中得到的聚类都比前一次迭代少。
这个过程一直持续到我们获得一个大聚类(根),其元素是具有可比性的聚类。一旦所有聚类完成,我们用散点图将数据聚类可视化。
我们可以通过考虑下面的流程图来进一步加强对这个算法的理解。

源于此。显示r
在这个流程图中,我们假设一个有N个元素的数据集,其中N=6。 以下是上述聚类所涉及的步骤。
- 第1步:最初,假设每个数据点是一个独立的聚类,即6个聚类。
- 第2步:进入一个聚类,将两个最接近的数据点合并。通过这样做,我们最终得到了5个聚类。
- 第3步:再次将两个最接近的聚类合并成一个聚类。通过这样做,我们最终得到了4个聚类。
- 第4步:重复上述第三步,直到获得所有数据点的单一集群。
如果我们将树状图可视化,我们应该得到一个树状结构,根部在顶部,如下图所示。

一般来说,这就是聚类算法的特点。
分裂式聚类
分裂式聚类是一种自上而下的方法。换句话说,我们可以很自如地说这是一个与聚类法相反的顺序。在聚类的开始,所有的数据点都被认为是同质的,因此它从所有数据点的一个大聚类开始。
然后,在每个聚类迭代中,最异质的一组被分成两个不同的聚类,使它们的方差减少。这个过程一直持续到达到所有最优的聚类数量。
然而,在现实世界中,Divisive聚类的初始假设,即数据是同质的,比Agglomerative聚类的假设,即所有的数据点都是不同的,所占的权重较小。这使得这种算法在聚类任务中的利用率低于聚集聚类。
因此,本文将密切关注聚集式聚类,因为它是我们在未来聚类任务中最有可能应用的算法。
我们的聚集聚类算法谈到了。那么,我们如何确定集群之间有多大的距离?
在机器学习中,有各种距离指标,我们可以利用这些指标来衡量各点之间的距离。
这些指标包括。
- 欧几里得距离
- 明斯基距离
- 汉明距离
- 曼哈顿距离
与其他度量标准相比,欧氏距离在距离测量中显示出广泛的使用范围。这个度量的计算方法是:

既然我们知道了这些度量,我们就可以使用和测量固定点之间的距离。
现在是时候回去回答我们的问题了;我们如何在聚类之间进行这种测量?
当我们谈论集群的时候,我们指的是一组点。为了测量这些点组之间的距离,我们需要制定一个明确的方法来加强我们聚类任务的一致性。
两个聚类之间的距离可以采取五种不同的方法。这些方法一般被称为联结法。
让我们看看它们,并尝试了解它们是如何工作的。
- 单一链接法:这种方法计算两个聚类中所有元素对之间的异同度。最小的不相似度才有资格成为两个聚类之间的距离。这在下图中得到了说明。

- 完全链接法:这种方法计算两个聚类中所有元素对之间的异同度。最大的相异性就是两个集群之间的距离。这在下图中得到了说明。

- 平均联系:这种方法通过寻找两个聚类之间所有可能的不相似性来计算两个聚类之间的距离。然后对所有的不相似性进行平均,然后将平均值作为这些聚类之间的距离。
- 中心点连接法:这种方法包括将每个聚类置于中心位置,然后测量所获得的两个聚类的中心之间的距离。

- 沃德最小方差法:沃德距离是一个比较好的衡量标准,用于取舍聚类之间的距离。这种方法寻找的是总的偏差。例如,如果我们有两个聚类,我们可以假装将它们合并成一个聚类,然后估计所得到的聚类的中心点。之后,我们找到所有点与新中心点的偏差平方之和。对于不同的合并,我们将得到其他的变化。因此,我们选择具有最小合并的距离作为我们的距离。
实施分层聚类
现在是将我们上面讨论的所有内容付诸行动的时候了。在这里,我们将使用一个真实世界的数据集来实现一个聚类模型,最后直观地看到该模型如何从数据中发现各种聚类。
一旦我们下载了我们的数据,第一件事就是为这个环节导入所有必要的库。下面的代码导入了这些库。
导入必要的库
import numpy as np # to handle numeric data
import matplotlib.pyplot as plt # for visualization
import pandas as pd # for handling dataframe
读取数据集到工作区
现在我们的库已经导入,让我们把数据读到我们的工作区,并使用head() 函数打印前五行。
ourData = pd.read_csv('Mall_Customers.csv') # read the data
ourData.head() # print the first five rows of our dataset

我们将使用这个数据集在Annual Income (k$) 和Spending Score()1-100 列上实现我们的分层聚类模型。因此,我们需要从我们的数据集中提取这两个特征。下面的代码完成了这项活动。
newData = ourData.iloc[:, [3, 4]].values # extract the two features from our dataset
我们的newData的两个特征几乎在同一尺度上。因此,我们不需要将数据的规模扩大。然而,情况并不总是这样的。
我们将与那些数值完全在不同尺度上的数据集一起工作。在这种情况下,我们必须对数据进行缩放,使各种特征具有可比性;否则,我们最终会得到一个劣质的模型。原因是分层聚类,像机器学习中的许多其他算法一样,是基于距离的(欧氏距离)。
在尝试对我们的数据进行聚类之前,我们需要知道我们的数据能被最佳地聚类到多少个集群。因此,让我们首先在我们的数据集上实现一个树状图,以获得这种知识。
用树状图确定最佳的聚类数量
下面的代码将在我们的数据集上建立一个树状图。
import scipy.cluster.hierarchy as sch # importing scipy.cluster.hierarchy for dendrogram
dendrogram = sch.dendrogram(sch.linkage(X, method = 'ward')) # finding the optimal number of clusters using dendrogram
plt.title('Dendrogram') # title of the dendrogram
plt.xlabel('Customers') # label of the x-axis
plt.ylabel('Euclidean distances') # label of the y-axis
plt.show() # show the dendrogram
输出
上面的代码返回一个树状图,如下图所示。

考虑到上面的树状图,可以按以下方法确定最优的集群数量;假设,推断整个树状图的所有水平线,然后找到不与这些假设线交叉的最长的垂直线。
在这条最长的线上,建立一个阈值。我们可以对数据进行最佳聚类的数量等于所建立的阈值所跨越的欧几里得距离(垂直线)的数量。
在我们刚刚得到的树状图中,没有延伸的水平线交叉的最长垂直线是在绿色部分。第三条线是在欧氏距离(110-250)之间。以我们的阈值为150,得到的最佳集群数是5个。
知道了我们的数据应该聚类的最佳数量;我们现在可以训练我们的聚类模型来实现这个目标。
分层聚类模型在数据上的训练
from sklearn.cluster import AgglomerativeClustering # this line of code imports AgglomerativeClustering model from sk-learn
'''
we need to create an AgglomerativeClustering object, and in it, we pass the following parameters:
n_cluster= 5, the number of clusters our model should return
affinity=euclidean, specify metric to be used to calculate distances
linkage= ward to regulate how distance calculation will be carried out between different clusters.
'''
Agg_hc = AgglomerativeClustering(n_clusters = 5, affinity = 'euclidean', linkage = 'ward')
y_hc = Agg_hc.fit_predict(newData) # model fitting on the dataset
上面的代码训练了我们的模型,我们现在可以继续并可视化数据是如何聚类的。要做到这一点,请运行下面的代码。
聚类通过可视化
# plotting cluster 1
plt.scatter(newData[y_hc == 0, 0], newData[y_hc == 0, 1], s = 100, c = 'red', label = 'Cluster 1') # plotting cluster 2
plt.scatter(newData[y_hc == 1, 0], newData[y_hc == 1, 1], s = 100, c = 'blue', label = 'Cluster 2') # plotting cluster 3
plt.scatter(newData[y_hc == 2, 0], newData[y_hc == 2, 1], s = 100, c = 'green', label = 'Cluster 3') # plotting cluster 4
plt.scatter(newData[y_hc == 3, 0], newData[y_hc == 3, 1], s = 100, c = 'cyan', label = 'Cluster 4') # plotting cluster 5
plt.scatter(newData[y_hc == 4, 0], newData[y_hc == 4, 1], s = 100, c = 'magenta', label = 'Cluster 5')
# plot title addition
plt.title('Clusters of customers')
# labelling the x-axis
plt.xlabel('Annual Income (k$)')
# label of the y-axis
plt.ylabel('Spending Score (1-100)')
# printing the legend
plt.legend()
# show the plot
plt.show()

关于分层聚类,我们需要知道的最后一个细节是,它的时间和空间都很复杂,因此不适合用于大数据集的聚类问题。
总结
在这篇文章中,我们看了分层聚类和它的类型。首先,我们了解了这些类型的分层聚类是如何工作的,后来得出结论,最合适的类型是聚集型聚类。
我们还研究了用于测量数据点之间距离的各种方法以及指导我们如何进行这些测量的标准(墨迹方法)。
最后,我们实现了我们的模型,在这个过程中,我们学会了如何使用树状图获得最佳的聚类数量。