how to fix "OperatorNotAllowedInGraphError " error in Tensorflow 2.0
Asked Answered
S

3

14

I'm learn tensorflow2.0 from official tutorials.I can understand the result from below code.

def square_if_positive(x):
  return [i ** 2 if i > 0 else i for i in x]
square_if_positive(range(-5, 5))

# result
[-5, -4, -3, -2, -1, 0, 1, 4, 9, 16]

But if I change the inputs with tensor not python code, just like this

def square_if_positive(x):
  return [i ** 2 if i > 0 else i for i in x]
square_if_positive(tf.range(-5, 5))

I get below error!!

OperatorNotAllowedInGraphError            Traceback (most recent call last)
<ipython-input-39-6c17f29a3443> in <module>
      2 def square_if_positive(x):
      3     return [i**2 if i > 0 else i for i in x]
----> 4 square_if_positive(tf.range(10))
      5 # measure_graph_size(square_if_positive, range(10))

~/tf2_workspace/tf2.0/lib/python3.6/site-packages/tensorflow_core/python/eager/def_function.py in __call__(self, *args, **kwds)
    437     # This is the first call of __call__, so we have to initialize.
    438     initializer_map = {}
--> 439     self._initialize(args, kwds, add_initializers_to=initializer_map)
    440     if self._created_variables:
    441       try:

~/tf2_workspace/tf2.0/lib/python3.6/site-packages/tensorflow_core/python/eager/def_function.py in _initialize(self, args, kwds, add_initializers_to)
    380     self._concrete_stateful_fn = (
    381         self._stateful_fn._get_concrete_function_internal_garbage_collected(  # pylint: disable=protected-access
--> 382             *args, **kwds))
    383 
    384     def invalid_creator_scope(*unused_args, **unused_kwds):

~/tf2_workspace/tf2.0/lib/python3.6/site-packages/tensorflow_core/python/eager/function.py in _get_concrete_function_internal_garbage_collected(self, *args, **kwargs)
   1793     if self.input_signature:
   1794       args, kwargs = None, None
-> 1795     graph_function, _, _ = self._maybe_define_function(args, kwargs)
   1796     return graph_function
   1797 

~/tf2_workspace/tf2.0/lib/python3.6/site-packages/tensorflow_core/python/eager/function.py in _maybe_define_function(self, args, kwargs)
   2093         graph_function = self._function_cache.primary.get(cache_key, None)
   2094         if graph_function is None:
-> 2095           graph_function = self._create_graph_function(args, kwargs)
   2096           self._function_cache.primary[cache_key] = graph_function
   2097         return graph_function, args, kwargs

~/tf2_workspace/tf2.0/lib/python3.6/site-packages/tensorflow_core/python/eager/function.py in _create_graph_function(self, args, kwargs, override_flat_arg_shapes)
   1984             arg_names=arg_names,
   1985             override_flat_arg_shapes=override_flat_arg_shapes,
-> 1986             capture_by_value=self._capture_by_value),
   1987         self._function_attributes,
   1988         # Tell the ConcreteFunction to clean up its graph once it goes out of

~/tf2_workspace/tf2.0/lib/python3.6/site-packages/tensorflow_core/python/framework/func_graph.py in func_graph_from_py_func(name, python_func, args, kwargs, signature, func_graph, autograph, autograph_options, add_control_dependencies, arg_names, op_return_value, collections, capture_by_value, override_flat_arg_shapes)
    851                                           converted_func)
    852 
--> 853       func_outputs = python_func(*func_args, **func_kwargs)
    854 
    855       # invariant: `func_outputs` contains only Tensors, CompositeTensors,

~/tf2_workspace/tf2.0/lib/python3.6/site-packages/tensorflow_core/python/eager/def_function.py in wrapped_fn(*args, **kwds)
    323         # __wrapped__ allows AutoGraph to swap in a converted function. We give
    324         # the function a weak reference to itself to avoid a reference cycle.
--> 325         return weak_wrapped_fn().__wrapped__(*args, **kwds)
    326     weak_wrapped_fn = weakref.ref(wrapped_fn)
    327 

~/tf2_workspace/tf2.0/lib/python3.6/site-packages/tensorflow_core/python/framework/func_graph.py in wrapper(*args, **kwargs)
    841           except Exception as e:  # pylint:disable=broad-except
    842             if hasattr(e, "ag_error_metadata"):
--> 843               raise e.ag_error_metadata.to_exception(type(e))
    844             else:
    845               raise

OperatorNotAllowedInGraphError: in converted code:

    <ipython-input-37-6c17f29a3443>:3 square_if_positive  *
        return [i**2 if i > 0 else i for i in x]
    /Users/zhangpan/tf2_workspace/tf2.0/lib/python3.6/site-packages/tensorflow_core/python/framework/ops.py:547 __iter__
        self._disallow_iteration()
    /Users/zhangpan/tf2_workspace/tf2.0/lib/python3.6/site-packages/tensorflow_core/python/framework/ops.py:540 _disallow_iteration
        self._disallow_when_autograph_enabled("iterating over `tf.Tensor`")
    /Users/zhangpan/tf2_workspace/tf2.0/lib/python3.6/site-packages/tensorflow_core/python/framework/ops.py:518 _disallow_when_autograph_enabled
        " decorating it directly with @tf.function.".format(task))

    OperatorNotAllowedInGraphError: iterating over `tf.Tensor` is not allowed: AutoGraph did not convert this function. Try decorating it directly with @tf.function.

I can't find any specifications about this error. I think the real reason is not "iterating over tf.Tensor is not allowed" . Becase I can write like this.

@tf.function
def square_if_positive(x):
    for i in x:
        if i>0:
            tf.print(i**2)
        else:
            tf.print(i)
square_if_positive(tf.range(10))

I iterate over tensor just like above code.

So my question is what's the real reason about this error? Any suggestions will help me. I really can't understand this error through I read a lot of materials.

Sorkin answered 11/9, 2019 at 12:12 Comment(0)
C
4

The root cause is that autograph doesn't yet support list comprehensions (primarily because it's difficult to determine the dtype of the result in all cases)

As a workaround, you can use tf.map_fn for the comprehension:

return tf.map_fn(lambda i: i ** 2 if i > 0 else i, x)

For more information please take a look at this issue

Chaechaeronea answered 9/3, 2020 at 16:48 Comment(0)
E
2

In case it helps someone.

I had the same problem with a code that did:

for index, image in enumerate(inputs):
    ... My code ...

The solution was just to do:

index = 0
for image in inputs:
    .... My code ...
    index += 1
Enculturation answered 19/6, 2020 at 9:27 Comment(0)
P
0

I had a similar issue when using tf.range() instead of python's range() for a list comprehension inside a tensorflow graph function. I was training a 3D segmentation neural net and had to use range() for the code to work.

Check the pseudo code below:-

Y         = # [Batch,Height,Width,Depth,Channels]
y_predict = # [B,H,W,D,C,MC_Runs] ; MC_Runs=Monte Carlo Runs

@tf.function
def train_loss(Y,y_predict):
    # calulate loss and return scalar value

@tf.function
def train_step():
    loss = [train_loss(Y, y_predict[:,:,:,:,:,id_])) for id_ in range(MC_RUNS)]
    loss = tf.math.reduce_mean(loss)
Postnatal answered 21/6, 2021 at 10:56 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.