Python 每个小批量是否只更新一次重量/偏差?

Python 每个小批量是否只更新一次重量/偏差?,python,neural-network,gradient-descent,stochastic-gradient,Python,Neural Network,Gradient Descent,Stochastic Gradient,我正在学习神经网络教程,我有一个关于更新权重的函数的问题 def update_mini_batch(self, mini_batch, eta): """Update the network's weights and biases by applying gradient descent using backpropagation to a single mini batch. The "mini_batch" is a list of tuples "(x, y)"

我正在学习神经网络教程,我有一个关于更新权重的函数的问题

def update_mini_batch(self, mini_batch, eta):
    """Update the network's weights and biases by applying
    gradient descent using backpropagation to a single mini batch.
    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]                #Initialize bias matrix with 0's
    nabla_w = [np.zeros(w.shape) for w in self.weights]               #Initialize weights matrix with 0's
    for x, y in mini_batch:                                           #For tuples in one mini_batch
        delta_nabla_b, delta_nabla_w = self.backprop(x, y)            #Calculate partial derivatives of bias/weights with backpropagation, set them to delta_nabla_b
        nabla_b = [nb+dnb for nb, dnb in zip(nabla_b, delta_nabla_b)] #Generate a list with partial derivatives of bias of every neuron
        nabla_w = [nw+dnw for nw, dnw in zip(nabla_w, delta_nabla_w)] #Generate a list with partial derivatives of weights for every neuron
    self.weights = [w-(eta/len(mini_batch))*nw                        #Update weights according to update rule
                    for w, nw in zip(self.weights, nabla_w)]          #What author does is he zips 2 lists with values he needs (Current weights and partial derivatives), then do computations with them.
    self.biases = [b-(eta/len(mini_batch))*nb                         #Update biases according to update rule
                   for b, nb in zip(self.biases, nabla_b)]
这里我不明白的是,使用for循环来计算nabla_b和nabla_w(权重/偏差的偏导数)。对于小批量中的每个训练示例使用反向传播,但只更新一次权重/偏差

在我看来,假设我们有一个尺寸为10的小批量,我们计算nabla_b和nabla_w 10次,在for循环完成权重和偏差更新之后。但是for循环不是每次都重置nabla_b和nabla_b列表吗?为什么不在for循环中更新
self.weights
self.bias

神经网络工作得很好,所以我想我在某个地方犯了一个小小的思考错误


仅供参考:以下教程的相关部分可以找到

否,更新发生在批次结束后,依次应用每个培训更新。规范描述说,我们计算所有更新的平均值,并根据该平均值进行调整;反过来,通过每次更新进行调整在算术上是等价的

首先,初始化偏差和权重数组

nabla_b = [np.zeros(b.shape) for b in self.biases]                #Initialize bias matrix with 0's
nabla_w = [np.zeros(w.shape) for w in self.weights]               #Initialize weights matrix with 0's
对于小型比赛中的每次观察, 将训练结果插入偏差和权重数组

for x, y in mini_batch:                                           #For tuples in one mini_batch
    delta_nabla_b, delta_nabla_w = self.backprop(x, y)            #Calculate partial derivatives of bias/weights with backpropagation, set them to delta_nabla_b
    nabla_b = [nb+dnb for nb, dnb in zip(nabla_b, delta_nabla_b)] #Generate a list with partial derivatives of bias of every neuron
    nabla_w = [nw+dnw for nw, dnw in zip(nabla_w, delta_nabla_w)] #Generate a list with partial derivatives of weights for every neuron
最后,依次调整每个权重和偏差,调整每个训练结果的值

self.weights = [w-(eta/len(mini_batch))*nw                        #Update weights according to update rule
                for w, nw in zip(self.weights, nabla_w)]          #What author does is he zips 2 lists with values he needs (Current weights and partial derivatives), then do computations with them.
self.biases = [b-(eta/len(mini_batch))*nb                         #Update biases according to update rule
               for b, nb in zip(self.biases, nabla_b)]

否,更新发生在批处理结束后,依次应用每个培训更新。规范描述说,我们计算所有更新的平均值,并根据该平均值进行调整;反过来,通过每次更新进行调整在算术上是等价的

首先,初始化偏差和权重数组

nabla_b = [np.zeros(b.shape) for b in self.biases]                #Initialize bias matrix with 0's
nabla_w = [np.zeros(w.shape) for w in self.weights]               #Initialize weights matrix with 0's
对于小型比赛中的每次观察, 将训练结果插入偏差和权重数组

for x, y in mini_batch:                                           #For tuples in one mini_batch
    delta_nabla_b, delta_nabla_w = self.backprop(x, y)            #Calculate partial derivatives of bias/weights with backpropagation, set them to delta_nabla_b
    nabla_b = [nb+dnb for nb, dnb in zip(nabla_b, delta_nabla_b)] #Generate a list with partial derivatives of bias of every neuron
    nabla_w = [nw+dnw for nw, dnw in zip(nabla_w, delta_nabla_w)] #Generate a list with partial derivatives of weights for every neuron
最后,依次调整每个权重和偏差,调整每个训练结果的值

self.weights = [w-(eta/len(mini_batch))*nw                        #Update weights according to update rule
                for w, nw in zip(self.weights, nabla_w)]          #What author does is he zips 2 lists with values he needs (Current weights and partial derivatives), then do computations with them.
self.biases = [b-(eta/len(mini_batch))*nb                         #Update biases according to update rule
               for b, nb in zip(self.biases, nabla_b)]

理解这个循环如何增加每个训练示例的偏差和权重的关键是要注意。具体来说,
=
符号右侧的所有内容在分配给
=
符号左侧的变量之前都会进行计算

这是一个更容易理解的简单示例:

nabla_b = [0, 0, 0, 0, 0]
for x in range(10):
    delta_nabla_b = [-1, 2, -3, 4, -5]
    nabla_b = [nb + dnb for nb, dnb in zip(nabla_b, delta_nabla_b)]
在这个例子中,我们只有五个标量偏差和一个恒定的梯度。在这个循环的末尾,什么是
nabla_b
?考虑使用定义的扩展,并记住在代码写在左边的变量名之前,对<代码>=<代码>符号的所有内容进行评估:

nabla_b = [0, 0, 0, 0, 0]
for x in range(10):
    # nabla_b is defined outside of this loop
    delta_nabla_b = [-1, 2, -3, 4, -5]

    # expand the comprehension and the zip() function
    temp = []
    for i in range(len(nabla_b)):
        temp.append(nabla_b[i] + delta_nabla_b[i])

    # now that the RHS is calculated, set it to the LHS
    nabla_b = temp
在这一点上,应该清楚的是,
nabla_b
的每个元素都与理解中的
delta___b
的每个对应元素相加,并且该结果将覆盖
nabla_b
,用于循环的下一次迭代

因此,在教程示例中,
nabla_b
nabla_w
是偏导数的总和,在小批量中,每个训练示例都会向其添加一次梯度。从技术上讲,每个训练示例都会重置它们,但它们会重置为以前的值加上渐变,这正是您想要的。写这篇文章的更清晰(但不那么简洁)的方式可能是:

def update_mini_batch(self, mini_batch, eta):
    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)
        # expanding the comprehensions
        for i in range(len(nabla_b)):
            nabla_b[i] += delta_nabla_b[i]      # set the value of each element directly
        for i in range(len(nabla_w)):
            nabla_w[i] += delta_nabla_w[i]
    self.weights = [w-(eta/len(mini_batch))*nw  # note that this comprehension uses the same trick
                    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)]

理解这个循环如何增加每个训练示例的偏差和权重的关键是要注意。具体来说,
=
符号右侧的所有内容在分配给
=
符号左侧的变量之前都会进行计算

这是一个更容易理解的简单示例:

nabla_b = [0, 0, 0, 0, 0]
for x in range(10):
    delta_nabla_b = [-1, 2, -3, 4, -5]
    nabla_b = [nb + dnb for nb, dnb in zip(nabla_b, delta_nabla_b)]
在这个例子中,我们只有五个标量偏差和一个恒定的梯度。在这个循环的末尾,什么是
nabla_b
?考虑使用定义的扩展,并记住在代码写在左边的变量名之前,对<代码>=<代码>符号的所有内容进行评估:

nabla_b = [0, 0, 0, 0, 0]
for x in range(10):
    # nabla_b is defined outside of this loop
    delta_nabla_b = [-1, 2, -3, 4, -5]

    # expand the comprehension and the zip() function
    temp = []
    for i in range(len(nabla_b)):
        temp.append(nabla_b[i] + delta_nabla_b[i])

    # now that the RHS is calculated, set it to the LHS
    nabla_b = temp
在这一点上,应该清楚的是,
nabla_b
的每个元素都与理解中的
delta___b
的每个对应元素相加,并且该结果将覆盖
nabla_b
,用于循环的下一次迭代

因此,在教程示例中,
nabla_b
nabla_w
是偏导数的总和,在小批量中,每个训练示例都会向其添加一次梯度。从技术上讲,每个训练示例都会重置它们,但它们会重置为以前的值加上渐变,这正是您想要的。写这篇文章的更清晰(但不那么简洁)的方式可能是:

def update_mini_batch(self, mini_batch, eta):
    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)
        # expanding the comprehensions
        for i in range(len(nabla_b)):
            nabla_b[i] += delta_nabla_b[i]      # set the value of each element directly
        for i in range(len(nabla_w)):
            nabla_w[i] += delta_nabla_w[i]
    self.weights = [w-(eta/len(mini_batch))*nw  # note that this comprehension uses the same trick
                    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)]

完美答案!完全明白了。Tyvm=)完美答案!完全明白了。Tyvm=)