MNIST-Vanilla神经网络:成本函数为何持续上升?
我已花费一周时间排查下述代码,却仍未明确为何成本函数会如图所示持续上升。降低学习率仅能起到微乎其微的改善效果。恳请各位帮忙找出成本函数未达预期的原因?我清楚CNN更适用,但仍想理解该简单网络失效的缘由,盼各位相助:)
代码片段:
import numpy as np import tensorflow as tf from tensorflow.examples.tutorials.mnist import input_data import matplotlib.pyplot as...
可能的原因及排查步骤
数据预处理缺失或错误
MNIST的原始像素值是0-255的范围,如果没有归一化到0-1或者-1到1区间,过大的输入值会让权重更新出现异常,直接导致成本函数飙升。先检查是否做了x = x / 255.0这类归一化操作;另外,标签格式也很关键——如果用交叉熵损失,分类任务的标签需要是one-hot编码(对应categorical_crossentropy)或者整数格式(对应sparse_categorical_crossentropy),格式不匹配会让损失计算完全偏离预期。损失函数与输出层激活函数不匹配
MNIST是10分类任务,输出层应该搭配softmax激活函数,再对应匹配的交叉熵损失。如果错误地用了MSE损失(适合回归任务),或者输出层用了sigmoid却配了分类损失,都会导致损失不下降甚至持续上升。这是新手很容易踩的坑,优先排查这一点。权重初始化不合理
如果初始权重的方差太大,会让网络初始输出值过高,直接触发激活函数的饱和区(比如sigmoid两端的梯度几乎为0),或者让初始损失值爆炸。试试用小方差的初始化方式,比如tf.Variable(tf.random.normal(shape, mean=0, stddev=0.01))或者Glorot均匀初始化,避免权重一开始就“跑偏”。梯度异常(消失/爆炸)
即便简单网络,若用了sigmoid这类易导致梯度消失的激活函数做多层连接,或者学习率调整后仍无法抵消初始权重过大的影响,都会出现梯度爆炸,表现为损失持续上升。可以在训练过程中打印梯度值,看看是否出现NaN或者极大的数值,这能直接定位问题。网络结构维度不匹配
比如输入层没把MNIST图片平展成784维,或者隐藏层与输出层的维度对接错误,会让网络计算出无意义的损失值,自然不会下降。检查每一层的输入输出维度是否对应,比如Dense层的input_shape参数是否设置正确。
快速验证建议
先搭建一个极简版网络:输入层(784维)→ 单隐藏层(比如128神经元,relu激活)→ 输出层(10神经元,softmax激活),搭配正确的预处理和交叉熵损失,看看损失是否正常下降。如果这个版本没问题,再逐步叠加你原代码的模块,就能快速定位出问题的部分。
内容的提问来源于stack exchange,提问作者alwayscurious

