我有一些不同的块,因为我必须使用共享参数,所以我需要以子类形式实现此模型
卷积和恒等块
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
互斥锁块
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
融合块
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
最终架构
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
尝试取得子类别模型的摘要
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()
我接受这个错误我不知道该怎么办.
值错误:必须始终传递Layer.call
的第一个参数。
1条答案
按热度按时间jchrr9hc1#
试试这个,但我会告诉你这个错误背后的原因,这个错误发生时,你使用相同的两个层的一个名称,并将其发送到keras.模型,我已经改变了代码一点点,并不返回模型输出在每一层只是返回x它是一样的,因为你正在做的,但复杂性很低...
第一个问题: