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

基于Nielsen教材实现MNIST神经网络时遇元组解包值错误

报错根因定位

1. 核心触发原因:数据加载接口调用错误

你的神经网络代码要求传入的训练/测试数据,是单个样本为二元组(x, y)的可遍历集合,其中x是单个样本的输入向量,y是对应的标签值。
但你训练启动时调用的是mnist_loader.load_data(),这个接口返回的原始数据结构完全不符合要求:

  • 整体返回是三元组(训练集, 验证集, 测试集)
  • 每个子数据集本身又是两个独立的大数组:第一个元素是包含全部5万/1万张图像的高维数组,第二个元素是包含全部对应标签的一维数组,根本不是逐样本配对的二元组列表
    当你把这个大数组转成列表传给SGD方法后,代码走到for x, y in mini_batch逐样本解包时,会拿到包含数千个元素的大数组试图拆成2个值,直接触发ValueError: too many values to unpack (expected 2)。

2. 附带的逻辑bug,就算修正数据源也会导致训练失效

你写的SGD方法存在缩进错误:

  • 遍历mini batch更新参数的循环、以及epoch结束后的评估打印代码,全部没有缩进在for j in range(epochs):的循环内部
  • 现在的代码执行逻辑是:先循环30次打乱数据、切分batch,等循环完全结束后,才只跑1次batch更新、只打印1次结果,完全不符合逐epoch训练的设计逻辑

3. 代码书写错误,会触发后续连锁报错

  • sigmoid函数存在两处书写错误:一是多写了一层np(写成了np.np.exp(-z),会触发属性不存在的报错);二是公式符号写错(分母写成1 - np.exp(-z),正确应为1 + np.exp(-z),符号反了会导致激活值完全不符合设计,模型无法收敛)
  • Python 3环境下,load_data_wrapper()里用zip()生成的是一次性迭代器,如果不转成列表,第一次epoch遍历完迭代器就会耗尽,后续循环拿不到任何数据
修复方案
  • 修正训练启动代码,替换成正确的加载接口,同时适配Python3的迭代器特性:
import network
import mnist_loader

# 必须调用load_data_wrapper,该接口会把原始数据转成要求的逐样本二元组格式
training_data, validation_data, test_data = mnist_loader.load_data_wrapper()
# 将zip生成的一次性迭代器转成列表,避免遍历一次就耗尽
training_data = list(training_data)
test_data = list(test_data)

net = network.Network([784, 30, 10])
# 原书推荐的初始学习率为3.0,你之前用的0.001过低会导致模型完全不收敛
net.SGD(training_data, 30, 10, 3.0, test_data=test_data)
  • 修正SGD方法的缩进,把batch更新、评估打印的代码挪到epoch循环内部:
def SGD(self, training_data, epochs, mini_batch_size, eta, test_data=None):
    if test_data: n_test = len(test_data)
    n = len(training_data)
    for j in range(epochs):
        random.shuffle(training_data)
        mini_batches = [training_data[k:k+mini_batch_size]
                        for k in range(0, n, mini_batch_size)]
        # 以下代码缩进进epoch循环内部
        for mini_batch in mini_batches:
            self.update_mini_batch(mini_batch, eta)
        if test_data:
            print("Epoch {0}: {1} /{2}".format(
                j, self.evaluate(test_data), n_test))
        else:
            print("Epoch {0} complete".format(j))
  • 修正sigmoid函数的书写错误:
def sigmoid(z):
    """The sigmoid function."""
    return 1.0/(1 + np.exp(-z))

内容的提问来源于stack exchange,提问作者Eyal Werber

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.24 01:45:05