OperatorNotAllowedInGraphError 仍然存在,启用了急切执行并添加了装饰器

OperatorNotAllowedInGraphError still there with eager execution enabled and decorator added

我正在努力在 tensorflow 中重现一个简单的代码。

我有自己定义的函数用作我的模型的指标。

这是一个简单的三元组损失函数(稍作修改),但如果我使用普通的损失函数,问题仍然是一样的。

import pandas as pd
import numpy as np

import tensorflow as tf

from tensorflow.keras.activations import sigmoid
from tensorflow.keras import backend
from tensorflow.keras.models import Model, Sequential
from tensorflow.keras.layers import Input, Embedding, Flatten, Dense, Dropout, Lambda, dot, concatenate


@tf.function
def bpr_triplet_loss(inputs):

    anchor_latent, positive_item_latent, negative_item_latent  = inputs

    # BPR loss
    loss = 1.0 - backend.sigmoid(
        backend.sum(anchor_latent * positive_item_latent, axis=-1, keepdims=True) -
        backend.sum(anchor_latent * negative_item_latent, axis=-1, keepdims=True))

    return loss

def getModel(n_users, n_items, emb_dim = 20):

    # Input Layers
    user_input = Input(shape=[1], name = 'user_input')
    pos_item_input = Input(shape=[1], name = 'pos_item_input')
    neg_item_input = Input(shape=[1], name = 'neg_item_input')

    # Embedding Layers
    # Shared embedding layer for positive and negative items
    user_embedding = Embedding(output_dim=emb_dim, input_dim=n_users + 1, input_length=1, name='user_emb')(user_input)
    item_embedding = Embedding(output_dim=emb_dim, input_dim=n_items + 1, input_length=1, name='item_emb')

    pos_item_embedding = item_embedding(pos_item_input)
    neg_item_embedding = item_embedding(neg_item_input)

    user_vecs = Flatten()(user_embedding)
    pos_item_vecs = Flatten()(pos_item_embedding)
    neg_item_vecs = Flatten()(neg_item_embedding)

    # Triplet loss function 
    output = concatenate([user_vecs, pos_item_vecs, neg_item_vecs])
    loss = Lambda(bpr_triplet_loss, (1,))(output)

    model = Model(inputs=[anchor, positive, negative], outputs=loss)
    model.compile(optimizer='Adam', loss='mse',
                  metrics=["mae"])

    # Define and Compile Model
    #model = Model(inputs = [user_input, pos_item_input, neg_item_input], outputs = output)
    #model.compile(optimizer='Adam', loss=bpr_triplet_loss, metrics=[bpr_triplet_loss])

    return model

model = getModel(n_users, n_items) # 6706, 3040

当我 运行 这段代码时,我得到以下(开始令人沮丧的)错误

---------------------------------------------------------------------------
OperatorNotAllowedInGraphError            Traceback (most recent call last)
/opt/conda/lib/python3.7/site-packages/tensorflow_core/python/keras/engine/base_layer.py in __call__(self, inputs, *args, **kwargs)
    841                   with auto_control_deps.AutomaticControlDependencies() as acd:
--> 842                     outputs = call_fn(cast_inputs, *args, **kwargs)
    843                     # Wrap Tensors in `outputs` in `tf.identity` to avoid

/opt/conda/lib/python3.7/site-packages/tensorflow_core/python/keras/layers/core.py in call(self, inputs, mask, training)
    794     with variable_scope.variable_creator_scope(self._variable_creator):
--> 795       return self.function(inputs, **arguments)
    796 

/opt/conda/lib/python3.7/site-packages/tensorflow_core/python/eager/def_function.py in __call__(self, *args, **kwds)
    456     tracing_count = self._get_tracing_count()
--> 457     result = self._call(*args, **kwds)
    458     if tracing_count == self._get_tracing_count():

/opt/conda/lib/python3.7/site-packages/tensorflow_core/python/eager/def_function.py in _call(self, *args, **kwds)
    502       initializer_map = object_identity.ObjectIdentityDictionary()
--> 503       self._initialize(args, kwds, add_initializers_to=initializer_map)
    504     finally:

/opt/conda/lib/python3.7/site-packages/tensorflow_core/python/eager/def_function.py in _initialize(self, args, kwds, add_initializers_to)
    407         self._stateful_fn._get_concrete_function_internal_garbage_collected(  # pylint: disable=protected-access
--> 408             *args, **kwds))
    409 

/opt/conda/lib/python3.7/site-packages/tensorflow_core/python/eager/function.py in _get_concrete_function_internal_garbage_collected(self, *args, **kwargs)
   1847       args, kwargs = None, None
-> 1848     graph_function, _, _ = self._maybe_define_function(args, kwargs)
   1849     return graph_function

/opt/conda/lib/python3.7/site-packages/tensorflow_core/python/eager/function.py in _maybe_define_function(self, args, kwargs)
   2149         if graph_function is None:
-> 2150           graph_function = self._create_graph_function(args, kwargs)
   2151           self._function_cache.primary[cache_key] = graph_function

/opt/conda/lib/python3.7/site-packages/tensorflow_core/python/eager/function.py in _create_graph_function(self, args, kwargs, override_flat_arg_shapes)
   2040             override_flat_arg_shapes=override_flat_arg_shapes,
-> 2041             capture_by_value=self._capture_by_value),
   2042         self._function_attributes,

/opt/conda/lib/python3.7/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)
    914 
--> 915       func_outputs = python_func(*func_args, **func_kwargs)
    916 

/opt/conda/lib/python3.7/site-packages/tensorflow_core/python/eager/def_function.py in wrapped_fn(*args, **kwds)
    357         # the function a weak reference to itself to avoid a reference cycle.
--> 358         return weak_wrapped_fn().__wrapped__(*args, **kwds)
    359     weak_wrapped_fn = weakref.ref(wrapped_fn)

/opt/conda/lib/python3.7/site-packages/tensorflow_core/python/framework/func_graph.py in wrapper(*args, **kwargs)
    904             if hasattr(e, "ag_error_metadata"):
--> 905               raise e.ag_error_metadata.to_exception(e)
    906             else:

OperatorNotAllowedInGraphError: in converted code:

    <ipython-input-2-d2d9c7117621>:15 bpr_triplet_loss  *
        anchor_latent, positive_item_latent, negative_item_latent  = inputs
    /opt/conda/lib/python3.7/site-packages/tensorflow_core/python/framework/ops.py:547 __iter__
        self._disallow_iteration()
    /opt/conda/lib/python3.7/site-packages/tensorflow_core/python/framework/ops.py:540 _disallow_iteration
        self._disallow_when_autograph_enabled("iterating over `tf.Tensor`")
    /opt/conda/lib/python3.7/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.


During handling of the above exception, another exception occurred:

TypeError                                 Traceback (most recent call last)
<ipython-input-8-083f67ca66a0> in <module>
----> 1 model = getModel(n_users, n_items)

<ipython-input-6-75edf8b5cf85> in getModel(n_users, n_items, emb_dim)
     20     # Triplet loss function
     21     output = concatenate([user_vecs, pos_item_vecs, neg_item_vecs])
---> 22     loss = Lambda(bpr_triplet_loss, (1,))(output)
     23 
     24     model = Model(inputs=[anchor, positive, negative], outputs=loss)

/opt/conda/lib/python3.7/site-packages/tensorflow_core/python/keras/engine/base_layer.py in __call__(self, inputs, *args, **kwargs)
    852                               'dynamic. Pass `dynamic=True` to the class '
    853                               'constructor.\nEncountered error:\n"""\n' +
--> 854                               str(e) + '\n"""')
    855           else:
    856             # We will use static shape inference to return symbolic tensors

TypeError: You are attempting to use Python control flow in a layer that was not declared to be dynamic. Pass `dynamic=True` to the class constructor.
Encountered error:
"""
in converted code:

    <ipython-input-2-d2d9c7117621>:15 bpr_triplet_loss  *
        anchor_latent, positive_item_latent, negative_item_latent  = inputs
    /opt/conda/lib/python3.7/site-packages/tensorflow_core/python/framework/ops.py:547 __iter__
        self._disallow_iteration()
    /opt/conda/lib/python3.7/site-packages/tensorflow_core/python/framework/ops.py:540 _disallow_iteration
        self._disallow_when_autograph_enabled("iterating over `tf.Tensor`")
    /opt/conda/lib/python3.7/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.

"""

note tf.executing_eagerly() 给出 True 正如我在 Tensorflow 2.0.0

报错信息有误,是报错的bug。

主要问题是 autograph 当前不处理张量解包。它隐藏在多层堆栈跟踪中,但这是指向错误的行:


    <ipython-input-2-d2d9c7117621>:15 bpr_triplet_loss  *
        anchor_latent, positive_item_latent, negative_item_latent  = inputs

所以你必须手动解压张量:anchor_latent, positive_item_latent, negative_item_latent = tf.unstack(inputs)