Getting this error in my custom layer using layer subclassing in Tensorflow 2.0 "The first argument to `Layer.call` must always be passed."

14,376

During the call method change the forward pass of batch norms to h=self.bn_1(inputs) . Since you are passing training=True for the whole layer tensorflow will automatically take care of maintaining the same flag for all of it's sublayers and you don't need to pass it explicitly for each of them. But if your application is such that you want to control batch norm differently compared to other layers use h=self.bn_1(inputs, training=True) . And your final return statement is not in correct format and should be like 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)))

So once your model is called with example input of tf.ones(), build will be called to create the batch norm and convolution layers. For conv layer you are using the number of filters same as the input by indexing into the last dimension

Share:
14,376
Abhinav Prakash
Author by

Abhinav Prakash

Updated on June 05, 2022

Comments

  • Abhinav Prakash
    Abhinav Prakash almost 2 years

    I've made this custom layer using layer using Tensorflow 2.0 layer subclassing. I'm trying to make a layer of residual block. But when I add this custom layer in my model through sequential API I'm getting the below error.

    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)
    

    But when I initialize this layer I'm getting the error.

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

    My error logs:

    ---------------------------------------------------------------------------
    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.
    
  • Abhinav Prakash
    Abhinav Prakash almost 4 years
    I've changed my according to your question but now I'm facing new error." TypeError: unsupported operand type(s) for *: 'NoneType' and 'float'"
  • gouthamvgk
    gouthamvgk almost 4 years
    Remove input_shape from your init function. If you are using build function then the first time you call your model with some input, tensorflow will consider that input tensor shape inside the build function. You shouldn't pass the input_shape manually in the init. Also in your build function you are using input_shape[0] which is batch dimension, correct it according to your needs.
  • Abhinav Prakash
    Abhinav Prakash almost 4 years
    Actually this are the instructions that I've to follow.
  • Abhinav Prakash
    Abhinav Prakash almost 4 years
    actually I've to follow certain instructions. Kindly have a look into my colab notebook: colab.research.google.com/drive/… . Thanks
  • gouthamvgk
    gouthamvgk almost 4 years
    see the changed answer
  • Abhinav Prakash
    Abhinav Prakash almost 4 years
    Getting again error while executing in this manner: pk = ResidualBlock() model = tf.keras.Sequential([pk(input_shape=(28, 28, 1), name="residual_block")]) model.summary()
  • gouthamvgk
    gouthamvgk almost 4 years
    pk = ResidualBlock() model = tf.keras.Sequential([pk]) You create the layer without using input_shape and directly use it in sequential