Aymal Khan
Aymal Khan

Reputation: 289

Keras Creating CNN Model "The added layer must be an instance of class Layer"

from tensorflow.keras.layers import Conv2D, MaxPooling2D, BatchNormalization
from tensorflow.keras.layers import Dropout, Flatten, Input, Dense

def create_model():

    def add_conv_block(model, num_filters):

        model.add(Conv2D(num_filters, 3, activation='relu', padding='same'))
        model.add(BatchNormalization())
        model.add(Conv2D(num_filters, 3, activation='relu', padding='valid'))
        model.add(MaxPooling2D(pool_size=2))
        model.add(Dropout(0.2))

        return model

    model = tf.keras.models.Sequential()
    model.add(Input(shape=(32, 32, 3)))

    model = add_conv_block(model, 32)
    model = add_conv_block(model, 64)
    model = add_conv_block(model, 128)

    model.add(Flatten())
    model.add(Dense(3, activation='softmax'))

    model.compile(loss='categorical_crossentropy', optimizer='adam', metrics=['accuracy'])
    return model

model = create_model()
model.summary()

enter image description here

Upvotes: 2

Views: 1850

Answers (2)

Marco Cerliani
Marco Cerliani

Reputation: 22031

I think that the problem is related to the TF version... however I suggest u this implementation. In this way, you can specify the input_shape in the first layer of the sequential model and override the problem

def create_model():

    def add_conv_block(model, num_filters, input_shape=None):

        if input_shape:
            model.add(Conv2D(num_filters, 3, activation='relu', padding='same', input_shape=input_shape))
        else:
            model.add(Conv2D(num_filters, 3, activation='relu', padding='same'))

        model.add(BatchNormalization())
        model.add(Conv2D(num_filters, 3, activation='relu', padding='valid'))
        model.add(MaxPooling2D(pool_size=2))
        model.add(Dropout(0.2))

        return model

    model = tf.keras.models.Sequential()
    model = add_conv_block(model, 32, input_shape=(32, 32, 3))
    model = add_conv_block(model, 64)
    model = add_conv_block(model, 128)

    model.add(Flatten())
    model.add(Dense(3, activation='softmax'))

    model.compile(loss='categorical_crossentropy', optimizer='adam', metrics=['accuracy'])

    return model

model = create_model()
model.summary() 

Upvotes: 1

jkr
jkr

Reputation: 19310

The solution is to use InputLayer instead of Input. InputLayer is meant to be used with Sequential models. You can also omit the InputLayer entirely and specify input_shape in the first layer of the sequential model.

Input is meant to be used with the TensorFlow Keras functional API, not the sequential API.

from tensorflow.keras.layers import Conv2D, MaxPooling2D, BatchNormalization
from tensorflow.keras.layers import Dropout, Flatten, InputLayer, Dense

def create_model():

    def add_conv_block(model, num_filters):

        model.add(Conv2D(num_filters, 3, activation='relu', padding='same'))
        model.add(BatchNormalization())
        model.add(Conv2D(num_filters, 3, activation='relu', padding='valid'))
        model.add(MaxPooling2D(pool_size=2))
        model.add(Dropout(0.2))

        return model

    model = tf.keras.models.Sequential()
    model.add(InputLayer((32, 32, 3)))

    model = add_conv_block(model, 32)
    model = add_conv_block(model, 64)
    model = add_conv_block(model, 128)

    model.add(Flatten())
    model.add(Dense(3, activation='softmax'))

    model.compile(loss='categorical_crossentropy', optimizer='adam', metrics=['accuracy'])
    return model

model = create_model()
model.summary()

Upvotes: 2

Related Questions