MNIST自定义多分类神经网络训练准确率下降溢出问题排查
MNIST自写神经网络训练异常排查
你的代码出现溢出警告、准确率先升后降的问题,全部是细节实现错误导致的,整体逻辑框架没有问题,具体错误点和修正方式如下:
- 前向传播第二层线性变换偏置调用错误
计算第二层线性输出z2时,你错误使用了第一层偏置b1,代码为self.z2 = self.w2.dot(self.a1) + self.b1,需要改为使用第二层偏置b2。 - Softmax实现存在两个核心问题,是溢出警告的直接来源
- 没有做数值稳定处理:当输入
Z的值稍大时,np.exp(Z)会直接超出浮点数表示范围触发溢出,计算前需要减去每个样本对应的Z最大值,避免指数运算结果过大 - 归一化维度错误:原代码
np.sum(np.exp(Z))是对所有样本、所有类别的指数值全局求和,正确做法是指定axis=0按单个样本维度求和,同时保留维度避免广播逻辑错误
修正后的Softmax代码:
def Softmax(self, Z): Z_shift = Z - np.max(Z, axis=0, keepdims=True) exponentials = np.exp(Z_shift) sumexp = np.sum(exponentials, axis=0, keepdims=True) return exponentials / sumexp - 没有做数值稳定处理:当输入
- 反向传播ReLU梯度计算错误,是准确率下降的核心原因
计算隐层误差e1时,你乘的是self.ReLu(self.a1)也就是激活后的输出值,不是ReLU的导数,梯度计算完全错误,训练多轮之后参数会被更新到错误方向。另外你写的ReLu_Derv方法存在API拼写错误,numpy没有np.greaterthan方法,正确写法是np.greater,修正后:
对应反向传播中def ReLu_Derv(self, x): return np.greater(x, 0).astype(int)e1的计算逻辑修改为:e1 = self.w2.T.dot(e2) * self.ReLu_Derv(self.Z1) - 其他潜在隐患
权重初始化方法的参数顺序和传参顺序不匹配(方法定义为(n_in, n_out),调用时传入顺序是(n_out, n_in)),当前代码靠形状巧合能正常运行,后续调整网络结构时很容易出现维度不匹配问题,建议调整传参顺序和参数定义保持一致。
修正以上问题后,使用现有超参数(学习率0.01、全批量梯度下降、1000轮训练)即可在训练集达到90%以上的准确率,不会再出现溢出和准确率下降的问题。
内容的提问来源于stack exchange,提问作者that annoying kid
相关产品推荐
相关产品推荐

