
简介面向机器学习与数据挖掘入门者的KMeans聚类分析MATLAB仿真资源基于MATLAB 2021a实现重点演示如何对数据进行聚类、输出聚类点并绘制算法收敛图适合需要直观理解KMeans迭代过程的学生、科研人员或竞赛爱好者。资源共4个文件压缩包仅27KB其中m文件为核心算法源码txt文件提供示例数据docx文档包含项目介绍与运行说明便于边读边练。KMeans实现覆盖初始化质心、距离分配与质心更新等关键步骤并借助可视化呈现质心移动轨迹与收敛趋势同时附带fpga与matlab相关文本拓展了硬件加速聚类的思考方向。运行后可获得清晰的聚类散点图和收敛曲线帮助理解不同迭代次数对结果的影响。已有755人学习这份小而精的资料能帮助初学者快速跑通从数据读取、聚类计算到结果展示的完整流程是理解经典聚类算法的实用入门素材。1. 聚类分析的入口用 kmeans 在 MATLAB 2021a 中定位数据簇聚类分析在 MATLAB 2021a 里的落地形态通常就是一行kmeans(X,k)但要让输出的聚类点和聚类收敛图真正可信得先弄清楚迭代过程中算法到底在做什么。kmeans 把无标签样本划分成 k 个互不相交的簇使总体簇内平方和SSE尽量小收敛图就是 SSE 随迭代次数变化的下降曲线。它既能证明这个聚类分析任务的迭代确实收住了也能在 K 值选取不当、初始化不合理时直接暴露出病态曲线。对做数据分析、信号处理、图像像素分割的工程师来说聚类分析的意义就是把看似无序的数据变成可解释的结构而是否收敛、收敛到哪个目标值直接决定这组结构能不能用。本文就用 MATLAB 2021a 的 kmeans 函数从最小代码出发覆盖聚类点输出、聚类收敛图绘制和参数诊断这几个关键环节。2. K-means 迭代机制与 MATLAB 2021a 的收敛逻辑2.1 目标函数与分配、更新两阶段循环K-means 的核心优化目标是把样本划分进 k 个簇最小化簇内平方和J Σ(j1..k) Σ(i∈Cj) || xi - μj ||²其中 μj 是簇 Cj 的均值向量即该簇质心。求解过程是交替迭代分配阶段把每个样本归入距离最近的质心更新阶段用簇内样本均值重算质心。每轮迭代后 J 单调下降但由于目标函数非凸最终会停在某个局部极小值MATLAB 里的 kmeans 函数实现的正是这个标准 Lloyd 流程。MATLAB 2021a 的 kmeans 默认最大迭代次数是 100如果质心不再明显移动或相对 SSE 变化低于默认容差 1e-4迭代会提前终止。这两个触发条件都由 Options 结构中的 TolFun 和 TolX 控制。我一般会在调试阶段把收敛图需要的迭代日志打开确认每条样本是不是真的进入了稳定分配再决定要不要增大 MaxIter。2.2 kmeans 函数输出与关键参数速查[idx, C, sumd, D] kmeans(X, k, Name, Value);X 是 n×p 样本矩阵n 个样本、p 维特征类型为 double不能含 NaN 或 Inf。idx 是 n×1 簇标签向量取值 1 到 k。C 是 k×p 质心矩阵每行对应一个簇中心。sumd 是 1×k 向量记录每个簇内的 SSE总体 SSE 即 sum(sumd)。D 是 n×k 距离矩阵D(i,j) 表示样本 i 到质心 j 的最近距离按指定距离度量计算。其中 sumd 就是判断收敛和选择 K 值的直接依据。每次运行 kmeans 后比较不同参数组合下的 sum(sumd)本质就是在比较不同聚类划分质量。参数默认值作用Distancesqeuclidean距离度量默认欧氏距离平方Startplus初始质心策略k-meansReplicates1随机初始化重复次数取最小 SSE 结果MaxIter100单次运行最大迭代次数Optionsstatset控制 TolFun、TolX、Display 等EmptyActionsingleton空簇出现时的处理方式2.3 收敛判定与 Display 迭代日志很多人在 MATLAB 里做完 kmeans 只拿 idx 和 C却不知道迭代到底收敛没有。常用做法是打开 Display 选项opts statset(Display, iter, TolFun, 1e-6, TolX, 0); [idx, C, sumd] kmeans(X, k, Options, opts, Replicates, 1);运行后命令行会逐行打印迭代次数、阶段、参与计算的样本数和当前 SSE。最后一行会给出最佳距离总和。这里 TolFun 设为 1e-6 比默认更严格适合需要精确收敛图的场景。TolX 设为 0 表示只依赖目标函数变化判定。如果显示日志里 SSE 最后几行不再变化说明已经收敛如果到达 MaxIter 时 SSE 仍在下降就要提高 MaxIter。3. 在 MATLAB 2021a 中输出聚类点数据准备与可视化3.1 构造测试数据与最小可复现调用先用合成数据走通完整链路。生成三簇二维高斯样本模拟聚类分析最常见的处理对象% 生成三类二维高斯样本模拟真实聚类分析场景 rng(1); X [randn(60,2)*0.6 [2,2]; randn(60,2)*0.5 [-2,-1]; randn(60,2)*0.7 [0,3]]; k 3; [idx, C, sumd] kmeans(X, k, Replicates, 5); totalSSE sum(sumd); fprintf(总体 SSE %.4f\n, totalSSE);这段代码里 rng(1) 固定随机数种子保证每次运行结果一致。randn 生成高斯分布样本分别向右上、左下、正上方偏移形成三个可分离的簇。Replicates 设为 5 表示用 5 组不同随机初始质心分别运行最后返回 SSE 最小的一次结果。这样能明显降低局部极小值带来的抖动是中间章节实际项目里最常用的防护手段。3.2 多维特征标准化zscore 与缺失值清理真实数据往往各维度量纲不同比如年龄和收入混在一起直接做 kmeans 会由量纲大的特征主导距离收敛图会好看但聚类结果没有业务意义。% 标准化到零均值、单位标准差 X zscore(X); % 若存在 NaN 行删除后再聚类 X(any(isnan(X), 2), :) [];标准化对 kmeans 并不是强制步骤但几乎总是推荐。zscore 等价于对每列做 (x - mean) ./ std。如果特征分布偏斜严重也可以改用 min-max 归一化。对图像分割这类像素值本身在同一量纲的场景标准化反而可能破坏原始对比度这时跳过这一步。3.3 用散点图绘制聚类点与质心二维数据聚类后直接用 gscatter 着色质心用五角星叠加figure; gscatter(X(:,1), X(:,2), idx, brk, .x, 8); hold on; plot(C(:,1), C(:,2), kp, MarkerSize, 14, MarkerFaceColor, m); legend(簇 1, 簇 2, 簇 3, 质心, Location, best); grid on; title(kmeans 聚类点与质心MATLAB 2021a);gscatter 第一个参数是 x 坐标列第二个是 y 坐标列第三个是分组变量 idx。brk 指定三个簇的颜色蓝、红、黑.x 指定每个簇的标记符号。这里数据是二维所以直接用原始特征坐标绘制。如果数据维度超过三维常见做法是先做主成分分析PCA降到两维再用同样代码可视化聚类点之间的空间关系仍然可用。数据维度可视化方式1 维scatter(X, ones(size(X)))2 维gscatter(X(:,1), X(:,2), idx)3 维scatter3(X(:,1), X(:,2), X(:,3), 20, idx)高于 3 维PCA 降维到 2 维后再 gscatter4. 聚类收敛图迭代曲线绘制与典型异常诊断4.1 手动迭代记录 SSE 轨迹绘制收敛图MATLAB 的 kmeans 函数本身不返回逐次迭代的 SSE 向量所以要输出完整的聚类收敛图常用做法是把 Lloyd 迭代手动实现一遍每次记录 SSE% 以第 3 章生成的 X、k3 为基础手动实现 kmeans 迭代 rng(1); centroids X(randperm(size(X,1), k), :); % 随机挑 k 个样本作初始质心 maxIters 50; sseLog zeros(1, maxIters); for iter 1:maxIters % 分配阶段计算每个样本到全部质心的欧氏距离 dists pdist2(X, centroids, euclidean); [~, idx] min(dists, [], 2); % 更新阶段用每个簇的均值作为新质心 for j 1:k members X(idx j, :); if ~isempty(members) centroids(j, :) mean(members, 1); end end % 更新后重新计算 SSE dists2 pdist2(X, centroids, euclidean).^2; [minD, ~] min(dists2, [], 2); sseLog(iter) sum(minD); end figure; plot(1:maxIters, sseLog, b-o, LineWidth, 1.5); grid on; xlabel(迭代次数); ylabel(簇内平方和 SSE); title(kmeans 聚类收敛图MATLAB 2021a 仿真);这段代码的逻辑要点在分配和更新两个阶段。pdist2 计算距离矩阵min 取每行最小值得到最近质心更新质心时用 mean 取簇内样本均值。注意 SSE 计算用的是欧氏距离平方因为聚类目标本身是平方误差取平方值才能和内置 kmeans 的 sumd 对齐。代码里加了对空簇的判断避免某个簇完全没有样本时 mean 计算出 NaN。实际仿真时我会把这段手动迭代封装成一个函数输入 X 和 k输出 sseLog 和最终质心。4.2 用内置 Options 输出标准迭代日志做交叉对比手写迭代能拿到完整曲线但和官方实现的质心初始化策略不完全一致。交叉验证办法是打开 MATLAB 内置迭代日志opts statset(Display, iter, MaxIter, 50); [idx, C, sumd] kmeans(X, k, Options, opts, Replicates, 1);命令行会输出每轮迭代的 SSE 变化最后给出 best total distance。这个值应该和手动迭代的 sseLog 末尾一致。如果两个结果差异明显优先以内置 kmeans 为准检查手写代码里的距离度量和初始化方式。交叉验证是聚类分析仿真里最容易遗漏的一步却最能在问题初期暴露实现错误。4.3 收敛图典型病态与参数对照收敛图形态可能原因调整方式曲线在第 MaxIter 次仍未走平MaxIter 太小增大到 300 或 500多次运行曲线末尾 SSE 不同局部极小值增大 Replicates 到 10 以上曲线出现向上跳动空簇引发质心重置检查 EmptyAction 设置曲线下降缓慢但不停留在高位距离度量选择不当标准化数据或换 cityblock所有簇几乎重合K 值偏大结合 4.4 节肘部法则降 K4.4 用肘部法则帮助确定 K 值聚类收敛图只证明算法在某个 K 值下达到稳定不能证明 K 选对了。肘部法则通过对比不同 K 值下的总体 SSE 来辅助选择Klist 1:8; sseK zeros(size(Klist)); for k Klist [~, ~, sumd] kmeans(X, k, Replicates, 10); sseK(k) sum(sumd); end figure; plot(Klist, sseK, ro-, LineWidth, 1.5); grid on; xlabel(簇数 K); ylabel(总体 SSE); title(肘部法则选择 K 值);当 K 从 1 逐渐增大SSE 会持续下降但下降幅度会在某个 K 处明显变缓曲线的拐点就是所谓的肘部。对第 3 章的合成数据拐点应该在 K3 附近。这里 Replicates 设置到 10是避免个别初始化差导致 SSE 偏高让曲线更平滑。5. 验证聚类结果的进阶技巧evalclusters 与可复现收敛图5.1 用 evalclusters 批量比较 K 值肘部法则依赖人工看图自动化的做法是用 MATLAB 自带的 evalclusterseva evalclusters(X, kmeans, silhouette, KList, 1:8); figure; plot(eva); xlabel(簇数 K); ylabel(轮廓平均值);evalclusters 会按 KList 逐个运行 kmeans并计算轮廓系数、Calinski-Harabasz 或 GAP 统计量。轮廓平均值越接近 1说明簇内紧凑、簇间分离越明显。判读原则是选轮廓平均值最高或明显尖峰处的 K。silhouette 计算量比肘部法则大数据量到十万条样本时建议先抽样再评估。5.2 用固定 Start 生成可复现的聚类收敛图验证类场景和论文仿真里收敛图必须能复现。kmeans 默认的随机初始化每次结果会有差异解决办法是手动固定初始质心rng(0); initC X(randperm(size(X,1), k), :); % 固定取前 k 个样本当质心 [idxFinal, CFinal] kmeans(X, k, Start, initC, MaxIter, 300);这样即使换一台机器重跑只要 X 不变聚类点和收敛图就完全一致。实际项目中我还会把标准化参数 meanX、stdX 一起保存对新增样本做同样的标准化后再预测归属。这样处理之后K 值选择、聚类标签可视化、收敛图输出和验证后发布之间形成一条可全量重跑的链路这也是从仿真脚本升级为可交付分析代码的关键一步。本文还有配套的精品资源点击获取