Сцепление пользовательских слоев Keras в функциональном стиле - PullRequest
0 голосов
/ 19 марта 2020

Я хочу построить модель, используя tf.keras 'функциональный API. Моя модель довольно большая, поэтому я хотел бы создавать собственные слои, наследуя от tf.keras.layers.Layer. Ниже приведена моя попытка, вдохновленная документацией TensorFlow .

import tensorflow as tf

class Conv2D(tf.keras.layers.Layer):
    def __init__(self):
        super().__init__()

        input_layer = tf.keras.layers.Input(
            shape=(256, 256, 3)
        )
        self.conv = tf.keras.layers.Conv2D(
            filters=16,
            kernel_size=3,
            strides=(1, 1),
            padding="same"
        )(input_layer)

    def call(self, inputs):
        return self.conv(inputs)

outer_input_layer = tf.keras.layers.Input(
    shape=(256, 256, 3)
)
x = Conv2D()(outer_input_layer)

Этот код вылетает со следующей ошибкой.

Traceback (most recent call last):
  File "c:\Users\user\.vscode\extensions\ms-python.python-2020.2.64397\pythonFiles\ptvsd_launcher.py", line 48, in <module>
    main(ptvsdArgs)
  File "c:\Users\user\.vscode\extensions\ms-python.python-2020.2.64397\pythonFiles\lib\python\old_ptvsd\ptvsd\__main__.py", line 432, in main
    run()
  File "c:\Users\user\.vscode\extensions\ms-python.python-2020.2.64397\pythonFiles\lib\python\old_ptvsd\ptvsd\__main__.py", line 316, in run_file
    runpy.run_path(target, run_name='__main__')
  File "C:\Users\user\code\.env\lib\runpy.py", line 263, in run_path
    pkg_name=pkg_name, script_name=fname)
  File "C:\Users\user\code\.env\lib\runpy.py", line 96, in _run_module_code
    mod_name, mod_spec, pkg_name, script_name)
  File "C:\Users\user\code\.env\lib\runpy.py", line 85, in _run_code
    exec(code, run_globals)
  File "c:\Users\user\code\tests.py", line 23, in <module>
    x = Conv2D()(outer_input_layer)
  File "C:\Users\user\code\.env\lib\site-packages\tensorflow_core\python\keras\engine\base_layer.py", line 773, in __call__        
    outputs = call_fn(cast_inputs, *args, **kwargs)
  File "C:\Users\user\code\.env\lib\site-packages\tensorflow_core\python\autograph\impl\api.py", line 237, in wrapper
    raise e.ag_error_metadata.to_exception(e)
TypeError: in converted code:

    c:\Users\user\code\tests.py:18 call  *
        return self.conv(inputs)
    C:\Users\user\code\.env\lib\site-packages\tensorflow_core\python\autograph\impl\api.py:447 converted_call
        f in m.__dict__.values() for m in (collections, pdb, copy, inspect, re)):
    C:\Users\user\code\.env\lib\site-packages\tensorflow_core\python\autograph\impl\api.py:447 <genexpr>
        f in m.__dict__.values() for m in (collections, pdb, copy, inspect, re)):
    C:\Users\user\code\.env\lib\site-packages\tensorflow_core\python\ops\math_ops.py:1351 tensor_equals
        return gen_math_ops.equal(self, other, incompatible_shape_error=False)
    C:\Users\user\code\.env\lib\site-packages\tensorflow_core\python\ops\gen_math_ops.py:3240 equal
        name=name)
    C:\Users\user\code\.env\lib\site-packages\tensorflow_core\python\framework\op_def_library.py:477 _apply_op_helper
        repr(values), type(values).__name__, err))

    TypeError: Expected float32 passed to parameter 'y' of op 'Equal', got 'collections' of type 'str' instead. Error: Expected float32, got 'collections' 
of type 'str' instead.

Что не так с моим подходом?

1 Ответ

1 голос
/ 19 марта 2020

Ни один пользовательский слой не имеет входных слоев. Это не имеет особого смысла. Ввод - это то, что вы передаете слою, когда вызываете его.

Итак:

import tensorflow as tf

class ConvBN(tf.keras.layers.Layer):
    def __init__(self, activation, name):
        super().__init__()

        #here you just "store" the layers, you don't use them
        #you also store any other property you find necessary for the call
        self.conv = tf.keras.layers.Conv2D(
            filters=16,
            kernel_size=3,
            strides=(1, 1),
            padding="same",
            name = name+'_conv'
        )
       self.bn = tf.keras.layers.BatchNormalization(name = name + "_bn")
       self.activation = tf.keras.layers.Activation(activation, name = name + "_act")

    def call(self, inputs):
        #here you "use" the layers with the given input to produce an output
        out = self.conv(inputs)
        out = self.bn(out)
        out = self.activation(out)

        return out

Вы также можете, если не собираетесь использовать «один и тот же слой» более одного раза, создавать более простые блоки:

def convGroup(input_tensor, activation, name):
    out = tf.keras.layers.Conv2D(
            filters=16,
            kernel_size=3,
            strides=(1, 1),
            padding="same",
            name = name+'_conv'
        )(input_tensor)
    out = tf.keras.layers.BatchNormalization(name = name + "_bn")(out)
    out = tf.keras.layers.Activation(activation, name = name + "_act")(out)

    return out
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...