技术心得记录:机器学习笔记之聚类算法层次聚类HierarchicalClustering

简介: 技术心得记录:机器学习笔记之聚类算法层次聚类HierarchicalClustering

阅读目录


0x01 层次聚类简介0x02 自顶向下的层次聚类算法(Divisive)0x03 自底向上的层次聚类算法(Agglomerative)0x04 利用 Scipy 实现层次聚类0x05 利用 Sklearn 实现层次聚类0x06 转载


0x01 层次聚类简介


层次聚类算法(Hierarchical Clustering)将数据集划分为一层一层的clusters,后面一层生成的clusters基于前面一层的结果。层次聚类算法一般分为两类:


Divisive 层次聚类:又称自顶向下(top-down)的层次聚类,最开始所有的对象均属于一个cluster,每次按一定的准则将某个cluster 划分为多个cluster,如此往复,直至每个对象均是一个cluster。


Agglomerative 层次聚类:又称自底向上(bottom-up)的层次聚类,每一个对象最开始都是一个cluster,每次按一定的准则将最相近的两个cluster合并生成一个新的cluster,如此往复,直至最终所有的对象都属于一个cluster。


下图直观的给出了层次聚类的思想以及以上两种聚类策略的异同:


层次聚类算法是一种贪心算法(greedy algorithm),因其每一次合并或划分都是基于某种局部最优的选择。


0x02 自顶向下的层次聚类算法(Divisive)


2.1 Hierarchical K-means算法


Hierarchical K-means算法是“自顶向下”的层次聚类算法,用到了基于划分的聚类算法那K-means,算法思路如下:


首先,把原始数据集放到一个簇C,这个簇形成了层次结构的最顶层


使用K-means算法把簇C划分成指定的K个子簇Ci,i=1,2,…,k,形成一个新的层


对于步骤2所生成的K个簇,递归使用K-means算法划分成更小的子簇,直到每个簇不能再划分(只包含一个数据对象)或者满足设定的终止条件。


如下图,展示了一组数据进行了二次K-means算法的过程:


Hierarchical K-means算法一个很大的问题是,一旦两个点在最开始被划分到了不同的簇,即使这两个点距离很近,在后面的过程中也不会被聚类到一起。


对于以上的例子,红色椭圆框中的对象聚类成一个簇可能是更优的聚类结果,但是由于橙色对象和绿色对象在第一次K-means就被划分到不同的簇,之后也不再可能被聚类到同一个簇。


Bisecting k-means聚类算法,即二分k均值算法,是分层聚类(Hierarchical clustering)的一种。更多关于二分k均值法,可以查看聚类算法之K-Means。


0x03 自底向上的层次聚类算法(Agglomerative)


层次聚类的合并算法通过计算两类数据点间的相似性,对所有数据点中最为相似的两个数据点进行组合,并反复迭代这一过程。简单的说层次聚类的合并算法是通过计算每一个类别的数据点与所有数据点之间的距离来确定它们之间的相似性,距离越小,相似度越高。并将距离最近的两个数据点或类别进行组合,生成聚类树。


相比于Hierarchical K-means算法存在的问题,Agglomerative Clustering算法能够保证距离近的对象能够被聚类到一个簇中,该算法采用的“自底向上”聚类的思路。


3.1 Agglomerative算法示例


对于如下数据:


1、 将A到F六个点,分别生成6个簇


2、 找到当前簇中距离最短的两个点,这里我们使用单连锁的方式来计算距离,发现A点和B点距离最短,将A和B组成一个新的簇,此时簇列表中包含五个簇,分别是{A,B},{C},{D},{E},{F},如下图所示:


3、重复步骤2、发现{C}和{D}的距离最短,连接之,然后是簇{C,D}和簇{E}距离最短,依次类推,直到最后只剩下一个簇,得到如下所示的示意图:


4、此时原始数据的聚类关系是按照层次来组织的,选取一个簇间距离的阈值,可以得到一个聚类结果,比如在如下红色虚线的阈值下,数据被划分为两个簇:簇{A,B,C,D,E}和簇{F}


Agglomerative聚类算法的优点是能够根据需要在不同的尺度上展示对应的聚类结果,缺点同Hierarchical K-means算法一样,一旦两个距离相近的点被划分到不同的簇,之后也不再可能被聚类到同一个簇,即无法撤销先前步骤的工作。另外,Agglomerative性能较低,并且因为聚类层次信息需要存储在内存中,内存消耗大,不适用于大量级的数据聚类。


3.2 对象之间的距离衡量


衡量两个对象之间的距离的方式有多种,对于数值类型(Numerical)的数据,常用的距离衡量准则有 Euclidean 距离、Manhattan 距离、Chebyshev 距离、Minkowski 距离等等。


3.3 Cluster 之间的距离衡量


除了需要衡量对象之间的距离之外,层次聚类算法还需要衡量cluster之间的距离,常见的cluster之间的衡量方法有 Single-link 方法、Complete-link 方法、UPGMA(Unweighted Pair Group Method using arithmetic Averages)方法、WPGMA(Weighted Pair Group Method using arithmetic Averages)方法、Centroid 方法(又称 UPGMC,Unweighted Pair Group Method using Centroids)、Median 方法(又称 WPGMC,weighted Pair Group Method using Centroids)、Ward 方法。前面四种方法是基于图的,因为在这些方法里面,cluster是由样本点或一些子cluster(这些样本点或子cluster之间的距离关系被记录下来,可认为是图的连通边)所表示的;后三种方法是基于几何方法的(因而其对象间的距离计算方式一般选用 Euclidean 距离),因为它们都是用一个中心点来代表一个cluster。


假设Ci和Cj为两个cluster,则前四种方法定义的Ci和Cj之间的距离如下表所示:


简单的理解:


Single Linkage:方法是将两个组合数据点中距离最近的两个数据点间的距离作为这两个组合数据点的距离。这种方法容易受到极端值的影响。两个很相似的组合数据点可能由于其中的某个极端的数据点距离较近而组合在一起。


Complete Linkage:Complete Linkage的计算方法与Single Linkage相反,将两个组合数据点中距离最远的两个数据点间的距离作为这两个组合数据点的距离。Complete Linkage的问题也与Single Linkage相反,两个不相似的组合数据点可能由于其中的极端值距离较远而无法组合在一起。


Average Linkage:Average Linkage的计算方法是计算两个组合数据点中的每个数据点与其他所有数据点的距离。将所有距离的均值作为两个组合数据点间的距离。这种方法计算量比较大,但结果比前两种方法更合理。


其中 Single-link 定义两个 cluster 之间的距离为两个 cluster 之间距离最近的两个对象间的距离,这样在聚类的过程中就可能出现链式效应,即有可能聚出长条形状的 cluster;而 Complete-link 则定义两个 cluster 之间的距离为两个 cluster 之间距离最远的两个对象间的距离,这样虽然避免了链式效应,但其对异常样本点(不符合数据集的整体分布的噪声点)却非常敏感,容易产生不合理的聚类;UPGMA 正好是 Single-link 和 Complete-link 的一个折中,其定义两个 cluster 之间的距离为两个 cluster 之间两个对象间的距离的平均值;而 WPGMA 则计算的是两个 cluster 之间两个对象之间的距离的加权平均值,加权的目的是为了使两个 cluster 对距离的计算的影响在同一层次上,而不受 cluster 大小的影响(其计算方法这里没有给出,因为在运行层次聚类算法时,我们并不会直接通过样本点之间的距离之间计算两个 cluster 之间的距离,而是通过已有的 cluster 之间的距离来计算合并后的新的 cluster 和剩余cluster 之间的距离,这种计算方法将由下一部分中的 Lance-Williams 方法给出)。


Centroid/UPGMC方法给每一个cluster 计算一个质心,两个 cluster 之间的距离即为对应的两个质心之间的距离,一般计算方法如下:


3.4 常用Agglomerative算法


0x04 利用 Scipy 实现层次聚类


4.1 生成测试数据


from sklearn.datasets import make_blobs


import matplotlib.pyplot as plt


centers = 【【1, 1】, 【-1, -1】, 【1, -1】】


X, labels_true = make_blobs(n_samples=750, centers=centers, cluster_std=0.4, random_state=0)


plt.figure(figsize=(10, 8))


plt.scatter(X【:, 0】, X【:, 1】, c='b')


plt.show()


4.2 SciPy层次聚类实现


SciPy 里面进行层次聚类非常简单,直接调用 linkage 函数,一行代码即可搞定:


from scipy.cluster.hierarchy import linkage


Z = linkage(X, method='ward', metric='euclidean')


print(Z.shape)


print(Z【: 5】)


以上即进行了一次cluster间距离衡量方法为Ward、样本间距离衡量准则为Euclidean距离的Agglomerative层次聚类,其中method参数可以为’single’、’complete’、’average’、’weighted’、’centroid’、’median’、’ward’中的一种,分别对应我们前面讲到的 Single-link、Complete-link、UPGMA、WPGMA、UPGMC、WPGMC、Ward 方法,而样本间的距离衡量准则也可以由 metric 参数调整。


linkage 函数的返回值 Z 为一个维度(n-1)*4的矩阵,记录的是层次聚类每一次的合并信息,里面的 4 个值分别对应合并的两个cluster的序号、两个cluster之间的距离以及本次合并后产生的新的 cluster 所包含的样本点的个数。


4.3 画出树形图


SciPy 中给出了根据层次聚类的结果 Z 绘制树形图的函数dendrogram,我们由此画出本次实验中的最后 20 次的合并过程。


from scipy.cluster.hierarchy import dendrogram


plt.figure(figsize=(10, 8))


dendrogram(Z, truncate_mode='lastp', p=20, show_leaf_counts=False, leaf_rotation=90, leaf_font_size=15,


show_contracted=True)


plt.show()


得到的树形图如下所示:


可以看到,该树形图的最后两次合并相比之前合并过程的合并距离要大得多,由此可以说明最后两次合并是不合理的;因而对于本数据集,该算法可以很好地区分出 3 个 cluster(和实际相符),分别在上图中由三种颜色所表示。


4.4、获取聚类结果


在得到了层次聚类的过程信息 Z 后,我们可以使用 fcluster 函数来获取聚类结果。可以从两个维度来得到距离的结果,一个是指定临界距离 d,得到在该距离以下的未合并的所有 cluster 作为聚类结果;另一个是指定 cluster 的数量 k,函数会返回最后的 k 个 cluster 作为聚类结果。使用哪个维度由参数 criterion 决定,对应的临界距离或聚类的数量则由参数 t 所记录。fcluster 函数的结果为一个一维数组,记录每个样本的类别信息。


from scipy.cluster.hierarchy import fcluster


# 根据临界距离返回聚类结果


d = 15


labels_1 = fcluster(Z, t=d, criterion='distance')


print(labels_1【: 100】) # 打印聚类结果


print(len(set(labels_1))) # 看看在该临界距离下有几个 cluster


# 根据聚类数目返回聚类结果


k = 3


labels_2 = fcluster(Z, t=k, criterion='maxclust')


print(labels_2【: 100】)


list(labels_1) == list(labels_2) # 看看两种不同维度下得到的聚类结果是否一致


# 聚类的结果可视化,相同的类的样本点用同一种颜色表示


plt.figure(figsize=(10, 8))


plt.scatter(X【:, 0】, X【:, 1】, c=labels_2, cmap='prism')


plt.show()


上图的聚类结果和实际的数据分布基本一致,但有几点值得注意,一是在聚类之前我们没法知道合理的聚类的数目或者最大的距离临界值,只有在得到全部的层次聚类信息并对其进行分析后我们才能预估出一个较为合理的数值;二是本次实验的数据集比较简单,所以聚类的结果较好,但对于复杂的数据集(比如非凸的、噪声点比较多的数据集),层次聚类算法有其局限性。


4.5 比较不同方法下的聚类结果


最后,我们对同一份样本集进行了 cluster 间距离衡量准则分别为 Single-link、Complete-link、UPGMA(Average)和 Ward 的 Agglomerative 层次聚类,取聚类数目为 3,代码如下:


from time import time


import numpy as np


from sklearn.datasets import make_blobs


from scipy.cluster.hierarchy import linkage, fcluster


from sklearn.metrics.cluster import adjusted_mutual_info_score


import matplotlib.pyplot as plt


# 生成样本点


centers = 【【1, 1】, 【-1, -1】, 【1, -1】】


X, labels = make_blobs(n_samples=750, centers=centers,


cluster_std=0.4, random_state=0)


# 可视化聚类结果


def plot_clustering(X, labels, title=None):


plt.scatter(X【:, 0】, X【:, 1】, c=labels, cmap='prism')


if title is not None:


plt.title(title, size=17)


plt.axis('off')


plt.tight_layout()


# 进行 Agglomerative 层次聚类


linkage_method_list = 【'single', 'complete', 'average', 'ward'】


plt.figure(figsize=(10, 8))


ncols, nrows = 2, int(np.ceil(len(linkage_method_list) / 2))


plt.subplots(nrows=nrows, ncols=ncols)


for i, linkage_method in enumerate(linkage_method_list):


print('method %s:' % linkage_method)


start_time = time()


Z = linkage(X, method=linkage_method)


labels_pred = fcluster(Z, t=3, criterion='maxclust')


print('Adjust mutual information: %.3f' % adjusted_mutual_info_score(labels, labels_pred))


print('time used: %.3f seconds' % (time() - start_time))


plt.subplot(nrows, ncols, i + 1)


plot_clustering(X, labels_pred, '%s linkage' % linkage_method)


plt.show()


可以得到 4 种方法下的聚类结果如图所示:


在上面的过程中,我们还为每一种聚类产生的结果计算了一个用于评估聚类结果与样本的真实类之间的相近程度的AMI(Adjust Mutual Information)量,该量越接近于 1 则说明聚类算法产生的类越接近于真实情况。程序的打印结果如下:


method single:


Adjust mutual information: 0.002


time used: 0.010 seconds


method complete:


Adjust mutual information: 0.840


time used: 0.021 seconds


method average:


Adjust mutual information: 0.945


time used: 0.027 seconds


method ward:


Adjust mutual information: 0.956


time used: 0.021 seconds


从上面的图和 AMI 量的表现来看,Single-link 方法下的层次聚类结果最差,它几乎将所有的点都聚为一个 cluster,而其他两个 cluster 则都仅包含个别稍微有点偏离中心的样本点,这充分体现了 Single-link 方法下的“链式效应”,也体现了 Agglomerative 算法的一个特点,即“赢者通吃”(rich getting richer): Agglomerative 算法倾向于聚出不均匀的类,尺寸大的类倾向于变得更大,对于 Single-link 和 UPGMA(Average) 方法尤其如此。由于本次实验的样本集较为理想,因此除了 Single-link 之外的其他方法都表现地还可以,但当样本集变复杂时,上述“赢者通吃” 的特点会显现出来。


0x05 利用 Sklearn 实现层次聚类


除了Scipy外,scikit-learn也提供了层次聚类的方法sklearn.cluster.AgglomerativeClustering,使用示例


from sklearn.datasets import make_blobs


from sklearn.cluster import AgglomerativeClustering


import //代码效果参考:http://hnjlyzjd.com/xl/wz_24944.html

matplotlib.pyplot as plt

# 生成样本点


centers = 【【1, 1】, 【-1, -1】, 【1, -1】】


X, labels = make_blobs(n_samples=750, centers=centers,


cluster_std=0.4, random_state=0)


clustering = AgglomerativeClustering(nclusters=3, linkage='ward').fit(X)


plt.figure(figsize=(10, 8))


plt.scatter(X【:, 0】, X【:, 1】, c=clustering.labels, cmap='prism')


plt.show()


参考链接:


聚类分析(一):层次聚类算法


0x06 转载

相关文章
|
2天前
|
存储 算法 Java
技术笔记:JVM的垃圾回收机制总结(垃圾收集、回收算法、垃圾回收器)
技术笔记:JVM的垃圾回收机制总结(垃圾收集、回收算法、垃圾回收器)
|
2天前
|
机器学习/深度学习 分布式计算 算法
在机器学习项目中,选择算法涉及问题类型识别(如回归、分类、聚类、强化学习)
【6月更文挑战第28天】在机器学习项目中,选择算法涉及问题类型识别(如回归、分类、聚类、强化学习)、数据规模与特性(大数据可能适合分布式算法或深度学习)、性能需求(准确性、速度、可解释性)、资源限制(计算与内存)、领域知识应用以及实验验证(交叉验证、模型比较)。迭代过程包括数据探索、模型构建、评估和优化,结合业务需求进行决策。
5 0
|
2天前
|
机器学习/深度学习 算法
机器学习中的超参数优化涉及手动尝试、网格搜索、随机搜索、贝叶斯优化、梯度优化、进化算法等策略
【6月更文挑战第28天】**机器学习中的超参数优化涉及手动尝试、网格搜索、随机搜索、贝叶斯优化、梯度优化、进化算法等策略。工具如scikit-optimize、Optuna助力优化,迁移学习和元学习提供起点,集成方法则通过多模型融合提升性能。资源与时间考虑至关重要,交叉验证和提前停止能有效防止过拟合。**
5 0
|
2天前
|
Java BI C#
技术笔记:SM4加密算法实现Java和C#相互加密解密
技术笔记:SM4加密算法实现Java和C#相互加密解密
|
3天前
|
数据采集 机器学习/深度学习 算法
机器学习方法之决策树算法
决策树算法是一种常用的机器学习方法,可以应用于分类和回归任务。通过递归地将数据集划分为更小的子集,从而形成一棵树状的结构模型。每个内部节点代表一个特征的判断,每个分支代表这个特征的某个取值或范围,每个叶节点则表示预测结果。
11 1
|
7天前
|
机器学习/深度学习 人工智能 算法
【昆虫识别系统】图像识别Python+卷积神经网络算法+人工智能+深度学习+机器学习+TensorFlow+ResNet50
昆虫识别系统,使用Python作为主要开发语言。通过TensorFlow搭建ResNet50卷积神经网络算法(CNN)模型。通过对10种常见的昆虫图片数据集('蜜蜂', '甲虫', '蝴蝶', '蝉', '蜻蜓', '蚱蜢', '蛾', '蝎子', '蜗牛', '蜘蛛')进行训练,得到一个识别精度较高的H5格式模型文件,然后使用Django搭建Web网页端可视化操作界面,实现用户上传一张昆虫图片识别其名称。
129 7
【昆虫识别系统】图像识别Python+卷积神经网络算法+人工智能+深度学习+机器学习+TensorFlow+ResNet50
|
7天前
|
机器学习/深度学习 人工智能 算法
算法金 | 统计学的回归和机器学习中的回归有什么差别?
**摘要:** 统计学回归重在解释,使用线性模型分析小数据集,强调假设检验与解释性。机器学习回归目标预测,处理大数据集,模型复杂多样,关注泛化能力和预测误差。两者在假设、模型、数据量和评估标准上有显著差异,分别适用于解释性研究和预测任务。
37 8
算法金 | 统计学的回归和机器学习中的回归有什么差别?
|
4天前
|
机器学习/深度学习 人工智能 自然语言处理
机器学习算法入门:从K-means到神经网络
【6月更文挑战第26天】机器学习入门:从K-means到神经网络。文章涵盖了K-means聚类、逻辑回归、决策树和神经网络的基础原理及应用场景。K-means用于数据分组,逻辑回归适用于二分类,决策树通过特征划分做决策,神经网络则在复杂任务如图像和语言处理中大显身手。是初学者的算法导览。
|
4天前
|
机器学习/深度学习 算法 数据挖掘
Python机器学习10大经典算法的讲解和示例
为了展示10个经典的机器学习算法的最简例子,我将为每个算法编写一个小的示例代码。这些算法将包括线性回归、逻辑回归、K-最近邻(KNN)、支持向量机(SVM)、决策树、随机森林、朴素贝叶斯、K-均值聚类、主成分分析(PCA)、和梯度提升(Gradient Boosting)。我将使用常见的机器学习库,如 scikit-learn,numpy 和 pandas 来实现这些算法。
|
8天前
|
机器学习/深度学习 人工智能 Dart
AI - 机器学习GBDT算法
梯度提升决策树(Gradient Boosting Decision Tree),是一种集成学习的算法,它通过构建多个决策树来逐步修正之前模型的错误,从而提升模型整体的预测性能。