ValueError: The first argument to `Layer.call` must always be passed. I want to type this model in subclassing way

Question:

I have some different block and because I have to use shared parameters so I need to implement this model in subclassing form

convolution and identity block

def convolutional_block(x, filter):
    # copy tensor to variable called x_skip
    x_skip = x
    # Layer 1
    x = tf.keras.layers.Conv2D(filter, (1, 1), strides = (2, 2))(x)
    x = tf.keras.layers.BatchNormalization(axis=3)(x)
    x = tf.keras.layers.Activation('relu')(x)
    # Layer 2
    x = tf.keras.layers.Conv2D(filter, (3, 3), padding = 'same')(x)
    x = tf.keras.layers.BatchNormalization(axis=3)(x)
    x = tf.keras.layers.Activation('relu')(x)
    # Layer 3
    x = tf.keras.layers.Conv2D(filter * 4, (1, 1))(x)
    x = tf.keras.layers.BatchNormalization(axis=3)(x)
    # Processing Residue with conv(1,1)
    x_skip = tf.keras.layers.Conv2D(filter * 4, (1, 1), strides = (2, 2))(x_skip)
    # Add Residue
    x = tf.keras.layers.Add()([x, x_skip])
    x = tf.keras.layers.Activation('relu')(x)
    return x

def identity_block(x, filter, name):
    # copy tensor to variable called x_skip
    x_skip = x
    # Layer 1
    x = tf.keras.layers.Conv2D(filter, (1, 1))(x)
    x = tf.keras.layers.BatchNormalization(axis=3)(x)
    x = tf.keras.layers.Activation('relu')(x)
    # Layer 2
    x = tf.keras.layers.Conv2D(filter, (3, 3), padding = 'same')(x)
    x = tf.keras.layers.BatchNormalization(axis=3)(x)
    x = tf.keras.layers.Activation('relu')(x)
    # Layer 3
    x = tf.keras.layers.Conv2D(filter * 4, (1, 1))(x)
    x = tf.keras.layers.BatchNormalization(axis=3)(x)
    # Add Residue
    x = tf.keras.layers.Add()([x, x_skip])
    x = tf.keras.layers.Activation('relu', name=f'identity_{name}')(x)
    return x

Mutex block

class MutexAttentionBlock(tf.keras.layers.Layer):
    def __init__(self):
        super(MutexAttentionBlock, self).__init__()
        self.softmax = tf.keras.layers.Activation('softmax')
        self.multiply = tf.keras.layers.Multiply()

    def call(self, x, y):
        distance = tf.math.square(tf.math.subtract(x, y))
        x = tf.keras.layers.Reshape((-1, distance.shape[-1]))(distance)
        x = self.softmax(x)
        x = tf.keras.layers.Reshape((distance[1], distance[2], distance[3]))(x)
        f_am = self.multiply(x, y)
        return f_am

Fusion block

class FuseAttentionBlock(tf.keras.layers.Layer):
    def __init__(self):
        super(FuseAttentionBlock, self).__init__()
        self.first_add = tf.keras.layers.Add()
        self.global_avg_pool = tf.keras.layers.GlobalAveragePooling2D()
        self.global_max_pool = tf.keras.layers.GlobalMaxPooling2D()
        self.second_add = tf.keras.layers.Add()
        self.concat = tf.keras.layers.Concatenate(axis=0)
        self.softmax = tf.keras.layers.Softmax(axis=0)
        self.first_multiply = tf.keras.layers.Multiply()
        self.second_multiply = tf.keras.layers.Multiply()
        self.third_add = tf.keras.layers.Add()
    
    def call(self, f_am, y):
        f_mix = self.first_add([f_am, y])

        x = self.global_avg_pool(f_mix)
        y = self.global_max_pool(f_mix)

        x = self.second_add([x, y])

        for i in range(2):
            x = tf.keras.layers.Dense(32)(x)
            x = tf.keras.layers.BatchNormalization()(x)
            x = tf.keras.layers.Activation('relu')(x)
        
        m = tf.keras.layers.Dense(f_am.shape[-1])(x)
        n = tf.keras.layers.Dense(y.shape[-1])(x)

        concated = self.concat([m, n], axis=0)

        attention_weights = self.softmax(concated)

        f_am = self.first_multiply([f_am, attention_weights])
        y = self.second_multiply([y, attention_weights])

        f_fm = self.third_add([f_am, y])
        return f_fm

Final Architecture

class MutexAttentionResModel(tf.keras.models.Model):
    def __init__(self, shape, num_classes):
        super(MutexAttentionResModel, self).__init__()
        self.shape=shape
        self.num_classes = num_classes

        input_img = tf.keras.layers.Input(self.shape)
        x = tf.keras.layers.ZeroPadding2D((3, 3))(input_img)
        x = tf.keras.layers.Conv2D(64, kernel_size=7, strides=2, padding='same')(x)
        x = tf.keras.layers.BatchNormalization()(x)
        x = tf.keras.layers.Activation('relu')(x)
        x = tf.keras.layers.MaxPool2D(pool_size=3, strides=2, padding='same')(x)
        self.first_layer = tf.keras.Model(inputs=input_img, outputs=x)

        input_second_layer = self.first_layer.output
        x = convolutional_block(input_second_layer, 64)
        for i in range(2):
            x = identity_block(x, 64, name=f'2_{i}')
        self.second_layer = tf.keras.Model(inputs=input_second_layer, outputs=x)

        input_third_layer = self.second_layer.output
        x = convolutional_block(input_third_layer, 128)
        for i in range(3):
            x = identity_block(x, 128, name=f'3_{i}')
        self.third_layer = tf.keras.Model(inputs=input_third_layer, outputs=x)

        input_fourth_layer = self.third_layer.output
        x = convolutional_block(input_fourth_layer, 256)
        for i in range(5):
            x = identity_block(x, 256, name=f'4_{i}')
        self.fourth_layer = tf.keras.Model(inputs=input_fourth_layer, outputs=x)

        input_fifth_layer = self.fourth_layer.output
        x = convolutional_block(input_fifth_layer, 512)
        for i in range(2):
            x = identity_block(x, 512, name=f'5_{i}')
        self.fifth_layer = tf.keras.Model(inputs=input_fifth_layer, outputs=x)

        self.first_mutex_attention_block = MutexAttentionBlock()
        self.first_fuse_attention_block = FuseAttentionBlock()

        self.second_mutex_attention_block = MutexAttentionBlock()
        self.second_fuse_attention_block = FuseAttentionBlock()

        self.third_mutex_attention_block = MutexAttentionBlock()
        self.third_fuse_attention_block = FuseAttentionBlock()

        self.fourth_mutex_attention_block = MutexAttentionBlock()
        self.fourth_fuse_attention_block = FuseAttentionBlock()

        self.fifth_mutex_attention_block = MutexAttentionBlock()
        self.fifth_fuse_attention_block = FuseAttentionBlock()

        self.global_max_pool = tf.keras.layers.GlobalMaxPooling2D()

        self.first_dense = tf.keras.layers.Dense(self.num_classes, activation='softmax')
        self.second_dense = tf.keras.layers.Dense(self.num_classes, activation='softmax')

    def call(self, pos_input, neg_input):
        x = self.first_layer(pos_input)
        y = self.first_layer(neg_input)
        f_am = self.first_mutex_attention_block(x, y)
        y = self.first_fuse_attention_block(f_am, y)

        x = self.second_layer(x)
        y = self.second_layer(y)
        f_am = self.second_mutex_attention_block(x, y)
        y = self.second_fuse_attention_block(f_am, y)

        x = self.third_layer(x)
        y = self.third_layer(y)
        f_am = self.third_mutex_attention_block(x, y)
        y = self.third_fuse_attention_block(f_am, y)

        x = self.fourth_layer(x)
        y = self.fourth_layer(y)
        f_am = self.fourth_mutex_attention_block(x, y)
        y = self.fourth_fuse_attention_block(f_am, y)

        x = self.fifth_layer(x)
        y = self.fifth_layer(y)
        f_am = self.fifth_mutex_attention_block(x, y)
        y = self.fifth_fuse_attention_block(f_am, y)

        x_flatten = tf.keras.layers.Flatten(name='x_flatten')(x)
        y_flatten = tf.keras.layers.Flatten(name='y_flatten')(y)

        x = self.global_max_pool(x)
        y = self.global_max_pool(y)

        x = self.first_dense(x)
        y = self.second_dense(y)

        return x, y, x_flatten, y_flatten

Try to get summary of subclassing model

model = MutexAttentionResModel(shape = config.IMG_SHAPE, num_classes = 2)

image = plt.imread('architectureimages.jpg')
image = tf.image.resize(image,[224,224])
image = tf.cast(image,dtype = tf.float32)

image = tf.expand_dims(image,0)
output = model(ct_input= image,mutex_input = image)
print(image.shape)
model.summary()

I take this error I don’t have any Idea what I have to do.

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

Asked By: Novinnam

||

Answers:

Try this one, but I will tell you the reason behind this error, this error occurs when you use one name for the same two layers and send it to the keras.Model, I have changed the code a little bit, and don’t return a Model output at each layer just return the x it is the same as you were doing but the complexity of that is low…

def element_substraction(inputs):
    (x, y) = inputs
    return tf.math.pow(tf.math.subtract(x, y), 2)

def mutex_attention_block(x, y):
    not_reshaped = tf.keras.layers.Lambda(element_substraction)([x, y])
    x = tf.keras.layers.Reshape((-1, not_reshaped.shape[-1]))(not_reshaped)
    
    x = tf.keras.layers.Activation('softmax')(x)

    target_shape = (not_reshaped.shape[-3], not_reshaped.shape[-2], not_reshaped.shape[-1])
    x = tf.keras.layers.Reshape(target_shape)(x)
    f_am = tf.keras.layers.Multiply()([x, y])
    return f_am
def binary_attention(inputs):
    (a_c, f_am, y) = inputs
    return (a_c * f_am + (1 - a_c) * y)

def fuse_attention_block(f_am, y, channel_size):
    f_mix = tf.keras.layers.Add()([f_am, y])

    x = tf.keras.layers.GlobalAveragePooling2D()(f_mix)
    y = tf.keras.layers.GlobalMaxPooling2D()(f_mix)

    x = tf.keras.layers.Add()([x, y])

    for i in range(2):
        x = tf.keras.layers.Dense(32)(x)
        x = tf.keras.layers.BatchNormalization()(x)
        x = tf.keras.layers.Activation('relu')(x)

    m = tf.keras.layers.Dense(channel_size)(x)
    n = tf.keras.layers.Dense(channel_size)(x)

    concated_layer = tf.keras.layers.Concatenate(axis=0)([m, n])

    a_c = tf.keras.layers.Softmax(axis=0)(concated_layer)
    f_om = tf.keras.layers.Lambda(binary_attention)([a_c, f_am, y])
    return f_om
def convolutional_block(x, filter):
    # copy tensor to variable called x_skip
    x_skip = x
    # Layer 1
    x = tf.keras.layers.Conv2D(filter, (1, 1), strides = (2, 2))(x)
    x = tf.keras.layers.BatchNormalization(axis=3)(x)
    x = tf.keras.layers.Activation('relu')(x)
    # Layer 2
    x = tf.keras.layers.Conv2D(filter, (3, 3), padding = 'same')(x)
    x = tf.keras.layers.BatchNormalization(axis=3)(x)
    x = tf.keras.layers.Activation('relu')(x)
    # Layer 3
    x = tf.keras.layers.Conv2D(filter * 4, (1, 1))(x)
    x = tf.keras.layers.BatchNormalization(axis=3)(x)
    # Processing Residue with conv(1,1)
    x_skip = tf.keras.layers.Conv2D(filter * 4, (1, 1), strides = (2, 2))(x_skip)
    # Add Residue
    x = tf.keras.layers.Add()([x, x_skip])
    x = tf.keras.layers.Activation('relu')(x)
    return x

def identity_block(x, filter):
    # copy tensor to variable called x_skip
    x_skip = x
    # Layer 1
    x = tf.keras.layers.Conv2D(filter, (1, 1), padding = 'same')(x)
    x = tf.keras.layers.BatchNormalization(axis=3)(x)
    x = tf.keras.layers.Activation('relu')(x)
    # Layer 2
    x = tf.keras.layers.Conv2D(filter, (3, 3), padding = 'same')(x)
    x = tf.keras.layers.BatchNormalization(axis=3)(x)
    x = tf.keras.layers.Activation('relu')(x)
    # Layer 3
    x = tf.keras.layers.Conv2D(filter * 4, (1, 1), padding = 'same')(x)
    x = tf.keras.layers.BatchNormalization(axis=3)(x)
    # Add Residue
    x = tf.keras.layers.Add()([x, x_skip])
    x = tf.keras.layers.Activation('relu')(x)
    return x
def first_block(shape):
    x_input = tf.keras.layers.Input(shape)
    x = tf.keras.layers.ZeroPadding2D((3, 3))(x_input)
    x = tf.keras.layers.Conv2D(64, kernel_size=7, strides=2)(x)
    x = tf.keras.layers.BatchNormalization()(x)
    x = tf.keras.layers.Activation('relu')(x)
    x = tf.keras.layers.ZeroPadding2D()(x)
    x = tf.keras.layers.MaxPool2D(pool_size=3, strides=2)(x)
    return x, x_input

def second_block(x_input):
    x = convolutional_block(x_input, 64)
    for i in range(2):
        x = identity_block(x, 64)
    return x

def third_block(x_input):
    x = convolutional_block(x_input, 128)
    for i in range(3):
        x = identity_block(x, 128)
    return x

def fourth_block(x_input):
    x = convolutional_block(x_input, 256)
    for i in range(5):
        x = identity_block(x, 256)
    return x

def fifth_block(x_input):
    x = convolutional_block(x_input, 512)
    for i in range(2):
        x = identity_block(x, 512)
    return x
tf.keras.backend.clear_session()
shape= (224,224,3)
x, pos_input = first_block(shape)
y, neg_input = first_block(shape)
f_am = mutex_attention_block(x, y)
y = fuse_attention_block(f_am, y, channel_size=64)
# second mutex attention res layer
x = second_block(x)
y = second_block(y)
f_am = mutex_attention_block(x, y)
y = fuse_attention_block(f_am, y, channel_size=256)
# third mutex attention res layer
x = third_block(x)
y = third_block(y)
f_am = mutex_attention_block(x, y)
y = fuse_attention_block(f_am, y, channel_size=512)
# fourth mutex attention res layer
x = fourth_block(x)
y = fourth_block(y)
f_am = mutex_attention_block(x, y)
y = fuse_attention_block(f_am, y, channel_size=1024)
# fifth mutex attention res layer
x = fifth_block(x)
y = fifth_block(y)
f_am = mutex_attention_block(x, y)
y = fuse_attention_block(f_am, y, channel_size=2048)

x = tf.keras.layers.GlobalMaxPooling2D(name='final_global_maxpool_x')(x)
y = tf.keras.layers.GlobalMaxPooling2D(name='final_global_maxpool_y')(y)

x = tf.keras.layers.Dense(2, name='final_dense_x')(x)
y = tf.keras.layers.Dense(2, name='final_dense_y')(y)

x = tf.keras.layers.Activation('softmax', name='final_softmax_x')(x)
y = tf.keras.layers.Activation('softmax', name='final_softmax_y')(y)
model = keras.Model(inputs=[pos_input,neg_input], outputs=[x,y])
model.summary()
Answered By: Mohammad Ahmed
Categories: questions Tags: , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.