为什么 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)
希望这能解释您的问题,祝您学习愉快!
我使用 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)
希望这能解释您的问题,祝您学习愉快!