首页 文章

与训练“预缓存”功能相比,通过冻结conv_base进行Keras传输学习的准确性较差

提问于
浏览
1

我正在使用Keras 2.1.6进行转移学习,并使用两种非常着名的标准方法 . 这两个都在Chollet的书的第5章和https://github.com/fchollet/deep-learning-with-python-notebooks/blob/master/5.3-using-a-pretrained-convnet.ipynb详细详述

这两种方式是概括的:

A)从conv_base缓存表示,然后分别在FC上训练 . 这被认为是快速但不允许在Keras中进行数据增加 .

B)使用FC扩展conv_base模型并冻结conv_base权重,并端到端训练 . 这对于在CPU上训练来说是昂贵的,但是将允许更大的灵活性,特别是增加数据增加 .

对于我的特定数据集和使用MobileNet(而不是VGG),我尝试了两种方式 . 方法(A)将在10个时期后给出约75%的验证准确度,但方法(B)将仅给出~58%(没有数据增加) . 但是,我希望它们大致相同 . 我试图调试,看看我做了什么重大错误,但无法发现任何问题 .

我读到的一件事是,由于过去的错误,假设在方法B)中被冻结的权重可能不会被冻结 . 但目前的Keras版本2.1.6应该是免费的 . 以下是我在conv_base中冻结权重的方法 .

conv_base.trainable = False
for layer in conv_base.layers:
    layer.trainable = False

可能不需要循环但我添加它以防万一 . 事实证明,在几个时代之后检查它们的重量实际上是冻结的 . 所以这可能不是导致问题的原因 .

任何有关如何调试或可能出错的提示的人都请告诉我 .

我发布了两个运行作为GitHub的要点 . 我在谷歌colab上运行它并导出它们 . 相关部分应从那些Keras进口开始 .

方法A):https://gist.github.com/kechan/38b4e6c85501246a2a49deadd26aefd7

方法B):https://gist.github.com/kechan/f3fea62279ac847e9adc100351b7e9e8

更新

我进一步将两种转移学习方法结合到一个笔记本中,并试图尽可能地保持其他一切“不变” . 这是新的要点:

https://gist.github.com/kechan/9487fad4dfeaede212e3d9899fb21105

1 回答

  • 0

    这似乎是 BatchNormalization 层(BN)或任何其他层的效果,它们在训练与推理中的工作方式不同 . 特别是BN在推理中使用已保存的人口统计数据,但在培训中使用当前的小批量统计数据 . 当您冻结基础模型中的BN图层的权重然后进行训练时会发生什么,将使用小批量统计数据 . 这可能导致不良结果,因为相邻的转换层期望使用保存的人口统计数据标准化输入 .

    如果首先使用基本模型提取要素,则不会看到任何不良影响,因为基本模型处于推理模式并且使用了总体统计数据 .

    解决方案是子类 BatchNormalization 并覆盖 __call__ 方法,将 training 标志设置为False . 类似于以下内容:

    class InferenceBatchNormalization(BatchNormalization):
        def __init__(self, **kwargs):
            super(BatchNormalization, self).__init__(**kwargs)
    
        def call(self, inputs, training=None):
            return super(BatchNormalization, self).__call__(inputs, training=False)
    

    看看keras代码,它将变得清晰:https://github.com/keras-team/keras/blob/master/keras/layers/normalization.py#L132

相关问题