问题
例如,当使用Tensorflow实现自定义神经网络层时,实现反向传播的标准实践是什么?我们不需要研究自动微分公式吗?
背景
对于numpy,当创建一个层(例如matmul )时,反向传播梯度首先被解析地导出并相应地编码。
def forward(self, X):
self._X = X
np.matmul(self.X, self.W.T, out=self._Y)
return self.Y
def backward(self, dY):
"""dY = dL/dY is a jacobian where L is loss and Y is matmul output"""
self._dY = dY
return np.matmul(self.dY, self.W, out=self._dX)在Tensorflow中,有自差,它似乎负责雅可比计算。这是否意味着我们不必手动导出梯度公式,而是让Tensorflow磁带来处理它?
计算渐变以自动区分,TensorFlow需要记住在前进过程中发生了什么顺序的操作。然后,在向后传递期间,TensorFlow以反向顺序遍历此操作列表,以计算梯度。
发布于 2021-04-06 14:14:52
基本上,Tensorflow是一个基于数据流和可微编程的符号数学库。我们不需要手动处理自动微分公式。所有这些数学运算都会在后面自动完成。您正确引用了官方文档中关于梯度计算的内容。但是,如果您想知道如何使用numpy手动完成,我建议您检查一下神经网络与深度学习的这个奇妙的过程,特别是第4周,或者另一个源这里。
FYI,在TF 2中,我们可以通过重写tf.keras.Model类的train_step从零开始进行自定义培训,在那里我们可以使用tf.GradientTape API进行自动区分;也就是说,计算一些输入的计算梯度。同样的官方页面包含了更多有关这方面的信息。另外,必须看到这是一篇在tf.GradientTape上写得很好的文章.例如,使用这个API,我们可以轻松地计算梯度,如下所示:
import tensorflow as tf
# some input
x = tf.Variable(3.0, trainable=True)
with tf.GradientTape() as tape:
# some output
y = x**3 + x**2 + x + 5
# compute gradient of y wrt x
print(tape.gradient(y, x).numpy())
# 34此外,我们还可以计算更高阶的导数,例如
x = tf.Variable(3.0, trainable=True)
with tf.GradientTape() as tape1:
with tf.GradientTape() as tape2:
y = x**3 + x**2 + x + 5
# first derivative
order_1 = tape2.gradient(y, x)
# second derivative
order_2 = tape1.gradient(order_1, x)
print(order_2.numpy())
# 20.0现在,在tf. keras中的自定义模型培训中,我们首先进行forward传递,然后计算模型中有关loss的可训练变量的loss和下一个计算gradients。随后,我们基于这些gradients更新模型的权重。下面是它的代码片段,下面是端到端的详细信息。从头开始写一个训练循环。
# Open a GradientTape to record the operations run
# during the forward pass, which enables auto-differentiation.
with tf.GradientTape() as tape:
# Run the forward pass of the layer.
# The operations that the layer applies
# to its inputs are going to be recorded
# on the GradientTape.
logits = model(x_batch_train, training=True) # Logits for this minibatch
# Compute the loss value for this minibatch.
loss_value = loss_fn(y_batch_train, logits)
# Use the gradient tape to automatically retrieve
# the gradients of the trainable variables with respect to the loss.
grads = tape.gradient(loss_value, model.trainable_weights)
# Run one step of gradient descent by updating
# the value of the variables to minimize the loss.
optimizer.apply_gradients(zip(grads, model.trainable_weights))发布于 2021-04-06 14:15:02
正确,您只需定义前传球,Tensorflow就会生成适当的后传球。来自tf2自差
TensorFlow提供了用于自动区分的tf.GradientTape API;也就是说,根据某些输入(通常是tf.Variables )计算计算的梯度。TensorFlow将在tf.GradientTape上下文中执行的相关操作“记录”到“磁带”上。然后,TensorFlow使用该磁带来使用反向模式微分计算“记录”计算的梯度。
为了做到这一点,Tensorflow给出了向前通过(或损失)和一组tf.Variable变量来计算导数。此过程仅可用于Tensorflow本身定义的一组特定操作。为了创建自定义NN层,您需要使用这些操作(所有这些操作都是TF的一部分或由某个转换器转换到它)来定义它的前向pas。
因为您似乎有一个numpy背景,所以可以使用numpy定义自定义向前传递,然后使用API接口将其转换为Tensorflow。您也可以使用tf.numpy_function。在此之后,TF将为您创建反向传播。
(*)注意一些操作,例如控制语句本身是不可微的,因此它们对基于梯度的优化器是不可见的。关于这些,有一些警告。
https://stackoverflow.com/questions/66964498
复制相似问题