keras.losses.binary_crossentropy 输出张量的形状

shape of output tensor by keras.losses.binary_crossentropy

我想在binary_crossEntropy的基础上在keras中实现自定义损失函数。我对 Keras.losses.binary_crossentropy 的输出 tnesor 的形状有疑问。我希望它应该是长度为 batch_size 的一维张量。但它 returns 是一个形状为 [batch size, 类] 的张量,所有 类 的每一行都有相同的损失量。 我应该沿行手动使用 max 吗?有没有更好的办法? 为什么 K.binary_crossentropy 的输出不是一维张量?它与数学概念有关吗?

def custom_loss(y_true, y_pred):
    loss_tensor = K.binary_crossentropy(y_true, y_pred)
    # return K.max(loss_tensor, axis=1)
    return  loss_tensor

# model.compile(loss={'classifier':'kullback_leibler_divergence'},optimizer='Nadam',metrics=['acc'])


tmp_y_true = tf.constant([[0.0, 1.0], [1.0, 0.0]])
tmp_y_pred = tf.constant([[0.8, 0.2], [0.75, 0.25]])
output = custom_loss(tmp_y_true, tmp_y_pred)
tmp_out = K.eval(output)

二进制 cross-entropy 是一个容易混淆的名字。从每个数据点获得 01 的意义上来说,这并不意味着二进制。它用于 multi-class 问题。例如。预测图像是否具有 0 dogs, 0 cats1 dog, 0 cats0 dogs, 1 cat1 dog, 1 cat。每个 class 都有自己单独的预测是否存在。损失是二进制的,因为每个 class 都是二进制的(存在或不存在)。所以预期的输出形状是 [batch size, classes].

查看更多信息:

binary_crossentropy的计算公式为

−(ylog(p)+(1−y)log(1−p))

but it returns a tensor with shape of [batch size, classes] with identical loss amount in each row for all classes.

这是因为 binary_crossentropy 应用于每个位置。以提供的示例中的第一组为例,y_true = [0.0, 1.0] 和 y_pred = [0.8, 0.2]

y_true = 0, y_pred = 0.8,应用公式,loss = -(0 * log(0.8) + 1 * log(1 - 0.8)) = 1.609

y_true = 1, y_pred = 0.2,应用公式,loss = -(1 * log(0.2) + 0 * log(1 - 0.2)) = 1.609

>>> y_true = tf.constant([0.0, 1.0])
>>> y_pred = tf.constant([0.8, 0.2])
>>> K.eval(K.binary_crossentropy(y_true, y_pred))
array([1.6094381, 1.609438 ], dtype=float32)

should i manually use max along rows?

否,因为值是 one-hot 编码的,所以必须取平均值。

>>> K.eval(K.mean(K.binary_crossentropy(y_true, y_pred), axis=-1))
1.609438

https://github.com/keras-team/keras/blob/ed07472bc5fc985982db355135d37059a1f887a9/keras/losses.py#L76

或者,可以使用 categorical_crossentropy,因为值是 one-hot 编码的。

>>> K.eval(K.categorical_crossentropy(y_true, y_pred))
1.609438