如何在Keras中实现带有残差连接和批正规化的一维卷积神经网络?

时间:2018-09-24 01:50:42

标签: python tensorflow keras conv-neural-network deep-residual-networks

我正在尝试根据论文Cardiologist-Level Arrhythmia Detection with Convolutional Neural Networks,使用keras开发具有残差连接和批量归一化的一维卷积神经网络。 到目前为止,这是代码:

# define model
x = Input(shape=(time_steps, n_features))

# First Conv / BN / ReLU layer
y = Conv1D(filters=n_filters, kernel_size=n_kernel, strides=n_strides, padding='same')(x) 
y = BatchNormalization()(y)
y = ReLU()(y)

shortcut = MaxPooling1D(pool_size = n_pool)(y)

# First Residual block
y = Conv1D(filters=n_filters, kernel_size=n_kernel, strides=n_strides, padding='same')(y) 
y = BatchNormalization()(y)
y = ReLU()(y)
y = Dropout(rate=drop_rate)(y)
y = Conv1D(filters=n_filters, kernel_size=n_kernel, strides=n_strides, padding='same')(y) 
# Add Residual (shortcut)
y = add([shortcut, y])

# Repeated Residual blocks   
for k in range (2,3): # smaller network for testing

    shortcut = MaxPooling1D(pool_size = n_pool)(y)
    y = BatchNormalization()(y)
    y = ReLU()(y)
    y = Dropout(rate=drop_rate)(y)
    y = Conv1D(filters=n_filters * k, kernel_size=n_kernel, strides=n_strides, padding='same')(y)    
    y = BatchNormalization()(y)
    y = ReLU()(y)
    y = Dropout(rate=drop_rate)(y)
    y = Conv1D(filters=n_filters * k, kernel_size=n_kernel, strides=n_strides, padding='same')(y) 
    y = add([shortcut, y])

z = BatchNormalization()(y)
z = ReLU()(z)    
z = Flatten()(z)
z = Dense(64, activation='relu')(z)
predictions = Dense(classes, activation='softmax')(z)

model = Model(inputs=x, outputs=predictions)

# Compiling 
model.compile(loss='categorical_crossentropy', optimizer='adam', metrics=['categorical_accuracy'])

# Fitting 
model.fit(train_x, train_y, epochs=n_epochs, batch_size=n_batch)

这是我尝试构建的model的简化图。

本文描述的模型使用的过滤器数量递增:

  

该网络由16个残差块组成,每个块具有2个卷积层。卷积层的滤波器长度均为16,具有64k滤波器,其中k从1开始,每第4个残差块递增一次。每个备用残差块以2的因子对输入进行二次采样,因此最终以2 ^ 8的因子对原始输入进行二次采样。当残差块对输入进行子采样时,相应的快捷方式连接也会使用具有相同子采样因子的最大池操作对它们的输入进行子采样。

但是,仅当我在每个Conv1D层中使用相同数量的滤镜,且k = 1,strides = 1和padding = same且不应用任何MaxPooling1D时,我才能使其工作。这些参数的任何更改都将导致张量大小不匹配,并且编译失败时会出现以下错误:

ValueError: Operands could not be broadcast together with shapes (70, 64) (70, 128)

有人知道如何解决此尺寸不匹配问题并使其正常工作吗?

此外,如果输入具有多个通道(或功能),则失配甚至更严重!有没有一种方法可以处理多个渠道?

1 个答案:

答案 0 :(得分:0)

张量形状不匹配的问题应该在add([y, shortcut])层中发生。由于您使用的是MaxPooling1D层,因此默认情况下这会将您的时间步减半,您可以使用pool_size参数对其进行更改。另一方面,您的剩余部分不会减少相同数量的时间步长。在Conv1D层的任何一层(最好是最后一层)中添加stride=2padding='same'之前,应将shortcuty一起应用。

作为参考,您可以在Keras-applications-github

处查看Resnet代码。