在Michael Nielsen的神经网络教程中,他有以下代码:
def update_mini_batch(self, mini_batch, eta):
"""The ``mini_batch`` is a list of tuples ``(x, y)``, and ``eta``
is the learning rate."""
nabla_b = [np.zeros(b.shape) for b in self.biases]
nabla_w = [np.zeros(w.shape) for w in self.weights]
for x, y in mini_batch:
delta_nabla_b, delta_nabla_w = self.backprop(x, y)
nabla_b = [nb+dnb for nb, dnb in zip(nabla_b, delta_nabla_b)]
nabla_w = [nw+dnw for nw, dnw in zip(nabla_w, delta_nabla_w)]
self.weights = [w-(eta/len(mini_batch))*nw
for w, nw in zip(self.weights, nabla_w)]
self.biases = [b-(eta/len(mini_batch))*nb
for b, nb in zip(self.biases, nabla_b)]
我理解元组和列表是什么,我理解zip函数正在做什么,但我不明白变量nb,dnb,nw和dnw如何在这两行代码上更新:
nabla_b = [nb+dnb for nb, dnb in zip(nabla_b, delta_nabla_b)]
nabla_w = [nw+dnw for nw, dnw in zip(nabla_w, delta_nabla_w)]
任何人都可以帮助解释这两行中的魔力吗?
这两行是Python list comprehensions的典型例子。
从本质上讲,您的第一个清单:
nabla_b = [nb+dnb for nb, dnb in zip(nabla_b, delta_nabla_b)]
这意味着:
zip(nabla_b, delta_nabla_b)
拿第一对;将它们命名为nb
和dnb
nb+dnb
)nabla_b
的第一个元素nabla_b
,直到所有来自zip(nabla_b, delta_nabla_b)
的对已经筋疲力尽举个简单的例子,列表理解如下:
squares = [x**2 for x in range(10)]
print(squares)
# [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
等效于以下for
循环:
squares = []
for x in range(10):
squares.append(x**2)
print(squares)
# [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
有关更多示例和快速介绍,请参阅here。
zip
函数将两个列表逐个元素组合在一起,这样如果你给它:
a = [1, 2, 3, 4]
b = ["a", "b", "c", "d"]
zip(a, b)
将返回:
[(1, "a"), (2, "b"), ...]
(每个元素都是tuple
)
你可以使用元素list
中每个变量之间的逗号来解压缩tuple
s(或list
s)的tuple
s元素:
for elem_a, elem_b in zip(a, b):
print(elem_a, elem_b)
这将打印:
1 a
2 b
3 c
4 d
所以在你的情况下,它添加了两个列表nabla_b
和delta_nabla_b
elementwise,所以你得到一个列表,每个元素是压缩列表中相应元素的总和。
它可能看起来有点奇怪,因为for
循环都在一行上,但这被称为“列表理解”。简单列表理解读起来像英语。