我正在使用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 回答
这似乎是
BatchNormalization
层(BN)或任何其他层的效果,它们在训练与推理中的工作方式不同 . 特别是BN在推理中使用已保存的人口统计数据,但在培训中使用当前的小批量统计数据 . 当您冻结基础模型中的BN图层的权重然后进行训练时会发生什么,将使用小批量统计数据 . 这可能导致不良结果,因为相邻的转换层期望使用保存的人口统计数据标准化输入 .如果首先使用基本模型提取要素,则不会看到任何不良影响,因为基本模型处于推理模式并且使用了总体统计数据 .
解决方案是子类
BatchNormalization
并覆盖__call__
方法,将training
标志设置为False . 类似于以下内容:看看keras代码,它将变得清晰:https://github.com/keras-team/keras/blob/master/keras/layers/normalization.py#L132