Lambda layer: An op outside of the function building code is being passed a “Graph” tensor

Viewed 1451

I have a problem similar to this post: Tensorflow 2.1.0 - An op outside of the function building code is being passed a "Graph" tensor

My model includes a TimeDistributed wrapper around a CNN, whose input layer is first normalized by a lambda function:

    # ENCODER
    # video input
    frames = 10
    video_input = tf.keras.Input(shape=(frames, 256, 256, 3))

    # cnn 1 frame input
    frame_in = Input(shape=(256,256,3), name='frame_input')
    #normalisation layer
    cnn = Lambda(lambda inputs: frame_in / 255)(frame_in)
    # add cnn layers + activations
    cnn = Conv2D(filters=num_filters[0], kernel_size=(4,4), strides=(4,4), padding='same', activation = 'relu', data_format='channels_last', name = 'Layer_1')(cnn) #input_shape=(64,64,3), data_format='channels_last'), name = 'Layer_1')(frame_in)
    cnn = Conv2D(filters=num_filters[1], kernel_size=(4,4), strides=(4,4), padding='same', activation = 'relu', name = 'Layer_2')(cnn)
    cnn = Conv2D(filters=num_filters[2], kernel_size=(4,4), strides=(2,2), padding='same', activation = 'relu', name = 'Layer_3')(cnn)
    cnn = Conv2D(filters=num_filters[3], kernel_size=(4,4), strides=(2,2), padding='same', activation = 'relu', name = 'Layer_4')(cnn)
    cnn = Conv2D(filters=num_filters[4], kernel_size=(4,4), strides=(1,1), padding='valid', activation = 'relu', name = 'Layer_5')(cnn)
    # flatten
    cnn = Flatten()(cnn)
    #time distributed
    time_dist_cnn = Model(inputs=frame_in, outputs=cnn, name='Time_Distributed_CNN')
    time_dist_0 = TimeDistributed(time_dist_cnn)(video_input)

The error is the same:

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: frame_input:0

I know the problem is almost the same, and stems from the use of a lambda expression, but I'm not sure how to solve it in this context.

1 Answers

If running under eager mode, tensorflow operations will check if the inputs are of type tensorflow.python.framework.ops.EagerTensor and keras ops are implemented as DAGs. So if the inputs to the eager mode is of tensorflow.python.framework.ops.Tensor, then this throws the error.

You can change the input type to EagerTensor by explicity telling tensorflow to run in eager mode for keras by using tf.config.experimental_run_functions_eagerly(True). Adding this statement should solve your issue.

Alternatively, also disabling the eager execution by adding tf.compat.v1.disable_eager_execution() at the top of the program will also runs the program successfully.

For example, this program throws the error you are facing -

Code to reproduce the error-

import numpy as np
import tensorflow as tf
print(tf.__version__)
from tensorflow.keras import layers, losses, models

def get_loss_fcn(w):
    def loss_fcn(y_true, y_pred):
        loss = w * losses.mse(y_true, y_pred)
        return loss
    return loss_fcn

data_x = np.random.rand(5, 4, 1)
data_w = np.random.rand(5, 4)
data_y = np.random.rand(5, 4, 1)

x = layers.Input([4, 1])
w = layers.Input([4])
y = layers.Activation('tanh')(x)
model = models.Model(inputs=[x, w], outputs=y)
loss = get_loss_fcn(model.input[1])

model.compile(loss=loss)
model.fit((data_x, data_w), data_y)

Output -

2.2.0
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
/usr/local/lib/python3.6/dist-packages/tensorflow/python/eager/execute.py in quick_execute(op_name, num_outputs, inputs, attrs, ctx, name)
     59     tensors = pywrap_tfe.TFE_Py_Execute(ctx._handle, device_name, op_name,
---> 60                                         inputs, attrs, num_outputs)
     61   except core._NotOkStatusException as e:

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: input_8:0

During handling of the above exception, another exception occurred:

_SymbolicException                        Traceback (most recent call last)
8 frames
/usr/local/lib/python3.6/dist-packages/tensorflow/python/eager/execute.py in quick_execute(op_name, num_outputs, inputs, attrs, ctx, name)
     72       raise core._SymbolicException(
     73           "Inputs to eager execution function cannot be Keras symbolic "
---> 74           "tensors, but found {}".format(keras_symbolic_tensors))
     75     raise e
     76   # pylint: enable=protected-access

_SymbolicException: Inputs to eager execution function cannot be Keras symbolic tensors, but found [<tf.Tensor 'input_8:0' shape=(None, 4) dtype=float32>]

Solution 1 - Adding this tf.config.experimental_run_functions_eagerly(True) at the top of the program runs the program successfully. Also adding tf.compat.v1.disable_eager_execution() at the top of the progrm to disable eager execution also runs the program successfully.

Fixed code -

import numpy as np
import tensorflow as tf
print(tf.__version__)
from tensorflow.keras import layers, losses, models

tf.config.experimental_run_functions_eagerly(True)

def get_loss_fcn(w):
    def loss_fcn(y_true, y_pred):
        loss = w * losses.mse(y_true, y_pred)
        return loss
    return loss_fcn

data_x = np.random.rand(5, 4, 1)
data_w = np.random.rand(5, 4)
data_y = np.random.rand(5, 4, 1)

x = layers.Input([4, 1])
w = layers.Input([4])
y = layers.Activation('tanh')(x)
model = models.Model(inputs=[x, w], outputs=y)
loss = get_loss_fcn(model.input[1])

model.compile(loss=loss)
model.fit((data_x, data_w), data_y)

print('Done.')

Output -

2.2.0
1/1 [==============================] - 0s 1ms/step - loss: 0.0000e+00
Done.

Solution 2 - Also kindly try the below solution, you can try modifying as below and see if works -

1) Create normalize_input function as follows:

def normalize_input(inputs):
    norm_input = inputs / 255
    return norm_input

2) Modify the Lambda layer as follows:

cnn = tf.keras.layers.Lambda(function=normalize_input)([frame_in])

Hope this answers your question. Happy Learning.

Related