聚类算法核心对比:划分聚类、层次聚类与密度聚类
在无监督学习中,聚类算法根据其核心思想和构建簇的方式,主要分为基于划分、基于层次和基于密度三大类。下表从定义、核心原理、关键步骤及应用场景等方面对这三种主流方法进行了系统性对比。
| 特征维度 | 划分聚类 (Partitioning Clustering) - 以K-Means为代表 | 层次聚类 (Hierarchical Clustering) | 密度聚类 (Density-Based Clustering) - 以DBSCAN为代表 |
|---|---|---|---|
| 核心思想 | 将数据集划分为K个互斥的簇,通过迭代优化簇内相似度最大化(或误差最小化)。 | 通过构建数据的层次嵌套簇(树状图,Dendrogram)来揭示数据的层次结构。 | 基于数据分布的密度来发现任意形状的簇,将高密度区域划分为簇,低密度区域视为噪声。 |
| 簇形状假设 | 假设簇是凸形的(如球形),且大小相近。对非球形、大小不一的簇效果不佳。 | 无特定形状假设,能反映数据的内在层次关系。 | 无特定形状假设,能发现任意形状的簇,对噪声和异常值鲁棒。 |
| 关键参数 | K(簇的数量),需预先指定。 | 距离度量方式(如欧氏、曼哈顿)、链接准则(如单/全/平均/ward链接)。 | ε (eps):邻域半径;MinPts:核心点的最小邻域样本数。 |
| 核心算法流程 | 1. 随机初始化K个质心。 2. 分配样本到最近质心。 3. 重新计算质心。 4. 迭代2-3步直至收敛。 | 凝聚法 (自底向上): 1. 视每个样本为独立簇。 2. 合并距离最近的两个簇。 3. 重复直至所有样本聚为一类。 | 1. 标记所有点(核心点、边界点、噪声点)。 2. 从任意核心点出发,密度可达的所有点形成一个簇。 3. 重复直至所有核心点被访问。 |
| 是否需要预设簇数 | 是,必须预先指定K值。 | 否,通过设定距离阈值或观察树状图来最终确定簇的划分。 | 否,簇的数量由数据密度和参数(ε, MinPts)自然决定。 |
| 对噪声/异常值的敏感性 | 敏感,离群点会显著影响质心位置。 | 中等敏感,取决于链接准则,某些准则(如单链接)对噪声敏感。 | 不敏感,能将低密度区域的点直接标记为噪声。 |
| 输出结果 | 一个扁平的簇划分(每个样本属于一个簇)。 | 一个树状层次结构,可在不同粒度上切割以获得不同数量的簇。 | 簇的划分,以及明确的噪声点标记。 |
| 典型算法 | K-Means, K-Medoids, K-Means++。 | AGNES (凝聚层次聚类), DIANA (分裂层次聚类)。 | DBSCAN, OPTICS, HDBSCAN。 |
| 主要优缺点 | 优点:简单、高效,适用于大数据集。 缺点:需预设K、对初始值敏感、对非凸簇和噪声敏感。 | 优点:无需预设簇数,可视化好(树状图),能展示层次关系。 缺点:计算和存储复杂度高(O(n²)或O(n³)),合并/分裂决策不可逆。 | 优点:无需预设簇数,能发现任意形状簇,抗噪声能力强。 缺点:对参数(ε, MinPts)敏感,高维数据中距离度量失效(“维度灾难”)。 |
| 最佳应用场景 | 数据集呈凸形、簇大小均匀、分布密集,且簇数K已知或可估计的场景,如客户细分(RFM模型)、图像颜色量化、文档主题分类。 | 需要探索数据层次结构或簇数未知的场景,如生物物种分类(系统发育树)、社交网络社区发现、文档/新闻的层次化主题归类。 | 数据簇形状不规则、含有大量噪声或离群点、簇密度不均匀的场景,如地理信息系统中识别城市群、异常检测(如信用卡欺诈)、卫星图像中识别森林区域。 |
核心算法原理与关键代码实现
1. 划分聚类:K-Means
K-Means的目标是最小化簇内误差平方和(SSE)。其核心是迭代的“分配-更新”过程。
from sklearn.cluster import KMeans import numpy as np # 模拟数据 np.random.seed(0) X = np.random.randn(300, 2) # K-Means聚类 kmeans = KMeans(n_clusters=3, init='k-means++', n_init=10, max_iter=300, random_state=42) kmeans.fit(X) labels = kmeans.labels_ centroids = kmeans.cluster_centers_ print(f"簇中心坐标: {centroids}") print(f"SSE (惯性): {kmeans.inertia_:.2f}")2. 层次聚类:凝聚层次聚类 (AGNES)
凝聚层次聚类从每个点作为一个簇开始,逐步合并最相似的簇。
from scipy.cluster.hierarchy import dendrogram, linkage, fcluster from sklearn.preprocessing import StandardScaler import matplotlib.pyplot as plt # 数据标准化 scaler = StandardScaler() X_scaled = scaler.fit_transform(X) # 计算链接矩阵 (使用Ward方法最小化簇内方差) Z = linkage(X_scaled, method='ward') # 绘制树状图 plt.figure(figsize=(10, 5)) dendrogram(Z, truncate_mode='lastp', p=12, show_leaf_counts=True) plt.title('凝聚层次聚类树状图') plt.xlabel('样本索引') plt.ylabel('合并距离') plt.show() # 在指定距离阈值处切割树状图,形成扁平簇 max_d = 5 # 距离阈值 clusters = fcluster(Z, max_d, criterion='distance') print(f"在距离阈值{max_d}处切割,得到 {len(np.unique(clusters))} 个簇")3. 密度聚类:DBSCAN
DBSCAN基于核心点、边界点和噪声点的定义来扩展簇。
from sklearn.cluster import DBSCAN from sklearn.datasets import make_moons # 生成半月形非凸数据 X_moons, _ = make_moons(n_samples=300, noise=0.05, random_state=0) # DBSCAN聚类 dbscan = DBSCAN(eps=0.3, min_samples=5) labels_db = dbscan.fit_predict(X_moons) # 统计结果(-1表示噪声点) n_clusters = len(set(labels_db)) - (1 if -1 in labels_db else 0) n_noise = list(labels_db).count(-1) print(f"估计的簇数量: {n_clusters}") print(f"识别出的噪声点数量: {n_noise}") # 可视化 plt.scatter(X_moons[:, 0], X_moons[:, 1], c=labels_db, cmap='viridis', s=50, edgecolors='k') plt.title('DBSCAN聚类结果 (能识别任意形状簇)') plt.show()算法选择指南与应用实例
选择哪种算法取决于数据的特性和分析目标:
数据形状与分布:
- 若数据呈球形或凸形,且簇大小均匀,选K-Means。
- 若数据呈任意形状(如流形、环状),或有噪声,选DBSCAN。
- 若想探索数据的层次关系,选层次聚类。
先验知识:
- 若已知或能估计簇数K,可考虑K-Means。
- 若完全未知,且不想预设参数,可先尝试层次聚类观察结构,或用DBSCAN。
计算效率与数据规模:
- 大数据集:K-Means(效率高,O(n))。
- 中小数据集,需可视化层次:层次聚类。
- 中等规模,形状复杂:DBSCAN。
综合应用实例:鸢尾花数据集聚类对比
from sklearn import datasets from sklearn.metrics import adjusted_rand_score import pandas as pd # 加载鸢尾花数据集 iris = datasets.load_iris() X = iris.data y_true = iris.target # 真实标签(仅用于评估) # 分别应用三种算法 kmeans = KMeans(n_clusters=3, random_state=42).fit(X) hierarchical = fcluster(linkage(X, method='ward'), t=3, criterion='maxclust') - 1 # 切割为3簇 dbscan = DBSCAN(eps=0.5, min_samples=5).fit(X) # 评估(使用调整兰德指数ARI,越接近1越好) results = { '算法': ['K-Means', '层次聚类', 'DBSCAN'], 'ARI分数': [ adjusted_rand_score(y_true, kmeans.labels_), adjusted_rand_score(y_true, hierarchical), adjusted_rand_score(y_true, dbscan.labels_) ], '发现的簇数': [ len(set(kmeans.labels_)), len(set(hierarchical)), len(set(dbscan.labels_)) ] } df_results = pd.DataFrame(results) print(df_results)在这个例子中,鸢尾花数据近似球形分布,K-Means和层次聚类通常表现良好,而DBSCAN可能因参数设置不当而将部分点判为噪声。
参考来源
- 机器学习:聚类(层次聚类,密度聚类,K-means,谱聚类)
- 【Python机器学习实战】聚类算法——层次聚类(HAC)和DBSCAN
- 【机器学习】任务七:聚类算法 (K-means 算法、层次聚类、密度聚类对鸢尾花(Iris)数据进行聚类)
- 层次聚类和密度聚类思想及实现
- k均值,密度聚类,层次聚类三种聚类底层逻辑的区别
- 了解聚类是什么。聚类方法:k-means、核聚类、层次聚类、谱聚类