【发布时间】: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