2

我正在尝试在带有 Tensorflow 后端的 Keras 上实现一个 3D convnet,然后是 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 切片组成),

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

谢谢

4

1 回答 1

2

这取决于您要在应用程序中执行的操作。如果您只是想根据切片处理 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就是这样一种流行的模型。ShapeNetPascal3D是流行的 3D 数据集。

这个关于如何处理视频数据的讨论也可能有助于让您更好地了解如何进行。

于 2018-09-25T16:44:24.720 回答