理解Michael Nielsen的反向传播代码

时间:2017-11-05 20:09:22

标签: python numpy machine-learning neural-network backpropagation

我正在尝试理解/运行Michael Neilsen的神经网络和深度学习第2章中关于反向传播的代码:http://neuralnetworksanddeeplearning.com/chap2.html#the_code_for_backpropagation

在向后传球开始时,它有:

delta = self.cost_derivative(activations[-1], y) * \
    sigmoid_prime(zs[-1])
nabla_b[-1] = delta
nabla_w[-1] = np.dot(delta, activations[-2].transpose())

正向传递创建activations列表,其中activations[i]包含层i中神经元激活的向量。所以activations[-1]是最后一层。 y是所需的输出。

cost_derivative定义为:

def cost_derivative(self, output_activations, y):
"""Return the vector of partial derivatives \partial C_x /
\partial a for the output activations."""
return (output_activations-y)

这样第一行输出的形状与输出层的形状相同。所以我的问题是第4行的np.dot应该如何工作?我的理解是activations[-2]是倒数第二层神经元激活的载体,它可以有任意数量的神经元,所以我不确定我们如何能够产生它(或者它的产品)转换)具有delta,具有输出层的形状。

我运行代码(https://github.com/mnielsen/neural-networks-and-deep-learning/blob/master/src/network.py)并添加了一些调试行以尝试理解这一点,但它似乎不起作用:

>>> from network import *; net = Network([2,1,2])
>>> net.backprop([1,2], [3,4])

Activations[0]
[1, 2]

Activations[1]
[[ 0.33579893]]

Activations[2]
[[ 0.37944698]
 [ 0.45005939]]

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<snip>/neural-networks-and-deep-learning/src/network.py", line 117, in backprop
    nabla_w[-1] = np.dot(delta, activations[-2].transpose())
ValueError: shapes (2,2) and (1,1) not aligned: 2 (dim 1) != 1 (dim 0)

activations看起来和我期望的完全一样 - 2次激活,然后是1次,然后是2次。失败就在我不清楚的地方,并且按照我的预期失败了。但是,据推测,本书中的代码已经过测试(本书非常出色)而且我一定做错了。我正在编写一个独立的实现并遇到同样的问题,因此我希望能够将这些代码分开来解决它 - 但我无法弄清楚它应该如何工作,或者为什么它适用于作者

我很欣赏我在这里缺少的任何见解。谢谢! :)

1 个答案:

答案 0 :(得分:1)

为什么backprop中的形状匹配

假设网络架构为[...,N,M],即最后一层输出大小为M的向量,大小为N之前的向量(让我们关注最后两层并忽略其余的部分)。 NM可以是任意的。另外,让我们忽略批处理,如你的问题所示:我们正在输入一个输入和一个标签。

在这种情况下,最后一个权重矩阵(即self.weights[-1])将具有[M,N]形状,因此nabla_w[-1]必须正确执行更新。现在:

  • delta将具有[M,1]形状(对应于输出)。
  • activations[-2]将具有[N,1]形状,因此转置为[1,N]
  • 他们的点积产生[M,1]*[1,N] -> [M,N]形状,这正是我们所需要的。

为什么测试运行失败

因为在numpy中,(2,)形状与[1,2][2,1]不同:

>>> np.array([1, 2]).shape
(2,)

网络体系结构区分xy的行和列,您必须提供正确的形状才能使其正常工作。否则,您将获得意外的广播和形状不匹配。试试这个例子来看它的实际效果:

net = Network([2,1,2])
x = np.array([1, 2]).reshape([2, 1])  # one example of size 2
y = np.array([3, 4]).reshape([2, 1])  # one example of size 2
net.backprop(x, y)