Tensorflow evaluate 给出的误差比训练的最后一个 epoch 大

Tensorflow evaluate gives larger error than last epoch of training

我有一个 TensorFlow 回归模型。我认为模型层的细节与问题无关,所以我跳过了。如果您认为它有用,我可以添加。

我用下面的代码编译。损失和指标是均方误差。

model.compile(
    loss=tf.keras.losses.MeanSquaredError(), optimizer=tf.keras.optimizers.Adam(lr=0.001),
    metrics=['mse']
)

现在,我 运行 下面的代码来训练网络并对其进行评估。我训练它 2 个时期,然后我使用 evaluate 方法评估相同数据的模型,然后使用 predict 方法和 MSE 公式手动评估它。

print('fit')
model.fit(X, y, epochs=2, batch_size=32)

print('evaluate')
print(model.evaluate(X, y))

print('manual evaluate')
print(((y - model.predict(X).ravel()) ** 2).mean())

结果如下:

3152/3152 [==============================] - 12s 3ms/step - loss: 7.7276 - mse: 7.7275
Epoch 2/2
3152/3152 [==============================] - 11s 4ms/step - loss: 0.9898 - mse: 0.9894
evaluate
3152/3152 [==============================] - 2s 686us/step - loss: 1.3753 - mse: 1.3748
[1.3753225803375244, 1.3747814893722534]
manual evaluate
1.3747820755885116

我有轻微的正则化,所以损失比预期的 mse 大一点。

但是,如您所见,MSE 在最后一个 epoch 结束时为 0.98。但是,当我通过 evaluate 方法评估它或当我实际手动计算它时,我得到 1.37 MSE。据我所知,该模型使用最后一个纪元之后的权重,所以这两个数字应该相等,对吗?我在这里缺少什么?我尝试了不同的 batch_size 和纪元计数。在拟合方法的最后一个时期,评估的 MSE 总是高于 MSE。

注:y是一维NumPy数组

y.shape
> (100836,)

编辑:我 运行 带有 validation_data 参数的 fit 方法使用相同的 (X, y) 作为验证数据:

model.fit(X, y, epochs=2, batch_size=32, validation_data=(X, y))

输出:

Epoch 1/2
3152/3152 [==============================] - 23s 7ms/step - loss: 7.9766 - mse: 7.9764 - val_loss: 2.0284 - val_mse: 2.0280
Epoch 2/2
3152/3152 [==============================] - 22s 7ms/step - loss: 0.9839 - mse: 0.9836 - val_loss: 1.3436 - val_mse: 1.3431
evaluate
[1.3436073064804077, 1.3430677652359009]

现在,它有些道理了。最后一个纪元的 val_mse 似乎与 evaluate 结果匹配。但是,我期望进度条中的 mseval_mse 值相同,因为训练数据和验证数据相同。我认为我对进度条显示的内容的理解不正确。谁能解释一下我应该如何解释进度条以及为什么进度条上的 mseval_mse 值不同?

对于相同的数据,在训练和验证步骤中指标(在您的情况下为损失)不同的原因很简单。即,在训练您的模型 trains 期间,通过逐批更改其参数。在进度条中,您会看到所有批次的指标的 mean。相反,在 validation 步骤期间,您的网络参数被冻结。使用的参数是在处理网络看到的最后一批之后获得的参数。这解释了差异。

为什么验证损失结果是更大的训练损失这个问题很微妙。一个原因可能是您的模型具有在训练和验证期间表现不同的层(例如,Frightera 注意到的 BatchNorm)。另一个原因可能是学习率不当。如果太大,参数将变化太多,从而跳过真正的最小值。即使使用 adam 优化,情况也可能如此。

要了解问题是否与学习率有关,请尝试将其调小得多。如果指标的差异持续存在,那么您的网络层在训练和验证阶段表现不同。

指标差异可能还有其他原因。例如,训练数据有噪声,导致网络无法很好地训练。这会导致损失在均值附近波动,这是正常的。要了解是否属于这种情况,您应该研究不同批次的损失图(例如,使用 TensorBoard)。