如何在Python中解决Kohonen神经网络的维度不匹配与权重显示问题
Kohonen自组织映射(SOM)实现问题解答
问题描述
我正在Python中实现Kohonen自组织映射(SOM),目标是基于标准化输入数据X_scaled训练SOM,并在多轮epoch中迭代更新权重。目前遇到两个核心问题:
- 维度不匹配:不确定输入数据
X_scaled(5000个样本,17个特征)与权重矩阵weights(2×17)的维度是否正确对齐; - 权重显示效率:不确定在训练循环内显示权重是否是跟踪其更新过程的最优方式。
我已用随机值初始化权重矩阵,训练循环会根据获胜神经元更新权重,期望SOM能正确训练、权重随epoch更新,但不确定维度是否对齐以及当前权重显示方式的效率。以下是我的代码:
import numpy as np class Kohonen: def __init__(self, weights): self.weights = weights def win(self, sample): distances = np.sum((sample - self.weights)**2, axis=1) return np.argmin(distances) def update(self, sample, k, alpha): self.weights[k] += alpha * (sample - self.weights[k]) # Initialize weights for the neural network weights = np.random.normal(size=(2, 17), loc=0, scale=1) # Create the Kohonen model kohonen = Kohonen(weights) # Number of epochs and learning rate epochs = 260 alpha = 0.1 # Input data (ensure dimensions are consistent) X_scaled = np.random.random((5000, 17)) # Replace with actual data # Training loop for epoch in range(epochs): print(f"Epoch: {epoch}") for sample in X_scaled: winner = kohonen.win(sample) kohonen.update(sample, winner, alpha) print(kohonen.weights) # Display weights after each epoch
问题解答
1. 维度匹配验证
你的维度设置是完全正确的:
- 输入数据
X_scaled的(5000,17)形状,对应5000个17维特征的样本; - 权重矩阵
weights的(2,17)形状,对应2个输出神经元,每个神经元拥有与输入特征维度一致的17个权重参数; - 在
win方法中,单个样本(形状(17,))与权重矩阵做广播运算计算欧氏距离,axis=1对每个神经元的特征维度求和,最终得到2个神经元与样本的距离值,逻辑完全自洽。
2. 权重跟踪的优化方案
当前每轮epoch打印权重的方式会产生大量冗余输出,且无法直观观察变化趋势,推荐以下几种优化方式:
定期打印
减少打印频率,比如每20轮epoch输出一次权重,避免刷屏:
for epoch in range(epochs): print(f"Epoch: {epoch}") for sample in X_scaled: winner = kohonen.win(sample) kohonen.update(sample, winner, alpha) # 每20轮打印一次权重 if epoch % 20 == 0: print(f"Epoch {epoch} weights:\n{kohonen.weights}")
可视化变化趋势
用Matplotlib绘制权重随epoch的变化曲线,直观观察每个特征权重的更新轨迹:
import numpy as np import matplotlib.pyplot as plt class Kohonen: def __init__(self, weights): self.weights = weights def win(self, sample): distances = np.sum((sample - self.weights)**2, axis=1) return np.argmin(distances) def update(self, sample, k, alpha): self.weights[k] += alpha * (sample - self.weights[k]) weights = np.random.normal(size=(2, 17), loc=0, scale=1) kohonen = Kohonen(weights) epochs = 260 alpha = 0.1 X_scaled = np.random.random((5000, 17)) # 记录每轮权重 weight_history = [] for epoch in range(epochs): for sample in X_scaled: winner = kohonen.win(sample) kohonen.update(sample, winner, alpha) weight_history.append(kohonen.weights.copy()) weight_history = np.array(weight_history) # 形状: (epochs, 2, 17) # 绘制第一个神经元的特征权重变化 plt.figure(figsize=(12,6)) for feat_idx in range(17): plt.plot(weight_history[:, 0, feat_idx], label=f"特征 {feat_idx+1}") plt.title("神经元1的权重变化趋势") plt.xlabel("Epoch") plt.ylabel("权重值") plt.legend(bbox_to_anchor=(1.05, 1), loc="upper left") plt.tight_layout() plt.show() # 绘制第二个神经元的特征权重变化 plt.figure(figsize=(12,6)) for feat_idx in range(17): plt.plot(weight_history[:, 1, feat_idx], label=f"特征 {feat_idx+1}") plt.title("神经元2的权重变化趋势") plt.xlabel("Epoch") plt.ylabel("权重值") plt.legend(bbox_to_anchor=(1.05, 1), loc="upper left") plt.tight_layout() plt.show()
保存权重到文件
将权重历史保存为CSV文件,方便后续离线分析:
import pandas as pd weight_history = [] for epoch in range(epochs): for sample in X_scaled: winner = kohonen.win(sample) kohonen.update(sample, winner, alpha) # 展平权重为一维数组,便于存入DataFrame weight_history.append(kohonen.weights.flatten()) # 生成列名并保存 columns = [f"神经元{n}_特征{f}" for n in range(2) for f in range(17)] df = pd.DataFrame(weight_history, columns=columns) df.to_csv("som_weight_history.csv", index=False)
内容的提问来源于stack exchange,提问作者Anhar Alsaeed
相关产品推荐
相关产品推荐

