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

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

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

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

为了从一个基本示例开始,我采用了 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 切片组成),

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

谢谢

最佳答案

这取决于您希望在应用程序中执行的操作。 如果您只是想以切片的形式处理 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 权重,您可以使用 load_weights Keras 的功能。

model.load_weights(filepath, by_name=True)

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

但是,使用 3D ConvNet 可以更好地完成时空特征学习。 如果这是您的应用程序的基础,那么您无法直接将 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关于如何处理视频数据也可能有助于让您更好地了解如何继续。

关于python-3.x - 如何将权重从 2D 卷积网络复制到 Keras 上的 3D 卷积网络?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52446965/

相关文章:

python - 输入 'ref' 在构建 NodeDef 时传递了 int32 预期的引用类型

python - 使用三元组损失预测图像

python - Django key 泄露

python-3.x - python - 如何允许在没有类名的情况下从外部访问类属性?

python - 使用 (X)HTML 实体解析 XML

python - parking 位角点坐标通过 Python 3.6 中的 OpenCV 收集

python - 使用具有 LSTM 和动态 RNN 的可训练词嵌入层 : AdamOptimizer expected float_ref instead of float

python - RNN python numpy 内存错误

machine-learning - Dropout 应该插入到哪里?全连接层。?卷积层。?或两者。?

python - 当 channel 数增加时,ResNet 快捷连接的零填充