如何将权重从2D卷积网络复制到Keras上的3D卷积网络?

时间:2018-09-21 15:32:48

标签: python-3.x tensorflow keras conv-neural-network transfer-learning

我正在尝试在带有Tensorflow后端的Keras上实现3D卷积网络,然后实现LSTM层以使用3D图像作为输入来生成序列。

我想从现有的预先训练模型的权重开始训练,以避免随机初始化的常见问题。

以一个基本的示例开始,我使用了VGG-16,并实现了该网络的“ 3D”版本(没有FC层):

img_input = Input((100,80,80,3))
x = Conv3D(64, (3, 3 ,3), activation='relu', padding='same', name='block1_conv1')(img_input)

x = Conv3D(64, (3, 3 ,3), activation='relu', padding='same', name='block1_conv2')(x)

x = MaxPooling3D((1, 2, 2), strides=(1, 2, 2), name='block1_pool')(x)

x = Conv3D(128, (3, 3 ,3), activation='relu', padding='same', name='block2_conv1')(x)

x = Conv3D(128, (3, 3 ,3), activation='relu', padding='same', name='block2_conv2')(x)
x = MaxPooling3D((1, 2 ,2), strides=(1,2, 2), name='block2_pool')(x)

x = Conv3D(256, (3, 3 ,3), activation='relu', padding='same', name='block3_conv1')(x)
x = Conv3D(256, (3, 3 , 3), activation='relu', padding='same', name='block3_conv2')(x)
x = Conv3D(256, (3, 3, 3), activation='relu', padding='same', name='block3_conv3')(x)
x = MaxPooling3D((1, 2 ,2), strides=(1,2, 2), name='block3_pool')(x)

x = Conv3D(512, (3, 3 ,3), activation='relu', padding='same', name='block4_conv1')(x)
x = Conv3D(512, (3, 3 ,3), activation='relu', padding='same', name='block4_conv2')(x)
x = Conv3D(512, (3, 3 ,3), activation='relu', padding='same', name='block4_conv3')(x)
x = MaxPooling3D((1, 2 ,2), strides=(1, 2, 2), name='block4_pool')(x)

x = Conv3D(512, (3, 3 ,3), activation='relu', padding='same', name='block5_conv1')(x)
x = Conv3D(512, (3, 3 ,3), activation='relu', padding='same', name='block5_conv2')(x)
x = Conv3D(512, (3, 3 ,3), activation='relu', padding='same', name='block5_conv3')(x)
x = MaxPooling3D((1, 2 ,2), strides=(1, 2, 2), name='block5_pool')(x)

所以我想知道如何将预训练的VGG-16的权重加载到100个切片中的每个切片中(我的3D图像由100个80x80 rgb切片组成),

任何建议您可以给我的建议都会有用,

谢谢

1 个答案:

答案 0 :(得分:1)

这取决于您要在应用程序中执行的操作。 如果您只是想根据切片来处理3D图像,则可以定义TimeDistributed VGG16网络(Conv2D而不是Conv3D)。

然后,您在上面定义的每个图层的模型都将变成这样:

img_input = Input((100,80,80,3))
x = TimeDistributed(Conv2D(64, (3, 3), activation='relu', padding='same', name='block1_conv1', trainable=False))(img_input)
x = TimeDistributed(Conv2D(64, (3, 3), activation='relu', padding='same', name='block1_conv2', trainable=False))(x)
x = TimeDistributed((MaxPooling2D((2, 2), strides=(2, 2), name='block1_pool', trainable=False)(x)
...
...

请注意,我在此处包括选项“ trainable = False”。如果您只想训练较深的层次并使用训练有素的VGG权重冻结较低的层次,这将非常有用。

要为模型加载VGG权重,则可以使用Keras的load_weights功能。

model.load_weights(filepath, by_name=True)

如果将不想训练的图层名称设置为与VGG16中定义的名称相同,则可以在此处按名称简单地加载这些图层。

但是,时空特征学习可以通过使用3D ConvNets更好地完成。 如果这是您应用程序的基础,那么您将无法直接将VGG16权重导入Conv3D模型,因为现在每层中的参数数量都增加了,因为过滤器从3 * 3变为3 * 3 * 3例子。

您仍然可以通过考虑将3 * 3 * 3中的3 * 3补丁最适合使用VGG16权重进行初始化,将权重逐层加载到模型中。 set_weights()函数将一个numpy数组的列表作为输入(分别用于内核权重和偏倚)。您可以从VGG16中提取每个图层的权重,然后为等效的Conv3D权重矩阵构造一个新的numpy数组,并将其输入到Conv3D模型中。

但是我鼓励您查看用于处理3D图像的现有文献和模型,以查看它们是否可以使用转移学习为您提供更好的初始化。

例如,C3D是这样一种流行的模型。 ShapeNetPascal3D是流行的3D数据集。

This discussion上有关如何处理视频数据的信息也可能有助于您更好地了解如何进行视频处理。