数学建模学习-自组织映射(Self-Organizing Maps)教程(34)
写在最前
注意本文的相关代码及例子为同学们提供参考,借鉴相关结构,在这里举一些通俗易懂的例子,方便同学们根据实际情况修改代码,很多同学私信反映能否添加一些可视化,这里每篇教程都尽可能增加一些可视化方便同学理解,但具体使用时,同学们要根据实际情况选择是否在论文中添加可视化图片。
系列教程计划持续更新,同学们可以免费订阅专栏,内容充足后专栏可能付费,提前订阅的同学可以免费阅读,同时相关代码获取可以关注博主评论或私信。
目录
算法简介
自组织映射(Self-Organizing Maps, SOM)是一种无监督学习的人工神经网络,由芬兰学者Teuvo Kohonen于1982年提出。SOM网络能够将高维输入数据映射到低维(通常是二维)空间,同时保持数据的拓扑结构,这使得它成为数据可视化和聚类分析的有力工具。
SOM网络的主要目标是在保持数据拓扑关系的同时实现降维,这意味着在原始空间中相邻的数据点在映射后的低维空间中仍然保持相邻关系。这种特性使得SOM成为了探索和理解复杂数据集内在结构的理想工具。
算法特点
-
维度降维:
- 能够将高维数据映射到低维空间
- 保持数据的主要特征和结构
- 便于数据可视化和分析
- 降低数据处理的复杂度
-
拓扑保持:
- 保持输入数据的空间关系
- 相似的输入数据会映射到网络中相邻的神经元
- 有助于发现数据的内在结构
- 保持数据的局部特征
-
自组织学习:
- 通过竞争学习机制自动组织
- 网络能够自动调整权重
- 无需人工干预的学习过程
- 具有良好的自适应能力
-
无监督学习:
- 不需要标签数据
- 可以直接从数据中学习特征
- 适用于探索性数据分析
- 能够发现数据的隐藏模式
-
可视化能力:
- 提供直观的数据分布可视化
- 便于理解数据结构
- 支持交互式数据探索
- 有助于数据分析和决策
数学原理
SOM网络的数学原理可以通过以下几个关键公式来理解:
-
距离计算:
使用欧氏距离计算输入向量与权重向量之间的距离:D(x, w) = √∑(xᵢ - wᵢ)²其中:
- x 是输入向量
- w 是权重向量
- i 是向量的维度索引
-
最佳匹配单元(BMU)选择:
选择距离最小的神经元作为BMU:BMU = argmin(D(x, w)) -
邻域函数:
高斯邻域函数计算:h(t) = exp(-||rᵢ - rₖ||² / (2σ(t)²))其中:
- rᵢ 是当前神经元的位置
- rₖ 是BMU的位置
- σ(t) 是时间t时的邻域半径
-
学习率衰减:
α(t) = α₀ * exp(-t/T)其中:
- α₀ 是初始学习率
- t 是当前迭代次数
- T 是总迭代次数
-
权重更新规则:
w(t+1) = w(t) + α(t) * h(t) * (x - w(t))
算法原理
SOM算法的核心原理包括以下几个步骤:
-
初始化:
- 创建一个二维网格,每个节点代表一个神经元
- 随机初始化每个神经元的权重向量
- 设置初始学习率和邻域半径
-
竞争过程:
- 对于每个输入样本,计算其与所有神经元权重向量的距离
- 找到距离最小的神经元,称为最佳匹配单元(BMU)
- 这个过程实现了网络的自组织特性
-
合作过程:
- 确定BMU的邻域范围
- 计算邻域内所有神经元的邻域函数值
- 邻域范围随训练进行逐渐缩小
-
自适应过程:
- 更新BMU及其邻域内神经元的权重
- 权重更新公式:
其中:W(t+1) = W(t) + α(t) * h(t) * (X - W(t))- W(t)是t时刻的权重
- α(t)是学习率
- h(t)是邻域函数
- X是输入样本
环境准备
本教程需要以下Python库:
import numpy as np
import matplotlib.pyplot as plt
from sklearn.preprocessing import StandardScaler
import seaborn as sns
from matplotlib.font_manager import FontProperties
代码实现
SOM类的实现
首先,我们实现SOM网络的核心类:
class SelfOrganizingMap:
def __init__(self, map_size=(10, 10), input_dim=2, learning_rate=0.1, sigma=1.0, n_iterations=1000):
"""
初始化SOM网络
参数:
map_size: 输出层网格大小
input_dim: 输入数据维度
learning_rate: 学习率
sigma: 邻域函数的宽度
n_iterations: 训练迭代次数
"""
self.map_size = map_size
self.input_dim = input_dim
self.initial_learning_rate = learning_rate
self.initial_sigma = sigma
self.n_iterations = n_iterations
# 初始化权重矩阵
self.weights = np.random.randn(map_size[0], map_size[1], input_dim)
# 创建网格坐标
self.coordinates = np.array([(i, j) for i in range(map_size[0])
for j in range(map_size[1])]).reshape(map_size[0], map_size[1], 2)
核心方法实现
def find_bmu(self, x):
"""找到最佳匹配单元(BMU)"""
distances = np.sum((self.weights - x) ** 2, axis=2)
return np.unravel_index(np.argmin(distances), self.map_size)
def neighborhood_function(self, bmu_loc, iteration):
"""计算邻域函数"""
sigma = self.initial_sigma * np.exp(-iteration / self.n_iterations)
distances = np.sum((self.coordinates - np.array(bmu_loc)) ** 2, axis=2)
return np.exp(-distances / (2 * sigma ** 2))
def train(self, data):
"""训练SOM网络"""
error_history = []
for i in range(self.n_iterations):
error = 0
learning_rate = self.initial_learning_rate * np.exp(-i / self.n_iterations)
# 随机选择一个样本
x = data[np.random.randint(len(data))]
# 找到BMU
bmu_loc = self.find_bmu(x)
# 计算邻域函数
neighborhood = self.neighborhood_function(bmu_loc, i)
# 更新权重
for j in range(self.map_size[0]):
for k in range(self.map_size[1]):
weight_delta = learning_rate * neighborhood[j, k] * (x - self.weights[j, k])
self.weights[j, k] += weight_delta
error += np.sum(weight_delta ** 2)
error_history.append(error)
# 每100次迭代保存一次可视化结果
if i % 100 == 0:
self.visualize_map(data, i)
return error_history
数据生成与预处理
为了演示SOM的效果,我们生成两个环形分布的示例数据:
def generate_sample_data(n_samples=1000):
"""生成两个环形分布的示例数据"""
# 第一个环
r1 = np.random.normal(2, 0.2, n_samples//2)
theta1 = np.random.uniform(0, 2*np.pi, n_samples//2)
x1 = r1 * np.cos(theta1)
y1 = r1 * np.sin(theta1)
# 第二个环
r2 = np.random.normal(4, 0.2, n_samples//2)
theta2 = np.random.uniform(0, 2*np.pi, n_samples//2)
x2 = r2 * np.cos(theta2)
y2 = r2 * np.sin(theta2)
# 合并数据
X = np.vstack([np.column_stack([x1, y1]), np.column_stack([x2, y2])])
# 标准化数据
scaler = StandardScaler()
X_scaled = scaler.fit_transform(X)
return X_scaled
运行结果分析
训练过程可视化
SOM网络的训练过程展示了网络如何逐步适应数据分布:
- 初始阶段(迭代0次):
[外链图片转存中…(img-Ra6DfiTy-1737344510400)]
- 网络权重随机分布
- 网格结构尚未形成
- 与数据分布无关
- 中期阶段(迭代500次):
[外链图片转存中…(img-Y51BW3ho-1737344519874)]
- 网格开始适应数据分布
- 权重向数据密集区域移动
- 保持了大致的网格结构
- 最终阶段(迭代900次):

- 网格完全适应数据分布
- 清晰展现了数据的环形结构
- 保持了良好的拓扑关系
误差收敛分析
[外链图片转存中…(img-WdnFaKVt-1737344538845)]
从误差收敛曲线可以观察到以下特点:
- 初期误差较大,学习速度快
- 中期误差逐渐减小,学习趋于稳定
- 后期误差趋于平稳,网络收敛
常见问题与解决方案
-
网格大小选择问题
- 问题:网格太大会导致过拟合,太小会导致欠拟合
- 解决方案:
- 根据数据量和维度选择合适的网格大小
- 可以通过交叉验证选择最优网格大小
- 一般建议网格节点数为样本数的5-10%
-
学习率设置问题
- 问题:学习率过大导致不稳定,过小导致收敛慢
- 解决方案:
- 初始学习率设置在0.1-0.5之间
- 采用指数衰减的学习率调整策略
- 可以使用自适应学习率
-
训练时间问题
- 问题:大规模数据训练时间长
- 解决方案:
- 使用批量训练策略
- 采用并行计算
- 优化距离计算方法
-
初始化敏感性
- 问题:不同初始化可能导致不同结果
- 解决方案:
- 使用PCA初始化
- 多次运行取最优结果
- 采用确定性初始化方法
应用场景
SOM网络在实际应用中有广泛的用途:
-
数据可视化:
- 高维数据的二维展示
- 复杂数据关系的直观表达
- 数据分布特征探索
-
模式识别:
- 图像分割
- 语音识别
- 文本分类
-
数据挖掘:
- 客户分群
- 异常检测
- 特征提取
-
生物信息学:
- 基因表达数据分析
- 蛋白质序列分类
- 疾病诊断
-
金融分析:
- 市场细分
- 风险评估
- 投资组合分析
总结
自组织映射网络是一种强大的无监督学习工具,它能够有效地进行数据降维和可视化。通过本教程的示例,我们展示了SOM网络如何从随机初始状态逐步学习并适应数据的分布结构。这种自组织的特性使得SOM在各种实际应用中都表现出色。
在实际应用中,需要注意以下几点:
- 网格大小的选择要根据具体问题和数据规模来确定
- 学习率和邻域函数的参数需要适当调整以获得最佳效果
- 数据预处理(如标准化)对最终结果有重要影响
- 训练迭代次数要足够多以确保网络充分学习数据特征
优化建议
-
数据预处理:
- 进行特征标准化
- 处理缺失值和异常值
- 考虑特征选择
-
参数调优:
- 使用网格搜索找最优参数
- 采用交叉验证评估性能
- 根据具体问题调整网络结构
-
结果评估:
4 - 使用定量指标评估- 可视化分析结果
- 与其他方法比较
-
实际应用:
- 考虑计算资源限制
- 注意模型的可解释性
- 关注结果的实用性
同学们如果有疑问可以私信答疑,如果有讲的不好的地方或可以改善的地方可以一起交流,谢谢大家。
1万+

被折叠的 条评论
为什么被折叠?



