python - 深度学习:Python 中的反向传播代码
问题描述
我正在阅读免费的在线书籍,并且正在为某些代码而苦苦挣扎。
(代码来自 Michael Nielsen)
class Network(object):
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]
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)]
def backprop(self, x, y):
nabla_b = [np.zeros(b.shape) for b in self.biases]
nabla_w = [np.zeros(w.shape) for w in self.weights]
# feedforward
activation = x
activations = [x] # list to store all the activations, layer by layer
zs = [] # list to store all the z vectors, layer by layer
for b, w in zip(self.biases, self.weights):
z = np.dot(w, activation)+b
zs.append(z)
activation = sigmoid(z)
activations.append(activation)
# backward pass
因为它说mini_batch
的是一个元组列表,所以函数中的(x, y)
参数是一个标量,对吧?如果是这样,因为(weights) 是一个矩阵(比如说它的维数是),它的行在第 th 层有神经元,而列在第 th 层有神经元。那么, 一定是向量。我感到困惑。x
backprop
w
n*p
n
l
p
l-1
x
n x 1
在本书的例子中,它使用了[2,3,1]
,即三层,分别有 2,3 和 1 个神经元。因为第一层输入,它有两个元素。所以第 2 层的权重矩阵有 3*2 维。似乎x
应该是一个长度为 2 的向量来与 进行矩阵乘法w
。
此外,关于激活 a 的偏导数的代码C_x
如下:
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)
我检查了我理解的公式,(output_activations-y
)表示成本的变化。但这应该除以激活的变化吗?
你可以帮帮我吗?
解决方案
因为它说“mini_batch”是一个元组列表“(x,y)”,所以函数backprop中x的参数是一个标量,对吧?
不,“batch”这个词对应于一个python列表。在批处理/python 列表中有一对,如(x, y)
,其中x
表示输入向量,y
是标签。的形状x
取决于您如何创建网络对象。在这种情况下[2, 3, 1]
, x 应该是 shape 的向量(2,)
。
但这应该除以激活的变化吗?
不。
首先,您正在考虑的内容称为“数值微分”。既然你没有成本的变化,你不应该通过激活的变化来分割它。
其次,作者使用的东西叫做“解析微分”。说,你有一个功能f(x, y) = 0.5*(x-y)^2
。f
wrt的偏导数x
是x-y
。因此,您不需要将其除以 的变化x
。但是,您需要注意使用的实际成本函数才能得出正确的导数。有时,如何计算这些值并不明显。在这种情况下,损失是均方误差,如在线书籍中所述。
回复评论:
输入为vector_x = (1,2,3)的训练集
训练集应该是一个包含一组训练样本的容器,其中每个训练样本由一个输入和相应的标签组成。因此,小批量的一个示例可能是一个 Python 列表,例如:[([0, 1], [1, 2]), ([2, 1], [3, 2])]
,它表示有两个训练样本。第一个是([0, 1], [1, 2])
,第二个是([2, 1], [3, 2])
。以第一个为例,它的输入是[0, 1]
(形状为 的向量(2,)
),它的输出是[1, 2]
,这意味着单个训练样本的输入和期望的输出都可以是向量。您的问题 ( ) 有一些含糊不清,[(1,a),(2,b),(3,c)]
所以我希望我的解释。
推荐阅读
- mongodb - 为什么删除 STS 应用程序不会自动删除 OpenEBS Jiva 卷 pvc?
- c# - 将时间从 DateTimePicker 传递到数据库参数
- ios - 在标签中显示 IOS CABasicAnimation 进度
- odoo - TypeError: list.fields[order.name] 未定义
- r - 如何让传说独立于美学?
- javascript - 如何将属性添加到 JSON 对象的根由对象数组组成?
- html - 将excel单元格内容转换为html标记
- php - 如何用逗号分隔创造价值?
- azure-devops - 使用 rest api 将 VSTS 测试用例状态更新为 PASS / FAIL
- javascript - koa2:如何组织路由器控制器逻辑(中间件与非中间件)?