如何在迁移学习期间冻结批标准化层

Nic*_*e11 5 neural-network keras tensorflow batch-normalization tensorflow2.0

我正在遵循TensorFlow 官方网站上的迁移学习和微调指南。它指出在微调期间,批量归一化层应处于推理模式:

BatchNormalization关于图层的重要说明

许多图像模型包含BatchNormalization图层。从所有可以想象的角度来看,该层都是一个特例。以下是一些需要记住的事情。

  • BatchNormalization包含 2 个不可训练的权重,在训练期间更新。这些是跟踪输入的均值和方差的变量。
  • 当您设置 时bn_layer.trainable = FalseBatchNormalization图层将在推理模式下运行,并且不会更新其均值和方差统计数据。一般来说,其他层的情况并非如此,因为权重可训练性和推理/训练模式是两个正交的概念。但在层的情况下两者是并列的BatchNormalization
  • 当您解冻包含BatchNormalization图层的模型以进行微调时,您应该在调用基础模型时BatchNormalization通过传递将图层保持在推理模式。training=False否则,应用于不可训练权重的更新将突然破坏模型所学到的知识。

您将在本指南末尾的端到端示例中看到此模式的实际应用。

尽管如此,其他一些来源,例如这篇文章(标题为 ResNet 的迁移学习),说了一些完全不同的内容:

for layer in resnet_model.layers:
    if isinstance(layer, BatchNormalization):
        layer.trainable = True
    else:
        layer.trainable = False
Run Code Online (Sandbox Code Playgroud)

training无论如何,我知道 TensorFlow 中的和参数之间存在差异trainable

我正在从文件加载模型,如下所示:

model = tf.keras.models.load_model(path)
Run Code Online (Sandbox Code Playgroud)

我以这种方式解冻(或者实际上冻结其余部分)一些顶层:

model.trainable = True

for layer in model.layers:
    if layer not in model.layers[idx:]:
        layer.trainable = False

Run Code Online (Sandbox Code Playgroud)

现在关于批量归一化层:我可以这样做:

for layer in model.layers:
    if isinstance(layer, keras.layers.BatchNormalization):
      layer.trainable = False
Run Code Online (Sandbox Code Playgroud)

或者

  for layer in model.layers:
    if layer.name.startswith('bn'):
      layer.call(layer.input, training=False)
Run Code Online (Sandbox Code Playgroud)

我应该做哪一项?最后是否最好冻结批归一化层?

ZWa*_*ang 4

不确定训练与可训练的区别,但就我个人而言,我在设置 trainable = False 时得到了很好的结果。

现在至于是否首先冻结它们:我在不冻结它们的情况下取得了很好的结果。推理很简单,batchnorm层学习初始训练数据的移动平均值。这可能是猫、狗、人类、汽车等,但是当你进行迁移学习时,你可能会转移到一个完全不同的领域。这个新图像域的移动平均值与之前的数据集有很大不同。

通过解冻这些层并冻结 CNN 层,我的模型的准确率提高了 6-7%(82 -> 89% 左右)。我的数据集与 effectivenet 训练的初始 Imagenet 数据集有很大不同。

PS 根据您计划在训练后运行模式的方式,我建议您在模型训练后冻结批量归一化层。出于某种原因,如果您在线运行模型(一次一张图像),批标准化会变得很奇怪并给出不规则的结果。训练后冷冻它们解决了我的问题。