【问题标题】:Keras, tensorflow: Initializer for variable... is from inside a control-flow construct, a loop or conditionalKeras,张量流:变量的初始化器......来自控制流构造,循环或条件
【发布时间】:2018-07-08 23:04:41
【问题描述】:

我正在训练一个掩码 r-cnn 模型,请参阅 github 上的这个代表: https://github.com/matterport/Mask_RCNN

我遇到一个问题,似乎是使用 Keras 的问题,所以我来这里。

代码从感兴趣区域(rois)和特征图计算掩码:

mrcnn_mask = build_fpn_mask_graph(rois, mrcnn_feature_maps,
    config.IMAGE_SHAPE,
    config.MASK_POOL_SIZE,
    config.NUM_CLASSES)

但是,有时 rois 可能全为零,在这种情况下,我想直接返回全零。所以,我像这样使用 tf.cond:

def ff_true():
    mrcnn_mask = build_fpn_mask_graph(rois, mrcnn_feature_maps,
       config.IMAGE_SHAPE,
       config.MASK_POOL_SIZE,
       config.NUM_CLASSES)

def ff_false():
    return tf.zeros_like(target_mask)

mrcnn_mask = KL.Lambda(lambda x: tf.cond(tf.equal(tf.reduce_mean(x), 0), 
    ff_true, ff_true)) (rois)

这会引发错误:

ValueError:变量 lambda_5/cond/mrcnn_mask_conv1/kernel/ 的初始化程序来自控制流构造内部,例如循环或条件。在循环或条件中创建变量时,请使用 lambda 作为初始值设定项。

我用谷歌搜索,但没有得到有用的信息。 这似乎是错误使用 keras/tensorflow 的问题。 欢迎任何线索!

顺便说一句,如果我使用这个代码,它不会出错(但我不想提前计算a):

a = build_fpn_mask_graph(rois, mrcnn_feature_maps,
    config.IMAGE_SHAPE,
    config.MASK_POOL_SIZE,
    config.NUM_CLASSES)   
def ff_true():
    return a
def ff_false():
    return tf.zeros_like(target_mask)

mrcnn_mask = KL.Lambda(lambda x: tf.cond(tf.equal(tf.reduce_mean(x), 0), 
    ff_true, ff_true)) (rois)

【问题讨论】:

  • 有时由于数据类型不匹配(例如,尝试连接 tf.float32 和 tf.int32 类型的张量)会出现此错误。这在此处进行了更详细的讨论:stackoverflow.com/questions/47393356/… 和此处:github.com/tensorflow/tensorflow/issues/14729。不幸的是,我认为您的代码实际上并非如此,因为您有一个实际的 lambda。但即使不是,这些链接也可能对在谷歌搜索该错误时发现此问题的其他人有用。
  • 是的,不是数据类型的问题。这只是 Keras 的一个问题。 Keras 使用张量来初始化变量,这在条件内部是不合法的。参考:github.com/matterport/Mask_RCNN/issues/170我还没找到解决办法。

标签: tensorflow keras


【解决方案1】:

错误基本上就是消息所说的内容。条件内不能有变量初始化器。与普通编程语言的粗略类比是:

if my_condition:
    a = 1
print a    # can't do this. a might be uninitialized.

这里有一个简单的例子来说明这个问题和错误消息中建议的修复:

import tensorflow as tf

def cond(i, _):
  return i < 10

def body(i, _):
  zero = tf.zeros([], dtype=tf.int32)
  v = tf.Variable(initial_value=zero)
  return (i + 1, v.read_value())

def body_ok(i, _):
  zero = lambda: tf.zeros([], dtype=tf.int32)
  v = tf.Variable(initial_value=zero, dtype=tf.int32)
  return (i + 1, v.read_value())

tf.while_loop(cond, body, [0, 0])

这是使用tf.while_loop,但它与tf.cond 相同。如果您按原样运行此代码,您将收到相同的错误。如果您将body 替换为body_ok,一切都会好起来的。原因是当初始化器是一个函数时,tensorflow 可以将其置于“控制流上下文之外”以确保它始终运行。

为了澄清未来读者可能的困惑,“首先计算a”的方法并不理想,但有一个微妙的原因。首先,请记住您在这里所做的是构建计算图(假设您没有使用eager execution)。所以,你实际上并没有计算a。您只是在定义它可以如何计算。 Tensorflow 运行时根据session.run() 的参数决定需要在运行时计算什么。因此,人们可能期望如果条件为假,则返回a 的分支将不会被执行(因为它不需要)。不幸的是,这不是 TensorFlow 运行时的工作方式。您可以在第一个答案here 中找到更多详细信息,但简而言之,TensorFlow 运行时将为 either 分支执行所有 依赖项,只有 true_fn/false_fn 内的操作将是有条件地执行。

【讨论】:

  • 谢谢,这真的很有帮助!
【解决方案2】:

在使用 keras 和 CNN-LSTM 时,我也遇到了同样的问题。该代码在 GPU 服务器上运行良好,但是当我尝试在本地计算机上运行它时,出现了这个奇怪的错误。

以下技巧对我有用。

解决方案:清除变量并重新启动内核。这对我有用。也许其他人遇到与我完全相同的问题会有所帮助。

【讨论】:

  • 我正在疯狂地寻找解决此错误的方法。我在 LSTM 上应用它时得到了它。最后,你的回答帮我解决了。我正在使用 Google Colab,但我在重新启动运行时后不再收到此错误。
猜你喜欢
  • 1970-01-01
  • 2017-12-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-11-13
相关资源
最近更新 更多