TypeError:函数构建代码之外的操作正在传递一个图张量

Posted

技术标签:

【中文标题】TypeError:函数构建代码之外的操作正在传递一个图张量【英文标题】:TypeError: An op outside of the function building code is being passed a Graph tensor 【发布时间】:2020-02-22 05:49:24 【问题描述】:

我收到以下异常

TypeError: An op outside of the function building code is being passed
a "Graph" tensor. It is possible to have Graph tensors
leak out of the function building context by including a
tf.init_scope in your function building code.
For example, the following function will fail:
  @tf.function
  def has_init_scope():
    my_constant = tf.constant(1.)
    with tf.init_scope():
      added = my_constant * 2
The graph tensor has name: conv2d_flipout/divergence_kernel:0

这也会引发以下异常

tensorflow.python.eager.core._SymbolicException: Inputs to eager execution function cannot be Keras symbolic tensors, but found [<tf.Tensor 'conv2d_flipout/divergence_kernel:0' shape=() dtype=float32>]

运行以下代码时

from __future__ import print_function

import tensorflow as tf
import tensorflow_probability as tfp


def get_bayesian_model(input_shape=None, num_classes=10):
    model = tf.keras.Sequential()
    model.add(tf.keras.layers.Input(shape=input_shape))
    model.add(tfp.layers.Convolution2DFlipout(6, kernel_size=5, padding="SAME", activation=tf.nn.relu))
    model.add(tf.keras.layers.Flatten())
    model.add(tfp.layers.DenseFlipout(84, activation=tf.nn.relu))
    model.add(tfp.layers.DenseFlipout(num_classes))
    return model

def get_mnist_data(normalize=True):
    img_rows, img_cols = 28, 28
    (x_train, y_train), (x_test, y_test) = tf.keras.datasets.mnist.load_data()

    if tf.keras.backend.image_data_format() == 'channels_first':
        x_train = x_train.reshape(x_train.shape[0], 1, img_rows, img_cols)
        x_test = x_test.reshape(x_test.shape[0], 1, img_rows, img_cols)
        input_shape = (1, img_rows, img_cols)
    else:
        x_train = x_train.reshape(x_train.shape[0], img_rows, img_cols, 1)
        x_test = x_test.reshape(x_test.shape[0], img_rows, img_cols, 1)
        input_shape = (img_rows, img_cols, 1)

    x_train = x_train.astype('float32')
    x_test = x_test.astype('float32')

    if normalize:
        x_train /= 255
        x_test /= 255

    return x_train, y_train, x_test, y_test, input_shape


def train():
    # Hyper-parameters.
    batch_size = 128
    num_classes = 10
    epochs = 1

    # Get the training data.
    x_train, y_train, x_test, y_test, input_shape = get_mnist_data()

    # Get the model.
    model = get_bayesian_model(input_shape=input_shape, num_classes=num_classes)

    # Prepare the model for training.
    model.compile(optimizer=tf.keras.optimizers.Adam(), loss="sparse_categorical_crossentropy",
                  metrics=['accuracy'])

    # Train the model.
    model.fit(x_train, y_train, batch_size=batch_size, epochs=epochs, verbose=1)
    model.evaluate(x_test, y_test, verbose=0)


if __name__ == "__main__":
    train()

问题显然与tfp.layers.Convolution2DFlipout 层有关。为什么我会得到这些异常?这是由于我的代码中的逻辑错误还是可能是 TensorFlow 或 TensorFlow Probability 中的错误?这些错误是什么意思?我该如何解决?

我使用的是 TensorFlow 2.0.0(默认情况下会急切执行)。和 TensorFlow Probability 0.8.0 和 Python 3.7.4。我还打开了相关问题here 和here。

请不要建议我使用 TensorFlow 1 来懒惰地执行我的代码(也就是说,在导入 TensorFlow 后使用 tf.compat.v1.disable_eager_execution(),因为我知道这会使上面的代码运行而不会得到提到的异常)或显式创建会话或占位符。

【问题讨论】:

在编译器中不使用 ,experimental_run_tf_function=False 的情况下找到解决问题的方法了吗?对我来说,这是唯一让它起作用的东西。不确定性能是否下降。 @MathieuChâteauvert 见https://github.com/tensorflow/probability/issues/620#issuecomment-620821990。 【参考方案1】:

这个问题可以通过将compile 方法的参数experimental_run_tf_function 设置为False 来部分解决,正如我在comment to the Github issue I had opened 中所写的那样。

但是,如果将experimental_run_tf_function 设置为False 并尝试使用predict 方法,则会出现另一个错误。见this Github issue。


编辑(2020 年 9 月 28 日)

experimental_run_tf_function 在最新版本的 TF 中被移除。然而,在最新版本的 TFP 中(我使用的具体版本在下面列出),贝叶斯卷积层(至少是使用 Flipout 估计器的那个)的问题得到了修复。请参阅https://github.com/tensorflow/probability/issues/620#issuecomment-620821990 和https://github.com/tensorflow/probability/commit/1574c1d24c5dfa52bdf2387a260cd63a327b1839。

具体来说,我使用了以下版本

tensorflow==2.3.0
tensorflow-probability==0.11.0

我同时使用了密集贝叶斯层和卷积贝叶斯层,但在调用compile 时,我确实使用了experimental_run_tf_function=False

【讨论】:

自从 TFv2.2 这个选项不再可用,不是吗? Here 来源 @AgustinBarrachina 我认为您是对的,但是如果您使用最新版本的 TFP,则在 TF 2.2(或 TF 2.3)中不会再出现此错误,因为该错误已在 TFP 中修复(如果我没记错)。检查 Github 问题。 您也许可以在编译模型时使用run_eagerly=False

以上是关于TypeError:函数构建代码之外的操作正在传递一个图张量的主要内容,如果未能解决你的问题,请参考以下文章

Tensorflow 2.1.0 - 函数构建代码之外的操作正在传递一个“图形”张量

TypeError:messaging.getToken 不是函数

将 2d numpy 数组传递给 C++ 时出现 TypeError

C++ 将列表作为参数传递给函数

typeerror: app.use() 需要中间件函数

TypeError:list.map 不是函数