但是 dropout 层通常会产生相反的效果,使评估的损失小于训练期间的损失。
不必要!尽管在 dropout 层中,一些神经元被丢弃了,但请记住,输出会根据 dropout 率进行缩减。在推理时间(即测试时间)中,dropout 被完全删除,并且考虑到您只训练了一个时期的模型,您看到的行为可能会发生。不要忘记,由于您只训练了一个 epoch 的模型,因此只有一部分神经元被丢弃在 dropout 层中,但它们都在推理时出现。
如果您继续对模型进行更多时期的训练,您可能会期望训练损失和测试损失(在相同数据上)变得或多或少相同。
自己试验一下:只需将trainable
Dropout 层的参数设置为False
,看看是否会发生这种情况。
看到一个时期的训练后,训练损失不等于同一批次数据的评估损失,人们可能会感到困惑(就像我一样)。这并不特定于具有Dropout
或BatchNormalization
层的模型。考虑这个例子:
from keras import layers, models
import numpy as np
model = models.Sequential()
model.add(layers.Dense(1000, activation='relu', input_dim=100))
model.add(layers.Dense(1))
model.compile(loss='mse', optimizer='adam')
x = np.random.rand(32, 100)
y = np.random.rand(32, 1)
print("Training:")
model.fit(x, y, batch_size=32, epochs=1)
print("\nEvaluation:")
loss = model.evaluate(x, y)
print(loss)
输出:
Training:
Epoch 1/1
32/32 [==============================] - 0s 7ms/step - loss: 0.1520
Evaluation:
32/32 [==============================] - 0s 2ms/step
0.7577340602874756
那么,如果它们是根据相同的数据计算的,为什么损失会不同,即0.1520 != 0.7577
?
如果你问这个,那是因为你和我一样,没有引起足够的重视:那0.1520
是更新模型参数之前的损失(即在做反向传播或反向传播之前)。0.7577
是模型权重更新后的损失。即使使用的数据相同,计算这些损失值时模型的状态也不相同(另一个问题:那么为什么反向传播后损失增加了?这仅仅是因为您只训练了一个 epoch因此权重更新还不够稳定)。
为了确认这一点,您还可以使用与验证数据相同的数据批次:
model.fit(x, y, batch_size=32, epochs=1, validation_data=(x,y))
如果您使用上面修改过的行运行上面的代码,您将得到如下输出(显然,确切的值可能对您不同):
Training:
Train on 32 samples, validate on 32 samples
Epoch 1/1
32/32 [==============================] - 0s 15ms/step - loss: 0.1273 - val_loss: 0.5344
Evaluation:
32/32 [==============================] - 0s 89us/step
0.5344240665435791
您会看到验证损失和评估损失完全相同:这是因为验证是在 epoch 结束时执行的(即当模型权重已经更新时)。