python - Tensorflow - autodiff 是否让我们从 back-prop 实现中解脱出来?
问题描述
问题
使用 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 中,有autodiff似乎负责雅可比计算。这是否意味着我们不必手动推导出梯度公式,而是让 Tensorflow 磁带来处理它?
计算梯度
为了自动区分,TensorFlow 需要记住在前向传递过程中以什么顺序发生的操作。然后,在反向传递期间,TensorFlow 以相反的顺序遍历这个操作列表来计算梯度。
解决方案
基本上,Tensorflow是一个基于数据流和可微分编程的符号数学库。我们不必手动处理自动微分公式。所有这些数学运算都将在后台自动完成。您从官方文档中正确引用了有关梯度计算的内容。但是,如果您想知道如何手动完成numpy
,我建议您查看神经网络和深度学习这门精彩的课程,尤其是第 4 周,或者这里的替代来源。
仅供参考,TF 2
我们可以通过覆盖类从头开始进行自定义训练,train_step
在tf.keras.Model
那里我们可以使用tf.GradientTape
API 进行自动区分;也就是说,计算关于某些输入的计算梯度。同一官方页面包含有关此的更多信息。此外,必须看到这篇写得很好的文章。例如,使用此 API,我们可以轻松计算梯度,如下所示:tf.GradientTape
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
模型gradients
的可训练变量相对于loss
. 稍后,我们根据这些更新模型的权重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))
推荐阅读
- html - 具有三个 div 的边框的可见性
- angular - 根据测试执行顺序,使用 TestBed.inject 的 Angular 单元测试成功/失败
- javascript - 如果值更改,javascript更新视图
- php - Symfony4:从数据库(实体)保存安全用户会话不起作用
- r - 提高查找“增加掷骰子序列”的速度
- pyspark - 在 Amazon EMR 集群上运行 jupyter notebook 时出现 Pyspark 内核错误
- function - Oracle pl/sql 将保存 sql 文本的变量分配给 sys_refcursor 并循环遍历记录
- json - 使用 Angular11,我的 HomeComponent 如何在 DataService 中检索 Subject 提供的数据?
- javascript - 检查当前页面中的 Adsense javascript 文件响应是否为 403
- python - 为多列绘制一种颜色的熊猫数据框