【问题标题】:How to add a convolutional layer in the shortcut connection using functional API in Keras?如何使用 Keras 中的功能 API 在快捷连接中添加卷积层?
【发布时间】:2020-07-31 14:58:52
【问题描述】:

我正在尝试使用 Keras 中的功能 API 实现一个自定义 CNN 模型,如附图所示。我已经编写了实现主分支的代码,但是在添加 1x1 卷积作为快捷连接时遇到了问题。为每一对卷积块添加快捷卷积,就在最大池化层之前。代码如下:

input_shape = (256,256,3)
model_input = Input(shape=input_shape)
print(model_input) 

def custom_cnn(model_input):
    x = Conv2D(16, (3, 3), strides = (2,2), padding = 'same')(model_input)
    x = BatchNormalization()(x)
    x = Activation('relu')(x)
    x = Conv2D(16, (3, 3), strides = (2,2), padding = 'same')(x)
    x = BatchNormalization()(x)
    x = Activation('relu')(x)
    x = MaxPooling2D(pool_size=(3, 3), strides=(2,2))(x)
    
    x = Conv2D(32, (3, 3), strides = (1,1), padding = 'same')(x)
    x = BatchNormalization()(x)
    x = Activation('relu')(x)
    x = Conv2D(32, (3, 3), strides = (1,1), padding = 'same')(x)
    x = BatchNormalization()(x)
    x = Activation('relu')(x)
    x = MaxPooling2D(pool_size=(3, 3), strides=(2,2))(x)
    
    x = Conv2D(48, (3, 3), strides = (1,1), padding = 'same')(x)
    x = BatchNormalization()(x)
    x = Activation('relu')(x)
    x = Conv2D(48, (3, 3), strides = (1,1), padding = 'same')(x)
    x = BatchNormalization()(x)
    x = Activation('relu')(x)
    x = MaxPooling2D(pool_size=(3, 3), strides=(2,2))(x)
    
    x = Conv2D(64, (3, 3), strides = (1,1), padding = 'same')(x)
    x = BatchNormalization()(x)
    x = Activation('relu')(x)
    x = Conv2D(64, (3, 3), strides = (1,1), padding = 'same')(x)
    x = BatchNormalization()(x)
    x = Activation('relu')(x)
    x = MaxPooling2D(pool_size=(3, 3), strides=(2,2))(x)
    
    x = Conv2D(80, (3, 3), strides = (1,1), padding = 'same')(x)
    x = BatchNormalization()(x)
    x = Activation('relu')(x)
    x = Conv2D(80, (3, 3), strides = (1,1), padding = 'same')(x)
    x = BatchNormalization()(x)
    x = Activation('relu')(x)
    x = MaxPooling2D(pool_size=(3, 3), strides=(2,2))(x)
            
    x = GlobalAveragePooling2D()(x)
    x = Dense(num_classes, activation='softmax')(x)
    model = Model(inputs=model_input, outputs=x, name='custom_cnn')
    return model

#instantiate the model
custom_model = custom_cnn(model_input)

#display model summary
custom_model.summary() 

【问题讨论】:

    标签: tensorflow keras deep-learning conv-neural-network


    【解决方案1】:

    这里是按照架构在网络中实现残差块:

    num_classes = 3
    input_shape = (256,256,3)
    model_input = Input(shape=input_shape)
    
    def custom_cnn(model_input):
        
        x = Conv2D(16, (3, 3), strides = (2,2), padding = 'same')(model_input)
        x = BatchNormalization()(x)
        x = Activation('relu')(x)
        x = Conv2D(16, (3, 3), strides = (2,2), padding = 'same')(x)
        x = BatchNormalization()(x)
        x = Activation('relu')(x)
        xx = Conv2D(16, (1,1), strides= (4,4), padding = 'same')(model_input)
        x = Add()([x,xx])
        xx = MaxPooling2D(pool_size=(3, 3), strides=(2,2))(x)
        
        x = Conv2D(32, (3, 3), strides = (1,1), padding = 'same')(xx)
        x = BatchNormalization()(x)
        x = Activation('relu')(x)
        x = Conv2D(32, (3, 3), strides = (1,1), padding = 'same')(x)
        x = BatchNormalization()(x)
        x = Activation('relu')(x)
        xx = Conv2D(32, (1,1), strides= (1,1), padding = 'same')(xx)
        x = Add()([x,xx])
        xx = MaxPooling2D(pool_size=(3, 3), strides=(2,2))(x)
        
        x = Conv2D(48, (3, 3), strides = (1,1), padding = 'same')(xx)
        x = BatchNormalization()(x)
        x = Activation('relu')(x)
        x = Conv2D(48, (3, 3), strides = (1,1), padding = 'same')(x)
        x = BatchNormalization()(x)
        x = Activation('relu')(x)
        xx = Conv2D(48, (1,1), strides= (1,1), padding = 'same')(xx)
        x = Add()([x,xx])
        xx = MaxPooling2D(pool_size=(3, 3), strides=(2,2))(x)
        
        x = Conv2D(64, (3, 3), strides = (1,1), padding = 'same')(xx)
        x = BatchNormalization()(x)
        x = Activation('relu')(x)
        x = Conv2D(64, (3, 3), strides = (1,1), padding = 'same')(x)
        x = BatchNormalization()(x)
        x = Activation('relu')(x)
        xx = Conv2D(64, (1,1), strides= (1,1), padding = 'same')(xx)
        x = Add()([x,xx])
        xx = MaxPooling2D(pool_size=(3, 3), strides=(2,2))(x)
        
        x = Conv2D(80, (3, 3), strides = (1,1), padding = 'same')(xx)
        x = BatchNormalization()(x)
        x = Activation('relu')(x)
        x = Conv2D(80, (3, 3), strides = (1,1), padding = 'same')(x)
        x = BatchNormalization()(x)
        x = Activation('relu')(x)
        xx = Conv2D(80, (1,1), strides= (1,1), padding = 'same')(xx)
        x = Add()([x,xx])
        xx = MaxPooling2D(pool_size=(3, 3), strides=(2,2))(x)
                
        x = GlobalAveragePooling2D()(xx)
        x = Dense(num_classes, activation='softmax')(x)
        model = Model(inputs=model_input, outputs=x, name='custom_cnn')
        return model
    
    #instantiate the model
    custom_model = custom_cnn(model_input)
    
    #display model summary
    custom_model.summary() 
    

    【讨论】:

      【解决方案2】:

      您可以使用keras.layers.concatenate 函数合并多个层,因此如果您有两个“平行”层xy,您可以像这样将它们合并到层z

      z = layers.concatenate([x, y])
      

      在您的代码中,它看起来像这样:

      首先,创建一个“平行”层(请注意,x 和之后的y 两个层都将应用于从model_input 层开始的同一层)

      x = Conv2D(16, (3, 3), strides = (2,2), padding = 'same')(model_input)
      x = BatchNormalization()(x)
      x = Activation('relu')(x)
      x = Conv2D(16, (3, 3), strides = (2,2), padding = 'same')(x)
      x = BatchNormalization()(x)
      x = Activation('relu')(x)
      

      然后您将创建第二个“平行”层:

      y = Conv2D(...)(model_input)
      

      合并它们

      z = layers.concatenate([x, y])
      

      并在z 上应用最大池化(在作为连接结果的层上)

      z = MaxPooling2D(pool_size=(3, 3), strides=(2,2))(z)
      

      再一次,创建两个分支,都将z 作为输入(其中z 等同于上一次迭代中的model_input)并在需要应用连接的每个块中重复。

      【讨论】:

      • 谢谢,但在第一次连接后会引发错误:ValueError: A Concatenate 层需要具有匹配形状的输入,但连接轴除外。得到输入形状:[(None, 8, 8, 32), (None, 31, 31, 32)] 因为不同输入维度的连接存在问题。作者的 tensorflow 代码位于 github.com/frapa/tbcnn/blob/master/net.py,但我在将它们转换为 Keras 兼容代码时遇到了问题。
      • 这是因为您要连接的图层的尺寸必须相同,除了您执行连接的轴。您可以指定要在哪个轴上连接,但其余轴必须匹配,而输出的情况并非如此,其中 2 个维度不匹配(8 != 31 和 8 != 31)
      猜你喜欢
      • 2023-03-08
      • 1970-01-01
      • 2017-11-26
      • 2019-03-06
      • 1970-01-01
      • 2018-07-30
      • 1970-01-01
      • 1970-01-01
      • 2019-07-10
      相关资源
      最近更新 更多