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('architecture\images.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.
CodePudding user response:
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()