在进行机器学习时,我们往往要对数据进行聚类分析,聚类,说白了就是把相似的样品点/数据点进行归类,相似度高的样品点会放在一起,这样一个样本就会被分成几类。而聚类分析也有很多种方法,比如分解法、加入法、有序样品的聚类、模糊聚类法以及系统聚类法等。而本文要介绍的就是系统聚类法,以及如何用python来进行系统聚类分析。

首先来看一下系统聚类法的定义。系统聚类法( hierarchical clustering method ),又叫分层聚类法,是目前最常用的聚类分析方法。其基本步骤如下:假设样本中有n个样品,那么就先将这n个样品看作n类,也就是一个样品一个类,然后将性质最接近的两类合并为一个新的类,这样就得到n-1个类,接着从中再找出最接近的两个类,让其进行合并,这样就变为n-2个类,让此过程持续进行下去,最后所有的样品都归为一类,把上述过程绘制成一张图,这个图就称为聚类图,从图中再决定分为多少类。其大致过程如图1所示。

图1. 系统聚类分析示意图

而这里我们要确定各个样品的相似度,才能将其归类,那么如何确定其相似度呢?通常我们用的方法是计算各个样品点之间的距离,然后再根据距离来分类。这里我们根据距离来分类,同样也是有几种方法的,比如最短距离法、最长距离法、重心法、类平均法以及ward法。下面我们对这几种方法进行一个简单的介绍。

1. 最短距离法

最短距离法就是从两个类中找出距离最短的两个样品点,如图2所示。点3和点7是类G1和类G2中距离最短的两个点。计算公式如图4所示。

图2. 最短距离法示意图

2. 最长距离法

最长距离法就是从两个类中找出距离最长的两个样品点,如图3所示。点1和点6是类G1和类G2中距离最长的两个点。计算公式如图4所示。

图3. 最长距离法示意图

3. 重心法

从物理的观点看,一个类用它的重心,也就是类样品的均值,来做代表比较合理,类之间的距离也就是重心之间的距离。若样品之间用欧氏距离,设某一步将类G1与G2合并成G3,它们各有 n1、n2、n3 个样品,其中 n3=n1+n2 ,它们的重心用X1、X2和X3表示,则 X3=1/n3(n1X1+n2X2) 。重心法的计算公式参考图4。

4. 类平均法

这个顾名思义,就是取两个类之间所有点的距离的平均值。计算公式如图4所示。

图4. 常用的距离计算方法

5. 离差平方和法

离差平方和法又叫Ward法,其思想源于方差分析,即如果类分得正确,同类样品的离差平方和应当较小,类与类之间的离差平方和应该较大。计算公式如图4所示。

在了解了系统聚类法的基本知识以后,我们就用python代码来展示一下系统聚类法的具体使用。

首先还是导入各种库。

import numpy as np
from matplotlib import pyplot as plt
from scipy.cluster.hierarchy import dendrogram, linkage
 

接下来是生成数据集。我们这次用的数据集是随机生成的,数量也不多,一共15个数据点,分为两个数据簇,一个有7个数据点,另一个有8个。之所以把数据点数量设置这么少,是因为便于看清数据分布,以及后面画图时容易看清图片的分类。代码如下。

state = np.random.RandomState(99) #设置随机状态
a = state.multivariate_normal([10, 10], [[1, 3], [3, 11]], size=7)  #生成多元正态变量
b = state.multivariate_normal([-10, -10], [[1, 3], [3, 11]], size=8)
data = np.concatenate((a, b)) #把数据进行拼接
 

这里我们设置一个随机状态,便于重复试验。然后利用这个随机状态生成两个变量a和b,这两个变量就是前面说过的数据簇,a有7个数据点,b有8个,a和b都是多元正态变量,其中a的均值向量是[10, 10],b的均值向量是[-10, -10],两者协方差矩阵是[[1, 3], [3, 11]]。这里要注意的是协方差矩阵要是正定矩阵或半正定矩阵。然后对a与b进行拼接,得到变量data。

接下来要绘制数据点的分布。代码如下。

fig, ax = plt.subplots(figsize=(8,8)) #设置图片大小
ax.set_aspect('equal') #把两坐标轴的比例设为相等
plt.scatter(data[:,0], data[:,1])
plt.ylim([-30,30]) #设置Y轴数值范围
plt.xlim([-30,30])
plt.show()
 

这里代码比较简单,不再赘述,主要说一下ax.set_aspect('equal')这行代码,因为matplotlib默认情况下x轴和y轴的比例是不同的,也就是相同单位长度的线段,在显示时长度是不一样的,所以要把二者的比例设为一样,这样图片看起来更协调更准确。所绘制图片如图5所示,从图中可以明显看到两个数据簇,上面那个数据簇大概集中在坐标点[10, 10]附近,而下面那个大概集中在[-10, -10]附近,这和我们设置的是一样的。从图中可以很明显看出,这个数据集大概可以分为两类,即上面的数据簇分为一类,下面的数据簇分为另一类,但我们还要通过算法来计算一下。

图5. 所用数据分布图

然后是数据处理,代码如下。

z = linkage(data, "average") #用average算法,即类平均法
 

数据处理只有这一行代码,非常简单,但难点也就在这。首先我们来看一下z的结果,如图6所示。

图6. 聚类计算结果

很多人第一次看到这个结果都是一脸懵逼,甚至是n脸懵逼,但其实里面的道理很简单。scipy官方对此有一些设定,比如该结果中第一行有4个数字,即11、13、0.14740505、2,前两个数字就是指“类”,刚开始每个点就是一个类,所以11和13这两个点就是两个类,第三个数字0.14740505就是这两个点的距离,这两个点被合并成一个类,所以这个新的类包含两个点(11和13),这也就是第四个点的数值2,而这个新的类就被算为类15。注意这里是类15,不是第15个类,因为我们原来的数据集中有15个点,按照顺序就是类0、类1、类2...类14,因为python是从0开始,所以这里类15就是指第16个类。z的第二行数据里,前两个数字是2和5,就是原来类2和类5,距离是0.3131184,包含2个点,这行数据和第一行类似。然后再看第三行数据,前两个数字是10和15,就是类10与类15,类15就是前面第一行合并成的新类,其包含11和13这两个点,类15与类10的距离是0.39165998,这个数字是类11和13与类10的平均距离,因为我们这里用的算法是average,类10、11和13合并为了一个新类,其包含3个点,所以第四个数字就是3。z中其他行的数据按照此规律以此类推。最后一行数据中,类26和27合并成一个新类,这个类包含了全部15个点,也就是这15个点最终划为了一个类,算法终止。

接下来就是画图,代码如下,其结果如图7所示。

fig, ax = plt.subplots(figsize=(8,8))
dendrogram(z, leaf_font_size=14) #画图
plt.title("Hierachial Clustering Dendrogram")
plt.xlabel("Cluster label")
plt.ylabel("Distance")
plt.axhline(y=10) #画一条分类线
plt.show()
 

图7. 聚类结果图

从图中可以看出,这15个点可以分为两类,前面绿色的线连接的点代表一类,即点0到点6这7个点,后面红色的线连接的点代表第二类,即点7到点14这8个点。我们可以看到这个划分结果是非常正确的,和我们当时的设定是一样的。

系统聚类法的算法比较简单,实用性非常高,是目前使用最广泛的聚类方法,但该方法在处理极大数据量时会有所不足,所以最好配合其他算法来使用,同时使用者在使用时要根据自己的情况,来选择合适的距离计算方法。本文主要用类平均法来进行聚类操作,因为这个数据集非常简单,所以用其他距离计算方法得到的结果和这个是一样的。如果数据量比较大时,最终不同距离计算方法得到的结果可能不同,所以使用者要根据自己的情况来进行选择。

作者简介:Mort,数据分析爱好者,擅长数据可视化,比较关注机器学习领域,希望能和业内朋友多学习交流。

赞 赏 作 者

Python中文社区作为一个去中心化的全球技术社区,以成为全球20万Python中文开发者的精神部落为愿景,目前覆盖各大主流媒体和协作平台,与阿里、腾讯、百度、微软、亚马逊、开源中国、CSDN等业界知名公司和技术社区建立了广泛的联系,拥有来自十多个国家和地区数万名登记会员,会员来自以工信部、清华大学、北京大学、北京邮电大学、中国人民银行、中科院、中金、华为、BAT、谷歌、微软等为代表的政府机关、科研单位、金融机构以及海内外知名公司,全平台近20万开发者关注。

推荐阅读:

一文读懂高并发情况下的常见缓存问题

用 Django 开发基于以太坊智能合约的 DApp

一文读懂 Python 分布式任务队列 celery

5 分钟解读 Python 中的链式调用

用 Python 创建一个比特币价格预警应用

▼点击成为社区会员   喜欢就点个在看吧

在进行机器学习时,我们往往要对数据进行聚类分析,聚类,说白了就是把相似的样品点/数据点进行归类,相似度高的样品点会放在一起,这样一个样本就会被分成几类。而聚类分析也有很多种方法,比如分解...
何为聚类分析 聚类分析聚类是对一组对象进行分组的任务,使得同一组(称为聚类)中的对象(在某种意义上)与其他组(聚类)中的对象更相似(在某种意义上)。它是探索性数据挖掘的主要任务,也是统计 数据分析的常用技术,用于许多领域,包括机器学习,模式识别,图像分析,信息检索,生物信息学,数据压缩和计算机图形学。 聚类分析本身不是一个特定的算法,而是要解决的一般任务。它可以通过各种算法来实现,这些算法在理解...
Syntgen:一种使用用户指定的拓扑生成时态网络的系统”,以进行网络生成。 请参阅IEEE Xplore存储库(TBD)上的“时间网络中社区生命周期事件的分类法”,以进行生命周期事件分类。 该软件包是一个Python系统,用于生成离散的时间性,非加权性,非重叠性,无方向性网络,这些网络可以显示社区结构。 该系统根据用户规范生成网络,将节点随机链接或受程度分类规范的约束,并提供用户提供的社区大小序列,以及节点总数和社区内程度的双射。 提供幂律和其他分布采样器作为序列生成器的示例。 系统尝试在连续的时间转换中保持群集之间的最小共享信息距离。 用户可以在每次转换时更改序列,并删除选定的节点。 可能的用例: 在时态网络上运行的测试和基准测试算法,例如社区检测和进化算法; 实验研究网络指标的相关性; 分析不同网络属性下的经验网络(通过从经验时间网络加载社区序列,节点度和节点生命周期数据)。 Python 库:numpy,itertools,ran K-means 聚类是一种矢量量化方法,最初来自信号处理,在数据挖掘中流行用于聚类分析。 k-means聚类旨在将n个观测值划分为k个簇,其中每个观测值都属于具有最近均值的簇,作为簇的原型。 这导致将数据空间划分为 Voronoi 该代码实现了 K-means 算法并在一个简单的 数据集上对其进行了测试。 在这个例子中,我们首先从三个正态分布生成一个点数据集并标记数据集。 这个带有正确标签的数据集是我们的真实值。 然后我们重新调整标签并为新数据集运行 k-means 该算法正确地对数据集进行聚类,并估计聚类的中心。 在最后一步,我们将我们的结果与 Mathworks k-means 的结果进行比较。 我在我的机器上得到的结果如下: iteration: error: 1.8122, [-0.2165 4.0360], [4.2571 0.0152], [-1.1291 -3.0925] iterati
聚类聚类分析是无监督学习问题。它通常被用作数据分析技术,用于发现数据中的有趣模式,例如基于其行为的客户群。有许多聚类算法可供选择,对于所有情况,没有单一的最佳聚类算法。相反,最好探索一系列聚类算法以及每种算法的不同配置。在本教程中,你将发现如何在 python 中安装和使用顶级聚类算法。 完成本教程后,你将知道: 聚类是在输入数据的特征空间中查找自然组的无监督问题。 对于所有数据集,有许多不同的聚类算法和单一的最佳方法。 在 scikit-learn 机器学习库的 Python 中如何实现、适
聚类算法是在没有给定划分类别的情况下,根据数据相似度进行样本分组的一种方法,是一种无监督学习方法。聚类的输入是一组未被标记的样本,聚类根据数据自身的距离或相似度将他们划分为若干组,划分的原则是组内样本最小而组间距离最大化。 常用的聚类方法有: 常见的聚类分析算法有: 这里主要介绍一下最常用的K-Means聚类算法 一、K-Means聚类算法简介 K-Means算法是典型的基于距离的非层次聚类算法,在最小化误差函数的基础上将数据划分为预定的类数k,采用距离作为相似性评价指标,即认为两个对象的
from sklearn.cluster import KMeans #导入K均值聚类算法 import matplotlib.pyplot as plt import numpy as np import pandas as pd import os os.chdir(r'') datafile= r'air_data-utf8.csv' #原始数据文件 读数...
设计了一个分类、预测、聚类系统,每个系统选择不同的算法进行训练,选择适了多个指标对模型进行评估,采用可视化方法对结果进行分析。 其中,分类系统中采用k-近邻算法、贝叶斯分类器、决策树分类、AdaBoost、GBDT、随机森林、逻辑回归等 预测系统中采用贝叶斯网络、马尔科夫模型、线性回归、XGBoost、岭回归、多项式回归、决策树回归预测算法等 聚类系统中采用K-means、层次聚类BIRCH、密度聚类DBSCAN算法等 博主前期科研工作中,涉及到要对某个地区的一些空间点进行聚类分析,想到读研期间,曾经用DBSCAN聚类算法实现了四线激光雷达扫描的三维点云数据聚类(论文题目:基于改进DBSCAN算法的激光雷达目标物检测方法),当初用matlab实现的,虽说是改进的算法,但改进方法非常原始。DBSCAN是一种非常实用的密度聚类算法,而地理空间的经纬度点聚类,没有其他维度的信息的话,毫无疑问可以用密度聚类。于是博主重新熟悉了一下算法,并做了一些改进,用Python实现,记录在博客里面。 编译环境:Python3.7 iris = datasets.load_iris() X = iris.data df = pd.DataFrame(data=X, columns=iris.feature_names) 数据集的特征名称以及每个样本的特征值都存储在数据框df中。 接下来,我们使用scikit-learn中的AgglomerativeClustering()函数来进行系统聚类分析。这里我们设定n_clusters为3,表示我们要将Iris数据集分成3个簇。 ```python from sklearn.cluster import AgglomerativeClustering agg = AgglomerativeClustering(n_clusters=3) agg.fit(X) 我们可以使用labels_属性来获取每个样本所属的簇号。 ```python labels = agg.labels_ print(labels) 最后,我们可以将结果可视化。这里我们仍然选择使用Iris数据集,仅画出前两个特征值的图形。 ```python import matplotlib.pyplot as plt plt.scatter(X[:,0], X[:,1], c=labels) plt.xlabel('Sepal length') plt.ylabel('Sepal width') plt.show() 通过上述代码,我们可以轻松实现Python系统聚类分析,可视化结果也使得我们更好地理解聚类后的数据结构。