从零实现神经网络:反向传播函数致精度下降问题求助
双隐藏层神经网络反向传播精度下降问题排查
问题描述
为深入理解神经网络原理,从零实现了一个双隐藏层神经网络(基于MNIST数据集,输入层784神经元,第一隐藏层16个,第二隐藏层13个,输出层10个)。参考Samson Zhang的单隐藏层反向传播视频扩展逻辑,采用Z(未激活值)、A(激活值)标注规则,反向传播代码如下:
def backward_prop(Z1, A1, Z2, A2, Z3, A3, w1, w2, w3, X, Y): m = Y.size dZ3 = A3 - desired_output_vector(Y) dw3 = 1 / m * dZ3.dot(A2.T) db3 = 1 / m * np.sum(dZ3) dZ2 = w3.T.dot(dZ3) * ReLU_d(Z2) dw2 = 1 / m * dZ2.dot(A1.T) db2 = 1 / m * np.sum(dZ2) dZ1 = w2.T.dot(dZ2) * ReLU_d(Z1) dw1 = 1 / m * dZ1.dot(X.T) db1 = 1 / m * np.sum(dZ1) return dw1, db1, dw2, db2, dw3, db3
运行时模型精度持续下降,需排查代码中的数学推导与实现问题。
核心问题与修正方案
1. 偏置梯度计算维度错误
当前np.sum(dZ3)、np.sum(dZ2)、np.sum(dZ1)会将所有维度的元素求和为一个标量,但偏置b是与每层神经元数量匹配的向量(比如b3是(10,1))。正确做法是按样本维度(axis=1)求和并保留维度,否则会导致所有神经元的偏置被更新为同一个错误值,直接破坏模型收敛。
2. 输入维度与矩阵乘法顺序不匹配
若输入X的维度是(样本数m, 特征数784)(即样本在前,特征在后),那么dZ1.dot(X.T)的维度会与w1(应为(16,784))不匹配,导致梯度计算完全错误。需确认输入数据维度:
- 若
X是(784, m),当前矩阵乘法顺序正确; - 若
X是(m,784),需将dZ.dot(A_prev.T)改为A_prev.T.dot(dZ.T),同时调整后续维度。
3. ReLU导数实现错误
ReLU_d(Z)的逻辑必须是:当Z>0时返回1,Z<=0时返回0。如果实现反向(比如Z>0返回0),会导致梯度方向完全错误,模型沿着损失上升的方向更新,精度持续下降。
4. 权重更新方向错误
若在训练循环中,权重更新写成w = w + learning_rate * dw而非w = w - learning_rate * dw,会直接导致模型向损失增大的方向迭代,这是精度下降的常见原因。
修正后的反向传播代码
def backward_prop(Z1, A1, Z2, A2, Z3, A3, w1, w2, w3, X, Y): m = Y.size dZ3 = A3 - desired_output_vector(Y) dw3 = 1 / m * dZ3.dot(A2.T) # 按样本维度求和并保留维度,得到与b匹配的向量 db3 = 1 / m * np.sum(dZ3, axis=1, keepdims=True) dZ2 = w3.T.dot(dZ3) * ReLU_d(Z2) dw2 = 1 / m * dZ2.dot(A1.T) db2 = 1 / m * np.sum(dZ2, axis=1, keepdims=True) dZ1 = w2.T.dot(dZ2) * ReLU_d(Z1) dw1 = 1 / m * dZ1.dot(X.T) db1 = 1 / m * np.sum(dZ1, axis=1, keepdims=True) return dw1, db1, dw2, db2, dw3, db3
额外验证点
- 确认输出层
A3是softmax激活,且损失函数为交叉熵,此时dZ3 = A3 - Y的推导才成立; - 检查权重初始化是否合理(比如用He初始化ReLU层的权重),避免初始梯度爆炸或消失。
内容的提问来源于stack exchange,提问作者Adam
相关产品推荐
相关产品推荐

