Keras 损失和度量值在每个函数中与相同的函数不匹配

use*_*538 5 python deep-learning keras tensorflow

我正在使用具有自定义损失函数的 keras,如下所示:

def custom_fn(y_true, y_pred):
   # changing y_true, y_pred values systematically
   return mean_absolute_percentage_error(y_true, y_pred)
   
Run Code Online (Sandbox Code Playgroud)

然后,我打电话model.compile(loss=custom_fn)model.fit(X, y,..validation_data=(X_val, y_val)..)

Keras 然后保存loss并保存val_loss在模型历史中。作为健全性检查,当模型完成训练时,我正在使用,model.predict(X_val)因此我可以custom_fn使用经过训练的模型手动计算验证损失。

我正在使用此回调保存具有最佳时代的模型:

callbacks.append(ModelCheckpoint(path, save_best_only=True, monitor='val_loss', mode='min'))
Run Code Online (Sandbox Code Playgroud)

所以在计算这个之后,验证损失应该与 kerasval_loss的最佳时期的值相匹配。但这并没有发生。

作为解决这个问题的另一种尝试,我也在这样做:

    model.compile(loss=custom_fn, metrics=[custom_fn])
Run Code Online (Sandbox Code Playgroud)

令我惊讶的是,val_lossval_custom_fn没有匹配(无论是lossloss_custom_fn就此而言)。

这真的很奇怪,我custom_fn的本质上是 keras 内置mapey_true并且y_pred稍微被操纵。这里发生了什么?

PS:我使用的LSTM层是层和最后Dense一层。但我认为这些信息与问题无关。我也使用正则化作为超参数,但不使用 dropout。

更新

甚至删除custom_fn和使用 keras 内置mape的损失函数和度量,如下所示:

model.compile(loss='mape', metrics=['mape'])
Run Code Online (Sandbox Code Playgroud)

为简单起见,删除ModelCheckpoint回调具有相同的效果;val_loss并且val_mape对于每个 epoch 都不是等价的。这对我来说非常奇怪。我要么遗漏了一些东西,要么 Keras 代码中有一个错误……前者可能更现实。

use*_*538 5

这篇博文建议 keras 在计算验证损失时添加训练中使用的任何正则化。显然,在计算选择的度量时,没有应用正则化。这就是问题中所述的任何选择损失函数都会发生这种情况的原因。

我在 Keras 上找不到任何相关文档。然而,它似乎成立,因为当我删除所有正则化超参数时, 和val_lossval_custom_fn每个时期都完全匹配。

一个简单的解决方法是使用 作为度量并基于度量 ( ) 而不是基于custom_fn保存最佳模型。或者手动循环每个时期并在训练每个时期后手动计算正确的值。后者似乎更有意义,因为没有理由同时包含作为度量和损失函数。val_custom_fnval_lossval_losscustom_fn

如果有人可以在 Keras 文档中找到任何这方面的证据,那将会很有帮助。