Python 了解迈克尔·尼尔森';s反向传播码

Python 了解迈克尔·尼尔森';s反向传播码,python,numpy,machine-learning,neural-network,backpropagation,Python,Numpy,Machine Learning,Neural Network,Backpropagation,我试图理解/运行迈克尔·尼尔森的《神经网络和深度学习》第2章中的代码,关于反向传播: 在向后传球开始时,它有: delta = self.cost_derivative(activations[-1], y) * \ sigmoid_prime(zs[-1]) nabla_b[-1] = delta nabla_w[-1] = np.dot(delta, activations[-2].transpose()) 向前传递创建激活列表,其中激活[i]包含层i中神经元激活的向量。因此,激活

我试图理解/运行迈克尔·尼尔森的《神经网络和深度学习》第2章中的代码,关于反向传播:

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

delta = self.cost_derivative(activations[-1], y) * \
    sigmoid_prime(zs[-1])
nabla_b[-1] = delta
nabla_w[-1] = np.dot(delta, activations[-2].transpose())
向前传递创建
激活
列表,其中
激活[i]
包含层
i
中神经元激活的向量。因此,
激活[-1]
是最后一层<代码>y是所需的输出

成本衍生工具的定义如下:

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)
所以第一行输出一个向量,它的形状和我们的输出层相同。所以我的问题是第四行的
np.dot
应该如何工作?我的理解是,
激活[-2]
是第二层到最后一层神经元激活的向量,可以有任意数量的神经元,所以我不确定我们如何将它(或它的转置)与具有输出层形状的三角形点积

我运行代码()时添加了一些调试行,试图理解这一点,但它似乎不起作用:

>>> 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)
>>来自网络导入*;网络=网络([2,1,2])
>>>净资产净值([1,2],[3,4])
激活[0]
[1, 2]
激活[1]
[[ 0.33579893]]
激活[2]
[[ 0.37944698]
[ 0.45005939]]
回溯(最近一次呼叫最后一次):
文件“”,第1行,在
文件“/神经网络和深度学习/src/network.py”,第117行,在backprop中
nabla_w[-1]=np.dot(增量,激活[-2].转置())
ValueError:形状(2,2)和(1,1)未对齐:2(尺寸1)!=1(尺寸0)
激活
看起来和我预期的完全一样-2次激活,然后1次,然后2次。失败就在我不清楚的线上,正如我所预料的那样失败了。但是,大概这本书中的代码已经过测试(这本书非常好),我一定是做错了什么。我当时正在编写一个独立的实现,遇到了同样的问题,所以我希望能够把这段代码拆开来解决它——但我不知道它应该如何工作,也不知道它为什么适合作者

如果你能了解我在这里遗漏了什么,我将不胜感激。谢谢!:)

为什么backprop中的形状匹配 假设网络架构为
[…,N,M]
,即最后一层输出大小
M
的向量,之前的一层输出大小
N
(让我们关注最后两层,忽略其余部分)
N
M
可以是任意的。另外,让我们忽略批处理,正如您的问题:我们只输入一个输入和一个标签

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

  • delta
    将具有
    [M,1]
    形状(对应于输出)
  • 激活[-2]
    将具有
    [N,1]
    形状,因此转置是
    [1,N]
  • 他们的点积产生
    [M,1]*[1,N]->[M,N]
    形状,这正是我们需要的
为什么测试运行失败 因为在numpy中,形状
(2,)
[1,2]
[2,1]
不同:

>>> np.array([1, 2]).shape
(2,)
网络体系结构区分了
x
y
的行和列,您必须提供两者的正确形状才能使其工作。否则,您将得到意外的广播和形状不匹配。请尝试此示例以查看其实际效果:

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)

完美的答案,谢谢!我缺少的是,
np.dot
实际上在做矩阵乘法,这更有意义。而且
np.array
也起了作用,感谢您的解释:)