python ValueError:必须始终传递ウLayer.call Ж的第一个参数,我希望以子类化的方式键入此模型,

von4xj4u  于 2022-10-30  发布在  Python
关注(0)|答案(1)|浏览(146)

我有一些不同的块,因为我必须使用共享参数,所以我需要以子类形式实现此模型

卷积和恒等块

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的第一个参数。

jchrr9hc

jchrr9hc1#

试试这个,但我会告诉你这个错误背后的原因,这个错误发生时,你使用相同的两个层的一个名称,并将其发送到keras.模型,我已经改变了代码一点点,并不返回模型输出在每一层只是返回x它是一样的,因为你正在做的,但复杂性很低...
第一个问题:

相关问题