正在加载中...

展开本页目录
算法教程 KMeans-K-均值聚类

KMeans-K-均值聚类

No.122 · 在线教程

K-Means 是最常用的原型聚类方法之一,其核心思想是:给定簇数 K,通过迭代地执行“样本归属分配”和“簇中心更新”,使簇内平方和最小。与 DBSCAN、HDBSCAN 等基于密度的方法不同,K-Means 需要用户预先给定聚类数,更适合发现近似球状、规模相对均衡的簇结构。

KMeans-K-均值聚类

1. 方法概述

K-Means 是最常用的原型聚类方法之一,其核心思想是:给定簇数 \(K\),通过迭代地执行“样本归属分配”和“簇中心更新”,使簇内平方和最小。与 DBSCAN、HDBSCAN 等基于密度的方法不同,K-Means 需要用户预先给定聚类数,更适合发现近似球状、规模相对均衡的簇结构。

本项目中的 KMeans-K-均值聚类 模块并不是自写 K-Means 迭代器,而是对 sklearn.cluster.KMeans 的工程化封装。当前代码实现的主要特点包括:

  1. 支持从任意列中选择 label_col 作为样本名称展示列;
  2. 支持对数值特征执行 noneminmaxzscore 三种预处理;
  3. 支持 k-means++random 两种初始化;
  4. 支持 n_init 多次重复初始化并取最优结果;
  5. 可选自动评估 \(K\) 范围,输出 SSE 与轮廓系数曲线;
  6. 输出归一化空间中心、原始尺度中心、簇汇总表、指标表与聚类图。

与前面若干聚类模块不同,本模块不要求首列必须是样本 ID。上传数据后,程序会自动识别哪些列可以完整转换为数值列,并允许用户在界面中额外指定一列作为 label_col;真正参与聚类的是用户勾选的数值型特征列。

设共有 \(n\) 个样本、\(p\) 个被选中的特征,记参与聚类的原始特征矩阵为

$$ X=(x_{ij})_{n\times p},\quad i=1,2,\ldots,n,\ j=1,2,\ldots,p \tag{1} $$

2. 数据要求与预处理

2.1 数据约束

根据 upload_widget.pyindicators_widget.pydata_validator.py 的当前实现,模块对输入数据的真实要求如下:

  1. 数据表不能为空;
  2. 样本量至少为 2 行;
  3. 数据中至少要存在 1 列可完整转为数值的列;
  4. 被选中的特征列必须存在;
  5. 特征列不能含非数值或空值;
  6. 特征列不能是常数列;
  7. 真正开始计算时,还要求样本数不少于聚类数,即 \(n\ge K\)。

其中 label_col 是可选的。若用户未指定样本名称列,程序会自动生成

$$ \text{样本1},\text{样本2},\ldots,\text{样本}n \tag{2} $$

作为结果表中的样本标识。

2.2 Min-Max 归一化

normalize="minmax" 时,程序按列执行线性缩放:

$$ z_{ij}=\frac{x_{ij}-x_j^{\min}}{x_j^{\max}-x_j^{\min}} \tag{3} $$

若某列满足 \(x_j^{\max}=x_j^{\min}\),代码会把分母替换为 1,以避免除零。

2.3 Z-score 标准化

normalize="zscore" 时,程序执行

$$ z_{ij}=\frac{x_{ij}-\mu_j}{\sigma_j} \tag{4} $$

其中 \(\mu_j\) 和 \(\sigma_j\) 分别为第 \(j\) 个特征的均值与总体标准差;若 \(\sigma_j=0\),同样会以 1 替代。

normalize="none",则直接令

$$ z_{ij}=x_{ij} \tag{5} $$

经预处理后得到用于 K-Means 拟合的特征矩阵

$$ Z=(z_{ij})_{n\times p} \tag{6} $$

2.4 符号说明

符号 含义
\(n\) 样本数量
\(p\) 特征维数
\(K\) 聚类数 n_clusters
\(z_i\) 第 \(i\) 个样本的预处理后特征向量
\(c_k\) 第 \(k\) 个簇中心
\(y_i\) 第 \(i\) 个样本的簇标签
\(\mathcal{G}_k\) 第 \(k\) 个簇对应的样本集合
\(n_k\) 第 \(k\) 个簇的样本数
\(\mathrm{SSE}\) 总簇内平方和
\(R\) 重复初始化次数 n_init

3. 核心数学模型

3.1 K-Means 优化目标

K-Means 的目标是寻找 \(K\) 个簇中心,使簇内平方和最小:

$$ \min_{\{\mathcal{G}_k,c_k\}_{k=1}^{K}} \sum_{k=1}^{K}\sum_{z_i\in \mathcal{G}_k}\|z_i-c_k\|_2^2 \tag{7} $$

sklearn.cluster.KMeans 中,最终输出的 inertia_ 就是式(7) 对应的目标函数值,也就是项目结果表中的“总簇内平方和”。

3.2 样本分配与中心更新

从算法机理上,K-Means 在每轮迭代中会把样本分配给最近中心:

$$ y_i=\arg\min_{1\le k\le K}\|z_i-c_k\|_2 \tag{8} $$

然后对每个簇重新计算均值中心:

$$ c_k=\frac{1}{n_k}\sum_{i:y_i=k} z_i \tag{9} $$

本项目并未手工实现该迭代,而是把 n_clustersinitn_initmax_itertolrandom_state 直接传入 sklearn.cluster.KMeans 完成拟合。

3.3 初始化与多次重复拟合

当前界面支持两种初始化方式:

  1. k-means++
  2. random

同时支持重复初始化 \(R=\texttt{n\_init}\) 次。若第 \(r\) 次初始化得到的目标函数值记为

$$ \mathrm{SSE}^{(r)}=\sum_{k=1}^{K}\sum_{z_i\in \mathcal{G}_k^{(r)}}\|z_i-c_k^{(r)}\|_2^2 \tag{10} $$

则最终会保留目标函数值最小的那次结果:

$$ r^\ast=\arg\min_{1\le r\le R}\mathrm{SSE}^{(r)} \tag{11} $$

3.4 簇汇总统计量

项目会对每个簇输出样本数、簇内平方和与样本占比。对第 \(k\) 个簇,

$$ n_k=\sum_{i=1}^{n}\mathbf{1}(y_i=k) \tag{12} $$

簇内平方和为

$$ \mathrm{SSE}_k=\sum_{i:y_i=k}\|z_i-c_k\|_2^2 \tag{13} $$

样本占比为

$$ \pi_k=\frac{n_k}{n} \tag{14} $$

因此总簇内平方和满足

$$ \mathrm{SSE}=\sum_{k=1}^{K}\mathrm{SSE}_k \tag{15} $$

3.5 中心反变换

项目不仅输出归一化空间中的 Centers,还会把中心反变换回原始尺度,形成 Centers_Original

对 Min-Max 归一化,反变换为

$$ c_{kj}^{(\text{orig})}=c_{kj}^{(\text{norm})}\cdot (x_j^{\max}-x_j^{\min})+x_j^{\min} \tag{16} $$

对 Z-score 标准化,反变换为

$$ c_{kj}^{(\text{orig})}=c_{kj}^{(\text{norm})}\cdot \sigma_j+\mu_j \tag{17} $$

若未做归一化,则 Centers_OriginalCenters 一致。

4. 自动评估 K 范围

4.1 K 范围扫描规则

若勾选 eval_enabled=True,程序会在区间

$$ K\in\{K_{\min}, K_{\min}+\Delta K,\ldots,K_{\max}\} \tag{18} $$

上重复拟合 K-Means。其中

$$ K_{\min}=\max(2,\texttt{eval\_k\_min}),\qquad \Delta K=\max(1,\texttt{eval\_k\_step}) \tag{19} $$

并且代码会进一步把

$$ K_{\max}\leftarrow \min(\texttt{eval\_k\_max},\, n) \tag{20} $$

即扫描上界不会超过样本量。

4.2 SSE 曲线

对每个候选 \(K\),程序记录该模型的 inertia_,也就是

$$ \mathrm{SSE}(K)=\sum_{k=1}^{K}\sum_{z_i\in \mathcal{G}_k}\|z_i-c_k\|_2^2 \tag{21} $$

并据此绘制 elbow_curve.png。该曲线通常用于观察“肘部拐点”。

4.3 轮廓系数曲线

若候选聚类数满足 \(K>1\) 且 \(n>K\),程序尝试计算轮廓系数:

$$ s_i=\frac{b_i-a_i}{\max(a_i,b_i)} \tag{22} $$

$$ \mathrm{Silhouette}(K)=\frac{1}{n}\sum_{i=1}^{n}s_i \tag{23} $$

其中 \(a_i\) 为样本 \(i\) 与同簇样本的平均距离,\(b_i\) 为其到最近其他簇样本的平均距离。该值越大,通常表示聚类分离性越好。

5. 评价指标

对最终选定的聚类数 \(K\),项目会输出以下指标:

5.1 轮廓系数

项目仅在“簇数大于 1 且样本数大于簇数”时才计算轮廓系数,其定义见式(22) 与式(23)。

5.2 Calinski-Harabasz 指数

项目调用 sklearn.metrics.calinski_harabasz_score 计算 CH 指数,可写为

$$ \mathrm{CH}= \frac{\operatorname{tr}(B_K)/(K-1)} {\operatorname{tr}(W_K)/(n-K)} \tag{24} $$

其中 \(B_K\) 与 \(W_K\) 分别表示类间离散矩阵与类内离散矩阵。一般而言,CH 越大越好。

5.3 Davies-Bouldin 指数

项目还调用 sklearn.metrics.davies_bouldin_score 计算 DB 指数。若记第 \(k\) 个簇的平均类内离散度为 \(S_k\),簇 \(k,l\) 中心距离为 \(M_{kl}\),则

$$ R_{kl}=\frac{S_k+S_l}{M_{kl}} \tag{25} $$

$$ \mathrm{DB}=\frac{1}{K}\sum_{k=1}^{K}\max_{l\ne k}R_{kl} \tag{26} $$

一般而言,DB 越小越好。

6. 算法流程

结合当前项目代码,KMeans-K-均值聚类 的实际执行流程如下:

  1. 用户上传 .xlsx.xls.csv 文件;CSV 会依次尝试 utf-8-sigutf-8gbk 编码。
  2. 程序扫描每一列,识别哪些列能够完整转为数值列,作为可选特征集合。
  3. 在“特征设置”页,用户可选定一个 label_col 作为样本名称列,并勾选若干数值型特征参与聚类。
  4. 程序校验所选特征列是否存在、是否为数值列、是否含空值、是否为常数列。
  5. 在“算法参数”页设置 n_clustersinitn_initmax_itertolrandom_statenormalize 以及是否启用 K 范围评估。
  6. normalize="minmax"zscore,则对特征矩阵执行相应预处理。
  7. 若启用 K 范围评估,则先按式(18) 到式(23) 扫描候选 \(K\),生成 Evaluation 表。
  8. 调用 sklearn.cluster.KMeans.fit() 得到簇标签、簇中心与总簇内平方和。
  9. 计算簇汇总表、原始尺度簇中心、Silhouette、CH、DB 等指标。
  10. 绘制聚类散点图;若启用 K 范围评估,再额外绘制肘部法与轮廓系数曲线。
  11. 导出 Excel 文件 kmeans_results.xlsx,并自动生成复现脚本。

7. 关键参数说明

7.1 n_clusters

聚类数,界面允许范围为 2 到 200,默认值为 3。该参数直接决定最终分成多少个簇,也是 K-Means 最核心的先验输入。

7.2 init

初始化方式,当前支持:

  1. k-means++
  2. random

默认值为 k-means++。一般而言,k-means++ 能降低糟糕初始化带来的不稳定性。

7.3 n_init

重复初始化次数,默认值为 10。值越大,越有机会找到更优的局部最优解,但计算开销也更高。

7.4 max_itertol

二者都直接传给 sklearn.cluster.KMeans

  1. max_iter 控制单次初始化下的最大迭代轮数;
  2. tol 控制收敛阈值。

默认值分别为 300 和 \(10^{-4}\)。

7.5 random_state

界面标签写为“随机种子(0=不固定)”。代码中:

  1. 当输入值大于 0 时,传入固定随机种子;
  2. 当输入值为 0 时,实际传入 None,表示不固定随机性。

7.6 normalize

支持:

  1. none
  2. minmax
  3. zscore

若不同特征的量纲差异较大,通常建议优先考虑 minmaxzscore

7.7 eval_enabledeval_k_mineval_k_maxeval_k_step

这一组参数控制是否先对多个候选 \(K\) 做扫描评估。需要注意:

  1. eval_k_max < eval_k_min,评估表会为空;
  2. 实际扫描上界不会超过样本量;
  3. 只有启用评估时才会生成 Evaluation 工作表和两张评估曲线图。

8. 输出结果与导出说明

8.1 结果对象

当前代码返回的核心结果包括:

  1. raw_data:原始输入数据;
  2. processed_data:归一化或标准化后的特征矩阵;
  3. step_results.labels:样本名称与簇标签;
  4. step_results.cluster_summary:每个簇的样本数、簇内平方和、样本占比;
  5. step_results.centers:归一化空间簇中心;
  6. step_results.centers_original:原始尺度簇中心;
  7. step_results.metrics:样本数、特征数、聚类数、总簇内平方和、轮廓系数、CH、DB;
  8. step_results.evaluation:\(K\) 范围评估结果;
  9. charts:图表路径字典。

8.2 Excel 工作表

根据 _export_excel() 的实现,导出的 Excel 文件包含:

  1. Parameters
  2. RawData
  3. ProcessedData
  4. Labels
  5. Centers
  6. Centers_Original
  7. ClusterSummary
  8. Metrics
  9. Evaluation(仅在启用 K 范围评估时存在)
  10. Charts

8.3 图表文件

图表保存到结果目录下的 plots/ 子目录中,当前实现可能生成:

  1. cluster_scatter.png
  2. elbow_curve.png
  3. silhouette_curve.png

其中:

  1. 若特征数不少于 2,则 cluster_scatter.png 使用处理后数据前两维作图;
  2. 若只有 1 个特征,则以该特征为横轴、纵轴固定为 0 绘制单轴聚类散点图;
  3. 后两张图只有在启用 K 范围评估时才会生成。

9. 论文写作建议

9.1 方法描述模板

“本文采用 K-Means 方法对样本进行聚类分析。首先根据研究变量筛选数值型特征,并视量纲情况对特征进行 Min-Max 归一化或 Z-score 标准化。随后在给定聚类数 \(K\) 的条件下,利用 K-Means 最小化簇内平方和,获得各样本的聚类标签与簇中心。为提高初始解稳定性,模型采用多次随机初始化并保留总簇内平方和最小的结果,同时输出轮廓系数、CH 指数与 DB 指数用于评价聚类质量。”

9.2 结果解释模板

结果部分可写为:K-Means 在给定聚类数 \(K\) 条件下输出了各样本的聚类标签、簇中心与聚类评价指标。若轮廓系数较高且 Davies-Bouldin 指数较低,则说明当前聚类结果具有较好的紧凑性与可分性;若各簇样本占比差异明显,则可进一步结合簇中心解释样本结构差异。

9.3 若启用 K 范围评估的写法

“为辅助确定合理的聚类数,本文进一步在若干候选 \(K\) 上重复拟合 K-Means,并分别计算 SSE 与轮廓系数,结合肘部法曲线和轮廓系数曲线综合判断最优聚类数。”

9.4 图表题注模板

  • 图 1 K-Means 聚类结果散点图。
  • 图 2 K-Means 肘部法曲线。
  • 图 3 K-Means 轮廓系数曲线。
  • 表 1 各簇样本数、簇内平方和与样本占比。
  • 表 2 各簇中心及聚类评价指标。

10. 实现说明与注意事项

  1. K-Means 假设簇在欧氏空间中近似球状,对细长簇、不同密度簇或含大量噪声的数据并不稳健。
  2. 该模块当前固定使用欧氏意义下的 K-Means,不支持自定义距离度量。
  3. 若某列被选为 label_col,它不会再被当作聚类特征;若用户希望同时保留数值 ID 和真实特征,应明确区分这两类字段。
  4. Centers 是预处理空间中的中心,解释业务含义时通常应优先使用 Centers_Original
  5. eval_enabled 只提供辅助选 \(K\) 的曲线,不会自动替用户改写最终的 n_clusters;真正训练仍按当前参数中的 n_clusters 执行。

11. 单篇终审补充

11.1 图题与表题对齐建议

当前 KMeans 模块的真实工作簿包含:

  • Parameters
  • RawData
  • ProcessedData
  • Labels
  • Centers
  • Centers_Original
  • ClusterSummary
  • Metrics
  • Evaluation(仅启用 K 范围评估时存在)
  • Charts

这里应特别区分 MetricsEvaluation 的用途。Metrics 是最终一次聚类结果的质量指标,适合作为正文主表;Evaluation 是多组候选 \(K\) 的辅助评估表,更适合作为“选 \(K\) 过程表”或附录表。不要把 Evaluation 当成最终聚类结果表来引用。

图文件保存到结果目录下的 plots/ 子目录,当前实现真实输出:

  • cluster_scatter.png
  • elbow_curve.png
  • silhouette_curve.png

其中后两张图只有启用 eval_enabled 且评估表非空时才生成。因此论文图题可以写成“K-Means 聚类散点图”“K-Means 肘部法曲线”“K-Means 轮廓系数曲线”,但若本次运行并未启用 K 范围评估,就不应在正文中强行声称程序输出了三张图。

11.2 终审说明

这篇文档最需要避免的误写,是把 KMeans 的图表目录写成与其他聚类算法一样的时间戳子目录。当前实现固定把图保存到本次结果目录下的 plots/,而不是另建 KMeans_plots_<suffix> 目录,这一点应按真实工程口径写。

另一个需要点明的事实是:Excel 导出优先尝试 xlsxwriter,缺失时自动回退到 openpyxl。这不会改变工作表内容,但会影响列宽自适应效果。因此如果用户在不同环境下看到同样的 kmeans_results.xlsx 排版略有差异,这是导出引擎差异,不是算法结果差异。

11.3 全量强化补充

本篇终审补充绑定的真实算法目录为 具体的算法3/聚类与降维/KMeans-K-均值聚类,本次采用的真实结果目录为 具体的算法3/聚类与降维/KMeans-K-均值聚类/results/KMeans-K-均值聚类分析结果_20260329_171309。该目录同时保留了主工作簿、三张图、复现脚本和 repro_inputs,适合作为单轮结果证据。

主结果工作簿为 具体的算法3/聚类与降维/KMeans-K-均值聚类/results/KMeans-K-均值聚类分析结果_20260329_171309/kmeans_results.xlsx,实测工作表如下:

  • Parameters
  • RawData
  • ProcessedData
  • Labels
  • Centers
  • Centers_Original
  • ClusterSummary
  • Metrics
  • Evaluation
  • Charts

这套页名说明当前软件确实区分了最终聚类输出与选 \(K\) 辅助评估。论文正文如果写结果表,应优先引用 ClusterSummaryMetricsCenters_Original;若要说明调参过程,再单独引用 Evaluation。把 Evaluation 当成最终结果表,会直接写偏。

当前目录中的真实图文件为:

  • 具体的算法3/聚类与降维/KMeans-K-均值聚类/results/KMeans-K-均值聚类分析结果_20260329_171309/plots/cluster_scatter.png
  • 具体的算法3/聚类与降维/KMeans-K-均值聚类/results/KMeans-K-均值聚类分析结果_20260329_171309/plots/elbow_curve.png
  • 具体的算法3/聚类与降维/KMeans-K-均值聚类/results/KMeans-K-均值聚类分析结果_20260329_171309/plots/silhouette_curve.png

因此该轮结果可以真实写成“聚类散点图 + 肘部法曲线 + 轮廓系数曲线”三图并存。这里也再次说明 KMeans 当前实现的图目录就是结果目录下的 plots/,而不是另建带算法名前缀的时间戳子目录。

复现实物方面,该目录实际包含:

  • 具体的算法3/聚类与降维/KMeans-K-均值聚类/results/KMeans-K-均值聚类分析结果_20260329_171309/repro_kmeans_k_均值聚类.py
  • 具体的算法3/聚类与降维/KMeans-K-均值聚类/results/KMeans-K-均值聚类分析结果_20260329_171309/repro_inputs/window2_kmeans_baseline_input.csv

脚本中已实锤采用 INPUT_FILE = 'repro_inputs/window2_kmeans_baseline_input.csv',并带有基于脚本目录的候选解析逻辑。因此这一轮的真实口径应写成“主结果工作簿已经落地,repro 依赖结果目录内部输入副本可再执行”,而不是写成外部绝对路径驱动。

11. 软件实现核查补充(2026-07)

  • 当前主结果目录应写作 具体的算法3/聚类与降维/KMeans-K-均值聚类/results/KMeans-K-均值聚类分析结果_20260329_171309
  • 正文应围绕 FinalSummaryClusterSummaryCentersCenters_OriginalMetricsEvaluationCharts 来写。
  • 图证应对应 cluster_scatter.pngelbow_curve.pngsilhouette_curve.png,并把选 K 过程和最终聚类结果区分开。
  • 复现脚本应按 repro_kmeans_k_均值聚类.py + repro_inputs/window2_kmeans_baseline_input.csv 的口径说明。