SOM-自组织映射
自组织映射(Self-Organizing Map, SOM)是一类无监督神经网络方法,其目标是在尽量保持样本拓扑关系的同时,把高维特征映射到一个低维离散网格上。与 PCA、MDS、t-SNE 这类直接输出连续低维坐标的方法不同,SOM 的输出更像是一个二维神经元网格,每个样本…
SOM-自组织映射
1. 方法概述
自组织映射(Self-Organizing Map, SOM)是一类无监督神经网络方法,其目标是在尽量保持样本拓扑关系的同时,把高维特征映射到一个低维离散网格上。与 PCA、MDS、t-SNE 这类直接输出连续低维坐标的方法不同,SOM 的输出更像是一个二维神经元网格,每个样本会被映射到某个最佳匹配单元(BMU, Best Matching Unit)上。
本项目中的 SOM-自组织映射 模块并不是调用第三方 SOM 库,而是对 SOM 训练流程进行了直接实现。根据当前代码,它具有以下特点:
- 固定要求第 1 列为样本 ID,后续列为数值特征;
- 支持在第 2 列及以后勾选参与训练的特征列;
- 支持
standardize=True/False,即是否执行 z-score 标准化; - 支持
random与sample两种权重初始化方式; - 使用二维矩形网格、欧氏距离 BMU 搜索和高斯邻域更新;
- 输出 BMU 映射表、权重向量表、U-Matrix、量化误差与拓扑误差。
设共有 \(n\) 个样本、\(p\) 个被选中的特征。记原始特征矩阵为
$$ X=(x_{ij})_{n\times p},\quad i=1,2,\ldots,n,\ j=1,2,\ldots,p \tag{1} $$
其中程序默认第 1 列是样本名称列,不会参与 SOM 训练。
2. 数据要求与预处理
2.1 数据约束
根据 upload_widget.py、indicators_widget.py、data_validator.py 与 core/som_calculator.py 的实现,模块对输入数据的真实要求如下:
- 数据不能为空;
- 至少包含两列,即第 1 列对象名称和至少 1 列特征;
- 第 1 列对象名称不能重复;
- 第 2 列及以后必须是数值型列;
- 特征列不能含空值;
- 至少选择 1 个特征列;
- 网格尺寸
map_rows与map_cols都必须不小于 2; iterations必须不小于 10;learning_rate和sigma必须为正数。
与前面一些聚类模块不同,这个 SOM 实现没有额外检查常数列,也没有可选的 label_col 逻辑。
2.2 标准化方式
当 standardize=True 时,代码会对每个特征执行 z-score 标准化:
$$ z_{ij}=\frac{x_{ij}-\mu_j}{\sigma_j} \tag{2} $$
其中 \(\mu_j\) 为第 \(j\) 个特征均值,\(\sigma_j\) 为按 ddof=0 计算的总体标准差。若某列满足 \(\sigma_j=0\),代码会把该列标准差替换为 1。
若 standardize=False,则直接令
$$ z_{ij}=x_{ij} \tag{3} $$
记进入 SOM 训练的特征矩阵为
$$ Z=(z_{ij})_{n\times p} \tag{4} $$
2.3 符号说明
| 符号 | 含义 |
|---|---|
| \(n\) | 样本数量 |
| \(p\) | 特征维数 |
| \(R,C\) | SOM 网格的行数与列数 |
| \(M=RC\) | 神经元总数 |
| \(z_i\) | 第 \(i\) 个样本的预处理后特征向量 |
| \(w_m\) | 第 \(m\) 个神经元的权重向量 |
| \(b(i)\) | 样本 \(z_i\) 的 BMU 索引 |
| \(\eta_t\) | 第 \(t\) 次迭代的学习率 |
| \(\sigma_t\) | 第 \(t\) 次迭代的邻域半径 |
| \(U\) | U-Matrix |
3. 核心数学模型
3.1 二维网格与权重向量
代码先建立一个 \(R\times C\) 的二维矩形网格,共有
$$ M=R\times C \tag{5} $$
个神经元。每个神经元 \(m\) 对应一个权重向量
$$ w_m\in\mathbb{R}^{p},\quad m=1,2,\ldots,M \tag{6} $$
3.2 BMU 搜索
对任意样本 \(z_i\),程序使用欧氏距离寻找最佳匹配单元:
$$ b(i)=\arg\min_{1\le m\le M}\|z_i-w_m\|_2 \tag{7} $$
代码中的 _bmu() 正是按这个规则在全部节点上逐一比较并取最小距离索引。
3.3 指数衰减学习率与邻域半径
在第 \(t\) 次迭代时,代码把初始学习率 learning_rate 和初始邻域半径 sigma 按指数形式衰减:
$$ \eta_t=\eta_0\exp\!\left(-\frac{t}{T}\right) \tag{8} $$
$$ \sigma_t=\sigma_0\exp\!\left(-\frac{t}{T}\right) \tag{9} $$
其中 \(T=\texttt{iterations}\)。
3.4 高斯邻域函数与权重更新
设第 \(m\) 个节点在网格中的坐标为 \(r_m\),BMU 节点坐标为 \(r_{b(i)}\)。代码先计算网格距离平方
$$ d_m^2=\|r_m-r_{b(i)}\|_2^2 \tag{10} $$
再构造高斯邻域函数
$$ h_{m,t}=\exp\!\left(-\frac{d_m^2}{2\sigma_t^2}\right) \tag{11} $$
并执行权重更新:
$$ w_m^{(t+1)}=w_m^{(t)}+\eta_t h_{m,t}\big(z_i-w_m^{(t)}\big) \tag{12} $$
这正是 _train() 中的核心更新逻辑。
3.5 U-Matrix
当前项目的 U-Matrix 并不是任意邻接定义,而是仅考虑每个节点上下左右四个方向的直接邻居。对网格位置 \((r,c)\),其 U 值为该节点与所有有效四邻域节点权重距离的平均值:
$$ U_{rc}=\frac{1}{|\mathcal{N}_{rc}|}\sum_{m'\in\mathcal{N}_{rc}}\|w_{rc}-w_{m'}\|_2 \tag{13} $$
其中 \(\mathcal{N}_{rc}\) 表示该节点的四邻域集合。
4. 评价指标
4.1 量化误差
代码首先根据所有样本的 BMU 计算量化误差(Quantization Error):
$$ \mathrm{QE}=\frac{1}{n}\sum_{i=1}^{n}\|z_i-w_{b(i)}\|_2 \tag{14} $$
该值越小,通常说明神经元权重对样本分布的逼近越好。
4.2 拓扑误差
当前代码把“第一 BMU”和“第二 BMU”是否在网格上相邻,作为拓扑保持的判断依据。若样本 \(z_i\) 的前两个 BMU 不满足曼哈顿距离为 1,则记为一次拓扑错误。于是拓扑误差为
$$ \mathrm{TE}=\frac{1}{n}\sum_{i=1}^{n}\mathbf{1}\!\left(\|r_{b_1(i)}-r_{b_2(i)}\|_1\neq 1\right) \tag{15} $$
这里的邻接定义是严格的上下左右相邻,不包括对角邻居。
5. 项目中的初始化与实现口径
5.1 random 初始化
当 init_method="random" 时,代码不会从标准正态分布初始化,而是按每个特征在当前训练数据中的最小值和最大值,在对应区间内均匀采样生成权重向量。
5.2 sample 初始化
当 init_method="sample" 时,程序会从样本矩阵中随机抽取节点初始权重。需要注意:
- 抽样使用
replace=True; - 因此同一个样本可能被多个节点重复选中。
5.3 训练样本抽取方式
每一轮迭代中,代码只随机抽取一个样本参与更新,而不是整批样本遍历一次后再统一更新。因此当前实现更接近在线式 SOM 训练,而不是批量式 SOM。
5.4 权重向量的尺度口径
权重向量 工作表中保存的是 codebook 本身。也就是说:
- 若
standardize=True,则权重向量处在标准化后的特征空间; - 若
standardize=False,则权重向量处在原始特征空间。
当前代码不会把权重向量反变换回原始尺度,因此在报告中解释节点权重时必须先确认是否做过标准化。
6. 代码实现细节
6.1 BMU 映射结果
当前项目最终导出的 BMU映射 表包含:
- 样本名称列;
bmu_rowbmu_colbmu_index
其中 bmu_index 是按行优先顺序把二维网格展开后的节点索引。
6.2 U-Matrix 图与 BMU 散点图
项目会生成两张图:
u_matrix.pngbmu_scatter.png
其中:
u_matrix.png使用viridis色图显示 U-Matrix 热度;bmu_scatter.png直接绘制样本落在 SOM 网格上的 BMU 位置;bmu_scatter.png会调用invert_yaxis(),因此图中的行坐标方向与数组索引方向相反。
6.3 原始数据表的口径
当前 raw_data 并不是整个上传文件的完整拷贝,而是
- 第 1 列样本 ID;
- 被选中的特征列
组成的子表。这一点与某些其他模块把完整原始表全部写入 Excel 的做法不同。
7. 算法流程
结合当前项目代码,SOM-自组织映射 的实际执行流程如下:
- 读取
.xlsx、.xls或.csv文件,并校验首列样本名与后续数值特征。 - 在“特征选择”页从第 2 列及以后勾选参与训练的特征列。
- 在“方法设置”页设置
map_rows、map_cols、iterations、learning_rate、sigma、init_method、standardize与random_state。 - 取所选特征构造训练矩阵 \(X\),按需执行 z-score 标准化得到 \(Z\)。
- 在二维矩形网格上初始化全部节点权重向量。
- 重复执行随机抽样、BMU 搜索、指数衰减和高斯邻域更新,直到达到设定迭代次数。
- 计算每个样本的 BMU 位置、节点权重表和 U-Matrix。
- 计算量化误差与拓扑误差。
- 生成
u_matrix.png与bmu_scatter.png。 - 导出
SOM_results_<时间戳>.xlsx,并在同目录下生成SOM_plots_<时间戳>/图表目录。
8. 关键参数说明
8.1 map_rows 与 map_cols
表示 SOM 网格的行数和列数。当前界面范围为 2 到 50。网格越大,表达能力越强,但也更容易出现节点稀疏。
8.2 iterations
表示训练迭代次数。当前界面范围为 10 到 5000,默认值为 500。该值过小会导致权重尚未充分收敛。
8.3 learning_rate
初始学习率,默认值为 0.5。代码会在训练过程中指数衰减,而不是固定不变。
8.4 sigma
初始邻域半径,默认值为 3.0。该值越大,早期更新会影响更宽的邻域;越小则更偏向局部微调。
8.5 init_method
当前支持:
randomsample
random 是按特征范围均匀采样,sample 是从现有样本中放回抽样初始化。
8.6 standardize
若勾选,则执行 z-score 标准化;不勾选则直接使用原始特征。由于 SOM 中的 BMU 搜索和权重更新都依赖欧氏距离,特征量纲差异较大时通常更建议开启标准化。
9. 输出结果与导出说明
9.1 Excel 工作表
根据 save_results() 的实现,导出的 Excel 文件包含:
Parameters原始数据处理后数据BMU映射权重向量U矩阵评价指标Charts
其中:
处理后数据为训练时实际使用的特征矩阵;权重向量保存 SOM 节点权重与其网格坐标;评价指标目前只有quantization_error和topographic_error;Charts记录图表路径。
9.2 图表目录
当前图表会保存在结果目录下的
SOM_plots_<时间戳>/u_matrix.pngSOM_plots_<时间戳>/bmu_scatter.png
结果文件名则固定形如:
SOM_results_<时间戳>.xlsx
10. 论文写作建议
10.1 方法描述模板
“本文采用自组织映射(SOM)方法对样本进行无监督结构学习。该方法首先在二维神经元网格上初始化节点权重,然后通过最佳匹配单元搜索和邻域协同更新,使高维样本在保留局部拓扑结构的前提下映射到低维网格空间。本文进一步结合 U-Matrix、样本 BMU 分布、量化误差和拓扑误差对映射效果进行分析。”
10.2 结果解释模板
结果部分可写为:BMU映射 可用于观察样本在 SOM 网格上的聚集位置,U矩阵 中高值区域通常对应簇间边界,低值区域通常对应簇内相似节点。若 quantization_error 越小,说明节点原型对样本表示越精确;若 topographic_error 越小,则通常说明样本局部拓扑关系保持得越好。
10.3 图表题注模板
- 图 1 SOM U-Matrix 热力图。
- 图 2 样本在 SOM 网格上的 BMU 映射散点图。
- 表 1 SOM 样本 BMU 映射结果。
- 表 2 SOM 节点权重向量与评价指标。
11. 实现说明与注意事项
- 当前模块只支持“首列样本名,后续列为数值特征”的数据结构。
- 若启用了标准化,
权重向量表中的数值位于标准化空间,不应直接按原始业务量纲解释。 sample初始化采用放回抽样,因此多个节点可能从同一样本开始。- 拓扑误差中使用的是严格四邻域相邻判定,不包含对角邻接。
- 当前实现不会自动给节点再分簇,它输出的是 SOM 网格表示和 BMU 映射,而不是像 K-Means 那样直接给出若干类中心。
12. 单篇终审补充
12.1 图题与表题对齐建议
当前 SOM 模块的真实工作簿包含:
Parameters原始数据处理后数据BMU映射权重向量U矩阵评价指标Charts
其中 BMU映射 与 U矩阵 是正文最值得引用的两张核心表:前者解释样本落在哪个神经元节点,后者解释节点之间的相对边界结构。不要把 BMU映射 误写成“聚类标签表”,因为当前实现并没有直接输出 K 类标签。
图文件保存在结果目录下的 SOM_plots_<时间戳>/ 子目录,当前真实图名为:
u_matrix.pngbmu_scatter.png
因此图题建议分别写成“SOM U-Matrix 热力图”“SOM BMU 映射图”。这两张图的空间含义都是 SOM 网格空间,而不是原始特征前两维散点图。
12.2 终审说明
这篇文档最关键的工程事实,是 BMU映射 里的 bmu_row、bmu_col 和 bmu_index 全都属于网格坐标表达,不是降维连续坐标。因此论文中若用这张表解释样本结构,应写“映射到网格节点的位置”,不要写成“连续二维嵌入坐标”。
另外,当前 权重向量 来自 codebook,在开启 standardize=True 时处于标准化空间。也就是说,U矩阵、BMU 位置和节点权重都共享预处理后的训练空间口径,不能直接按原始量纲解释业务数值大小。
12.3 全量强化补充
本次全量强化绑定的真实结果目录为 具体的算法3/聚类与降维/SOM-自组织映射/results/SOM-自组织映射分析结果_20260329_171346。目录内首个主结果文件为 SOM_results_20260329_171346.xlsx,实际工作表为 Parameters、原始数据、处理后数据、BMU映射、权重向量、U矩阵、评价指标、Charts。
该目录下真实图文件分成两组:SOM_plots_20260329_171346/u_matrix.png、SOM_plots_20260329_171346/bmu_scatter.png,以及二次生成的 SOM_plots_20260329_171347/u_matrix.png、SOM_plots_20260329_171347/bmu_scatter.png。与之对应,目录里还同时存在 SOM_results_20260329_171346.xlsx 和 SOM_results_20260329_171347.xlsx。这说明当前目录不是单一静态快照,而是“主结果 + repro 再生成产物”并存。
复现脚本为 repro_som_自组织映射.py,脚本实际采用 INPUT_FILE = 'repro_inputs/som_自组织映射_repro_data.csv',而目录里还额外保留了 repro_inputs/som_ui_input.csv。因此这篇文档应如实写明:结果目录中既保存 UI 上传输入副本,也保存 repro 专用输入副本;主实验建议引用 171346 这组工作簿与图,而把 171347 这组视作在同目录再次运行后产生的复现实物。
13. 软件实现核查补充(2026-07)
- 当前主结果目录应写作
具体的算法3/聚类与降维/SOM-自组织映射/results/SOM-自组织映射分析结果_20260329_171346。 - 正文应围绕
Parameters、原始数据、处理后数据、BMU映射、权重向量、U矩阵、评价指标、Charts来写。 - 图证应对应
u_matrix.png与bmu_scatter.png,并把网格映射和 BMU 位置区分清楚。 - 复现脚本应按
repro_som_自组织映射.py + repro_inputs/som_自组织映射_repro_data.csv的口径说明,同时注意目录里也保留了 UI 输入副本。