【问题标题】:Tensorflow GradientTape "Gradients does not exist for variables" intermittentlyTensorflow GradientTape“变量不存在渐变”间歇性
【发布时间】:2019-11-30 08:16:36
【问题描述】:

在训练我的网络时,我偶尔会遇到以下警告:

W0722 11:47:35.101842 140641577297728 optimizer_v2.py:928] Gradients does not exist for variables ['model/conv1d_x/Variable:0'] when minimizing the loss.

这种情况很少发生(可能每 20 步成功执行一次)。我的模型基本上有两条路径,它们在网络中的不同位置连接在一起。为了说明这一点,这里有一个简化的例子来说明我的意思。

class myModel(tf.keras.Model):

  def __init__(self):

    self.conv1 = Conv2D(32)
    self.conv2 = Conv2D(32)
    self.conv3 = Conv2D(16)

  def call(self, inputs):

    net1 = self.conv1(inputs)
    net2 = self.conv2(inputs)
    net = tf.concat([net1, net2], axis=2)
    net = self.conv3(net)
    end_points = tf.nn.softmax(net)

model = myModel()

with tf.GradientTape() as tape:

  predicition = model(image)
  loss = myloss(labels, prediction)

gradients = tape.gradient(loss, model.trainable_variables)
optimizer.apply_gradients(zip(gradients, model.trainable_variables))

实际上,我的网络要大得多,但通常没有梯度的变量往往是网络顶部的变量。在每个Conv2D 层之前,我还有一个自定义渐变。有时当我出现错误时,我会注意到尚未调用该图层的渐变函数。

我的问题是,当通过我的网络向后传播时,渐变胶带有时如何采用看似不同的路径。我的第二个问题是,这是由于通过我的网络有两条单独的路由(即 conv1 和 conv2)造成的。这种网络架构是否存在根本缺陷?

理想情况下,我可以向GradientTape() 定义它必须找到每个顶层的渐变吗?

【问题讨论】:

  • 您好 D.Griffiths,根据您指定的代码和您给出的解释,我们无法重现您的错误。您能否分享完整的代码(代表您的架构和自定义渐变的虚拟代码就足够了),以便我们可以尝试重现错误并努力解决它。谢谢。
  • 嗨,重现问题的代码将是我的整个网络,它相当大,包含自定义操作和特定数据等。我不认为这是 TF 代码的错误。对于某些变量间歇性地导致错误抛出的梯度不存在的情况,我更加徘徊。例如,可能发生被零除是否正常,或者这是我应该担心的事情(甚至是我的错误)。
  • 它还在发生吗?
  • 我刚刚遇到了一个类似的问题,我总是收到警告。我的代码不同。基本上,在自定义类的构建函数中,我添加了一个权重并覆盖了我对它的引用。通过避免警告消失了。但你的情况似乎并不相似。

标签: python tensorflow keras


【解决方案1】:

我遇到了一个看起来相似的问题 - 可能会有所帮助或不确定,具体取决于您的网络的实际外观,但基本上,我有一个多输出网络,我意识到当我应用与输出相对应的渐变时分开,因此对于每个单独的损失,网络的一个分支的梯度为零,但这是完全有效的,并且每次都对应于紧接在非目标输出之前的终端层。出于这个原因,我最终用 tf.zeros_like 替换了任何 None 梯度,并且可以继续训练。如果网络的多个输入头始终位于图表的顶部,您是否会遇到同样的问题?

(下面 Nguyễn Thu 的 ETA 解决方案是我在上面描述的代码版本 - 与我处理它的方式完全相同)

我看到了其他没有计算梯度的答案,因为默认情况下不监视张量 - 你必须添加它们,但看起来这不是你的问题,因为你应该只处理 model.trainable_variables,或者也许您的 myLoss 函数有时会根据您的批次组成获得 NaN 结果或转换为 numpy 数组,这可以解释零星的性质(例如,如果您的数据非常不平衡,可能是在没有少数类实例的批次上?)

【讨论】:

  • 加1;我的损失函数的问题确实是我的情况。谢谢!
【解决方案2】:

如果预期会丢失渐变,则可以通过this workaround 抑制此警告:

optimizer.apply_gradients(
    (grad, var) 
    for (grad, var) in zip(gradients, model.trainable_variables) 
    if grad is not None
)

【讨论】:

    【解决方案3】:

    Nguyễn 和 gkennos 给出的解决方案将抑制错误,因为它将所有 None 替换为零。 但是,您的梯度在任何时间点都为空是一个大问题。 上述问题肯定是unconnected variables引起的(默认PyTorch会抛出运行时错误)。

    最常见的不连接层的例子如下:

     def some_func(x):
           x1 = x * some variables
           x2 = x1 + some variables #x2 discontinued after here
           x3 = x1 / some variables
           return x3
    

    现在观察x2 是未连接的,所以梯度不会被传播抛出它。仔细调试代码中未连接的变量。

    【讨论】:

    • 这是正确的答案,应该得到更多的支持。用None 抑制错误就像把头藏在沙子下假装问题不存在。
    • 同意@Leevo,这应该得到更多的支持。完美解决了我的问题。
    【解决方案4】:

    我遇到了同样的问题。找到了自定义渐变的解决方案

      def _compute_gradients(tensor, var_list):
          grads = tf.gradients(tensor, var_list)
      return [grad if grad is not None else tf.zeros_like(var)
          for var, grad in zip(var_list, grads)]
    

    来自github trouble shoot

    【讨论】:

    • 这将被添加到哪里?
    【解决方案5】:

    渐变胶带的gradient 方法有一个unconnected_gradients 参数,可让您指定未连接的渐变应为None 还是Zero。请参阅文档:https://www.tensorflow.org/api_docs/python/tf/GradientTape#gradient

    所以你可以换行:

    gradients = tape.gradient(loss, model.trainable_variables)
    

    gradients = tape.gradient(loss, model.trainable_variables, 
                    unconnected_gradients=tf.UnconnectedGradients.ZERO)
    

    这对我有用。

    编辑 - 重要提示:如果您实际上期望某些渐变为零,这只是一个解决方案。如果错误是由于反向传播损坏导致的,这不是解决方案。在这种情况下,您需要找到并修复它的损坏位置。

    【讨论】:

    • 可以确认。这也适用于我.. TF2.5
    【解决方案6】:

    我也遇到了同样的错误。这是因为我在tape.gradient() 函数中给出了错误的可训练变量。如果它可以帮助某人。

    在我的示例中,self.encoder_model.get_trainable_variables() 没有返回好的变量:

    @tf.function
    def train_step(x_batch):
        with tf.GradientTape() as tape:
            loss = self.encoder_model.loss.compute_loss(x_batch)
        gradients = tape.gradient(loss, self.encoder_model.get_trainable_variables())
        self.optimizer.apply_gradients(zip(gradients, self.encoder_model.get_trainable_variables()))
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-01-11
      • 1970-01-01
      • 2020-04-27
      • 2018-09-24
      • 2016-10-19
      相关资源
      最近更新 更多