简单易懂的 k-medoids 聚类算法 MATLAB 源码
项目简介
本项目提供了一个基于 MATLAB 实现的轻量级 k-medoids(k-中心点)聚类算法演示系统。该算法是经典 k-means 算法的鲁棒性改进版本。不同于 k-means 计算虚拟质心(Mean),k-medoids 严格选取数据集中的实际点作为聚类中心(Medoid),这一特性使其对数据集中的噪声和异常值(Outliers)具有极强的抗干扰能力。
本项目完整复现了 PAM(Partitioning Around Medoids)风格的迭代优化流程,代码逻辑简洁直观,且内置了数据生成与可视化模块,非常适合用于理解无监督学习中的基于划分的聚类思想。
功能特性
- 抗噪鲁棒性:算法核心强制中心点必须是原始数据中的真实样本,有效避免了异常值拉偏聚类中心。
- 完整算法流程:实现了从随机初始化、距离计算、指派归类到中心点迭代更新的完整闭环。
- 自动数据生成:内置数据生成模块,自动创建包含高斯分布簇和随机背景噪声的二维测试数据。
- 高效距离计算:利用 MATLAB 的向量化特性(或
pdist2)计算欧氏距离矩阵,并在迭代中复用。 - 丰富的可视化:
* 展示原始数据的分布情况(区分正常样本与噪声)。
* 通过颜色区分不同的簇。
* 绘制样本点与所属中心点的连线,直观展示归属关系。
* 用五角星高亮标记最终选定的 Medoids。
* 独立窗口绘制代价函数(Total Cost)的收敛曲线。
系统要求
- MATLAB R2016a 或更高版本(建议)。
- Statistics and Machine Learning Toolbox(可选):如果有该工具箱,代码将自动使用优化的
pdist2 函数;如果没有,代码会自动切换到内置的手动向量化实现,无需额外安装库。
使用方法
- 将源码保存为
main.m 文件。 - 在 MATLAB 命令窗口或编辑器中直接运行
main 函数。 - 程序将自动执行以下步骤:
* 生成模拟数据。
* 运行 k-medoids 算法进行训练。
* 输出迭代次数、最终代价值和耗时。
* 弹出两个图形窗口展示聚类结果和收敛分析。
代码核心逻辑与算法分析
本项目源码主要包含三个逻辑部分:主控流程、核心算法实现、辅助计算。
1. 主控流程 (main 函数)
- 参数配置:定义了样本总数(300)、簇数量(k=3)、最大迭代次数(100)等超参数。
- 数据合成:
* 使用
rng(42) 固定随机种子,确保实验结果可复现。
* 生成三个具有不同均值和方差的高斯分布簇。
* 在全局范围内撒入随机噪声点,用于验证算法对异常值的处理能力。
* 打乱所有数据的顺序,模拟真实场景。
*
子图1:绘制原始数据,展示未分类前的数据形态。
*
子图2:绘制聚类结果。包含根据类别着色的样本点、连接样本与中心的灰色连线(增强视觉联系)、以及被醒目标记出的最终 Medoids。
*
收敛图:单独绘制随迭代次数变化的 Cost 曲线,用于评估算法收敛速度。
2. 核心算法 (run_kmedoids 函数)
该函数实现了标准的迭代优化逻辑:
* 使用
randperm 从原始数据索引中随机抽取 k 个索引作为初始中心点。
* 预先计算所有样本点之间的距离矩阵 $D$,避免在循环中重复计算,提高效率。
1.
指派步骤 (Assignment Step):
* 从距离矩阵中提取当前 k 个中心点对应的列。
* 对每一行求最小值,将每个样本点分配给距离最近的中心点。
* 计算当前的全局代价(所有点到其中心点的距离之和)。
2.
收敛检查:
* 比较当前迭代的中心点索引集合与上一次是否一致(使用排序后的
isequal)。如果不一致则继续,否则跳出循环。
3.
更新步骤 (Update Step/Voronoi Iteration):
* 遍历每一个簇,提取属于该簇的所有样本点。
* 在簇内部计算寻找一个新的“最佳代表点”:该点到簇内其他所有点的距离之和最小。
* 将该最佳代表点的索引更新为该簇的新 Medoid。这一步确保了 Medoid 总是向簇内密度最大的位置移动。
3. 辅助功能 (calculate_distance_matrix 函数)
- 负责计算 $N times N$ 的全距离矩阵。
- 兼容性设计:代码首先检查是否存在
pdist2 函数。如果不存在(未安装工具箱),则使用 $a^2 + b^2 - 2ab$ 的公式进行手动向量化扩展计算,保证了代码在任何 MATLAB 环境下的可移植性。
注意事项
- 代码中为了视觉效果,当簇内点数少于 500 时会绘制连线。如果将样本量调整得非常大,建议注释掉绘图部分的相关代码以提高运行速度。
- 由于 K-medoids 对初始值的选择较为敏感(虽然比 K-means 好),不同的随机种子可能会导致收敛到不同的局部最优解,这是算法本身的特性。