
简介这份资源面向机器学习初学者与需要做故障诊断的工程人员提供KMeans聚类的样本数据与可视化源码帮助解决无监督场景下故障类型自动分组、聚类数目难以确定的问题。压缩包共2个文件约57KB包含1个xlsx数据表与1个m脚本数据表存放设备异常加热片段等故障样本脚本则实现聚类流程与结果可视化二者配合即可完成从数据读取到图形输出的完整实验。资源重点演示了用Calinski-Harabasz指数评估聚类效果、以指数最大值确定最佳聚类数的方法并借助散点图、直方图或箱线图直观呈现各簇分布便于理解类间分离度与类内紧凑性。目前已有4508人学习下载适合希望快速上手聚类分析、对照代码复现故障分类实验的读者参考。1. Kmeans 聚类样本 可视化源码从一份数据到一张能讲清楚的图手上拿到一份没有标签的样本表老板或客户只丢下一句「看看能分成几类」这大概是 Kmeans 出现频率最高的场景。它属于无监督学习里最朴素也最实用的一类给定样本集预先指定簇数 K算法反复把每个点分配给最近的质心再重新计算质心直到质心不再明显移动。它不告诉你「为什么」只告诉你「谁和谁更像」。配合可视化源码你能把高维特征压到二维平面上用散点颜色把聚类结果直接画出来一眼看出分簇是否合理、有没有离群点、K 选得对不对。这套「样本 可视化源码」的组合适合三类人做数据分析想快速摸清数据分布的从业者、需要给非技术同事交付一张聚类结论图的产品/运营、以及正在学聚类算法想跑通完整链路的学生。它不解决所有聚类问题密度不均、非球形簇、簇大小差异极大时Kmeans 会翻车这时候要换 DBSCAN 或层次聚类。但作为第一把锤子它足够快、足够好解释源码也短到能逐行读懂。下面按「先立住原理和选型再动手复现最后讲坑和进阶」的顺序展开。2. Kmeans 的数学直觉与选型为什么它先被拿来用2.1 目标函数与迭代逻辑Kmeans 要最小化的目标很直白每个点到它所属簇质心的距离平方和也就是 SSESum of Squared Errors。用公式写就是 ΣΣ||x - μ_i||²外层遍历簇内层遍历属于该簇的样本。算法分两步循环分配步固定质心把每个样本分给最近的质心更新步固定分配把每个质心移到它名下样本的均值位置。这两步交替SSE 单调不增所以一定收敛但收敛到的可能是局部最优不是全局最优。这解释了两个常见现象。第一初始质心不同结果可能不同所以要设n_init多次随机初始化取最优。第二K 必须预先给定因为目标函数里 K 是超参数算法自己不会告诉你该分几类。理解这两点后面调参和排错就有方向了。2.2 距离度量与数据预处理默认用欧氏距离这也是「欧氏聚类」这个热搜词的来源。欧氏距离对量纲敏感一个特征取值范围 0 到 1另一个 0 到 10000后者会主导距离计算聚类结果基本被它绑架。所以标准做法是先做标准化常用 Z-score减均值除标准差或 Min-Max 归一化。标准化之后每个特征权重相当聚类才反映整体结构。另一个预处理点是离群点。Kmeans 用均值更新质心均值对极端值敏感一个远离群体的点能把质心拽偏连带整个簇变形。如果业务上离群点本身是重点比如欺诈检测不要直接删可以先聚类再单独分析如果只是噪声考虑先剔除或改用对离群点更稳健的 K-medoids。2.3 和层次聚类、DBSCAN 的选型对比热搜里「层次聚类 python」「dbscan 聚类算法」和 Kmeans 经常一起出现说明大家在选型上纠结。给一张对比表按实际决策维度看维度Kmeans层次聚类DBSCAN是否需要预设簇数需要不需要看树状图切不需要靠密度簇形状假设近似球形、大小相近无强假设任意形状对离群点敏感较敏感能识别噪声大数据集速度快慢O(n²) 以上中等依赖参数结果可解释性高质心即代表中树状图直观中参数难调选型建议样本量大、簇大致球形、要快速出结论选 Kmeans样本量小、想看层次结构、不确定簇数选层次聚类簇形状不规则、有噪声、不想预设簇数选 DBSCAN。很多实际项目会先用 Kmeans 快速摸底再用 DBSCAN 验证密度结构两者结果对照着看。3. 用 sklearn 跑通 Kmeans从样本到标签的最小代码3.1 环境与依赖常见做法是 Python 3.8 以上装numpy、scikit-learn、matplotlib、pandas四个包就够。不指定具体版本号因为不同版本 API 基本兼容遇到KMeans参数报错再对照官方文档即可。安装命令pip install numpy scikit-learn matplotlib pandas如果要用中文标签matplotlib 默认字体可能显示方块需要额外设置字体这一步在可视化章节处理。3.2 生成或加载样本数据为了可复现先用make_blobs造一份带已知簇结构的数据方便验证算法是否正确。真实项目里把这段换成pd.read_csv读自己的样本表即可。import numpy as np from sklearn.datasets import make_blobs # 造 500 个样本4 个簇2 个特征random_state 固定保证可复现 X, y_true make_blobs( n_samples500, centers4, n_features2, cluster_std1.0, # 簇内标准差越大簇越松散 random_state42 ) print(X.shape) # (500, 2)n_samples控制样本量centers是真实簇数cluster_std控制簇的松散程度。真实数据没有y_true这里保留只是为了后面和聚类结果对照。random_state一定要固定否则每次跑出来的数据不同没法排查问题。3.3 标准化与训练from sklearn.preprocessing import StandardScaler from sklearn.cluster import KMeans # 标准化Kmeans 对量纲敏感这一步不能省 scaler StandardScaler() X_scaled scaler.fit_transform(X) # 训练n_clusters 是 Kn_init 是随机初始化次数random_state 固定 kmeans KMeans( n_clusters4, n_init10, # 跑 10 次不同初始化取 SSE 最小的 max_iter300, # 单次迭代上限 random_state42 ) labels kmeans.fit_predict(X_scaled) # 质心坐标已标准化空间 centers kmeans.cluster_centers_ print(labels[:10]) print(centers.shape) # (4, 2)n_init10是经验值样本量大或簇多时可以调到 20。max_iter一般 300 够用如果收敛警告频繁出现再调大。fit_predict一步完成训练和预测返回每个样本的簇标签。注意cluster_centers_是在标准化后的空间里要还原到原始量纲得用scaler.inverse_transform。3.4 评估聚类质量没有真实标签时用轮廓系数silhouette score和 SSE 两个指标。轮廓系数范围 -1 到 1越接近 1 说明簇内紧、簇间远。from sklearn.metrics import silhouette_score # 轮廓系数样本量大时可用 sample_size 抽样加速 score silhouette_score(X_scaled, labels, sample_size500, random_state42) print(f轮廓系数: {score:.3f}) # SSE即 inertia_用来画肘部图 print(fSSE: {kmeans.inertia_:.2f})sample_size在样本超过几万时能显著提速代价是估计值有波动。inertia_就是目标函数值K 越大它越小所以不能只看它绝对值要看下降拐点。4. 可视化源码把聚类结果画成能交付的图4.1 二维散点图与质心标注最基础也最常用的图样本按簇着色质心用大标记标出。import matplotlib.pyplot as plt plt.rcParams[font.sans-serif] [SimHei] # 中文标签 plt.rcParams[axes.unicode_minus] False plt.figure(figsize(8, 6)) # 散点clabels 按簇着色cmap 选定性色板 plt.scatter(X_scaled[:, 0], X_scaled[:, 1], clabels, cmapviridis, s30, alpha0.7) # 质心红色大叉 plt.scatter(centers[:, 0], centers[:, 1], cred, markerX, s200, label质心) plt.title(Kmeans 聚类结果K4) plt.xlabel(特征 1标准化) plt.ylabel(特征 2标准化) plt.legend() plt.tight_layout() plt.savefig(kmeans_result.png, dpi150) plt.show()clabels让每个簇自动分配颜色cmapviridis是连续色板簇多时换成tab10这类定性色板区分度更好。alpha控制透明度样本重叠时能看出密度。dpi150保证导出图清晰交付够用。4.2 肘部图选 KK 选不对图再漂亮也没意义。肘部图看 SSE 随 K 的下降曲线找拐点。sse [] k_range range(1, 11) for k in k_range: km KMeans(n_clustersk, n_init10, random_state42) km.fit(X_scaled) sse.append(km.inertia_) plt.figure(figsize(8, 5)) plt.plot(k_range, sse, markero) plt.xlabel(簇数 K) plt.ylabel(SSE) plt.title(肘部图) plt.xticks(k_range) plt.grid(alpha0.3) plt.tight_layout() plt.savefig(elbow.png, dpi150) plt.show()拐点判断有主观性常见做法是找下降速度明显变缓的位置。这份数据 K4 附近应该能看到拐点。如果曲线平滑没有明显拐点说明数据本身没有清晰簇结构别硬分。4.3 高维数据的降维可视化真实样本往往几十上百维直接画不了。常见做法是先用 PCA 降到二维再画注意降维只用于可视化聚类仍在原始标准化空间做。from sklearn.decomposition import PCA pca PCA(n_components2, random_state42) X_pca pca.fit_transform(X_scaled) plt.figure(figsize(8, 6)) plt.scatter(X_pca[:, 0], X_pca[:, 1], clabels, cmaptab10, s30, alpha0.7) plt.title(PCA 降维后的聚类结果) plt.xlabel(fPC1解释方差 {pca.explained_variance_ratio_[0]:.1%}) plt.ylabel(fPC2解释方差 {pca.explained_variance_ratio_[1]:.1%}) plt.tight_layout() plt.savefig(pca_cluster.png, dpi150) plt.show()坐标轴标注解释方差比例让读者知道这张二维图保留了多少原始信息。如果两个主成分加起来不到 50%说明二维图失真严重结论要谨慎。需要更强非线性降维可以换 t-SNE 或 UMAP但它们的坐标轴没有物理意义只适合看簇的分离度。5. 避坑与排查Kmeans 落地时最容易翻车的五件事5.1 不标准化直接聚类结果被大数值特征主导现象聚类结果和某个取值范围大的特征高度相关其他特征几乎没起作用。原因欧氏距离被大量纲特征主导。解决训练前统一做 Z-score 或 Min-Max 标准化并记录 scaler 用于还原质心。5.2 K 靠拍脑袋定肘部图不看现象换个人跑出不同簇数结论对不上。原因K 是超参数没有唯一正确答案。解决肘部图加轮廓系数双指标交叉验证再结合业务可解释性定 K把选择依据写进文档。5.3 每次结果不一样以为算法有 bug现象同一份数据两次运行簇标签不同。原因初始化随机且未固定random_state或n_init太小。解决固定random_staten_init设 10 以上保证结果可复现。5.4 用簇标签做后续分析忘了标签会随运行变化现象上次「簇 0」是高风险客户这次「簇 0」变成低风险。原因Kmeans 的簇编号是任意的没有固定语义。解决每次聚类后按质心特征或簇内统计量重新映射语义不要硬编码簇编号。5.5 高维稀疏数据硬上 Kmeans现象文本 TF-IDF 或 one-hot 数据聚类效果差簇内样本看不出共性。原因高维空间距离趋于均匀欧氏距离失效。解决先降维PCA/SVD或改用余弦距离的球形 Kmeans文本场景也可考虑主题模型替代。6. 进阶技巧让聚类结果真正能交付的三个习惯第一个习惯是给每个簇生成画像。光有散点图不够业务方要的是「这群人有什么共同点」。做法是对每个簇算各特征的均值和分布挑差异最大的几个特征写成一句话描述。代码上就是pd.DataFrame(X_scaled).groupby(labels).mean()再对照原始量纲解释。这一步能把「簇 2」翻译成「高消费低频次的中年用户」交付价值立刻不一样。第二个习惯是稳定性检验。Kmeans 对初始化和采样敏感靠谱的做法是多次重采样聚类看同一批样本是否稳定落在同一簇。可以用sklearn.utils.resample抽子集跑多次统计每个样本的簇归属一致性一致性低的样本往往是边界点结论里要标注出来。这一步能提前发现「看起来分开了其实很脆弱」的假象。第三个习惯是把可视化源码参数化。把簇数、颜色板、点大小、导出路径抽成配置换数据时只改配置不改逻辑。我一般会留一个plot_clusters(X, labels, centers, title, save_path)函数项目里反复调用。下面是一个可直接复用的封装def plot_clusters(X_2d, labels, centers_2dNone, title聚类结果, save_pathNone): 通用聚类可视化X_2d 为二维坐标centers_2d 可选 plt.figure(figsize(8, 6)) plt.scatter(X_2d[:, 0], X_2d[:, 1], clabels, cmaptab10, s30, alpha0.7) if centers_2d is not None: plt.scatter(centers_2d[:, 0], centers_2d[:, 1], cred, markerX, s200, label质心) plt.legend() plt.title(title) plt.tight_layout() if save_path: plt.savefig(save_path, dpi150) plt.show()X_2d可以是原始二维特征也可以是 PCA 降维结果函数不关心来源。centers_2d可选因为降维后质心需要单独变换。save_path为空时只显示不保存方便调试。最后说个血泪经验聚类没有标准答案别指望一次跑出完美结果。我现在的习惯是先跑三组不同 K 和预处理方案把图并排贴出来对比再和业务方一起挑。算法只是把数据摊开真正决定分几类、怎么解释的是对业务的理解。希望帮到你。本文还有配套的精品资源点击获取