【问题标题】:How to fine tune InceptionV3 in Keras如何在 Keras 中微调 InceptionV3
【发布时间】:2021-04-01 16:26:32
【问题描述】:

我正在尝试在 Keras 中训练基于 InceptionV3 架构的分类器。 为此,我加载了预训练的 InceptionV3 模型,没有顶部,并为我的分类问题的类添加了最终的全连接层。在第一次训练中,我冻结了 InceptionV3 基础模型,只训练了最后的全连接层。

在第二步中,我想通过解冻 InceptionV3 模型的一部分来“微调”网络。 现在我知道 InceptionV3 模型广泛使用了 BatchNorm 层。建议 (link to documentation),当 BatchNorm 层在迁移学习时“解冻”以进行微调时,保持 BatchNorm 层计算的均值和方差不变。这应该通过将 BatchNorm 层设置为推理模式而不是训练模式来完成。 另请参阅:What's the difference between the training argument in call() and the trainable attribute?

现在我的主要问题是:如何仅将 InceptionV3 模型的 BatchNorm 层设置为推理模式?

目前我通过在组装网络时设置“训练”参数将整个 InceptionV3 基础模型设置为推理模式:

inputs = keras.Input(shape=input_shape)
# Scale the 0-255 RGB values to 0.0-1.0 RGB values
x = layers.experimental.preprocessing.Rescaling(1./255)(inputs)
# Set include_top to False so that the final fully connected (with pre-loaded weights) layer is not included.
# We will add our own fully connected layer for our own set of classes to the network.
base_model = keras.applications.InceptionV3(input_shape=input_shape, weights='imagenet', include_top=False)
x = base_model(x, training=False)
# Classification block
x = layers.GlobalAveragePooling2D(name='avg_pool')(x)
x = layers.Dense(num_classes, activation='softmax', name='predictions')(x)
model = keras.Model(inputs=inputs, outputs=x)

我不喜欢的是,通过这种方式我将整个模型设置为推理模式,这可能会将某些层设置为不应该的推理模式。

下面是从我所做的初始训练中加载权重的代码部分,以及冻结前 150 层并解冻 InceptionV3 部分剩余层的代码:

model.load_weights(load_model_weight_file_name)
for layer in base_model.layers[: 150]:
    layer.trainable = False
for layer in base_model.layers[ 150:]:
    layer.trainable = True

我的其余代码(此处未显示)是通常的编译和拟合调用。

运行此代码似乎会导致网络无法真正学习(损失和准确性大致保持不变)。我尝试了不同数量级的优化步长,但这似乎没有帮助。

我观察到的另一件事是,当我使整个 InceptionV3 部分可训练时

base_model.trainable = True

训练开始时服务器的准确性比我的第一轮训练完成时要小几个数量级(当然损失要高得多)。谁可以给我解释一下这个?如果在准确性和损失方面停止训练,我至少希望训练能够继续。

【问题讨论】:

    标签: keras deep-learning transfer-learning batch-normalization image-classification


    【解决方案1】:

    你可以这样做:

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

    这将遍历每一层并检查类型,如果层为 BatchNorm,则设置为推理模式。

    至于迁移学习期间的低起始准确度,您只加载权重而不是优化器状态(就像加载架构、权重、优化器状态等的完整 model.load() 一样)。

    这并不意味着有错误,但如果您必须加载权重,只是让它训练,优化器将最终配置,您应该会看到进度。此外,由于您可能会在第二次运行中覆盖预训练的权重,因此请确保您使用较低的学习率,以便相比之下更新较小,即微调权重而不是将它们炸成碎片。

    【讨论】:

    • 感谢您的提示,但我想这不是我想要的。因为我确实希望这些层能够学习(因为它们必须学习 gamma 和 beta 权重,对吗?),我只是不希望它们处于训练模式以避免该层计算批次的均值和方差.
    • 我不太明白你对准确性的解释。当我加载权重时,在训练开始时,网络将与之前大致相同,因此分类结果将大致相同。即使在第一个 epoch 的第一步,我也看到比以前低得多的准确度(和更高的损失)。
    • 您的问题是“如何仅将 InceptionV3 模型的 BatchNorm 层设置为推理模式”,而这正是您要做的。我认为这里的术语可能有些混乱——如果你想让层学习 (layer.trainable=True),那么根据定义它们处于训练模式。设置 trainable = false 是推理模式的定义,也是 keras/tf 在调用base_model.predict 时自动执行的操作。您不能让图层学习并且不处于训练模式。
    • 只是为了澄清“建议,当 BatchNorm 层在迁移学习时“解冻”以进行微调时”-这里“解冻”意味着设置 layer.trainable = True,假设您freeze/set trainable=False 到所有其他层。您可以冻结整个模型并在顶部添加一些额外的层,或者解冻所有/部分层并选择低学习率来稍微调整整个模型的权重。
    • 关于准确性评论 - 当您仅加载权重(而不是优化器等)时,是的,模型权重将是相同的,但优化器在您训练模型时也会保留一个状态,所以如果您没有从第一轮训练中加载优化器(即优化器状态被重置),那么它将需要一些初始批次来重新计算其状态,这就是为什么您的准确性在开始时比以前低得多的原因.您是否允许它运行以查看准确性是否提高?
    猜你喜欢
    • 1970-01-01
    • 2019-05-26
    • 1970-01-01
    • 2019-04-18
    • 1970-01-01
    • 2018-02-05
    • 2017-10-07
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多