【问题标题】:Deep Learning: Using a pretrained network's earlier activations深度学习:使用预训练网络的早期激活
【发布时间】:2018-02-03 11:37:57
【问题描述】:

我有大约 25k 张图像,属于 14 个不同的类别(不同种类的颈线,例如 V 领、圆领等)。图像主要包含服装的上半部分和/或模特的脸。以下是一些示例:

为了做到这一点,我想在 VGG16 的第一个块(在 imagenet 上预训练)之后提取特征,因为早期块的特征图将捕获线条、形状等。这是model.summary() :

Layer (type)                 Output Shape              Param #   
=================================================================
block1_conv1 (Conv2D)        (None, 224, 224, 64)      1792      
_________________________________________________________________
block1_conv2 (Conv2D)        (None, 224, 224, 64)      36928     
_________________________________________________________________
block1_pool (MaxPooling2D)   (None, 112, 112, 64)      0         
_________________________________________________________________
flatten (Flatten)            (None, 802816)            0         
_________________________________________________________________
fc1 (Dense)                  (None, 4096)              3288338432
_________________________________________________________________
fc2 (Dense)                  (None, 4096)              16781312  
_________________________________________________________________
predictions (Dense)          (None, 16)                65552     
=================================================================
Total params: 3,305,224,016
Trainable params: 3,305,224,016
Non-trainable params: 0

问题是参数的总数是巨大的。考虑到我的具体数据集,您能否建议如何减少?

【问题讨论】:

  • 30 个 epoch 后的第一个 epoch 的损失是否准确?在这种情况下,在一个简单的 cnn 上进行训练可能会显示在批次等方面是否存在任何其他问题。
  • @Littleone,请看已编辑的问题

标签: computer-vision deep-learning keras


【解决方案1】:

问题是:密集层将为每个输入创建权重。

所以,因为你有一个充满像素的图像,并且你没有显着减小它的大小,所以添加Flatten + Dense 将导致这个荒谬的权重数量。

我不确定我是否理解您为什么只想要第一个块。这个块将识别非常基本的小形状而不考虑​​它们之间的关系。当然,没有更早的区块。

我确实建议您使用更多块来识别详细特征并减小图像大小。最好的办法是简单地使用 include_top=False 和 trainable=False 获取整个 VGG16 模型,并添加可训练的顶层 - (See Here)

现在,如果你真的想要有这么少的块而不减小图像大小,那么你可以尝试添加一个GlobalMaxPooling2D 层。这将仅获得整个图像中的最大值。这可能有用也可能没用,这取决于用这么少的卷积来识别你想要的东西的可能性。 (另一种选择是GlobalAveragePooling2D,但我相信在这种情况下效果更差)。在这种情况下,更多的块将导致更好的结果。

【讨论】:

  • 由于领口形状并不复杂,我想只使用block1。我的理解是,区分领口所需的信息将在早期的激活中捕获,因此以后的激活并不是真正需要的。这不是正确的理解吗?
  • 我不这么认为。 (但无论如何,您需要摆脱大量的参数)。基本形状是颜色过渡,从白色到黑色,从黑色到白色,垂直,水平,对角线等。甚至还没有接近线条。
  • 嗨丹尼尔,我试过你的方法。我的数据集每个类(11 个类)包含大约 600 张图像。 10 个 epoch 后,训练准确率为 94%,但验证准确率仅为 72%。密集层之后的辍学也没有帮助。你认为,我需要某种分割来仅提供颈部区域作为输入吗?
  • 您需要更多数据或数据扩充。或者一个不太强大的模型。你有一个过拟合的模型(这个模型太强大了,它能够记住你的训练数据)。
【解决方案2】:

您必须制作自己的特征提取器,通过从原始 VGG 中删除所有密集层来构建自己的密集层。我建议你也放置 2 个密集层,fc1 有 1024 个节点,fc2 有 512 个节点。当然,您必须添加第三个密集层,它将作为假分类器来训练特征提取器。然后只训练这三层,保持 VGG 的其余部分为trainable=false,这将减少参数。当然,在训练完这些层之后,您应该删除最后一个以获得特征提取器。现在,对于每张图像,您将拥有 512 个特征,您可以将它们放在简单的 NN 或 SVM 上,作为您的分类器。 你应该有一个至少 8GB 的​​ GPU。

在 Keras 博客中,您可以找到如何微调最后一层以获得您自己的特征提取器,这或多或少是您正在寻找的:https://blog.keras.io/building-powerful-image-classification-models-using-very-little-data.html

希望对你有帮助!!

【讨论】:

    【解决方案3】:

    您在正确的轨道上,但您(就像我曾经一样)被人们描述神经网络的方式不一致而感到困惑。在 Keras 文档中,“顶层”层是其他文档所称的“底层”、“最后”、“最终”或“最深”层。它是计算最终概率的层。为了实现迁移学习,你冻结了早期的层(图像进入网络并进行卷积)并替换或重新训练最后一层(答案出来的地方)。 Keras 将最后一层称为“顶层”。因此,在 Keras-talk 中,您可以使用 include_top=False 实例化模型,或者使用 model.pop() 删除一个层。

    希望对你有帮助。

    Eric 的回答是正确的。我赞同他的建议,即您阅读 Keras 的创建者 François Chollet 的这篇博文:https://blog.keras.io/building-powerful-image-classification-models-using-very-little-data.html

    【讨论】:

      【解决方案4】:

      如果您使用的是预训练模型,则无需重新训练较低层,只需保留最后几个分类层即可训练。例如,如果您想冻结前 6 层,您可以调用:

      for idx, layer in enumerate(model.layers[:6]):
          print('Make layer {} {} untrainable.'.format(idx, layer.name))
          layer.trainable = False
      

      然后,如果您调用 model.summary(),您会发现可训练的参数要少得多,这不仅会使训练更快,而且在不更改预训练卷积层的情况下通常会提供更好的结果。

      【讨论】:

        猜你喜欢
        • 2018-01-09
        • 2023-02-01
        • 2020-11-24
        • 2021-11-17
        • 2014-06-03
        • 2019-10-20
        • 2019-12-30
        • 2021-05-26
        • 2021-05-26
        相关资源
        最近更新 更多