MeanShift-MeanShift
Mean Shift 是一种典型的基于密度峰值搜索的聚类方法。它不要求用户预先指定聚类数,而是通过在特征空间中不断把样本向局部密度更高的位置平移,最终收敛到若干密度峰,并以这些峰作为簇中心。
MeanShift-MeanShift
1. 方法概述
Mean Shift 是一种典型的基于密度峰值搜索的聚类方法。它不要求用户预先指定聚类数,而是通过在特征空间中不断把样本向局部密度更高的位置平移,最终收敛到若干密度峰,并以这些峰作为簇中心。
本项目中的 MeanShift-MeanShift 模块并不是自写均值漂移迭代器,而是对 sklearn.cluster.MeanShift 及 sklearn.cluster.estimate_bandwidth 的工程化封装。当前代码的关键特点包括:
- 固定使用第 1 列作为样本 ID,后续列为数值特征;
- 支持手动输入
bandwidth,也支持根据quantile/n_samples自动估计带宽; - 支持
none、standard、minmax三种预处理方式; - 支持
bin_seeding、cluster_all与max_iter参数; - 输出聚类标签、中心坐标、簇统计、带宽信息与图表。
设共有 \(n\) 个样本、\(p\) 个被选中的特征。记原始特征矩阵为
$$ X=(x_{ij})_{n\times p},\quad i=1,2,\ldots,n,\ j=1,2,\ldots,p \tag{1} $$
其中程序约定第 1 列必须为样本 ID/对象名称列,且该列不能重复。
2. 数据要求与预处理
2.1 数据约束
根据 upload_widget.py、indicators_widget.py 与 data_validator.py 的实现,模块对输入数据的真实要求如下:
- 数据不能为空;
- 至少包含两列,即第 1 列对象名称和至少 1 列特征;
- 第 1 列对象名称必须唯一;
- 第 2 列及以后必须为数值型;
- 特征列不能含空值;
- 特征列不能是常数列;
- 样本数量至少为 2。
2.2 Z-score 标准化
当 normalization="standard" 时,程序调用 StandardScaler,对每个特征执行
$$ z_{ij}=\frac{x_{ij}-\mu_j}{\sigma_j} \tag{2} $$
2.3 Min-Max 归一化
当 normalization="minmax" 时,程序调用 MinMaxScaler,执行
$$ z_{ij}=\frac{x_{ij}-x_j^{\min}}{x_j^{\max}-x_j^{\min}} \tag{3} $$
若 normalization="none",则直接令
$$ z_{ij}=x_{ij} \tag{4} $$
记真正进入 Mean Shift 聚类的特征矩阵为
$$ Z=(z_{ij})_{n\times p} \tag{5} $$
2.4 符号说明
| 符号 | 含义 |
|---|---|
| \(n\) | 样本数量 |
| \(p\) | 特征维数 |
| \(z_i\) | 第 \(i\) 个样本的预处理后特征向量 |
| \(h\) | 核带宽 bandwidth |
| \(K_h(\cdot)\) | 带宽为 \(h\) 的核函数 |
| \(m(z)\) | Mean Shift 向量 |
| \(y_i\) | 第 \(i\) 个样本的聚类标签 |
| \(c_k\) | 第 \(k\) 个簇中心 |
| \(K\) | 最终簇数量 |
3. 核心数学模型
3.1 核密度思想
Mean Shift 可以理解为在核密度估计框架下寻找概率密度峰值。对任意位置 \(z\),其核密度估计可表示为
$$ \hat f(z)=\frac{1}{nh^p}\sum_{i=1}^{n}K\!\left(\frac{z-z_i}{h}\right) \tag{6} $$
其中 \(h\) 为带宽。带宽越大,密度面越平滑;带宽越小,越容易形成更多局部峰。
3.2 Mean Shift 向量
Mean Shift 方法的更新方向可表示为
$$ m(z)= \frac{\sum_{i=1}^{n} z_i\, g\!\left(\left\|\frac{z-z_i}{h}\right\|^2\right)} {\sum_{i=1}^{n} g\!\left(\left\|\frac{z-z_i}{h}\right\|^2\right)} -z \tag{7} $$
算法不断把当前位置 \(z\) 朝着 \(z+m(z)\) 方向移动,直到收敛到密度峰附近。
3.3 聚类结果形成
当不同样本的漂移轨迹收敛到同一个密度峰时,它们会被分配到同一个簇。最终得到的簇中心可记为
$$ \{c_1,c_2,\ldots,c_K\} \tag{8} $$
第 \(i\) 个样本的簇标签为
$$ y_i\in\{0,1,\ldots,K-1\} \tag{9} $$
若 cluster_all=False,部分未被归入任何簇的样本在 sklearn 中可能会被标记为
$$ y_i=-1 \tag{10} $$
本项目会在统计表中额外记录 num_noise。
4. 项目中的带宽估计逻辑
4.1 手动指定带宽
若用户直接输入 bandwidth,代码会把该值传给 MeanShift。当前要求
$$ h>0 \tag{11} $$
否则会直接报错。
4.2 自动估计带宽
若 bandwidth 留空,程序会调用
estimate_bandwidth(X, quantile=q, n_samples=s)
其中:
$$ 0<q\le 1 \tag{12} $$
且
$$ s=\min(\texttt{n\_samples},\, n) \tag{13} $$
若 n_samples 留空,则直接取全部样本。
4.3 带宽估计失败时的回退
这是当前项目一个很关键的工程细节:若 estimate_bandwidth() 结果不是有限正数,代码会回退为“各特征标准差的平均值”,若该值仍无效,则继续回退到 1.0,即
$$ h \leftarrow \operatorname{mean}\big(\operatorname{std}(Z_{\cdot 1}),\ldots,\operatorname{std}(Z_{\cdot p})\big) \tag{14} $$
若上述值为 0 或无效,再令
$$ h\leftarrow 1.0 \tag{15} $$
因此,项目一定会尽量构造一个可用带宽,而不是因为估计失败直接退出。
5. 评价指标
5.1 簇数量
项目在 Stats 表中记录
$$ K=\text{num\_clusters} \tag{16} $$
即最终得到的簇中心数量。
5.2 轮廓系数
若最终簇数量大于 1,且有效标签样本数足够,程序会调用 silhouette_score 计算轮廓系数。其定义为
$$ s_i=\frac{b_i-a_i}{\max(a_i,b_i)} \tag{17} $$
$$ \mathrm{Silhouette}=\frac{1}{n^\ast}\sum_{i=1}^{n^\ast}s_i \tag{18} $$
其中 \(n^\ast\) 表示参与该指标计算的样本数。需要注意:
- 当
cluster_all=True时,通常全部样本都参与计算; - 当
cluster_all=False时,代码会先剔除label=-1的样本,再计算轮廓系数。
5.3 统计表字段
当前 Stats 表中可能出现的字段包括:
num_clustersbandwidth_usedquantilen_samples_for_bandwidthmax_iternum_noise(仅cluster_all=False时)silhouette_score(仅在可计算时出现)
6. 代码实现细节
6.1 使用的是 sklearn.cluster.MeanShift
本项目没有手工实现均值漂移迭代,而是直接构造
MeanShift(bandwidth=..., bin_seeding=..., cluster_all=..., max_iter=...)
再调用 fit_predict(X) 得到簇标签。
6.2 中心坐标的口径
这是当前模块最容易写错的地方之一。代码中的 centers_df 直接来自
ms.cluster_centers_
而 ms.cluster_centers_ 是在预处理后的特征空间上得到的。当前实现没有把这些中心点再反变换回原始尺度,因此 Centers 工作表中的中心坐标是:
- 原始尺度坐标,当
normalization="none"; - 标准化后坐标,当
normalization="standard"; - Min-Max 缩放后坐标,当
normalization="minmax"。
论文或报告中若要解释中心值的业务含义,需要先注意这一点。
6.3 聚类散点图的口径
当前绘图使用的是 self.features,即原始选中特征值,而不是标准化后的矩阵 X。因此:
- 图中的点坐标通常是原始尺度;
- 但
Centers表中的簇中心可能是预处理空间坐标。
这两者口径并不完全一致,是当前代码的实际行为。
7. 算法流程
结合当前项目代码,MeanShift-MeanShift 的实际执行流程如下:
- 读取
.xlsx、.xls或.csv数据文件;CSV 会依次尝试utf-8-sig、utf-8、gbk编码。 - 校验数据结构:首列样本 ID 唯一,其余列必须是无空值数值型特征,且不能有常数列。
- 在“特征选择”页从第 2 列开始勾选参与聚类的特征。
- 在“方法与参数”页设置
bandwidth、quantile、n_samples、bin_seeding、cluster_all、max_iter与normalization。 - 根据
normalization执行标准化、区间缩放或不处理。 - 若
bandwidth留空,则先用estimate_bandwidth估计带宽;若估计失败,再按式(14) 到式(15) 回退。 - 调用
sklearn.cluster.MeanShift.fit_predict()得到样本簇标签和簇中心。 - 计算簇数量、实际带宽、噪声点数量和轮廓系数等统计量。
- 生成聚类散点图和簇规模柱状图。
- 导出 Excel 文件
meanshift_results_<时间戳>.xlsx,并自动生成复现脚本。
8. 关键参数说明
8.1 bandwidth
核带宽。若用户手动指定,则直接作为 Mean Shift 聚类的关键尺度参数;若留空,则走自动估计流程。
8.2 quantile
用于估计带宽的分位数,当前要求范围为
$$ 0<\text{quantile}\le 1 \tag{19} $$
其值越大,通常估计得到的带宽越大。
8.3 n_samples
估计带宽时使用的样本数。若留空,则使用全部样本;若填写,则实际使用值不会超过总样本量。
8.4 bin_seeding
是否启用 bin_seeding。该选项通常用于加速收敛,但可能改变初始核中心候选点的生成方式。
8.5 cluster_all
是否为全部样本分配簇:
True:通常所有样本都会获得簇标签;False:部分样本可能被标记为-1。
8.6 max_iter
均值漂移迭代的最大迭代次数,默认值为 300。
8.7 normalization
支持:
nonestandardminmax
当特征量纲差异明显时,一般建议优先考虑 standard 或 minmax。
9. 输出结果与导出说明
9.1 Excel 工作表
根据 save_to_excel() 的实现,导出的 Excel 文件包含:
RawDataFeaturesClusteredCentersStatsParametersCharts
其中:
RawData保存原始完整数据;Features保存参与聚类的原始特征矩阵;Clustered是在原始数据后附加cluster_label的结果表;Centers保存簇中心坐标;Stats保存聚类统计量;Parameters中会记录bandwidth_used。
9.2 图表文件
当前代码会在结果目录的 plots/ 子目录中生成:
cluster_scatter.pngcluster_size.png
其中:
- 若特征数不少于 2,则
cluster_scatter.png使用前两维原始特征作图; - 若只有 1 个特征,则绘制单轴散点图;
cluster_size.png展示各簇样本数分布。
10. 论文写作建议
10.1 方法描述模板
“本文采用 Mean Shift 方法对样本进行密度聚类分析。首先对选定数值特征进行必要的标准化或区间缩放,并结合核带宽参数构造局部核密度估计;随后通过均值漂移迭代,将样本逐步移动到局部密度峰附近,并据此形成若干聚类中心。与需要预设聚类数的方法不同,Mean Shift 可以根据带宽参数自适应地识别簇的个数。本文进一步输出聚类标签、簇中心、簇规模以及轮廓系数,用于评价聚类结构。”
10.2 结果解释模板
结果部分可写为:若 bandwidth_used 较大,通常会得到更少且更平滑的簇;若簇数量较多且簇规模分布高度不均衡,则说明当前带宽下局部峰较多。若 silhouette_score 较高,通常可认为簇间分离性较好。
10.3 图表题注模板
- 图 1 Mean Shift 聚类散点图。
- 图 2 Mean Shift 簇规模分布图。
- 表 1 Mean Shift 聚类中心与统计结果。
11. 实现说明与注意事项
- Mean Shift 对带宽极其敏感,带宽设置不当会导致簇数量过多或过少。
- 自动估计带宽只是启发式过程,最终仍建议结合业务场景和图形结果复核。
Centers工作表中的中心坐标可能处于预处理空间,而聚类散点图使用的是原始特征空间,解释时不要混淆。- 当
cluster_all=False时,结果中可能出现label=-1的未分配样本,需要在后续分析中单独处理。 - 当前模块不支持自定义核函数、距离度量或更复杂的带宽自适应策略,论文描述时应按当前实现口径表述。
12. 单篇终审补充
12.1 图题与表题对齐建议
当前 MeanShift 模块的真实工作簿包含:
RawDataFeaturesClusteredCentersStatsParametersCharts
其中 Clustered 是最适合正文引用的样本分组结果表,Centers 适合做簇中心补充说明,Stats 则适合汇总带宽、簇数和轮廓系数。不要把 Features 误写成“标准化后特征表”,因为当前实现导出的 Features 实际上是原始选中特征矩阵。
图文件保存在结果目录的 plots/ 子目录,当前实现真实输出:
cluster_scatter.pngcluster_size.png
因此图题建议分别写成“Mean Shift 聚类散点图”“Mean Shift 簇规模分布图”。两张图都是真实导出图,不需要再泛化成“密度峰值图”或“带宽演化图”。
12.2 终审说明
这篇文档最关键的工程事实,是 Centers 和散点图并不在同一个空间。当前 cluster_centers_ 是在归一化后的 X 上计算得到的,而 cluster_scatter.png 使用的是原始 self.features 前两维作图。因此论文里若把 Centers 的数值直接拿去和散点图坐标逐点对应,会出现解释偏差。
另外,当前 repro 脚本已采用 repro_inputs/... 相对路径,结果目录中可见如 repro_inputs/window1_dbscan_meanshift_input.csv 的输入副本引用。这意味着 MeanShift 现在的复现链路是新框架口径,不应再沿用旧版本绝对路径描述。
12.3 全量强化补充
本篇终审补充绑定的真实算法目录为 具体的算法3/聚类与降维/MeanShift-MeanShift,本次采用的代表性结果目录为 具体的算法3/聚类与降维/MeanShift-MeanShift/results/MeanShift-MeanShift分析结果_20260329_171328。该目录是单轮主结果目录,不是 pytest 的 repro 专用目录。
主结果工作簿为 具体的算法3/聚类与降维/MeanShift-MeanShift/results/MeanShift-MeanShift分析结果_20260329_171328/meanshift_results_20260329_171328.xlsx,实测工作表为:
RawDataFeaturesClusteredCentersStatsParametersCharts
这些页名说明当前结果重点是“样本分组 + 中心 + 统计摘要”,而不是密度峰值搜索轨迹。Centers 仍需按预处理空间解释,不能直接拿去和散点图坐标逐项对照。
本轮真实图文件为:
具体的算法3/聚类与降维/MeanShift-MeanShift/results/MeanShift-MeanShift分析结果_20260329_171328/plots/cluster_scatter.png具体的算法3/聚类与降维/MeanShift-MeanShift/results/MeanShift-MeanShift分析结果_20260329_171328/plots/cluster_size.png
因此本轮可写成“聚类散点图 + 簇规模图”,但不能补写带宽搜索曲线、密度峰值图或核函数演化图。
复现实物方面,该目录实际包含:
具体的算法3/聚类与降维/MeanShift-MeanShift/results/MeanShift-MeanShift分析结果_20260329_171328/repro_meanshift_meanshift.py具体的算法3/聚类与降维/MeanShift-MeanShift/results/MeanShift-MeanShift分析结果_20260329_171328/repro_inputs/window1_dbscan_meanshift_input.csv
脚本中明确写成 INPUT_FILE = 'repro_inputs/window1_dbscan_meanshift_input.csv',且输出目录按脚本目录解析。因此这一轮应描述为“可迁移的相对路径复现入口”,而不是仍依赖原始上传绝对路径。
11. 软件实现核查补充(2026-07)
- 当前主结果目录应写作
具体的算法3/聚类与降维/MeanShift-MeanShift/results/MeanShift-MeanShift分析结果_20260329_171328。 - 正文应围绕
Centers、Stats、Parameters、Charts来写。 - 图证应对应
cluster_scatter.png与cluster_size.png,并把带宽聚类与簇规模分开说明。 - 复现脚本应按
repro_meanshift_meanshift.py + repro_inputs/window1_dbscan_meanshift_input.csv的口径说明。