【问题标题】:What is tape-based autograd in Pytorch?Pytorch 中基于磁带的 autograd 是什么?
【发布时间】:2021-02-27 13:03:22
【问题描述】:

我了解autograd 用于表示自动区分。但是Pytorch 中的tape-based autograd 到底是什么,以及为什么有如此多的讨论肯定或否定它。

例如:

this

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

this

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

但不是this

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

如需进一步参考,请将其与Tensorflow 中的GradientTape 进行比较。

【问题讨论】:

    标签: python tensorflow machine-learning pytorch tensorflow2.0


    【解决方案1】:

    我怀疑这来自'tape' 这个词在自动微分上下文中的两种不同用法。

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

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

    ...

    基于磁带的框架,例如用于 Fortran 和 C 的 ADIFOR [8] 和 Tapenade [20] 使用一个全局堆栈,也称为“磁带”2,以确保中间变量保持活动状态。原始(原始)函数被扩充,以便它在前向传递期间将中间变量写入磁带,而伴随程序将在反向传递期间从磁带中读取中间变量。最近,基于磁带的 ST 在 ML 框架 Tangent [38] 中为 Python 实现。

    ...

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

    【讨论】:

      【解决方案2】:

      有不同类型的自动微分,例如forward-modereverse-modehybrids; (more explanation)。 Pytorch 中的 tape-based autograd 仅指 reverse-mode 自动微分的使用,sourcereverse-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_()
      

      仅供参考,在上面,可训练变量(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()
      

      【讨论】:

        猜你喜欢
        • 2021-10-02
        • 2017-10-27
        • 2020-05-12
        • 1970-01-01
        • 2023-01-01
        • 2020-05-13
        • 2018-09-06
        • 2020-04-28
        • 1970-01-01
        相关资源
        最近更新 更多