机器学习实战之路 —— 6 聚类算法

1. 聚类相关概述

1.1 学习模式

机器学习的核心是机器使用算法分析海量数据,通过学习数据,挖掘数据中存在的潜在联系,并训练出一个有效的模型,将其应用于决定或预测。目前,机器学习大致分为监督学习和无监督学习这两种基本类型。

1.1.1 监督学习

监督学习:在监督学习中,数据已被标记。换句话说,我们已经确定了分类标准。计算机使用训练模型来识别每种标记类型的新样本,确定该变量的输出值。此时,我们得到的结果可能是个连续值(即回归任务),也可能是一个离散值(即分类任务)。监督学习的常见基本算法在前面的章节已有介绍:Logistic回归、决策树与随机森林、Adaboost 算法、支持向量机等,可参见博主前面的博客。

1.1.2 无监督学习

现实生活中,针对数据的获取我们经常会遇到这样的问题:
(1)数据具有非常强的行业特性,对数据进行标注时,必须通过有相关经验的人来进行操作;
(2)对于数量非常大的训练数据,进行人工标注费时费力,成本很高。
因此,我们希望机器可以自动解决上述问题,无监督学习方法可以作为解决方案。
无监督学习(unsupervised learning):与监督学习相反,在无监督学习中,数据没有被标记。换句话说,我们还不清楚数据的分类标准。通常情况下,当面对众多的数据却缺乏了解时,我们可以使用无监督学习,利用机器先将这些陌生的数据挖掘出某些潜在的共性,并对它们聚类。因此,无监督学习中机器划分的类,是我们之前未知的。比方说,我们使用机器给大量未知特征的图片聚类,观察机器得出的结果我们才发现,在两个类簇中,一类图片都是人像,另一类则都是风景画。
无监督学习和监督学习具有以下几方面的不同点:
(1)监督学习需要同时提供训练数据和测试数据,而无监督学习不需要测试数据;
(2)无监督方法的输入只是数据本身,而不包含数据类型标签或者其它用于模型学习的标签,监督学习的训练数据集必须包含标签;
(3)无监督学习的结果不一定是分类,而是在数据集中寻找规律。

1.2 聚类分析

1.2.1 基本概念

聚类(clustering)就是一种研究最多、应用最广的无监督学习。聚类的主要任务就是根据待分类模式特征的相似或相异程度将数据进行归类,从而使同一类的数据尽可能相似,不同类的数据尽可能相异。在人们对数据一无所知的前提下,聚类分析能够“智能”的揭示数据之间的内在联系和区别,发现其中内在的结构和规律,因此,聚类分析技术已经广泛应用于许多关键的领域,例如图象分割、人工智能、语音识别、指纹分类、信息检索等。在无人驾驶场景中的环境感知方案研究中,K-Means聚类或DBSCAN聚类方法广泛应用于车辆障碍物的检测研究。

1.2.2 基本步骤

为了更好的研究聚类分析技术,一般将其分为如下四个步骤:特征选择和提取、聚类算法设计或选择、聚类有效性评估和聚类结果解释。其基本流程和关系可以用下图来表达:

在这里插入图片描述

一、特征选择和提取
数据集过多的特征常常会在聚类过程中产生干扰,从而降低聚类算法的效率和性能。特征选择和提取的基本任务就是从数据集的众多特征中找出那些最有效的特征,即把数据点从高维特征空间映射到低维特征空间,从而使数据集包含的各个簇之间更易于区分。通常来说,理想的特征应该能够突出同类数据之间的共性和不同类数据之间的差异,并对噪声有较强的免疫能力。此外,合理的特征选择和提取能够简化算法设计的复杂度和提高算法的效率。
二、聚类算法设计或选择
聚类算法的设计和选择是聚类分析的关键环节,主要包括以下两个方面数据点之间相似性度量的选取和最优划分准则的构建。显然,相似性度量用于衡量数据点之间的相似或相异程度,是影响聚类分析效果的基础。由于来自不同领域的数据千差万别,有其自身的结构特点,因此在选取相似性度量时应该充分考虑数据集的结构特点。另一方面,在设计聚类算法时,需要通过构建目标准则函数来指导聚类过程向前推进,从而得到数据集的最优划分。本质上,这将聚类问题转化为数学上的优化问题来解决。
三、聚类有效性评价
给定一数据集,不管其内部是否存在合理的结构,任何一个聚类算法都会将其划分成若干个簇。但是,不同的聚类算法所得到的结果往往相差很大即使对于同一算法,不同的参数设置、输入模式顺序的改变也会得到不同的聚类结果。因此根据一定的准则,评估聚类结果的有效性有着重要意义。通常可以把这些准则分成三种:外部准则、内部准则和相对准则。由于不同准则从不同的角度上考虑问题,因此聚类结果的有效性评估往往带有很大的主观性。如何根据实际情况来选择聚类有效性评估准则仍然是值得研究的问题。下面的章节会对有效性评价指标做进一步的展开。
四、聚类结果解释
聚类分析的最终目标是为了给用户提供来自原始数据集有意义的知识,对聚类结果给出合理的解释有助于他们解决问题。这是聚类操作完整流程中与最终用户距离最近的一步,具有重大的实际应用意义。

1.2.3 相似性度量

聚类分析是依照数据样本在本质上的关系亲疏程度来进行划分的。要使得聚类划分足够合理,则首先必须合理地对样本之间的关系亲疏程度进行描述。描述各个样本间的相似性的方法主要有两类:

1.2.3.1 距离度量

假如我们用N个特征变量来描述样本,那么每个样本我们就会得到一个N维向量。此时,每个样本就是N维空间中的一个点。因此可以度量N维空间中每个样本的距离来表示他们的亲疏关系。在聚类中常用的距离度量如下:
(1)闵可夫斯基距离(Minkowski)
d = ( ∑ i = 1 n ∣ x i − y i ∣ p ) 1 / p d=({\sum_{i=1}^n|x_i-y_i|^p})^{1/p} d=(i=1nxiyip)1/p
其中 p 是变量,可能取值1,2,∞。当 p =1 时,称为曼哈顿距离;当 p =2 时,称为欧氏距离;当 p =∞时,称为切比雪夫距离。因此闵可夫斯基表示的是一类距离。欧式距离是人们普遍使用的距离,但它存在以下缺点:没有考虑量纲的问题,若用于处理多元的数据,会对聚类结果产生较大的影响;没有考虑数据各分量的分布。
(2)马氏距离(Mahalanobis)
d = ( x i − y i ) T ∑ i = 1 n − 1 ( x i − y i ) d=(x_i-y_i)^T{\sum_{i=1}^n{^{-1}}(x_i-y_i)} d=(xiyi)Ti=1n1(xiyi)
其中 ∑ i = 1 n − 1 ( x i − y i ) {\sum_{i=1}^n{^{-1}}(x_i-y_i)} i=1n1(xiyi)表示样本的协方差矩阵。马氏距离相比欧式距离,不再受数据对象量纲的影响,且排除了两数据对象之间的相关性,但它存在将微小变化的变量夸大的不足。
(3)兰氏距离(Lance)
d = 1 n ∑ i = 1 n ∣ x i − y i ∣ ∣ x i + y i ∣ d=\frac{1}{n}{\sum_{i=1}^n\frac{|x_i-y_i|}{|x_i+y_i|}} d=n1i=1nxi+yixiyi
兰氏距离是无量纲的量,故不受量纲的影响,且对奇异值不敏感,但它仍没有考虑数据对象间的相关性。

1.2.3.1 相似系数度量

当两个样本越相似的时候,他们之间的相似系数就越接近,越不相似他们之间的相似系数就越接近0。在聚类分析中常用的相似系数如下:
(1)余弦相似度(Cosine Similarity)
S = x ⋅ y ∣ x ∣ ∣ y ∣ S={x \cdot y \over |x| |y|} S=xyxy
余弦相似度是计算两个数据对象所代表向量夹角的余弦值,该值的取值范围为[0,1]。余弦值越接近于 1,两数据对象的相似度越大,相反,相似性越低。当该值为 0 时,两向量正交,表明两数据对象不相关。
(2)皮亚逊相关系数(Pearson Correlation)

分子是两个集合的交集大小,分母是两个集合大小的几何平均值。是余弦相似性的一种形式。
r = ∑ i = 1 n ( X i − x ‾ ) ( y i − y ‾ ) ∑ i = 1 n ( X i − x ‾ ) 2 ∑ i = 1 n ( y i − y ‾ ) 2 r={\sum_{i=1}^n(X_i-\overline x)(y_i-\overline y) \over \sqrt{\sum_{i=1}^n (X_i-\overline x)^2} \sqrt{\sum_{i=1}^n (y_i-\overline y)^2}} r=i=1n(Xix)2 i=1n(yiy)2 i=1n(Xix)(yiy)

1.2.4 有效性评价准则指标

前述可知评估聚类结果的有效性有着重要意义,通常可以把这些准则和指标分成三种:外部准则、内部准则和相对准则,下面将依次展开论述。

1.2.4.1 外部评价准则及指标

外部评价方法意味着判定聚类算法的结果是基于其类的个数及每个数据项的正确的分类都是已知的情况下。下面介绍两种常用的常用的外部有效性指标有V-Measure指标、Rand指标、Jaccard指标等。这些指标将聚类算法产生的聚类结果与数据集的真实划分情况进行比较,评估聚类结果的质量和聚类算法的性能。
(1) V-Measure准则
V-Measure准则将精确率precision与召回率recall的思想相结合,来进行聚类评价,V-Measure值越高,聚类的结果越好。一般概念的precision、recall、F-Measure准则的具体公式描述请参见博主前面的SVM博客章节。
聚类结果中的类簇 j j j与此相关的真实分类 i i i的precision和recall定义如下:

在这里插入图片描述
其中, N i j N_{ij} Nij代表类簇 j j j中类别为 i i i的样本数, N j N_{j} Nj代表类簇 j j j中的样本数, N i N_{i} Ni代表类别 i i i中的样本数。
均一性(Homogeneity)
若一个簇中只包含一个类别的样本,则满足均一性。概念对应精确率,实际计算需遍历每个簇计算,加和求平均。
实现代码如下:

from sklearn.metrics.cluster import homogeneity_score
homogeneity_score(labels_true, labels_pred)

完整性(Completeness)
若同类别样本被归属到相同的簇中,则满足完整性。概念对应召回率,实际计算需遍历每个簇计算,加和求平均。

from sklearn.metrics.cluster import completeness_score
completeness_score(labels_true, labels_pred)

V-measure
整个聚类结果的V-measure计算公式为:
V = ∑ i N i N max ⁡ j ( V − m e a s u r e ( i , j ) ) \begin{aligned} V=\sum_{i}^{}\frac{N_{i}}{N} \max_{j}(V-measure(i,j)) \\ \end{aligned} V=iNNijmax(Vmeasure(i,j))
实现代码如下:

from sklearn.metrics.cluster import v_measure_score
v_measure_score(labels_true, labels_pred)

(2)Rand指标 & Jaccard指标
设数据集X的聚类结果类簇为C={C1,C2,….,Cm},数据集真实划分为P={P1, P2,….,Ps},C中类数m和P中类数s不一定相同,可以通过对C和P进行比较来评价聚类结果的优劣。统计数据集中任一对点的下列项:

SS:两点属于C中同一类,P中同一组
SD:两点属于C中同一类,P中不同组
DS:两点属于C中不同类,P中同一组
DD:两点属于C中不同类,P中不同组

设SS、SD、DS、DD的大小分别用a、b、c、d表示,a和d用来计算两个划分的一致性,b和c则是用来计算其偏差。 M = a + b + c + d = N ∗ ( N − 1 ) / 2 M =a+b+c+d=N*(N-1)/2 M=a+b+c+d=N(N1)/2则为数据集中所有对的最大数。其中N为数据集中点的总数。与之间的相似程度可用如下有效性指标定义:
R a n d 指 数 : R I = ( a + d ) / M J a c c a r d 指 数 : J I = a / ( a + b + c ) \begin{aligned} Rand 指数:RI=(a+d)/M\\ Jaccard 指数:JI=a/( a+b+c) \end{aligned} RandRI=(a+d)/MJaccardJI=a/(a+b+c)
这两个指标取值范围均为[0,1]。当m=s时,即在聚类结果的划分C和数据集真实划分P的类分配完全相同的情况下,RI为1。RI值越小,则表示聚类结果越差。
为了实现“在聚类结果随机产生的情况下,指标应该接近零”,调整兰德系数(Adjusted rand index)被提出,它具有更高的区分度:
A R I = R I − E ∣ R I ∣ m a x ( R I ) − E ∣ R I ∣ ARI = \frac{RI - E|RI|}{ max(RI) - E|RI|} ARI=max(RI)ERIRIERI
ARI取值范围为[−1,1],值越大意味着聚类结果与真实情况越吻合。从广义的角度来讲,ARI衡量的是两个数据分布的吻合程度。
实现代码如下:

from sklearn.metrics.cluster import adjusted_rand_score
adjusted_rand_score(labels_true, labels_pred)
1.2.4.1 内部评价准则及指标

内部评价方法考虑数据集自身的分布特征来对聚类结果进行评价,利用类标签未知的数据集内在固有的量值和特征来评价一个聚类算法的结果。通常内部有效性指标可分为三种类型:基于数据集模糊划分的指标、基于数据集样本几何结构的指标和基于数据集统计信息的指标。其中,基于数据集模糊划分的指标主要对模糊聚类算法的聚类结果进行评估。常用的内部有效性指标有轮廓系数(Silhouette coefficient)、Calinski-Harabasz(CH)指标、戴维森保丁指数(Davies-Bouldin-Index)等。

(1)轮廓系数(Silhouette Coefficient)

较高的 Silhouette Coefficient 得分与具有更好定义的聚类的模型相关。Silhouette Coefficient 是为每个样本定义的,由两个得分组成:

  • a: 样本与同一类别中所有其他点之间的平均距离。
  • b: 样本与 下一个距离最近的簇 中的所有其他点之间的平均距离。

然后将单个样本的 Silhouette 系数 s 给出为:
s = b − a m a x ( a , b ) s = \frac{b - a}{max(a, b)} s=max(a,b)ba
给定一组样本的 Silhouette 系数作为每个样本的 Silhouette 系数的平均值。
轮廓系数S取值范围为[-1,1],取值越接近1则说明聚类性能越好;相反,取值越接近-1则说明聚类性能越差。

实现代码如下:

from sklearn.metrics.cluster import silhouette_score
silhouette_score(X, labels, metric='euclidean')

(2)Calinski-Harabaz
较高的 Calinski-Harabaz 的得分与具有更好定义的聚类的模型相关。类别内部数据的协方差越小越好,类别之间的协方差越大越好,这样的Calinski-Harabasz分数会高。 最大的优势是比轮廓系数快很多。

对于 k 簇,Calinski-Harabaz 得分 s 是作为 between-clusters dispersion mean (簇间色散平均值)与 within-cluster dispersion(群内色散之间)的比值给出的:
s ( k ) = T r ( B k ) T r ( W k ) s(k) = \frac{\mathrm{Tr}(B_k)}{\mathrm{Tr}(W_k)} s(k)=Tr(Wk)Tr(Bk)
其中 B K B_K BK 是 between group dispersion matrix (组间色散矩阵), W K W_K WK 是由以下定义的 within-cluster dispersion matrix (群内色散矩阵):
W k = ∑ q = 1 k ∑ x ∈ C q ( x − c q ) ( x − c q ) T W_k = \sum_{q=1}^k \sum_{x \in C_q} (x - c_q) (x - c_q)^T Wk=q=1kxCq(xcq)(xcq)T

B k = ∑ q n q ( c q − c ) ( c q − c ) T B_k = \sum_q n_q (c_q - c) (c_q - c)^T Bk=qnq(cqc)(cqc)T

N 为数据中的点数, C q ​ C_q​ Cq为 cluster (簇) q 中的点集, C q ​ C_q​ Cq 为 cluster(簇) 的 q 中心,c 为 E 的中心, n q ​ n_q​ nq为 cluster(簇) 中的 q 点数。

实现代码如下:

from sklearn.metrics.cluster import calinski_harabaz_score
calinski_harabaz_score(X, labels)

(2)戴 维 森 保 丁 指 数 ( Davies-Bouldin-Index - DBI )

DBI计算任意两类别的类内距离平均距离(CP)之和除以两聚类中心距离,求最大值。DBI越小意味着类内距离越小,同时类间距离越大。但因使用欧式距离,所以对于环状分布,聚类评测很差。

1.2.4.1 相对评价准则及指标

相对准则评价方法其基本思想是,在同一个数据集上,用同一种聚类算法取不同的输入参数从而得到的相应的聚类结果,对这些不同的聚类结果,再应用已定义的有效性函数作比较来判断最优划分。

2.1 聚类主要算法

已知的聚类分析算法有很多种,同时各种聚类方法也在不断地提出和改进,在实际应用中聚类算法的选择取决于待评判数据的类型和聚类的目的,不同的算法适合于不同类型的数据。根据各种聚类方法的特点,典型的聚类算法可被分成五类:划分法、层次法、基于密度的方法、基于网格的方法、基于模型的方法。
典型的聚类算法及其代表算法的Xmind绘图如下:
在这里插入图片描述

本小节仅给出前三类常用的聚类算法展开论述及实现,以作参考学习。

2.1.1 划分聚类

基于划分的聚类算法是在机器学习中应用最多的。它的原理是:假设聚类算法所使用的目标函数都是可微的,先对数据样本进行初步的分组,再将此划分结果作为初始值进行迭代,在迭代过程中根据样本点到各组的距离反复调整,重新分组,最终得到一个最优的目标函数。最终的聚类结果出现在目标函数收敛的情况下。
K-means 算法是基于划分的聚类算法中的经典算法之一。K-Means是发现给定数据集的 k 个簇的算法。簇个数 k 是用户给定的,每一个簇通过其质心(centroid), 即簇中所有点的中心来描述。 其算法过程伪代码表示如下:

创建k个点作为起始质心(经常是随机选择)
当任意一个点的簇分配结果发生改变时
	对数据集中的每个数据点
		对每个质心
			计算质心与数据点之间的距离
		将数据点分配到距其最近的簇
	对每一个簇,计算簇中所有点的均值并将均值作为质心

其计算过程示意图如下:
在这里插入图片描述

K-means 算法之所以成为经典算法,是它具有的优势决定的:时间复杂度与数据集大小呈线性关系;它收敛于局部最优解。当然没有一种算法是完美的,K-means 算法也具有它自身的缺点: 传统的 K-means 使用欧氏距离,仅适用于球形数据;对噪声和孤立点较为敏感。

2.1.1 层次聚类

基于层次的聚类算法也是一种非常常用的算法,层次聚类把数据对象构建成一组具有树状结构的嵌套簇,除了叶子节点的每个簇都是由其子节点(子簇)的并集构成,根节点包含所有的数据对象。根据层次分解的过程一般分为两类方法:(1) 凝聚法也称为自底向上的方法:从仅包含单个数据对象的簇开始,每次合并最接近的一对簇,直至簇中包含所有数据对象为止。(2) 分裂法也称为自顶向下的方法:它的思路与凝聚法刚好相反,从一个包含所有数据对象的簇开始,每次对簇进行分割,直至簇中仅包含一个数据对象为止。由于分裂型算法具有较高的时间复杂度,与聚合型算法相比,分裂型算法并不常见。两种聚类算法都是在聚类过程中构建具有一定亲属关系的系统树图,聚类的大体过程如下图所示:
在这里插入图片描述
最早的层次聚类算法有 AGNES( AGglomerative NESting)算法、DIANA(DIvisive ANAlysis) 算法,分别是聚合型与分裂型聚类的早期代表。BIRCH算法是一种改进的聚合型层次聚类算法。一般的聚类算法,都是以单一数据点为聚类的中心,导致最终的聚类簇形状是球形的。为了聚类各种形状的簇,可以采用CURE算法。
层次聚类相比于其他聚类在定义不同类别之间更便捷、限制更少;聚类数不需要预先制定,就能识别类的层次关系;可以聚类成其它形状。缺点是具有较高的计算复杂度;奇异值可能影响最终的聚类结果;算法可能聚类成链状。

2.1.1 密度聚类

基于密度的聚类方法是根基数据集密度的大小将数据集分类成簇,密度高的区域聚类成簇,密度低的区域作为噪声和孤立点处理,适用于空间中任意形状的簇,具有很强的抗噪能力。DBSCAN算法是经典的基于密度的聚类算法。其核心思想为:预先设置距离阈值和密度阈值,将数据对象都标记为核心点,任意数据对象由距离阈值确定的范围内不存在核心点,则将其视为噪声点消除。确定出每个距离阈值内的所有满足密度阈值的核心点的边界点,并把每一组连接的核心点分为一个簇,最后将边界点分配给相关核心点的簇。DBSCAN算法中点的分类定义如下:
核心点(Core point):在半径eps内含有超过MinPts数目的点,则该点为核心点。
边界点(Border point):在半径eps内点的数量小于MinPts数目,但是在核心点的邻居,通过核心的可达。
噪音点(Noise point):任何不是核心点或边界点的点。
MinPts:给定点在ε邻域内成为核心对象的最小邻域点数
如下图中,MinPts=4,点C1,C2,…,Cm等红色点都是核心点,因为它们的ε邻域(红色圆圈内)里面包含最少4个点(包括自己),由于它们之间相互可达,它们形成了一个聚类。点B1 − - Bm是边界点,虽然它们不是核心点,但是它们可经其他核心点可达,所以它们也属于同一个聚类。点N1 − - Nm是噪音点,它们既不是核心点,也不是边界点,不属于该聚类。
在这里插入图片描述
DBSCAN算法优点有:可以自动确定聚类数量;对任意形状的簇都适用;对数据异常点不敏感。缺点为需要设置合适的距离和密度阈值,处理空间分布稀疏的数据对象时难以得到满意的聚类结果,时间复杂度比K-Means算法高。

3 实战

3.1 划分聚类 — K-Means

本小节将采用使用划分聚类的 K-Means算法开展聚类实战:使用sklearn.datasets.make_blobs生成三维聚类数据集,并进行适当的变换处理。通过KMeans算法聚类,使用k-means++初始化方法来对生成数据集进行聚类,实现代码如下:

import numpy as np
import matplotlib.colors
import matplotlib.pyplot as plt
import sklearn.datasets as ds
from sklearn.metrics import homogeneity_score, completeness_score, v_measure_score, adjusted_mutual_info_score,\
    adjusted_rand_score, silhouette_score
from sklearn.cluster import KMeans
from mpl_toolkits.mplot3d import Axes3D

if __name__ == "__main__":
    # 生成样本集
    N = 400             # 样本个数
    centers = 4         # 簇的个数
    # 生成三维四个簇的高斯数据集
    data, y = ds.make_blobs(N, n_features=3, centers=centers, random_state=0)
    # 变换数据集的标准差
    data2, y2 = ds.make_blobs(N, n_features=3, centers=centers, cluster_std=(1,2.5,0.5,2), random_state=0)
    # 生成不均衡数据集
    data3 = np.vstack((data[y == 0][:], data[y == 1][:50], data[y == 2][:20], data[y == 3][:5]))
    y3 = np.array([0] * 100 + [1] * 50 + [2] * 20 + [3] * 5)
    # 生成由data经旋转后的数据集
    m = np.array(((1, 1, 1), (1, 6, 3), (6, 2, 1)))
    data_r = data.dot(m)

    data_list = data, data, data_r, data_r, data2, data2, data3, data3
    y_list = y, y, y, y, y2, y2, y3, y3
    titles = '原始数据', 'KMeans++聚类', '旋转后数据', '旋转后KMeans++聚类', '方差不相等数据', '方差不相等KMeans++聚类', '数量不相等数据', '数量不相等KMeans++聚类'

    # KMeans聚类,使用k-means++初始化方法
    model = KMeans(n_clusters=4, init='k-means++')
    matplotlib.rcParams['font.sans-serif'] = ['SimHei']
    matplotlib.rcParams['axes.unicode_minus'] = False
    cm = matplotlib.colors.ListedColormap(list('rgbm'))
    fig = plt.figure(figsize=(8, 9), facecolor='w')
    for i, (x, y, title) in enumerate(zip(data_list, y_list, titles), start=1):
        if i % 2 == 1:
            y_pred = y
        else:
            # 训练聚类,并得到预测值
            y_pred = model.fit_predict(x)

        # 输出各评价指标
        print(i, title)
        print('Homogeneity(均一性):', homogeneity_score(y, y_pred))
        print('Completeness(完整性):', completeness_score(y, y_pred))
        print('V measure:', v_measure_score(y, y_pred))
        print('AMI(调整互信息):', adjusted_mutual_info_score(y, y_pred))
        print('ARI(调整兰德指数):', adjusted_rand_score(y, y_pred))
        print('Silhouette(轮廓系数):', silhouette_score(x, y_pred), '\n')

        # 输出图形
        ax = fig.add_subplot(4, 2, i, projection= '3d')
        ax.scatter(x[:, 0], x[:, 1], x[:, 2], c=y_pred, s=10, cmap=cm, edgecolors='none')
        plt.title(title)

    plt.tight_layout(2, rect=(0, 0, 1, 0.97))  # 大标题的间距
    plt.suptitle('划分聚类-KMeans算法-数据分布对聚类的影响', fontsize=18)
    plt.show()

评价指标输出如下:

1 原始数据
Homogeneity(均一性): 1.0
Completeness(完整性): 1.0
V measure: 1.0
AMI(调整互信息): 1.0
ARI(调整兰德指数): 1.0
Silhouette(轮廓系数): 0.585991021926362 

2 KMeans++聚类
Homogeneity(均一性): 0.9755386902247056
Completeness(完整性): 0.9756970727365012
V measure: 0.9756178750526207
AMI(调整互信息): 0.9753363987158269
ARI(调整兰德指数): 0.9801537796138619
Silhouette(轮廓系数): 0.5893028393427763 

3 旋转后数据
Homogeneity(均一性): 1.0
Completeness(完整性): 1.0
V measure: 1.0
AMI(调整互信息): 1.0
ARI(调整兰德指数): 1.0
Silhouette(轮廓系数): 0.4826402978130291 

4 旋转后KMeans++聚类
Homogeneity(均一性): 0.750073193909673
Completeness(完整性): 0.7520308201484618
V measure: 0.751050731384886
AMI(调整互信息): 0.7480061623345577
ARI(调整兰德指数): 0.6650917159405569
Silhouette(轮廓系数): 0.5561094523058618 

5 方差不相等数据
Homogeneity(均一性): 1.0
Completeness(完整性): 1.0
V measure: 1.0
AMI(调整互信息): 1.0
ARI(调整兰德指数): 1.0
Silhouette(轮廓系数): 0.44077853624904384 

6 方差不相等KMeans++聚类
Homogeneity(均一性): 0.7996534861783875
Completeness(完整性): 0.8082360836131177
V measure: 0.8039218787894781
AMI(调整互信息): 0.7979960910662527
ARI(调整兰德指数): 0.7860791946016837
Silhouette(轮廓系数): 0.47746468201023695 

7 数量不相等数据
Homogeneity(均一性): 1.0
Completeness(完整性): 1.0
V measure: 1.0
AMI(调整互信息): 1.0
ARI(调整兰德指数): 1.0
Silhouette(轮廓系数): 0.4350603729416132 

8 数量不相等KMeans++聚类
Homogeneity(均一性): 0.9126743491313174
Completeness(完整性): 0.7091078879830717
V measure: 0.798115265191655
AMI(调整互信息): 0.7027483564436865
ARI(调整兰德指数): 0.6313988407011663
Silhouette(轮廓系数): 0.408504798563812 

生成图像如下:

在这里插入图片描述
由以上对比结果可知,当数据经过一定变换后,聚类分类效果会受到影响,并有可能变差。所以聚类分析时,需要对数据本身检查或做一定的变换处理,以获得更好聚类效果。

3.2 层次聚类 — AGNES

本小节将采用使用层次聚类的AGNES算法开展聚类实战,研究不同合并策略对聚类结果的影响。

import numpy as np
import matplotlib as mpl
import matplotlib.pyplot as plt
from sklearn.cluster import AgglomerativeClustering
import sklearn.datasets as ds
import warnings
from sklearn.metrics import adjusted_mutual_info_score, adjusted_rand_score, silhouette_score


if __name__ == '__main__':
    warnings.filterwarnings(action='ignore', category=UserWarning)
    # 生成样本集
    N = 400             # 样本个数
    centers = 4         # 簇的个数
    np.random.seed(0)   # 撒固定的种子,保证每次样本集数据相同

    # 生成二维四个簇的高斯数据集
    data1, y1 = ds.make_blobs(n_samples=N, n_features=2, centers=((-1, 1), (1, 1), (1, -1), (-1, -1)),
                              cluster_std=(0.1, 0.2, 0.3, 0.4), random_state=0)
    data1 = np.array(data1)
    n_noise = int(0.1*N)            # 噪声数量
    r = np.random.rand(n_noise, 2)  # 二维噪声数组
    data_min1, data_min2 = np.min(data1, axis=0)
    data_max1, data_max2 = np.max(data1, axis=0)
    # 限制噪声在数据集范围内
    r[:, 0] = r[:, 0] * (data_max1-data_min1) + data_min1
    r[:, 1] = r[:, 1] * (data_max2-data_min2) + data_min2
    # 数据集加入噪声
    data1_noise = np.concatenate((data1, r), axis=0)
    y1_noise = np.concatenate((y1, [4]*n_noise))

    # 生成两个交叉的半圆数据集
    data2, y2 = ds.make_moons(n_samples=N, noise=.05)
    data2 = np.array(data2)
    n_noise = int(0.1 * N)          # 噪声数量
    r = np.random.rand(n_noise, 2)  # 二维噪声数组
    data_min1, data_min2 = np.min(data2, axis=0)
    data_max1, data_max2 = np.max(data2, axis=0)
    # 限制噪声在数据集范围内
    r[:, 0] = r[:, 0] * (data_max1 - data_min1) + data_min1
    r[:, 1] = r[:, 1] * (data_max2 - data_min2) + data_min2
    # 数据集加入噪声
    data2_noise = np.concatenate((data2, r), axis=0)
    y2_noise = np.concatenate((y2, [3] * n_noise))

    mpl.rcParams['font.sans-serif'] = ['SimHei']
    mpl.rcParams['axes.unicode_minus'] = False
    cm = mpl.colors.ListedColormap(['r', 'g', 'b', 'm', 'c'])
    plt.figure(figsize=(10, 8), facecolor='w')
    plt.cla()

    # 合并策略
    linkages = ("ward", "complete", "average")
    for index, (n_clusters, data, y) in enumerate(((4, data1, y1), (4, data1_noise, y1_noise),
                                                   (2, data2, y2), (2, data2_noise, y2_noise))):
        # 原始图形
        plt.subplot(4, 4, 4*index+1)
        plt.scatter(data[:, 0], data[:, 1], c=y, s=12, edgecolors='k', cmap=cm)
        plt.title('Prime' + '\n'
                      + 'AMI:' +  str("%.2f" % adjusted_mutual_info_score(y,y))
                      + ' ARI:' + str("%.2f" % adjusted_rand_score(y, y))
                      + ' S:' + str("%.2f" % silhouette_score(data, y)), fontsize=12)
        plt.grid(b=True, ls=':')
        data_min1, data_min2 = np.min(data, axis=0)
        data_max1, data_max2 = np.max(data, axis=0)
        plt.xlim(extend(data_min1, data_max1))
        plt.ylim(extend(data_min2, data_max2))

        # 遍历合并策略
        for i, linkage in enumerate(linkages):
            # 层次聚类,选取欧氏距离,合并策略
            ac = AgglomerativeClustering(n_clusters=n_clusters, affinity='euclidean', linkage=linkage)
            ac.fit(data)        # 训练聚类
            y_pred = ac.labels_ # 聚类结果
            # 作图
            plt.subplot(4, 4, i+2+4*index)
            plt.scatter(data[:, 0], data[:, 1], c=y_pred, s=12, edgecolors='k', cmap=cm)
            plt.title(linkage + '\n'
                      + 'AMI:' +  str("%.2f" % adjusted_mutual_info_score(y,y_pred))
                      + ' ARI:' + str("%.2f" % adjusted_rand_score(y, y_pred))
                      + ' S:' + str("%.2f" % silhouette_score(data, y_pred)), fontsize=12)
            plt.grid(b=True, ls=':')
            plt.xlim(extend(data_min1, data_max1))
            plt.ylim(extend(data_min2, data_max2))

    plt.suptitle('层次聚类-AGNES算法-不同合并策略', fontsize=15)
    plt.tight_layout(0.5, rect=(0, 0, 1, 0.95))
    plt.show()

生成图像如下:

在这里插入图片描述
由结果可知,不同的合并策略对聚类结果的影响,在一定程度上与数据源本身有关联;数据噪声对聚类效果也有影响。

3.3 密度聚类 — DBSCAN

本小节将采用使用密度聚类的DBSCAN算法开展聚类实战,研究不同参数对聚类结果的影响。

import numpy as np
import matplotlib.pyplot as plt
import sklearn.datasets as ds
import matplotlib.colors
from sklearn.cluster import DBSCAN
from sklearn.preprocessing import StandardScaler
from sklearn.metrics import adjusted_mutual_info_score, adjusted_rand_score, silhouette_score

if __name__ == "__main__":
    N = 1000                                        # 样本个数
    centers = [[1, 2], [-1, -1], [1, -1], [-1, 1]]  # 簇中心点
    # 按照簇中心点生成二维高斯数据集
    data, y = ds.make_blobs(N, n_features=2, centers=centers, cluster_std=[0.5, 0.25, 0.7, 0.5], random_state=0)
    # 拟合并标准化
    data = StandardScaler().fit_transform(data)
    # 数据1的参数:(epsilon, min_sample)
    params = ((0.2, 5), (0.2, 10), (0.2, 15), (0.3, 5), (0.3, 10), (0.3, 15))

    matplotlib.rcParams['font.sans-serif'] = ['SimHei']
    matplotlib.rcParams['axes.unicode_minus'] = False
    plt.figure(figsize=(9, 7), facecolor='w')
    plt.suptitle('密度聚类-DBSCAN算法', fontsize=15)

    for i in range(6):
        eps, min_samples = params[i]    # DBSCAN参数
        # 创建DBSCAN聚类模型
        model = DBSCAN(eps=eps, min_samples=min_samples)
        model.fit(data)                 # 训练
        y_hat = model.labels_           # 结果集

        # 核心对象
        core_indices = np.zeros_like(y_hat, dtype=bool)
        core_indices[model.core_sample_indices_] = True

        # 簇信息
        y_unique = np.unique(y_hat)
        n_clusters = y_unique.size - (1 if -1 in y_hat else 0)
        print(y_unique, '聚类簇的个数为:', n_clusters)

        # 作图
        plt.subplot(2, 3, i+1)
        clrs = plt.cm.Spectral(np.linspace(0, 0.8, y_unique.size))
        for k, clr in zip(y_unique, clrs):
            cur = (y_hat == k)
            # 噪声点
            if k == -1:
                plt.scatter(data[cur, 0], data[cur, 1], s=10, c='k')
                continue
            plt.scatter(data[cur, 0], data[cur, 1], s=15, c=clr, edgecolors='k')
            # 核心对象
            plt.scatter(data[cur & core_indices][:, 0], data[cur & core_indices][:, 1], s=40, c=clr, marker='d', edgecolors='k')
        x1_min, x2_min = np.min(data, axis=0)
        x1_max, x2_max = np.max(data, axis=0)
        x1_min, x1_max = expand(x1_min, x1_max)
        x2_min, x2_max = expand(x2_min, x2_max)
        plt.xlim((x1_min, x1_max))
        plt.ylim((x2_min, x2_max))
        plt.plot()
        plt.grid(b=True, ls=':', color='#606060')
        plt.title('$\epsilon$ = %.1f  m = %d,聚类数目:%d \n AMI: %.2f ARI: %.2f S:%.2f' %
                  (eps, min_samples, n_clusters, adjusted_mutual_info_score(y, y_hat),
                   adjusted_rand_score(y, y_hat), silhouette_score(data, y_hat)), fontsize=12)
    plt.tight_layout()
    plt.subplots_adjust(top=0.87)
    plt.show()

生成图像如下:

在这里插入图片描述
DBSCAN算法需要设置合适的距离和密度阈值,以获得满意的聚类结果。本例中参数为ε=0.2,m=5时,分类结果及指标显示已经不错,如果继续增大核心邻域点数如m=15,则可发现周边的一些点不满足核心点条件,而被剔除,聚类效果变差。如果协同增大参数如ε=0.3,m=15,则聚类效果恢复较好。

4.参考学习的书目及论文

  1. 机器学习算法视频 - 邹博
  2. 《机器学习实战》第10章 利用K-均值聚类算法对未标注数据分组
  3. 《机器学习 - 周志华》第9章 聚类
  4. 《集体编程智慧》第3章 发现群组
  5. 《基于聚类和Python语言的深圳市城市道路车辆行驶工况构建》 宋怡帆 2018 硕士论文 第5章 基于聚类分析的短行程片段分类
  6. 《基于K均值聚类分析的车辆横向稳定性判定与控制策略研究》徐强2018 硕士论文 第3章 基于 K 均值聚类分析的车辆横向稳定性判定方法
  7. 《无人驾驶汽车车辆障碍物检测及换道决策研究》 徐兵2020 硕士论文 第2章 基于改进聚类算法的车辆障碍物检测研究

=文档信息=
本学习笔记由博主整理编辑,仅供非商用学习交流使用
由于水平有限,错误和纰漏之处在所难免,欢迎大家交流指正
如本文涉及侵权,请随时留言博主,必妥善处置
版权声明:非商用自由转载-保持署名-注明出处
署名(BY) :zhudj
文章出处:https://zhudj.blog.csdn.net/

  • 3
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Python实现Kmeans聚类算法的代码如下: ```python from sklearn.cluster import KMeans import numpy as np # 假设你的图像数据存储在一个名为X的数组中,每个样本是一个表示像素值的向量 # X的形状为(样本数量,像素数量) # 初始化KMeans模型 kmeans = KMeans(n_clusters=k) # 训练模型 kmeans.fit(X) # 获取每个样本的聚类标签 labels = kmeans.labels_ # 获取聚类中心 centroids = kmeans.cluster_centers_ ``` 你可以使用`sklearn.cluster.KMeans`类来实现Kmeans聚类算法。首先,你需要导入相关的库,并根据你的数据初始化一个KMeans模型。然后,使用`fit`方法对模型进行训练,并使用`labels_`属性获取每个样本的聚类标签。最后,使用`cluster_centers_`属性获取聚类中心。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [Python实现Kmeans聚类算法](https://download.csdn.net/download/weixin_38750829/12870422)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] - *2* *3* [机器学习实战之路 —— 6 聚类算法](https://blog.csdn.net/weixin_38135620/article/details/113888367)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值