Tensorflow 如何使用Keras中的函数API在快捷连接中添加卷积层?

Tensorflow 如何使用Keras中的函数API在快捷连接中添加卷积层?,tensorflow,keras,deep-learning,conv-neural-network,Tensorflow,Keras,Deep Learning,Conv Neural Network,我正在尝试使用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

我正在尝试使用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() 

您可以使用
keras.layers.concatenate
功能合并多个层,因此如果您有两个“并行”层
x
y
,您可以将它们合并到层
z
,如下所示:

z = layers.concatenate([x, y])
在您的代码中,它看起来如下:

z = layers.concatenate([x, y])
首先,创建一个“平行”层(注意,从
model_input
层开始,两个层
x
和以后的
y
将应用于同一层)

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

合并它们

z = layers.concatenate([x, y])
并在
z
上应用最大池(在连接的结果层上)


再次,创建两个分支,都将
z
作为输入(其中
z
相当于上一次迭代中的
model_输入
),并在需要应用串联的每个块上重复该操作。

这里,按照模式在网络中实现剩余块:


谢谢,但是在第一次连接之后它会抛出一个错误:ValueError:A
连接
层需要输入匹配的形状,concat轴除外。已获取输入形状:[(无,8,8,32),(无,31,31,32)],因为不同输入维度的连接问题。作者的tensorflow代码位于,但我在将其转换为Keras兼容代码时遇到问题。这是因为要连接的层的维度必须相同,但执行连接的轴除外。您可以指定要连接的轴,但其他轴必须匹配,这与您的输出不同,其中两个维度不匹配(8!=31和8!=31)@shiva请告诉我是否有问题,谢谢,但此处显示的模型不只是有剩余连接,而是使用具有不同步长的1x1卷积。我在使用连接层时也遇到了问题,因为尺寸不匹配。作者在github.com/frapa/tbcnn/blob/master/net.py上有他们的tensorflow代码,但我在将它们转换为与Keras兼容的代码时遇到了问题。。。1x1是您可以看到的过滤器Conv2D(…,(1,1))。我提供的模型是图片中所示内容的精确复制品。连接错误。。。您必须操作剩余连接谢谢,但我无法理解剩余连接中使用的不同步幅值。例如,第一个剩余连接使用4个步幅,而其余的使用一个步幅。我使用图片中报告的相同精确值(第一个块:4,第二个块:1,3个块:1,4个块:1,5个块:1)。当你操作连接时,为了匹配维度,你必须这样做。第一个块连接输入,而其他块连接池,池由他们自己操作,减少(因此需要1步)
z = layers.concatenate([x, y])
z = MaxPooling2D(pool_size=(3, 3), strides=(2,2))(z)
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()