交叉熵与极大似然

前言

交叉熵这玩意儿,最开始接触是在 Andrew Ng 的机器学习课程中讲二分类问题的时候,当时并没有觉得有多难,用极大似然对其进行推导也非常的顺畅。后来直接用到多分类问题中,我也没细想,毕竟在 pytorch 中就是调用一个 CrossEntropyLoss() 的事儿。不过昨天我又重新想了想怎么从极大似然法推导交叉熵,这一想,就把整个人给绕进去了,困扰了大半天,终于想通了之前的理解哪里出了问题,遂写下这篇文章记录一下。

交叉熵定义

假设 X 是离散的随机变量,我们有两个分布列 p(x),q(x),交叉熵定义如下: (1)H(q,p)=xq(x)logp(x) 我们常说交叉熵能衡量两个分布之间的相似程度,也即交叉熵越小,p,q 两个分布越相似。事实上,如果我们固定 q,那么可以证明:H(q,p)p=q 时达到最小。(详见参考资料[2]

极大似然法推导交叉熵

交叉熵能用极大似然法解释。回忆极大似然法:我们有若干未知的参数 θ,现在想对其进行估计,那么抽取一个样本 {x(1),,x(n)},计算在参数 θ 下这个样本被抽取出来的概率。这个概率是参数 θ 的函数,称之为似然函数,当似然函数(或对数似然函数)取到最大值时,对应的参数值就是我们的估计值。

欲用极大似然法解释交叉熵,我们可以把 p(x) 视为想去估计的「参数」,q(x) 视为样本的真实概率分布。为方便,假设 X 是离散的随机变量。我们现在抽取一个容量为 n 的样本,设其中 X=k 出现了 nk 次,那么在参数 p(x),这个样本被抽取出来的概率是 L(p)=kp(k)nk,对数似然为:logL(p)=knklogp(k)。除以样本量再取个负号,得到: (2)1nlogL(p)=knknlogp(k)kq(k)logp(k) 其中,nknq(k) 是因为 q 才是样本的真实分布。这样我们就得到了交叉熵的形式,让交叉熵最小,就是让似然函数最大,也就是让 p(x) 更接近真实分布 q(x)

分类问题中的交叉熵损失函数

现在在分类问题的背景下看交叉熵与极大似然。

考虑一个特定的输入 ,不妨设是一只猫咪吧。其类别的真实分布是一个 向量(仅在“猫”那一维为 ,其余为 ),预测分布为 pred 向量。正如前文所述,交叉熵衡量两个分布的相似程度,因而我们可以用交叉熵 作损失函数。可以发现,交叉熵用在分类问题中形式变得很简单,这归功于 这个其实完全没有随机性的概率分布。换句话说,我们常常用的交叉熵损失函数,其实是特殊的、指定了其中一个分布为 形式的交叉熵

在分类问题的背景下,用极大似然法解释上述交叉熵,其实是一件很无聊的事,主要是因为真实分布是 。极大似然法需要我们抽一个样本出来(设样本量为 ),这里的样本空间就是所有类别,但由于我们现在考虑的是一个特定的输入 (猫咪),所以我们的样本一定是:猫、猫、……、猫。于是似然函数就是 ,对数似然就是 ,除以样本量取个负,就得到了

如果只考虑二分类问题,上文依旧是成立的,但是二分类嘛,我们没必要输出一个大小为 的向量,只用输出一个概率值 就 OK 了。所以可以对上文的交叉熵形式做一个改写: 其中 ,就得到了我们非常熟悉的 Binary Cross-Entropy 的形式。


那为什么我之前被困扰了大半天呢?因为我把样本空间弄混了。极大似然法这个方法本身要求我们做一个采样,而这里采样的对象,其实是某一个特定输入的真实标签,然后颇为无聊地反复采若干次……我之前以为是训练模型的过程中采出的 minibatch,结果当然就死活想不通。所以一定要注意「训练过程中对数据集采样得到 minibatch」 和「极大似然法中的采样」是不同的。


不过,前者也有值得一说的地方,设 minibatch 是 ,用 表示模型( 为输入 时模型的输出),则在训练过程中,计算一个 iteration 的平均 是这样的: 由于采样再求平均,其实是在近似一个期望,所以更通用的,上式可以写作: 其中 表示数据集的分布。这个样子好像在哪里见过?没错,GAN 的论文[1]中作者就是写了这么个期望:

只不过 GAN 中判别网络 D 只需要二分类,所以把两类拆开分别写出来罢了。

参考资料

  1. Generative Adversarial Nets https://arxiv.org/abs/1406.2661 ↩︎
  2. 为什么交叉熵(cross-entropy)可以用于计算代价? - 灵剑的回答 - 知乎 https://www.zhihu.com/question/65288314/answer/849294209 ↩︎

交叉熵与极大似然
https://xyfjason.github.io/blog-main/2021/08/20/交叉熵与极大似然/
作者
xyfJASON
发布于
2021年8月20日
许可协议