交叉熵是什么?

116

我知道有很多关于交叉熵的解释,但我仍然感到困惑。

它只是描述损失函数的一种方法吗?我们可以使用梯度下降算法利用损失函数来找到最小值吗?


13
不适合在SO上发布。这里有一个关于数据科学的姐妹站点的类似问题:http://datascience.stackexchange.com/questions/9302/the-cross-entropy-error-function-in-neural-networks - Metropolis
对于一个简单的、非数学解释,请参考 https://towardsdatascience.com/cross-entropy-classification-losses-no-math-few-stories-lots-of-intuition-d56f8c7f06b0 - Allohvk
3个回答

280
跨熵通常用于量化两个概率分布之间的差异。在机器学习领域,它是一种用于分类多类问题中的误差度量。通常,“真实”分布(即您的机器学习算法尝试匹配的分布)用一位有效的分布来表示。
例如,假设对于一个特定的训练实例,真实标签为B(可能的标签为A,B和C)。因此,该训练实例的一位有效分布为:
Pr(Class A)  Pr(Class B)  Pr(Class C)
        0.0          1.0          0.0

你可以将上述真实分布解释为,训练实例属于A类的概率为0%,属于B类的概率为100%,属于C类的概率为0%。
现在,假设你的机器学习算法预测以下概率分布:
Pr(Class A)  Pr(Class B)  Pr(Class C)
      0.228        0.619        0.153

预测分布与实际分布的接近程度由交叉熵损失函数来确定。使用以下公式:

Cross entropy loss formula

其中p(x)是真实的概率分布(one-hot),q(x) 是预测的概率分布。求和范围是三个类别 A、B 和 C。在这种情况下,损失为0.479

H = - (0.0*ln(0.228) + 1.0*ln(0.619) + 0.0*ln(0.153)) = 0.479

对数底

请注意,只要您始终使用相同的对数底,使用哪种对数底并不重要。恰巧,Python Numpy log() 函数计算自然对数(以e为底)。

Python 代码

以下是上述示例使用 Numpy 在 Python 中表达的方式:

import numpy as np

p = np.array([0, 1, 0])             # True probability (one-hot)
q = np.array([0.228, 0.619, 0.153]) # Predicted probability

cross_entropy_loss = -np.sum(p * np.log(q))
print(cross_entropy_loss)
# 0.47965000629754095

这就是您的预测与真实分布之间“错误”或“偏离”的方式。机器学习优化器将尝试最小化损失(即它将尝试将损失从0.479减少到0.0)。

损失单位

从上面的例子中,我们可以看到损失为0.4797。因为我们使用的是自然对数(以e为底的对数),所以单位为nats,因此我们说损失为0.4797 nats。如果对数是以2为底的,则单位为比特。请参见this page以获取进一步的解释。

更多例子

为了更好地理解这些损失值反映了什么,让我们看一些极端的例子。

同样,假设真实的(one-hot)分布是:

Pr(Class A)  Pr(Class B)  Pr(Class C)
        0.0          1.0          0.0

现在假设你的机器学习算法表现得非常出色,以非常高的概率预测了B类:

Pr(Class A)  Pr(Class B)  Pr(Class C)
      0.001        0.998        0.001

当我们计算交叉熵损失时,可以看到损失非常小,仅为0.002:
p = np.array([0, 1, 0])
q = np.array([0.001, 0.998, 0.001])
print(-np.sum(p * np.log(q)))
# 0.0020020026706730793

在另一个极端,假设您的机器学习算法表现很差,高概率地预测了C类。由此产生的6.91损失将反映更大的错误。
Pr(Class A)  Pr(Class B)  Pr(Class C)
      0.001        0.001        0.998

p = np.array([0, 1, 0])
q = np.array([0.001, 0.001, 0.998])
print(-np.sum(p * np.log(q)))
# 6.907755278982137

现在,这两个极端之间会发生什么?假设您的机器学习算法无法下定决心,并以几乎相等的概率预测三个类别。
Pr(Class A)  Pr(Class B)  Pr(Class C)
      0.333        0.333        0.334

导致的损失为1.10。

p = np.array([0, 1, 0])
q = np.array([0.333, 0.333, 0.334])
print(-np.sum(p * np.log(q)))
# 1.0996127890016931

适合梯度下降

交叉熵是众多可能的损失函数之一(另一个流行的是SVM hinge loss)。这些损失函数通常被写成J(theta),可以在梯度下降中使用,这是一种迭代算法,用于将参数(或系数)移向最优值。在下面的方程中,您需要用H(p, q)替换J(theta)。但请注意,您需要先计算H(p,q)相对于参数的导数。

gradient descent

所以直接回答您最初的问题:

这只是一种描述损失函数的方法吗?

是的,交叉熵描述了两个概率分布之间的损失。它是许多可能损失函数之一。

那么我们可以使用例如梯度下降算法来找到最小值。

是的,交叉熵损失函数可以作为梯度下降的一部分使用。

进一步阅读:我其他答案中与TensorFlow相关的内容。


@theateist:通常不使用余弦(不)相似度。 - stackoverflowuser2010
1
显然这不是最佳解决方案,但我只是想理论上知道我们是否可以使用“余弦(不)相似度”来描述角度误差,然后尝试最小化角度。 - theateist
2
@Stephen:如果你看一下我给出的例子,p(x)将是每个类别的真实概率列表,即 [0.0, 1.0, 0.0]。同样,q(x)是每个类别的预测概率列表,即 [0.228, 0.619, 0.153]。然后,H(p, q)就是 - (0 * log(2.28) + 1.0 * log(0.619) + 0 * log(0.153)),计算结果为0.479。请注意,通常使用Python的np.log()函数,它实际上是自然对数;这并不重要。 - stackoverflowuser2010
这可能听起来很傻,但是为什么我们要计算其他类别(在独热编码中),当我们知道我们只对当前真实类别的概率分布感兴趣时呢? ln(0.619)的结果相同。 - HAr
1
@HAr:对于真实标签的独热编码,我们只关心一个非零类别。然而,交叉熵可以比较任意两个概率分布;并不需要其中一个具有独热概率。 - stackoverflowuser2010
显示剩余19条评论

5
简而言之,交叉熵是衡量预测值与真实标签之间差距的度量。

这里的交叉指的是计算两个或多个特征/真实标签(如0、1)之间的熵。
而熵本身指的是随机性,因此它的值越大,意味着你的预测与真实标签相差越远。
因此,权重被改变以减少CE,从而最终导致预测和真实标签之间的差异减小,从而提高准确性。

3

在上述文章的基础上,最简单的交叉熵损失形式被称为二元交叉熵(用于二进制分类的损失函数,例如,逻辑回归),而广义版本则是类别交叉熵(用于多类分类问题的损失函数,例如神经网络)。

思路保持不变:

  1. 当模型计算出来的(softmax)类概率接近于目标标签时(使用one-hot编码表示的训练实例,例如),相应的CCE损失减少为零

  2. 否则,随着与目标类相对应的预测概率变小,它会增加。

以下图示说明了这个概念(请注意从图中可以看出,当y和p都高或同时都低时,BCE变得很低,即存在一致性):

enter image description here

交叉熵相对熵KL散度密切相关,计算两个概率分布之间的距离。例如,在两个离散pmf之间的关系如下图所示:

enter image description here


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接