Tensorflow 2.1.0 - оператору вне кода построения функции передается тензор "Graph" - PullRequest
2 голосов
/ 05 марта 2020

Я пытаюсь реализовать недавнюю статью. Часть этой реализации включает переход с tf 1.14 на tf 2.1.0. Код работал с TF 1.14, но больше не работает.


ПРИМЕЧАНИЕ. Если я отключу нетерпеливое выполнение tf.compat.v1.disable_eager_execution(), то код будет работать, как и ожидалось.

Это решение? Я сделал много моделей раньше в TF 2.x , и мне никогда не приходилось отключать активное выполнение для достижения нормальной функциональности.


Я перевел проблему в очень короткая суть, которая показывает, что происходит.

Ссылки и код сначала сопровождаются подробным сообщением об ошибке


Ссылка на Gist - https://gist.github.com/darien-schettler/fd5b25626e9eb5b1330cce670bf9cc17

Код

# version 2.1.0
import tensorflow as tf

# version 1.18.1
import numpy as np


# ######## DEFINE CUSTOM FUNCTION FOR TF LAMBDA LAYER  ######## #
def resize_like(input_tensor, ref_tensor):
    """ Resize an image tensor to the same size/shape as a reference image tensor

    Args:
        input_tensor : (image tensor) Input image tensor that will be resized
        ref_tensor   : (image tensor) Reference image tensor that we want to resize the input tensor to.

    Returns:
        reshaped tensor
    """
    reshaped_tensor = tf.image.resize(images=input_tensor,
                                      size=tf.shape(ref_tensor)[1:3],
                                      method=tf.image.ResizeMethod.NEAREST_NEIGHBOR,
                                      preserve_aspect_ratio=False,
                                      antialias=False,
                                      name=None)
    return reshaped_tensor
# ############################################################# #

# ############ DEFINE MODEL USING TF.KERAS FN API  ############ #

# INPUTS
model_input_1 = tf.keras.layers.Input(shape=(160,160,3))
model_input_2 = tf.keras.layers.Input(shape=(160,160,3))

# OUTPUTS
model_output_1 = tf.keras.layers.Conv2D(filters=64, 
                                        kernel_size=(1, 1), 
                                        use_bias=False,
                                        kernel_initializer='he_normal',
                                        name='conv_name_base')(model_input_1)
model_output_2 = tf.keras.layers.Lambda(function=resize_like,
                                        arguments={'ref_tensor': model_output_1})(model_input_2)

# MODEL
model = tf.keras.models.Model(inputs=[model_input_1, model_input_2],
                                      outputs=model_output_2,
                                      name="test_model")

# ############################################################# #

# ######### TRY TO UTILIZE PREDICT WITH DUMMY INPUT  ########## #

dummy_input = [np.ones((1,160,160,3)), np.zeros((1,160,160,3))]
model.predict(x=dummy_input) # >>>>ERROR OCCURS HERE<<<<

# ############################################################# #

Полная ошибка

>>> model.predict(x=dummy_input) # >>>>ERROR OCCURS HERE<<<<

Traceback (most recent call last):
  File "/Users/<username>/.virtualenvs/<venv-name>/lib/python3.7/site-packages/tensorflow_core/python/eager/execute.py", line 61, in quick_execute
    num_outputs)
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: conv_name_base_1/Identity:0

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/Users/<user-name>/.virtualenvs/<venv-name>/lib/python3.7/site-packages/tensorflow_core/python/keras/engine/training.py", line 1013, in predict
    use_multiprocessing=use_multiprocessing)
  File "/Users/<user-name>/.virtualenvs/<venv-name>/lib/python3.7/site-packages/tensorflow_core/python/keras/engine/training_v2.py", line 498, in predict
    workers=workers, use_multiprocessing=use_multiprocessing, **kwargs)
  File "/Users/<user-name>/.virtualenvs/<venv-name>/lib/python3.7/site-packages/tensorflow_core/python/keras/engine/training_v2.py", line 475, in _model_iteration
    total_epochs=1)
  File "/Users/<user-name>/.virtualenvs/<venv-name>/lib/python3.7/site-packages/tensorflow_core/python/keras/engine/training_v2.py", line 128, in run_one_epoch
    batch_outs = execution_function(iterator)
  File "/Users/<user-name>/.virtualenvs/<venv-name>/lib/python3.7/site-packages/tensorflow_core/python/keras/engine/training_v2_utils.py", line 98, in execution_function
    distributed_function(input_fn))
  File "/Users/<user-name>/.virtualenvs/<venv-name>/lib/python3.7/site-packages/tensorflow_core/python/eager/def_function.py", line 568, in __call__
    result = self._call(*args, **kwds)
  File "/Users/<user-name>/.virtualenvs/<venv-name>/lib/python3.7/site-packages/tensorflow_core/python/eager/def_function.py", line 638, in _call
    return self._concrete_stateful_fn._filtered_call(canon_args, canon_kwds)  # pylint: disable=protected-access
  File "/Users/<user-name>/.virtualenvs/<venv-name>/lib/python3.7/site-packages/tensorflow_core/python/eager/function.py", line 1611, in _filtered_call
    self.captured_inputs)
  File "/Users/<user-name>/.virtualenvs/<venv-name>/lib/python3.7/site-packages/tensorflow_core/python/eager/function.py", line 1692, in _call_flat
    ctx, args, cancellation_manager=cancellation_manager))
  File "/Users/<user-name>/.virtualenvs/<venv-name>/lib/python3.7/site-packages/tensorflow_core/python/eager/function.py", line 545, in call
    ctx=ctx)
  File "/Users/<user-name>/.virtualenvs/<venv-name>/lib/python3.7/site-packages/tensorflow_core/python/eager/execute.py", line 75, in quick_execute
    "tensors, but found {}".format(keras_symbolic_tensors))
tensorflow.python.eager.core._SymbolicException: Inputs to eager execution function cannot be Keras symbolic tensors, but found [<tf.Tensor 'conv_name_base_1/Identity:0' shape=(None, 160, 160, 64) dtype=float32>]

Одним из возможных решений, о котором я подумал, будет замена Лямбда-слой с пользовательским слоем ... кажется, это также решает проблему. Не уверен, что лучшие практики окружают это все же. Код ниже.


# version 2.1.0
import tensorflow as tf

# version 1.18.1
import numpy as np


# ######## DEFINE CUSTOM LAYER DIRECTLY BY SUBCLASSING  ######## #
class ResizeLike(tf.keras.layers.Layer):
    """ tf.keras layer to resize a tensor to the reference tensor shape.

    Attributes:
        keras.layers.Layer: Base layer class.
            This is the class from which all layers inherit.
                -   A layer is a class implementing common neural networks
                    operations, such as convolution, batch norm, etc.
                -   These operations require managing weights,
                    losses, updates, and inter-layer connectivity.
    """
    def __init__(self, **kwargs):
        super().__init__(**kwargs)

    def call(self, inputs, **kwargs):
        """TODO: docstring

        Args:
            inputs (TODO): TODO

        **kwargs:
            TODO

        Returns:
            TODO
        """

        input_tensor, ref_tensor = inputs

        return self.resize_like(input_tensor, ref_tensor)


    def resize_like(self, input_tensor, ref_tensor):
        """ Resize an image tensor to the same size/shape as a reference image tensor

        Args:
            input_tensor: (image tensor) Input image tensor that will be resized
            ref_tensor: (image tensor) Reference image tensor that we want to resize the input tensor to.

        Returns:
            reshaped tensor
        """
        reshaped_tensor = tf.image.resize(images=input_tensor,
                                          size=tf.shape(ref_tensor)[1:3],
                                          method=tf.image.ResizeMethod.NEAREST_NEIGHBOR,
                                          preserve_aspect_ratio=False,
                                          antialias=False)
        return reshaped_tensor
# ############################################################# #

# ############ DEFINE MODEL USING TF.KERAS FN API  ############ #

# INPUTS
model_input_1 = tf.keras.layers.Input(shape=(160,160,3))
model_input_2 = tf.keras.layers.Input(shape=(160,160,3))

# OUTPUTS
model_output_1 = tf.keras.layers.Conv2D(filters=64, 
                                        kernel_size=(1, 1), 
                                        use_bias=False,
                                        kernel_initializer='he_normal',
                                        name='conv_name_base')(model_input_1)
model_output_2 = ResizeLike(name="resize_layer")([model_input_2, model_output_1])

# MODEL
model = tf.keras.models.Model(inputs=[model_input_1, model_input_2],
                                      outputs=model_output_2,
                                      name="test_model")

# ############################################################# #

# ######### TRY TO UTILIZE PREDICT WITH DUMMY INPUT  ########## #

dummy_input = [np.ones((1,160,160,3)), np.zeros((1,160,160,3))]
model.predict(x=dummy_input) # >>>>ERROR OCCURS HERE<<<<

# ############################################################# #

Мысли ??

Заранее спасибо !!

Дайте мне знать, если вы хотите, чтобы я предоставил что-нибудь еще .

1 Ответ

2 голосов
/ 07 марта 2020

Вы можете попробовать следующие шаги:

  1. Изменить resize_like следующим образом:

    def resize_like(inputs):
        input_tensor, ref_tensor = inputs
        reshaped_tensor = tf.image.resize(images=input_tensor,
                                  size=tf.shape(ref_tensor)[1:3],
    
        method=tf.image.ResizeMethod.NEAREST_NEIGHBOR,
                                  preserve_aspect_ratio=False,
                                  antialias=False,
                                  name=None)
        return reshaped_tensor
    
  2. Затем в Lambda слой:

    model_output_2 = tf.keras.layers.Lambda(function=resize_like)([model_input_2, model_output_1])
    
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...