Pytorch 中基于磁带的 autograd 是什么?

Lon*_*ong 8 python machine-learning tensorflow pytorch tensorflow2.0

我理解autograd是用来暗示自动微分的。但究竟什么是tape-based autogradPytorch为什么有一些肯定或否定它这么多的讨论。

例如:

这个

在pytorch中,没有传统意义上的胶带

我们本身并没有真正构建梯度磁带。但是图表。

但不是这个

Autograd 现在是用于自动微分的核心 Torch 包。它使用基于磁带的系统进行自动区分。

为了进一步参考,请将其与GradientTapein进行比较Tensorflow

uke*_*emi 6

我怀疑这来自于自动微分上下文中“磁带”一词的两种不同用法。

\n

当人们说不是基于磁带时,他们的意思是它使用运算符重载而不是[基于磁带]源转换来进行自动微分。

\n
\n

运算符重载】依赖于一种语言\xe2\x80\x99s重新定义函数和运算符含义的能力。所有原语都被重载,以便它们另外执行跟踪操作:原语及其输入记录到 \xe2\x80\x98tape\xe2\x80\x99 上,以确保这些中间变量保持活动状态。在函数\xe2\x80\x99s 执行结束时,该磁带包含程序中所有数值运算的线性跟踪。可以通过反向走动该磁带来计算导数。[...]
\nOO 是 PyTorch、Autograd 和 Chainer [37] 使用的技术。

\n

...

\n

基于磁带的框架(例如 Fortran 和 C 的 ADIFOR [8] 和 Tapenade [20])使用也称为 \xe2\x80\x98tape\xe2\x80\x99 2的全局堆栈来确保中间变量保持活动状态。原始(原始)函数被增强,以便在前向传递期间将中间变量写入磁带,并且伴随程序将在向后传递期间从磁带读取中间变量。最近,在 ML 框架 Tangent [38] 中为 Python 实现了基于磁带的 ST。

\n

...

\n

2 ST 中使用的磁带仅存储中间变量,而 OO 中的磁带是程序跟踪,还存储执行的原语。

\n
\n\n


M.I*_*nat 5

有不同类型的自动微分例如forward-modereverse-modehybrids; (更多解释)。中的tape-basedautogradPytorch简单地指的是反向模式自动微分的用途,source。在反向模式自动DIFF是简单地用于一个技术有效地计算梯度,并且它正好由反向传播使用


现在,在PyTorch 中,Autograd 是自动微分的核心 Torch 包。它使用自动微分tape-based系统。在前进阶段,磁带会记住它执行的所有操作,在后退阶段,它会重放操作autograd

TensorFlow 中也是如此,为了自动区分,它还需要记住在前向传递过程中以什么顺序发生了什么操作。然后,在反向传递期间,TensorFlow 以相反的顺序遍历此操作列表以计算梯度。现在,TensorFlow 提供了tf.GradientTape自动微分的API;也就是说,计算关于某些输入的计算梯度,通常为tf.Variables。TensorFlow将在 a的上下文中执行的相关操作记录tf.GradientTape磁带上。TensorFlow 然后使用该磁带来计算使用反向模式微分记录计算的梯度。

所以,从高层的角度来看,两者都在做同样的操作。然而,在自定义训练循环期间, 的forward传递和计算loss更加明确,TensorFlow因为它使用tf.GradientTapeAPI 范围,而在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_()
Run Code Online (Sandbox Code Playgroud)

仅供参考,在上面,可训练变量(wb)在两个框架中都是手动更新的,但我们通常使用优化器(例如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()
Run Code Online (Sandbox Code Playgroud)