Help with building custom model

I’m trying to build a custom model by subclassing the Model class, as shown in the videos, but when I call model.summary(), I keep getting this error:

ValueError: This model has not yet been built. Build the model first by calling `build()` or calling `fit()` with some data, or specify an `input_shape` argument in the first layer(s) for automatic build.

and I cannot train either.

I suspect it has to do with passing input shape to the custom model, which I haven’t seen Laurence doing in the resnet video. I tried adding Input layer in the init() function, in the call() function, adding ‘input_shape’ parameter and using build function, but nothing works. Can someone please help me with this?

Here is my code:

from tensorflow.keras.layers import Conv2D, Dense, Input, MaxPooling2D

class CustomModel(tf.keras.Model):
    def __init__(self, filters, kernel_size, pool_size, num_layers, input_shape, **kwargs):
        super().__init__(**kwargs)
        self.shape = input_shape
        self.conv = [Conv2D(filters=filters, kernel_size=kernel_size, activation='relu') for layer in range(num_layers)]
        self.pool = [MaxPooling2D(pool_size=pool_size) for layer in range(num_layers)]
#         self.conv.insert(0, Conv2D(filters=filters, kernel_size=kernel_size, input_shape=self.shape, activation='relu')) didn't work
        self.input_layer = Input(shape=self.shape)
    
    # def build(self, input_shape): 
       #  super().build(input_shape)
        
    def call(self, x):
        x = self.input_layer(x)
        for conv, pool in zip(self.conv, self.pool):
            x = conv(x)
            x = pool(x)
        
        return x
    
model = CustomModel(32, 3, 2, 2, (28, 28, 1))
# model.build((None, 28, 28, 1))
model.compile(loss='sparse_categorical_crossentropy', optimizer='adam')
model.summary()

Hi @Lakshmi_Narayana,
You haven’t described the operation that will be performed by the build method.

Hi @Arif_Hassan ,
The error message wanted me to use it for building the model. I think it was done to pass the input shape. but it didn’t work.

It would help if you defined the layer’s weights and then called ‘super().build(input_shape)’ to finalize your building process. You can follow the given link to grab the idea
To understand build

Regards
Arif

I’m not using any custom layers here, I’m just trying to build a model with existing layers. Also, I don’t think build is necessary as it is not shown in the videos for building models. I just want to know how to pass the input shape to the custom model.

Yes “build” method is not compulsory. You can check this link, I have mentioned this.

When you define a custom layer in TensorFlow using the tf.keras.layers.Layer class, specify the input_shape in the constructor to inform the expected shape of the input data. To pass the input shape to a custom model in TensorFlow, you can either specify the input shape when creating an instance of the model or use the tf.keras.Input layer to define the input shape dynamically.

You have the option to provide the input_shape parameter during the instantiation of your custom layer. This parameter is not mandatory but proves useful when designing the layer’s architecture, particularly if the layer’s functionality relies on characteristics of the input data shape.

TensorFlow automatically invokes the build method the first time the layer is utilized, providing the real input shape as an argument. If you omitted the input_shape in the constructor, you can obtain the input shape by extracting it from the input_shape argument within the build method.

Within the build method, you can leverage the input_shape details to appropriately initialize the layer’s weights. For example, in the case of a dense layer, the quantity of units in the output would be contingent on the final dimension of the input shape.

Model link

Input

Hello Lakshmi,

Is this assignment from the CustomCallback section ungraded lab??

Can you please share screenshot of the error you get when you run your model algorithm??

Based on the error what you have shown, seems you only made model algorithm without building any model which requires you to use model.fit() and then call your model with your CustomCallback.

Here is a link about how to create your own callback

STEPS TO CREATE YOUR OWN CALLBACK

  1. Global methods
  2. Batch-level methods for training/testing/predicting
  3. Epoch-level methods (training only)
  4. Now you create your own class using keras CustomCallback(keras.callbacks.Callback)
  5. Then in your model fit you recall callback as your CustomCallback into your model algorithm.

Please note the code functions you have used def init(self, schedule)
is to show how a custom Callback can be used to dynamically change the learning rate of the optimizer during the course of training. where in again model.fit() is required for your CustomCallback to work.

Please refer the link I have sent. It should help you understand better. Try again after reviewing the link.
If you still running into any error, let me know.

Happy Learning!!!

Regards
DP

Hi @Arif_Hassan , I tried overriding the build function with input shape as follows:

from tensorflow.keras.layers import Conv2D, Dense, Input, MaxPooling2D

class CustomModel(tf.keras.Model):
    def __init__(self, filters, kernel_size, pool_size, num_layers, input_shape, **kwargs):
        super().__init__(**kwargs)
        self.shape = input_shape
        self.conv = [Conv2D(filters=filters, kernel_size=kernel_size, activation='relu') for layer in range(num_layers)]
        self.pool = [MaxPooling2D(pool_size=pool_size) for layer in range(num_layers)]
#         self.conv.insert(0, Conv2D(filters=filters, kernel_size=kernel_size, input_shape=self.shape, activation='relu'))
    
    def build(self):
        super().build(self.shape)
        
    def call(self, inputs):
        x = inputs
        for conv, pool in zip(self.conv, self.pool):
            x = conv(x)
            x = pool(x)
        
        return x
    
model = CustomModel(32, 3, 2, 2, (28, 28, 1)) #, inputs=Input(shape=(28, 28, 1)))
model.compile(loss='sparse_categorical_crossentropy', optimizer='adam')
model.summary()

but it gives the following error:

ValueError: This model has not yet been built. Build the model first by calling `build()` or calling `fit()` with some data, or specify an `input_shape` argument in the first layer(s) for automatic build.

I also saw that model accepts inputs object as argument and tried passing it while instantiating, but I get the following error:

TypeError: ('Keyword argument not understood:', 'inputs')

Here is the code with this change:

from tensorflow.keras.layers import Conv2D, Dense, Input, MaxPooling2D

class CustomModel(tf.keras.Model):
    def __init__(self, filters, kernel_size, pool_size, num_layers, **kwargs):
        super().__init__(**kwargs)
        self.conv = [Conv2D(filters=filters, kernel_size=kernel_size, activation='relu') for layer in range(num_layers)]
        self.pool = [MaxPooling2D(pool_size=pool_size) for layer in range(num_layers)]
#         self.conv.insert(0, Conv2D(filters=filters, kernel_size=kernel_size, input_shape=self.shape, activation='relu'))
    
        
    def call(self, inputs):
        x = inputs
        for conv, pool in zip(self.conv, self.pool):
            x = conv(x)
            x = pool(x)
        
        return x
    
model = CustomModel(32, 3, 2, 2, inputs=Input(shape=(28, 28, 1)))
model.compile(loss='sparse_categorical_crossentropy', optimizer='adam')
model.summary()

This is not an assignment @Deepti_Prasad, I am trying to build my own custom function from the videos, but I have trouble passing the input shape to build the model.

Your codes are incorrect. Please refer the link sent to you in the previous comment and see if you applied the right model algorithm for input shape.

Regards
DP