为什么 BinaryCrossentropy 作为损失和指标在使用 tf.keras (Tensorflow 2.0) 的分类器训练中不相同?

Why BinaryCrossentropy as loss and metrics are not identical in classifier training using tf.keras (Tensorflow 2.0)?

我使用 BinaryCrossentropy 作为损失和指标之一:

model.compile(
    optimizer=tf.keras.optimizers.Adam(learning_rate=1e-5), 
    loss=tf.keras.losses.BinaryCrossentropy(), 
    metrics=[tf.keras.metrics.BinaryCrossentropy(), tf.keras.metrics.AUC()])

既然是一样的东西,我觉得应该是一样的结果。 然而,它们分别在训练集和验证集上显示出略有不同的值。为什么是这样? BinaryCrossentropy 不应该对相同的数据具有相同的值吗?

有没有可能,损失值是最终batch上的损失,metric值是在epoch的所有batch上计算的(平均值?)?

我试图在tf.keras.Model.compile上找到相关信息,但我还无法确认这一点。

如果您使用与损失和度量相同的函数,您通常会在深度网络中看到不同的结果。这通常只是由于floating point precision errors:即使数学等式是等价的,但运算的顺序并不运行,这可能会导致微小的差异。

如果您考虑两者的简单示例,它会 return 相同的结果。

BinaryCrossentropy 作为指标:

m.update_state([[0, 1], [0, 0]], [[0.6, 0.4], [0.4, 0.6]])
m.result().numpy()

0.81492424

BinaryCrossentropy 作为损失:

y_true = [[0., 1.], [0., 0.]]
y_pred = [[0.6, 0.4], [0.4, 0.6]]
bce = tf.keras.losses.BinaryCrossentropy()
bce(y_true, y_pred).numpy()

0.81492424

对于每个批次和Epoch的计算,在计算上没有差异,但是在训练数据集和验证数据集上的计算存在差异。对于 val 集,它是在整个 val 数据集的纪元结束时计算的。对于训练集:它是在批次结束时计算的,平均值不断更新直到 epochs 结束。

只有在使用样本权重时,指标和损失的计算方法才会发生变化,不仅仅是精度误差,在你的情况下你没有像下面这样定义任何样本权重,否则它会超过浮点数精度误差:

sample_weight = np.random.rand(len(y_train))
history = model.fit(X_train_scaled, y_train, epochs=2, sample_weight=sample_weight)
  • 自纪元开始以来的损失是所有批次损失的平均值 到目前为止看到。每批损失是加权实例的总和 损失除以批量大小(不是权重之和,所以 批量损失不是损失的加权平均值)。
  • 自纪元开始以来的指标等于 加权实例损失除以目前看到的所有权重之和。 换句话说,它是所有实例损失的加权平均值。 不是一回事。如果你算一下,你会发现

    loss =metric * mean of sample weights (plus some floating point precision error)

希望这能解释您的问题,祝您学习愉快!