【问题标题】:How to copy weights from a 2D convnet in to a 3D Convnet on Keras?如何在 Keras 上将权重从 2D 卷积网络复制到 3D 卷积网络?
【发布时间】:2019-02-26 01:18:49
【问题描述】:

我正在尝试在带有 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 切片组成),

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

谢谢

【问题讨论】:

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


    【解决方案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 wights 冻结较低的层,这将非常有用。

    要为模型加载 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 就是这样一种流行的模型。 ShapeNet 和 Pascal3D 是流行的 3D 数据集。

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

    【讨论】:

    • 非常感谢。我有使用 TimeDistributed 的想法,但我不确定复制权重是否有效。我将从这种方法开始,我会告诉你我的结果。微调 3D 现有网络的想法听起来不错,但目前我找不到用 Keras 制作的官方版本(例如,C3D 官方版本是在 caffe 上制作的),所以我稍后会考虑这种方法。关于手动复制权重我也会试一试。
    • 虽然没有正式版,但是github上会有很多模型架构和权重可用。 facebookresearch 已经提供了与Pytorch 兼容的 C3D 模型。只要确保您正在寻找基于 Keras 的模型,均值减法已经完成。
    猜你喜欢
    • 2019-08-18
    • 2016-04-17
    • 1970-01-01
    • 1970-01-01
    • 2020-11-01
    • 2019-04-11
    • 2017-01-01
    • 1970-01-01
    相关资源
    最近更新 更多