You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.16 00:22:45