【问题标题】:How to freeze batch-norm layers during Transfer-learning如何在迁移学习期间冻结批规范层
【发布时间】:2021-08-25 09:05:40
【问题描述】:

我正在关注 TensorFlow 官方网站上的Transfer learning and fine-tuning guide。它指出在微调期间,批量归一化层应该处于推理模式:

关于BatchNormalization层的重要说明

许多图像模型包含BatchNormalization 层。该层是 每个可以想象的计数的特殊情况。这里有几件事要保留 记住。

  • BatchNormalization 包含 2 个在训练期间更新的不可训练权重。这些是跟踪输入均值和方差的变量。
  • 当您设置bn_layer.trainable = False 时,BatchNormalization 层将在推理模式下运行,并且不会更新其均值和方差统计信息。这不是一般其他层的情况,as weight trainability & inference/training modes are two orthogonal concepts。但在BatchNormalization 层的情况下,两者是并列的。
  • 当您解冻包含BatchNormalization 层的模型以进行微调时,您应该在调用基本模型时通过传递training=FalseBatchNormalization 层保持在推理模式。否则,应用于不可训练权重的更新将突然破坏模型所学的内容。

您将在最后的端到端示例中看到这种模式的实际应用 本指南。

即便如此,其他一些来源,例如 this 文章(标题为使用 ResNet 进行迁移学习)说的完全不同:

for layer in resnet_model.layers:
    if isinstance(layer, BatchNormalization):
        layer.trainable = True
    else:
        layer.trainable = False

无论如何,我知道TensorFlow中的trainingtrainable参数是有区别的。

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

model = tf.keras.models.load_model(path)

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

model.trainable = True

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

现在关于批量标准化层:我可以这样做:

for layer in model.layers:
    if isinstance(layer, keras.layers.BatchNormalization):
      layer.trainable = False

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

我应该做哪一个?最终冻结批规范层是否更好?

【问题讨论】:

    标签: tensorflow keras neural-network tensorflow2.0 batch-normalization


    【解决方案1】:

    使用下面的代码查看批处理规范层是否被冻结。它不仅会打印图层名称,还会打印它们是否可训练。

    def print_layer_trainable(conv_model):
        for layer in conv_model.layers:
            print("{0}:\t{1}".format(layer.trainable, layer.name))
    

    在这种情况下,我已经测试了您的方法,但没有冻结我的模型的批量规范层。

    for layer in model.layers:
        if isinstance(layer, keras.layers.BatchNormalization):
          layer.trainable = False
    

    下面的代码对我很有效。在我的例子中,模型是 ResNetV2,批量规范层以后缀“preact_bn”命名。通过使用上面的代码打印层,您可以看到批量规范层是如何命名和配置的。

      for layer in new_model.layers[:]:          
        if ('preact_bn' in layer.name):
          trainable = False
        else:
          trainable = True
        layer.trainable = trainable
    
    

    【讨论】:

      【解决方案2】:

      不确定训练与可训练的区别,但我个人得到了很好的结果设置可训练 = 假。

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

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

      附:根据您计划在训练后运行模式的方式,我建议您在训练模型后冻结批规范层。出于某种原因,如果您在线运行模型(一次 1 张图像),批量规范会变得很时髦并给出不规则的结果。在训练后冻结他们为我解决了这个问题。

      【讨论】:

        猜你喜欢
        • 2017-11-23
        • 1970-01-01
        • 1970-01-01
        • 2018-10-26
        • 1970-01-01
        • 2021-04-24
        • 2019-12-17
        • 2020-10-23
        • 2020-11-07
        相关资源
        最近更新 更多