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

MNIST训练CNN时softmax输出概率均为0.1的问题求助

排查MNIST CNN训练中Softmax输出始终均匀的问题

嘿,我来帮你拆解一下这个问题!你遇到的softmax输出固定为[0.1, 0.1,...,0.1]的情况,核心原因几乎可以确定是模型梯度无法有效更新,导致参数根本没在学习。咱们一步步来梳理问题点和解决办法:

主要问题分析

  • 模型规模严重过载:你搭建的模型实在太庞大了——从128通道一路升到1024通道,还有4层连续的1024通道卷积,这对于MNIST这种简单的手写数字数据集来说完全是“杀鸡用牛刀”。这么深的网络很容易触发梯度消失:ReLU激活函数在深层网络中会让大量神经元输出为0,梯度无法反向传播到前面的层,参数自然不会更新,最后模型只能输出均匀概率。

  • 数据未做归一化:MNIST的原始像素值范围是0-255,你直接把这种大数值喂给模型,会导致卷积和全连接层的输入波动极大,很容易让ReLU进入饱和区(输出为0),进一步加剧梯度消失的问题。

  • 缺少正则化与归一化层:深层网络没有加入Dropout或Batch Normalization,不仅容易过拟合,还会让中间层的激活值分布失衡,影响梯度传递效率。

  • 全连接层维度冗余:虽然你计算的9216维度是正确的(3×3×1024),但这么大的全连接层在MNIST上完全没必要,只会增加参数数量,加重梯度更新的负担。

具体修改建议

1. 先做数据归一化

在加载数据后立刻加入归一化步骤,把像素值缩放到0-1区间:

data = np.asarray(mnist["data"],dtype=np.float32) / 255.0  # 关键:归一化到0-1

2. 大幅简化模型

把模型缩小到适合MNIST的规模,比如:

# 简化后的模型结构
conv1_1 = get_conv(x,[3,3,1,32])  # 减少通道数到32
conv1_2 = get_conv(conv1_1,[3,3,32,32])
pool1 = get_pool(conv1_2,[1,2,2,1])

conv2_1 = get_conv(pool1,[3,3,32,64])
conv2_2 = get_conv(conv2_1,[3,3,64,64])
pool2 = get_pool(conv2_2,[1,2,2,1])

# 加入Dropout防止过拟合
dropout = tf.nn.dropout(pool2, keep_prob=0.5)

# 计算正确的全连接层输入维度:28→14→7,7×7×64=3136
fc1 = get_fc(dropout,[3136,256])
fc1_drop = tf.nn.dropout(fc1, keep_prob=0.5)
fc2 = get_fc(fc1_drop,[256,10])

3. 训练过程中监控Loss

在训练循环里加入Loss打印,确认模型是否在学习:

for i in range(15):
    print(f"Step {i}")
    indices = np.random.randint(len(tr_data),size=[200])
    batch_data = tr_data[indices]
    batch_labels = tr_labels[indices]
    _, loss_val = sess.run([train_step, loss], feed_dict={x:batch_data,y:batch_labels})
    print(f"Loss: {loss_val:.4f}")  # 观察Loss是否下降

额外提示

15步训练确实很少,但如果模型正常的话,Loss应该会有明显下降,softmax输出也会开始出现差异。如果修改后Loss还是不动,那可以检查一下get_fc函数里的偏置初始化是否正确,或者尝试调小Adam的学习率(比如0.0001)。

内容的提问来源于stack exchange,提问作者Pian Pawakapan

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 08:10:45