我正在开发我的第一个神经网络,使用的是著名的MNIST手写数字数据库。我希望这个神经网络能够根据给定的图像识别从0到9的数字。
我的神经网络由三层组成:输入层(784个神经元,每个神经元对应数字的一个像素)、隐藏层(30个神经元,当然也可以是100个或50个,但我目前不太关注超参数调整)和输出层(10个神经元,每个神经元代表每个数字的激活状态)。这给我带来了两个权重矩阵:一个是30×784,另一个是10×30。
我了解并理解反向传播、优化及其背后的数学公式的理论,这本身不是问题。我可以优化第二权重矩阵的权重,成本确实随着时间的推移而减少。但由于矩阵结构,我无法继续向后传播。
我知道需要找到成本相对于权重的导数:
d(cost) / d(w) = d(cost) / d(f(z)) * d(f(z)) / d(z) * d(z) / d(w)
(其中f
是激活函数,z
是神经元的点积加上偏置)
所以我在最右边的层,有一个包含10个元素的输出数组。d(cost) / d(f(z))
是观察值与预测值的差。我可以将它乘以d(f(z)) / d(z)
,也就是最右层f'(z)
,这也是一个包含10个元素的单维向量,现在已经计算出d(cost) / d(z)
。然后,d(z)/d(w)
只是该层的输入,即前一层的输出,是一个30个元素的向量。我发现可以转置d(cost) / d(z)
,这样T( d(cost) / d(z) ) * d(z) / d(w)
给我一个(10, 30)的矩阵,这有意义,因为它与最右侧权重矩阵的维度匹配。
但之后我就卡住了。d(cost) / d(f(z))
的维度是(1, 10),d(f(z)) / d(z)
的维度是(1, 30),d(z) / d(w)
的维度是(1, 784)。我不知道如何得出结果。
这是我目前编写的代码。不完整的部分是_propagate_back
方法。我暂时不考虑偏置,因为我只是被权重卡住,首先我想解决这个问题。
(代码部分保持不变)
这是mnist_loader的代码,以防有人想要复制这个例子:
(代码部分保持不变)
回答:
一旦你有了d(cost) / d(z)
,我认为你实际上应该将它乘以权重矩阵:只有这样你才能将错误d(cost) / d(z)
向后传播到新层(并得到有意义的矩阵形状)。
这是我如何更改你的反向传播函数:
(代码部分保持不变)
两点说明:
- 行
hidden_err = np.dot(d_cost_d_z, output_layer.weights)
是我将d(cost) / d(z)
乘以权重矩阵的地方 - 我用
np.dot
函数(Numpy中的矩阵乘法)替换了一些*
运算符(如果我没记错的话,这是Numpy中的Hadamard乘积)的使用
我不是专家,所以我希望我没有犯什么可怕的错误…无论如何,我的回答主要是基于Michael Nielsen的《Neural Networks and Deep Learning》这本书的这一章节。