【问题标题】:Getting this error in my custom layer using layer subclassing in Tensorflow 2.0 "The first argument to `Layer.call` must always be passed."在 Tensorflow 2.0 中使用层子类化在我的自定义层中出现此错误“必须始终传递 `Layer.call` 的第一个参数。”
【发布时间】:2020-09-05 03:00:38
【问题描述】:

我使用 Tensorflow 2.0 图层子类化的图层制作了这个自定义图层。我正在尝试制作一层残块。但是当我通过顺序 API 在我的模型中添加这个自定义层时,我得到了 下面的错误。

class ResidualBlock(Layer):

    def __init__(self, **kwargs):
        super(ResidualBlock, self).__init__(**kwargs)

    def build(self, input_shape):
        """
        This method should build the layers according to the above specification. Make sure 
        to use the input_shape argument to get the correct number of filters, and to set the
        input_shape of the first layer in the block.
        """
        self.bn_1 = BatchNormalization(input_shape=input_shape)
        self.conv_1 = Conv2D( input_shape[0],(3,3), padding='SAME')
        self.bn_2 = BatchNormalization()
        self.conv_2 = Conv2D( input_shape[0],(3,3), padding='SAME')






    def call(self, inputs, training=False):
        """
        This method should contain the code for calling the layer according to the above
        specification, using the layer objects set up in the build method.
        """
        h = self.bn_1(training=True)(inputs)
        h = tf.nn.relu(h)
        h = self.conv_1(h)
        h = self.bn_2(training=True)(h)
        h = tf.nn.relu(h)
        h = self.conv_2(h)
        return Add(inputs, h)

但是当我初始化这个层时,我得到了错误。

test_model = tf.keras.Sequential([ResidualBlock(input_shape=(28, 28, 1), name="residual_block")])
test_model.summary()

我的错误日志:

---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-13-991ed1d78e4b> in <module>()
      1 # Test your custom layer - the following should create a model using your layer
      2 
----> 3 test_model = tf.keras.Sequential([ResidualBlock(input_shape=(28, 28, 1), name="residual_block")])
      4 test_model.summary()

5 frames
/usr/local/lib/python3.6/dist-packages/tensorflow/python/autograph/impl/api.py in wrapper(*args, **kwargs)
    263       except Exception as e:  # pylint:disable=broad-except
    264         if hasattr(e, 'ag_error_metadata'):
--> 265           raise e.ag_error_metadata.to_exception(e)
    266         else:
    267           raise

ValueError: in user code:

    <ipython-input-12-3beea3ca10b0>:32 call  *
        h = self.bn_1(training=True)(inputs)
    /usr/local/lib/python3.6/dist-packages/tensorflow/python/keras/engine/base_layer.py:800 __call__  **
        'The first argument to `Layer.call` must always be passed.')

    ValueError: The first argument to `Layer.call` must always be passed.

【问题讨论】:

    标签: python tensorflow tensorflow2.0 keras-layer


    【解决方案1】:

    在调用方法期间,将批处理规范的前向传递更改为 h=self.bn_1(inputs) 。由于您为整个层传递 training=True,因此 tensorflow 将自动为其所有子层维护相同的标志,您无需为每个子层显式传递它。但是,如果您的应用程序想要以不同于其他层的方式控制批规范,请使用 h=self.bn_1(inputs, training=True) 。而且您的最终退货声明格式不正确,应该像Add()([inputs, h])

    class ResidualBlock(Layer):
    
        def __init__(self, **kwargs):
            super(ResidualBlock, self).__init__(**kwargs)
    
        def build(self, input_shape):
            """
            This method should build the layers according to the above specification. Make sure 
            to use the input_shape argument to get the correct number of filters, and to set the
            input_shape of the first layer in the block.
            """
            self.bn_1 = BatchNormalization(input_shape=input_shape)
            self.conv_1 = Conv2D(input_shape[3],(3,3), padding='SAME')
            self.bn_2 = BatchNormalization()
            self.conv_2 = Conv2D(input_shape[3],(3,3), padding='SAME')
    
        def call(self, inputs, training=False):
            """
            This method should contain the code for calling the layer according to the above
            specification, using the layer objects set up in the build method.
            """
            h = self.bn_1(inputs)
            h = tf.nn.relu(h)
            h = self.conv_1(h)
            h = self.bn_2(h)
            h = tf.nn.relu(h)
            h = self.conv_2(h)
            return Add()([inputs, h])
    
    pk = ResidualBlock()
    model = tf.keras.Sequential([pk])
    model(tf.ones((1, 28, 28, 3)))
    

    因此,一旦使用 tf.ones() 的示例输入调用您的模型,就会调用 build 来创建批处理规范和卷积层。对于 conv 层,您通过索引到最后一个维度来使用与输入相同的过滤器数量

    【讨论】:

    • 我已根据您的问题更改了我的设置,但现在我遇到了新错误。" TypeError: unsupported operand type(s) for *: 'NoneType' and 'float'"
    • init 函数中移除 input_shape。如果您使用的是构建函数,那么当您第一次使用一些输入调用模型时,tensorflow 将在构建函数中考虑输入张量形状。您不应该在 init 中手动传递 input_shape。同样在您的构建功能中,您使用的是批处理维度的 input_shape[0],请根据您的需要进行更正。
    • 实际上这是我必须遵循的说明。
    • 实际上我必须遵循某些指示。请查看我的 colab 笔记本:colab.research.google.com/drive/…。谢谢
    • 查看更改后的答案
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-07-11
    • 2021-07-01
    • 2021-04-20
    • 2020-09-19
    • 2017-09-20
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多