我正在尝试在带有 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就是这样一种流行的模型。 ShapeNet和 Pascal3D是流行的 3D 数据集。
This discussion关于如何处理视频数据也可能有助于让您更好地了解如何继续。
关于python-3.x - 如何将权重从 2D 卷积网络复制到 Keras 上的 3D 卷积网络?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52446965/