我已经成功训练了超过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的参数相同。
有人可以给我一些建议吗?非常感谢您的提前帮助。 对不起,我的英语,但是我尽力解释了我的问题。
答案 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)
我在这里找到了可能的解释: https://github.com/keras-team/keras/pull/9965 和这里: https://github.com/keras-team/keras/issues/9214
答案 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%运行。