☰
SOM:无监督学习的「聚类之王」,为什么它能「自组织」?
2026/9/26 11:15:41 网站建设 项目流程

从竞争学习到 Kohonen 网络,理解无监督聚类的数学本质


开头:不需要标签也能学习?

上一篇我们学习了 PCA,它是有监督的降维(需要标签来计算方差)。

今天我们学习自组织映射(SOM)——一种无监督的学习算法。

有监督学习: 输入数据 + 标签 → 学习映射关系 无监督学习: 只有输入数据 → 自动发现数据的结构 SOM 的目标: 把高维数据映射到 2D 网格 相似的输入映射到相邻的网格位置 → 自动聚类 + 数据可视化

一、竞争学习

1.1 胜者通吃(Winner-Takes-All)

竞争学习的基本思想 ═══════════════════════════════════════════════════════════════════ 输入:x 神经元:w₁, w₂, ..., wₙ 竞争过程: 1. 计算每个神经元与输入的距离 2. 距离最近的神经元「获胜」 3. 只有获胜神经元更新权重 d(x, w₁) = ||x - w₁|| d(x, w₂) = ||x - w₂|| ... d(x, wₙ) = ||x - wₙ|| 获胜者:w* = argmin d(x, wᵢ) 权重更新: w* = w* + η (x - w*) (只更新获胜的神经元)

1.2 与感知器的区别

特性感知器竞争学习
学习方式监督(有标签)无监督(无标签)
更新规则所有神经元都更新只有获胜神经元更新
目标分类聚类

二、Kohonen 网络(SOM)

2.1 网络结构

SOM 网络结构 ═══════════════════════════════════════════════════════════════════ 输入层:x ∈ R^d(高维数据) 输出层:2D 网格(通常是矩形或六边形) 输入层 输出层(2D 网格) x₁ ──→ ┌─────────────┐ x₂ ──→ │ w₁ w₂ w₃ w₄ │ x₃ ──→ │ w₅ w₆ w₇ w₈ │ │ w₉ w₁₀ w₁₁ w₁₂│ └─────────────┘ 每个网格位置有一个权重向量 wᵢ ∈ R^d

2.2 自组织的含义

自组织(Self-Organizing) ═══════════════════════════════════════════════════════════════════ 关键特性:相邻神经元也更新 普通竞争学习: 只有获胜神经元 w* 更新 → 网格结构没有意义 SOM: 获胜神经元 w* 更新 相邻神经元也更新(但幅度较小) → 相似的输入映射到相邻位置 影响力随距离衰减: influence(d) = exp(-d² / 2σ²) d:神经元到获胜者的距离 σ:邻域半径

2.3 拓扑保持

拓扑保持(Topology Preserving) ═══════════════════════════════════════════════════════════════════ 输入空间中的相似性 → 输出空间中的相邻性 输入空间: 输出空间: A B C A B C D E F → D E F G H I G H I 相似的样本(A, B, D, E)在网格中也相邻

三、SOM 学习算法

3.1 算法步骤

SOM 学习算法 ═══════════════════════════════════════════════════════════════════ 输入: X:训练数据 grid_size:网格大小 n_iterations:迭代次数 步骤: 1. 初始化权重 for each grid position (i, j): w(i,j) = random vector in R^d 2. 对每个迭代 t: a. 选择学习率和邻域半径(衰减) lr(t) = lr₀ * (1 - t/T) σ(t) = σ₀ * (1 - t/T) b. 对每个样本 x: i. 找到最佳匹配单元(BMU) bmu = argmin ||x - w(i,j)||₂ ii. 更新 BMU 及其邻域的权重 for each neuron (i, j) in 邻域(bmu): w(i,j) = w(i,j) + lr(t) * influence(d) * (x - w(i,j)) 3. 输出:训练好的权重矩阵

3.2 关键参数

参数含义典型值
grid_size网格大小10×10, 20×20
lr₀初始学习率0.1 ~ 0.5
σ₀初始邻域半径grid_size/2
T总迭代次数1000 ~ 10000

四、Python 实现 SOM

4.1 完整代码

importnumpyasnpimportmatplotlib.pyplotaspltclassSOM:"""自组织映射(SOM)"""def__init__(self,grid_size,input_dim,learning_rate=0.1,sigma=None):""" 参数: grid_size: 网格大小(整数或元组) input_dim: 输入数据维度 learning_rate: 初始学习率 sigma: 初始邻域半径(None 则自动计算) """ifisinstance(grid_size,int):self.grid_size=(grid_size,grid_size)else:self.grid_size=grid_size self.input_dim=input_dim self.lr0=learning_rate self.sigma0=sigmaifsigmaelsemax(self.grid_size)/2# 初始化权重self.weights=np.random.randn(self.grid_size[0],self.grid_size[1],input_dim)*0.1# 记录训练过程self.quantization_errors=[]def_find_bmu(self,x):"""找到最佳匹配单元(BMU)"""distances=np.linalg.norm(self.weights-x,axis=2)bmu_idx=np.unravel_index(np.argmin(distances),distances.shape)returnbmu_idxdef_get_neighborhood(self,bmu_idx,sigma):"""获取邻域内的神经元"""i,j=bmu_idx neighbors=[]foriiinrange(self.grid_size[0]):forjjinrange(self.grid_size[1]):dist=np.sqrt((ii-i)**2+(jj-j)**2)ifdist<=sigma:neighbors.append((ii,jj,dist))returnneighborsdeffit(self,X,n_iterations=1000):""" 训练 SOM 参数: X: 训练数据,形状 (n_samples, input_dim) n_iterations: 迭代次数 """n_samples=X.shape[0]self.quantization_errors=[]fortinrange(n_iterations):# 衰减学习率和邻域半径lr=self.lr0*(1-t/n_iterations)sigma=self.sigma0*(1-t/n_iterations)# 随机选择样本idx=np.random.randint(n_samples)x=X[idx]# 找到 BMUbmu_idx=self._find_bmu(x)# 更新 BMU 及邻域neighbors=self._get_neighborhood(bmu_idx,sigma)forii,jj,distinneighbors:influence=np.exp(-dist**2/(2*sigma**2))self.weights[ii,jj]+=lr*influence*(x-self.weights[ii,jj])# 记录量化误差ift%100==0:qe=np.mean([np.min(np.linalg.norm(X-self.weights[i,j],axis=1))foriinrange(self.grid_size[0])forjinrange(self.grid_size[1])])self.quantization_errors.append(qe)defpredict(self,X):"""预测每个样本的 BMU 位置"""iflen(X.shape)==1:X=X.reshape(1,-1)bmu_positions=[]forxinX:bmu_idx=self._find_bmu(x)bmu_positions.append(bmu_idx)returnbmu_positionsdefget_umatrix(self):"""计算 U-Matrix(用于可视化)"""umatrix=np.zeros(self.grid_size)foriinrange(self.grid_size[0]):forjinrange(self.grid_size[1]):distances=[]foriiinrange(max(0,i-1),min(self.grid_size[0],i+2)):forjjinrange(max(0,j-1),min(self.grid_size[1],j+2)):if(ii,jj)!=(i,j):distances.append(np.linalg.norm(self.weights[i,j]-self.weights[ii,jj]))umatrix[i,j]=np.mean(distances)ifdistanceselse0returnumatrix

4.2 测试:聚类

fromsklearn.datasetsimportmake_blobs# 生成聚类数据X,y_true=make_blobs(n_samples=300,centers=4,cluster_std=0.60,random_state=42)# 训练 SOMsom=SOM(grid_size=10,input_dim=2,learning_rate=0.5)som.fit(X,n_iterations=1000)# 预测bmu_positions=som.predict(X)# 可视化fig,(ax1,ax2)=plt.subplots(1,2,figsize=(12,5))# 原始数据ax1.scatter(X[:,0],X[:,1],c=y_true,cmap='viridis',alpha=0.6)ax1.set_title('Original Data')# SOM 网格umatrix=som.get_umatrix()ax2.imshow(umatrix,cmap='gray')ax2.set_title('SOM U-Matrix')plt.tight_layout()plt.show()

4.3 测试:高维数据可视化

fromsklearn.datasetsimportload_irisfromsklearn.preprocessingimportStandardScaler# 加载鸢尾花数据(4 维)iris=load_iris()X=iris.data y=iris.target# 标准化scaler=StandardScaler()X_scaled=scaler.fit_transform(X)# 训练 SOMsom=SOM(grid_size=15,input_dim=4,learning_rate=0.5)som.fit(X_scaled,n_iterations=2000)# 可视化fig,axes=plt.subplots(1,3,figsize=(15,4))# U-Matrixumatrix=som.get_umatrix()axes[0].imshow(umatrix,cmap='gray')axes[0].set_title('U-Matrix')# 激活图hit_map=np.zeros(som.grid_size)bmu_positions=som.predict(X_scaled)forposinbmu_positions:hit_map[pos]+=1axes[1].imshow(hit_map,cmap='hot')axes[1].set_title('Hit Map')# 标签映射label_map=np.zeros(som.grid_size)count_map=np.zeros(som.grid_size)forpos,labelinzip(bmu_positions,y):label_map[pos]+=label count_map[pos]+=1label_map[count_map>0]/=count_map[count_map>0]axes[2].imshow(label_map,cmap='viridis')axes[2].set_title('Label Map')plt.tight_layout()plt.show()

五、SOM vs K-Means

5.1 对比表

特性SOMK-Means
拓扑保持✅ 是❌ 否
可视化✅ 2D 网格❌ 无
计算复杂度高 O(n × grid²)低 O(n × k)
参数数量多(grid_size, lr, σ)少(k)
结果稳定性高低(依赖初始化)

5.2 什么时候用 SOM?

SOM 适用场景 ═══════════════════════════════════════════════════════════════════ ✅ 适合 SOM: - 需要数据可视化 - 需要拓扑保持 - 数据有非线性结构 - 需要交互式探索 ❌ 不适合 SOM: - 数据量大(计算慢) - 只需要快速聚类(用 K-Means) - 网格大小难以选择

六、工业应用

6.1 数据可视化

数据可视化 ═══════════════════════════════════════════════════════════════════ 高维数据可视化: - 原始数据 → SOM → 2D 网格 - 每个网格位置代表一类数据 - 颜色表示类别或属性 应用场景: - 文档聚类可视化 - 图像分割可视化 - 客户分群可视化

6.2 聚类分析

聚类分析 ═══════════════════════════════════════════════════════════════════ SOM 自动发现数据中的模式: - 相似的样本映射到相邻位置 - 不同的簇在网格中分离 优势: - 不需要预设簇数 - 结果可解释 - 支持增量学习

6.3 异常检测

异常检测 ═══════════════════════════════════════════════════════════════════ 正常样本:映射到常见的网格位置 异常样本:映射到罕见的网格位置 方法: 1. 训练 SOM 2. 记录每个网格位置的激活次数 3. 激活次数少的位置 → 可能是异常

七、避坑指南:使用 SOM 的 3 个陷阱

坑 1:网格大小选择不当 → 分辨率不足

错误做法:网格太小

# ❌ 网格太小som=SOM(grid_size=3,input_dim=100)# 只有 9 个神经元,无法区分复杂模式

正确做法:根据数据量选择

# ✅ 经验法则:网格边长 ≈ 5√nn_samples=1000grid_size=int(5*np.sqrt(n_samples))# ≈ 158# 或者用较小的网格先探索som=SOM(grid_size=20,input_dim=100)

坑 2:学习率太大 → 不收敛

错误做法:learning_rate=5

# ❌ 学习率太大som=SOM(grid_size=10,input_dim=2,learning_rate=5)# 权重剧烈震荡,无法收敛

正确做法:从 0.1~0.5 开始

# ✅ 合适的学习率som=SOM(grid_size=10,input_dim=2,learning_rate=0.5)

坑 3:邻域太大 → 模糊

错误做法:sigma=100

# ❌ 邻域太大som=SOM(grid_size=10,input_dim=2)som.sigma0=100# 所有神经元都更新# 没有局部化,无法形成清晰的聚类

正确做法:从 grid_size/2 开始,逐渐衰减

# ✅ 自动衰减som=SOM(grid_size=10,input_dim=2)# sigma0 默认为 grid_size/2 = 5# 训练过程中会逐渐衰减到 0

八、本篇总结

核心要点回顾

  1. 竞争学习:胜者通吃,只有获胜神经元更新
  2. SOM 结构:输入层 + 2D 网格输出层
  3. 自组织:相邻神经元也更新,保持拓扑结构
  4. 学习算法:找 BMU → 更新邻域 → 衰减学习率和邻域半径
  5. 拓扑保持:相似输入映射到相邻输出
  6. SOM vs K-Means:SOM 有拓扑保持,K-Means 更快

下篇预告

下一篇我们学习信息论。

SOM 用距离度量相似性,信息论用信息量度量不确定性。

下一篇你将学到:

  • Shannon 信息论基础(熵、互信息、KL 散度)
  • Infomax 原理
  • 独立分量分析(ICA)
  • 用 Python 手写 ICA

本期互动

你对 SOM 有什么看法?

  • 你用过 SOM 吗?在什么场景下?
  • 你觉得 SOM 和 t-SNE 有什么区别?
  • 你知道 SOM 的哪些应用?

欢迎在评论区留言。


系列目录

篇标题状态
01Haykin 精讲开篇:从「只会调参」到「理解神经网络的灵魂」✅ 完成
02感知器:神经网络的「鼻祖」,为什么它能「学会」分类?✅ 完成
03LMS 算法:从最小二乘到随机梯度下降,工业自适应滤波的核心✅ 完成
04反向传播:神经网络为什么能「学习」?用 NumPy 手写 BP✅ 完成
05核方法:为什么 SVM 能处理非线性问题?理解「升维」的本质✅ 完成
06支持向量机:最大间隔的「艺术」,为什么它是「小数据之王」?✅ 完成
07正则化:为什么模型越复杂越容易过拟合?L1/L2/Dropout✅ 完成
08PCA:为什么降维能「去噪」?从特征值分解到核 PCA✅ 完成
09SOM:无监督学习的「聚类之王」,为什么它能「自组织」?✅ 当前
10信息论:为什么「信息最大化」能学特征?从熵到 ICA⏳ 下一篇
11玻尔兹曼机:深度学习的「前世」,从统计力学到 RBM⏳ 待写
12动态规划:强化学习的「数学基础」,从 MDP 到值迭代⏳ 待写
13Hopfield 网络:联想记忆的「鼻祖」,为什么它能「回忆」?⏳ 待写
14卡尔曼滤波:为什么它能「预测」?从贝叶斯推断到粒子滤波⏳ 待写
15Haykin 精讲终篇:从感知器到深度学习——一部神经网络的「进化史」⏳ 待写

点赞收藏转发,是我持续更新的动力!

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询