尝试在非持久磁带上仍然处于活动状态时调用tape.gradient

joh*_*ith 3 tensorflow

为什么TensorFlow会给我运行时错误(在标题中)?

我正在使用WinPython3.5.4.2并安装了TensorFlow 1.8.0.我一直关注https://www.tensorflow.org/get_started/eager上的教程,直到标题为"Training loop"的部分.

---------------------------------------------------------------------------
RuntimeError                              Traceback (most recent call last)
<ipython-input-9-e08164fd8374> in <module>()
 14     for x, y in train_dataset:
 15         # Optimize the model
---> 16         grads = grad(model, x, y)
 17         optimizer.apply_gradients(zip(grads, model.variables),
 18                                   global_step=tf.train.get_or_create_global_step())

<ipython-input-7-08164b502799> in grad(model, inputs, targets)
  6     with tf.GradientTape() as tape:
  7         loss_value = loss(model, inputs, targets)
----> 8         return tape.gradient(loss_value, model.variables)

C:\[deleted]\WinPython3.5.4.2\python-3.5.4.amd64\lib\site-packages\tensorflow\python\eager\backprop.py in gradient(self, target, sources, output_gradients)
765     flat_grad = imperative_grad.imperative_grad(
766         _default_vspace, self._tape, [target], flat_sources,
--> 767         output_gradients=output_gradients)
768 
769     if not self._persistent:

C:\[deleted]\WinPython3.5.4.2\python-3.5.4.amd64\lib\site-packages\tensorflow\python\eager\imperative_grad.py in imperative_grad(vspace, tape, target, sources, output_gradients)
 61   """
 62   return pywrap_tensorflow.TFE_Py_TapeGradient(
---> 63       tape._tape, vspace, target, sources, output_gradients)  # pylint: disable=protected-access

RuntimeError: Trying to call tape.gradient on a non-persistent tape while it is still active.
Run Code Online (Sandbox Code Playgroud)

ash*_*ash 8

我怀疑在你的样本中你是tape.gradient()with tf.GradientTape()上下文中调用而不是在它之外调用.改变自:

with tf.GradientTape() as tape:
  loss_value = loss(model, inputs, targets)
  return tape.gradient(loss_value, model.variables)
Run Code Online (Sandbox Code Playgroud)

with tf.GradientTape() as tape:
  loss_value = loss(model, inputs, targets)
# Notice the change in indentation of the line below
return tape.gradient(loss_value, model.variables)
Run Code Online (Sandbox Code Playgroud)

应该导致错误消失.

在a的上下文中执行的TensorFlow操作GradientTape被"记录",以便稍后可以区分记录的计算.这种记录需要记忆(因为由中间操作实现的张量必须保持活跃).tape.gradient()GradientTape上下文管理器中调用意味着也应该记录梯度计算,并且在梯度计算期间创建的张量需要保持活动.通常这不是用户想要的 - tape.gradient()调用只是意外地在上下文管理器中,导致比必要的内存占用更大.因此错误.虽然,可以说错误消息字符串的措辞并不是特别好(我相信在TensorFlow 1.8之后的版本中会有所改进).

引用文档

默认情况下,GradientTape一旦GradientTape.gradient()调用方法,就会释放a所拥有的资源.要在同一计算中计算多个渐变,请创建persistent渐变磁带.这允许gradient()在对磁带对象进行垃圾回收时释放资源,从而对方法进行多次调用.

因此,如果您确实想要记录渐变计算(例如,计算二阶导数),那么您可以创建一个持久磁带并将.gradient()调用保留在上下文管理器中.例如:

x = tfe.Variable(3.0)
with tf.GradientTape(persistent=True) as g:
  y = x * x
  dy = g.gradient(y, x)
  d2y = g.gradient(dy, x)
print(dy)
print(d2y)
Run Code Online (Sandbox Code Playgroud)

急切执行是TensorFlow中相对较新的功能,对它的反馈非常受欢迎.如果您认为错误消息可能更好(可能是!)和/或默认值应该更改(例如,默认情况下持久,并且特别关注内存开销的用户可以明确选择非持久性磁带) - 不要通过提供有关GitHub的反馈,犹豫不决

希望有所帮助!

  • 通过常规的 Python 行为,正确运行代码中的磁带显然超出了 with 语句的范围。它会导致正常代码出错。但在 tensorflow 中,情况正好相反。tensorflow 的这种行为不是 Python 编码器所期望的行为。意外行为会导致开发成本增加。 (2认同)