如何将权重从 2D convnet 复制到 Keras 上的 3D Convnet?
How to copy weights from a 2D convnet in to a 3D Convnet on Keras?
我正在尝试在带有 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 切片组成),
你能给我的任何建议都会很有用,
谢谢
这取决于您希望在您的应用程序中做什么。
如果您只是想根据切片处理 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 is one such popular model. ShapeNet and Pascal3D 是流行的 3D 数据集。
关于如何处理视频数据也可能有助于让您更好地了解如何继续。
我正在尝试在带有 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 切片组成),
你能给我的任何建议都会很有用,
谢谢
这取决于您希望在您的应用程序中做什么。 如果您只是想根据切片处理 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 is one such popular model. ShapeNet and Pascal3D 是流行的 3D 数据集。