在keras中对批处理归一化进行微调

时间:2018-12-24 09:44:11

标签: python tensorflow keras deep-learning batch-normalization

我已经成功训练了超过100000个样本的模型,该模型在训练集和测试集上均表现出色。然后,我尝试在一个特定样本(100000个样本之一)中对其进行微调,并将训练后的权重用作初始化。

但是结果有点奇怪,我相信这是由批处理规范化层引起的。具体来说,我的代码可以列出如下:

model = mymodel()
model.load_weights('./pre_trained.h5') #start from history
rate = model.evaluate(x, y)
print(rate)
checkpoint = tf.keras.callbacks.ModelCheckpoint('./trained.h5', monitor='loss',
        verbose=0, save_best_only=True, mode='min',save_weights_only=True)
model.fit(x, y,validation_data=[x, y], epochs=5, verbose=2, callbacks=[checkpoint])

model.load_weights('./ trained.h5')     比率= model.evaluate(x,y)     打印(费率)

mymodel是一个自定义函数,用于生成我的模型,由Dense和Batch规范化组成。 x,y是一个特定样本的输入和标签。我想进一步优化样本的损失。但是,结果很奇怪,因为:

 1/1 [==============================] - 0s 209ms/step
-6.087581634521484
Train on 1 samples, validate on 1 samples
Epoch 1/200
 - 1s - loss: -2.7749e-01 - val_loss: -6.0876e+00
Epoch 2/200
 - 0s - loss: -2.8791e-01 - val_loss: -6.0876e+00
Epoch 3/200
 - 0s - loss: -3.0012e-01 - val_loss: -6.0876e+00
Epoch 4/200
 - 0s - loss: -3.1325e-01 - val_loss: -6.0876e+00

如图所示,首先model.evaluate运作良好,因为损失结果(-6.087581634521484)接近已加载训练模型的性能。但是,训练集上的损失(实际上与model.fit()中的验证集相同)是奇怪的。 val_loss很正常,类似于第一行中的model.evaluate结果。所以我很困惑,为什么火车损失和推理损失之间仍然有很大的差异(火车损失更糟),因为火车样本和验证样本是相同的,我认为结果也应该相同,或至少非常接近。我怀疑问题是由BN层引起的,原因是训练与推理之间的差异很大。但是,我已经在加载预训练的权重之后并且在trainable = False之前设置了BN层的model.fit,但是问题没有解决。

out = tf.keras.layers.BatchNormalization(trainable=False)(out)

我仍然对BN层表示怀疑,并想知道设置trainable=False是否足以保持BN的参数相同。

有人可以给我一些建议吗?非常感谢您的提前帮助。 对不起,我的英语,但是我尽力解释了我的问题。

3 个答案:

答案 0 :(得分:0)

有点尴尬,在另一个问题Keras: Accuracy Drops While Finetuning Inception

中,我找到了一种解决问题的奇怪方法

实际上,我认为这还不够,但是当我添加

 tf.keras.backend.set_learning_phase(1)

model.compile()之前。结果变得很正常,尽管仍然存在一些问题:

1/1 [==============================] - 0s 246ms/step
-6.087581634521484
Train on 1 samples, validate on 1 samples
Epoch 1/10
 - 1s - loss: -6.0876e+00 - val_loss: -6.0893e+00
Epoch 2/10
 - 0s - loss: -6.0893e+00 - val_loss: -6.0948e+00
Epoch 3/10
 - 0s - loss: -6.0948e+00 - val_loss: -6.0903e+00
Epoch 4/10
 - 0s - loss: -6.0903e+00 - val_loss: -6.0927e+00

这是令人惊奇的,也是我想要的,但是我仍然对这个问题感到困惑。 首先,为什么起作用,tf.keras.backend.set_learning_phase(1)的作用是什么?另外,我设置了layers.trainbale=True,为什么在这种情况下BN层正常工作? 那么,为什么损失和val_loss仍然有很小的差异?由于样品相同,是什么原因引起的? 最后,我发现无论我使用tf.keras.backend.set_learning_phase(0)还是tf.keras.backend.set_learning_phase(1),结果都是相似且正常的。以下是tf.keras.backend.set_learning_phase(0)的结果:

1/1 [==============================] - 0s 242ms/step
-6.087581634521484
Train on 1 samples, validate on 1 samples
Epoch 1/10
 - 1s - loss: -6.0876e+00 - val_loss: -6.0775e+00
Epoch 2/10
 - 0s - loss: -6.0775e+00 - val_loss: -6.0925e+00
Epoch 3/10
 - 0s - loss: -6.0925e+00 - val_loss: -6.0908e+00
Epoch 4/10
 - 0s - loss: -6.0908e+00 - val_loss: -6.0883e+00

它与tf.keras.backend.set_learning_phase(1)有点不同,weber-api也要等待正确的解释。

我是深度学习和Keras的新手,我从Stack溢出中受益匪浅。就我的知识和英语而言。

谢谢您的帮助。

答案 1 :(得分:0)

答案 2 :(得分:0)

我想在pytorch中分享类似的发现。 首先,您的keras版本是什么?因为在2.1.3之后,设置BN层trainable = False将使BN在推理模式下的行为完全相同,这意味着它不会将输入归一化为0均值1方差(类似于训练模式),而是归一化为均值和方差。如果将学习阶段设置为1,则BN本质上成为实例范数,它忽略了运行均值和方差,只需将其归一化为0个均值和1个方差,这可能就是您想要的行为。

keras发行说明的参考链接:https://github.com/keras-team/keras/releases/tag/2.1.3

  

BatchNormalization中的API更改可训练属性现在禁用   批次统计信息的更新(即,如果可训练== False,则表示该层   现在将在推断模式下100%运行。