有不同类型的自动微分,例如forward-mode,reverse-mode,hybrids; (more explanation)。 Pytorch 中的 tape-based autograd 仅指 reverse-mode 自动微分的使用,source。 reverse-mode 自动差异只是一种用于有效计算梯度的技术,它恰好被反向传播使用,source。
现在,在PyTorch 中,Autograd 是用于自动微分的核心 Torch 包。它使用tape-based 系统进行自动区分。在前向阶段,autograd 磁带将记住它执行的所有操作,而在后向阶段,它将重播操作。
同TensorFlow,为了自动区分,还需要记住在前向传递过程中以什么顺序发生的操作。然后,在向后传递期间,TensorFlow 以逆序遍历这个操作列表来计算梯度。现在,TensorFlow 提供了tf.GradientTape API 用于自动区分;也就是说,计算一些输入的计算梯度,通常是tf.Variables。 TensorFlow 记录在tf.GradientTape 的上下文中执行的相关操作到磁带。然后,TensorFlow 使用该磁带来计算使用reverse mode differentiation 的记录计算的梯度。
所以,从高层次的角度来看,两者都在做同样的操作。但是,在自定义训练循环期间,forward 传递和loss 的计算在TensorFlow 中更明确,因为它使用tf.GradientTape API 范围,而在PyTorch 中,这些操作是隐式的,但需要设置required_grad 在更新训练参数(权重和偏差)时临时标记为 False。为此,它明确使用torch.no_grad API。换句话说,TensorFlow 的tf.GradientTape() 类似于 PyTorch 的loss.backward()。以下是上述语句代码中的简化形式。
# TensorFlow
[w, b] = tf_model.trainable_variables
for epoch in range(epochs):
with tf.GradientTape() as tape:
# forward passing and loss calculations
# within explicit tape scope
predictions = tf_model(x)
loss = squared_error(predictions, y)
# compute gradients (grad)
w_grad, b_grad = tape.gradient(loss, tf_model.trainable_variables)
# update training variables
w.assign(w - w_grad * learning_rate)
b.assign(b - b_grad * learning_rate)
# PyTorch
[w, b] = torch_model.parameters()
for epoch in range(epochs):
# forward pass and loss calculation
# implicit tape-based AD
y_pred = torch_model(inputs)
loss = squared_error(y_pred, labels)
# compute gradients (grad)
loss.backward()
# update training variables / parameters
with torch.no_grad():
w -= w.grad * learning_rate
b -= b.grad * learning_rate
w.grad.zero_()
b.grad.zero_()
仅供参考,在上面,可训练变量(w、b)在两个框架中都是手动更新的,但我们通常使用优化器(例如 adam)来完成这项工作。
# TensorFlow
# ....
# update training variables
optimizer.apply_gradients(zip([w_grad, b_grad], model.trainable_weights))
# PyTorch
# ....
# update training variables / parameters
optimizer.step()
optimizer.zero_grad()