不是二元交叉熵中的二元基本事实标签吗?
Not binary ground truth labels in binary crossentropy?
二元交叉熵不使用二元地面真值有意义吗?有正式证明吗?
看起来像在实践中使用:例如在https://blog.keras.io/building-autoencoders-in-keras.html中,即mnist图像不是二值图像,而是灰度图像。
这是代码示例:
1.Normal 案例:
def test_1():
print('-'*60)
y_pred = np.array([0.5, 0.5])
y_pred = np.expand_dims(y_pred, axis=0)
y_true = np.array([0.0, 1.0])
y_true = np.expand_dims(y_true, axis=0)
loss = keras.losses.binary_crossentropy(
K.variable(y_true),
K.variable(y_pred)
)
print("K.eval(loss):", K.eval(loss))
输出:
K.eval(loss): [0.6931472]
2.Not 二元地面真值案例:
def test_2():
print('-'*60)
y_pred = np.array([0.0, 1.0])
y_pred = np.expand_dims(y_pred, axis=0)
y_true = np.array([0.5, 0.5])
y_true = np.expand_dims(y_true, axis=0)
loss = keras.losses.binary_crossentropy(
K.variable(y_true),
K.variable(y_pred)
)
print("K.eval(loss):", K.eval(loss))
输出:
K.eval(loss): [8.01512]
3.Ground 超出 [0,1] 范围的真值:
def test_3():
print('-'*60)
y_pred = np.array([0.5, 0.5])
y_pred = np.expand_dims(y_pred, axis=0)
y_true = np.array([-2.0, 2.0])
y_true = np.expand_dims(y_true, axis=0)
loss = keras.losses.binary_crossentropy(
K.variable(y_true),
K.variable(y_pred)
)
print("K.eval(loss):", K.eval(loss))
输出:
K.eval(loss): [0.6931472]
出于某种原因,test_1
和 test_3
中的损失是相同的,可能是因为将 [-2, 2] 剪切为 [0, 1] 但我看不到剪切代码喀拉斯代码。
同样有趣的是,test_1
和 test_2
损失值有很大差异,但在第一种情况下我们有 [0.5, 0.5] 和 [0.0, 1.0],在第二种情况下我们有 [0.0, 1.0] 和[0.5, 0.5],这是相同的值,但顺序相反。
在 Keras 中 binary_crossentropy
定义为:
def binary_crossentropy(y_true, y_pred):
return K.mean(K.binary_crossentropy(y_true, y_pred), axis=-1)
def binary_crossentropy(target, output, from_logits=False):
"""Binary crossentropy between an output tensor and a target tensor.
# Arguments
target: A tensor with the same shape as `output`.
output: A tensor.
from_logits: Whether `output` is expected to be a logits tensor.
By default, we consider that `output`
encodes a probability distribution.
# Returns
A tensor.
"""
# Note: tf.nn.sigmoid_cross_entropy_with_logits
# expects logits, Keras expects probabilities.
if not from_logits:
# transform back to logits
_epsilon = _to_tensor(epsilon(), output.dtype.base_dtype)
output = tf.clip_by_value(output, _epsilon, 1 - _epsilon)
output = tf.log(output / (1 - output))
return tf.nn.sigmoid_cross_entropy_with_logits(labels=target,
logits=output)
是的,它 "makes sense" 因为交叉熵是概率分布之间差异的度量。也就是说,any 分布(当然是在同一个样本 space 上)——目标分布是 one-hot 的情况实际上只是一个特例,尽管频率很高它用于机器学习。
一般来说,如果 p
是您的真实分布并且 q
是您的模型,则 q = p
的交叉熵最小化。因此,使用交叉熵作为损失将鼓励模型向目标分布收敛。
关于情况1和情况2的区别:交叉熵不是对称的。它实际上等于真实分布的熵p
加上p
和q
之间的KL散度。这意味着它通常会更大 p
更接近均匀(更少 "one-hot"),因为这样的分布具有更高的熵(我想 KL 散度也会不同,因为它不是对称的)。
至于case 3:这其实是把0.5当成output
的神器。事实证明,在交叉熵公式中,项将以完全相同的方式抵消,无论标签如何,您总是会得到相同的结果 (log(2)
)。当您使用 output != 0.5; 时,这会发生变化;在这种情况下,不同的标签会给你不同的交叉熵。例如:
output
0.3,target
2.0 给出交叉熵 2.0512707
output
0.3, target
-2.0 给出 -1.3379208 的交叉熵
第二种情况实际上给出了负输出,这没有任何意义。恕我直言,该函数允许 [0,1] 范围之外的目标是一种疏忽;这应该会导致崩溃。交叉熵公式工作得很好,但结果没有意义。
我还建议阅读 the wikipedia article 关于交叉熵的内容。它很短,但包含一些有用的信息。
二元交叉熵不使用二元地面真值有意义吗?有正式证明吗?
看起来像在实践中使用:例如在https://blog.keras.io/building-autoencoders-in-keras.html中,即mnist图像不是二值图像,而是灰度图像。
这是代码示例:
1.Normal 案例:
def test_1():
print('-'*60)
y_pred = np.array([0.5, 0.5])
y_pred = np.expand_dims(y_pred, axis=0)
y_true = np.array([0.0, 1.0])
y_true = np.expand_dims(y_true, axis=0)
loss = keras.losses.binary_crossentropy(
K.variable(y_true),
K.variable(y_pred)
)
print("K.eval(loss):", K.eval(loss))
输出:
K.eval(loss): [0.6931472]
2.Not 二元地面真值案例:
def test_2():
print('-'*60)
y_pred = np.array([0.0, 1.0])
y_pred = np.expand_dims(y_pred, axis=0)
y_true = np.array([0.5, 0.5])
y_true = np.expand_dims(y_true, axis=0)
loss = keras.losses.binary_crossentropy(
K.variable(y_true),
K.variable(y_pred)
)
print("K.eval(loss):", K.eval(loss))
输出:
K.eval(loss): [8.01512]
3.Ground 超出 [0,1] 范围的真值:
def test_3():
print('-'*60)
y_pred = np.array([0.5, 0.5])
y_pred = np.expand_dims(y_pred, axis=0)
y_true = np.array([-2.0, 2.0])
y_true = np.expand_dims(y_true, axis=0)
loss = keras.losses.binary_crossentropy(
K.variable(y_true),
K.variable(y_pred)
)
print("K.eval(loss):", K.eval(loss))
输出:
K.eval(loss): [0.6931472]
出于某种原因,test_1
和 test_3
中的损失是相同的,可能是因为将 [-2, 2] 剪切为 [0, 1] 但我看不到剪切代码喀拉斯代码。
同样有趣的是,test_1
和 test_2
损失值有很大差异,但在第一种情况下我们有 [0.5, 0.5] 和 [0.0, 1.0],在第二种情况下我们有 [0.0, 1.0] 和[0.5, 0.5],这是相同的值,但顺序相反。
在 Keras 中 binary_crossentropy
定义为:
def binary_crossentropy(y_true, y_pred):
return K.mean(K.binary_crossentropy(y_true, y_pred), axis=-1)
def binary_crossentropy(target, output, from_logits=False):
"""Binary crossentropy between an output tensor and a target tensor.
# Arguments
target: A tensor with the same shape as `output`.
output: A tensor.
from_logits: Whether `output` is expected to be a logits tensor.
By default, we consider that `output`
encodes a probability distribution.
# Returns
A tensor.
"""
# Note: tf.nn.sigmoid_cross_entropy_with_logits
# expects logits, Keras expects probabilities.
if not from_logits:
# transform back to logits
_epsilon = _to_tensor(epsilon(), output.dtype.base_dtype)
output = tf.clip_by_value(output, _epsilon, 1 - _epsilon)
output = tf.log(output / (1 - output))
return tf.nn.sigmoid_cross_entropy_with_logits(labels=target,
logits=output)
是的,它 "makes sense" 因为交叉熵是概率分布之间差异的度量。也就是说,any 分布(当然是在同一个样本 space 上)——目标分布是 one-hot 的情况实际上只是一个特例,尽管频率很高它用于机器学习。
一般来说,如果 p
是您的真实分布并且 q
是您的模型,则 q = p
的交叉熵最小化。因此,使用交叉熵作为损失将鼓励模型向目标分布收敛。
关于情况1和情况2的区别:交叉熵不是对称的。它实际上等于真实分布的熵p
加上p
和q
之间的KL散度。这意味着它通常会更大 p
更接近均匀(更少 "one-hot"),因为这样的分布具有更高的熵(我想 KL 散度也会不同,因为它不是对称的)。
至于case 3:这其实是把0.5当成output
的神器。事实证明,在交叉熵公式中,项将以完全相同的方式抵消,无论标签如何,您总是会得到相同的结果 (log(2)
)。当您使用 output != 0.5; 时,这会发生变化;在这种情况下,不同的标签会给你不同的交叉熵。例如:
output
0.3,target
2.0 给出交叉熵 2.0512707output
0.3,target
-2.0 给出 -1.3379208 的交叉熵
第二种情况实际上给出了负输出,这没有任何意义。恕我直言,该函数允许 [0,1] 范围之外的目标是一种疏忽;这应该会导致崩溃。交叉熵公式工作得很好,但结果没有意义。
我还建议阅读 the wikipedia article 关于交叉熵的内容。它很短,但包含一些有用的信息。