深度学习必须熟悉的损失函数:交叉熵损失函数

深度学习必须熟悉的损失函数:交叉熵损失函数人类却能够根据明显的犯错快速地学习到正确的东西。相反,在我们的错误不是很好地定义的时候,学习的过程会变得更加缓慢。但神经网络却不一定如此,这种行为看起来和人类学习行为差异很大。人工神经元在其犯错较大的情况下其实学习很有难度。 为了理解这个问题的源头,想想我们的神经元是通过改变权…

望江人工智库

深度学习系列文章

为什么需要交叉熵代价函数

人类却能够根据明显的犯错快速地学习到正确的东西。相反,在我们的错误不是很好地定义的时候,学习的过程会变得更加缓慢。但神经网络却不一定如此,这种行为看起来和人类学习行为差异很大。人工神经元在其犯错较大的情况下其实学习很有难度。

为了理解这个问题的源头,想想我们的神经元是通过改变权重和偏置,并以一个代价函数的偏导数 \partial C/\partial w\partial C/\partial b 决定的速度学习。所以,我们在说“学习缓慢”时,实际上就是说这些偏导数很小。

用上一章《反向传播算法》的符号定义,对于二次代价函数,输出层的权重的偏导数为

\frac{\partial C}{\partial w^L_{jk}} = \frac{1}{n}
   \sum_x a^{L-1}_k  (a^L_j-y_j) \sigma'(z^L_j)

\sigma'(z^L_j) 会在一个输出神经元困在错误值时导致学习速度的下降。

深度学习必须熟悉的损失函数:交叉熵损失函数

我们可以从这幅图看出,当神经元的输出接近 1 的时候,曲线变得相当平,所以\sigma'(z) 就很小了。上面式子中的 \frac{\partial C}{\partial w^L_{jk}} 也会非常小。这其实就是学习缓慢的原因所在。而且,我们后面也会提到,这种学习速度下降的原因实际上也是更加一般的神经网络学习缓慢的原因,并不仅仅是在这个特例中特有的。

注意,在输出层使用线性神经元时使用二次代价函数。假设我们有一个多层多神经元网络,最终输出层的神经元都是线性神经元,输出不再是S型函数作用的结果,而是 a^L_j = z^L_j。如果我们使用二次代价函数,那么对单个训练样本 x 的输出误差就是

\delta^L = a^L-y

这表明如果输出神经元是线性的那么二次代价不再会导致学习速度下降的问题。在此情形下,二次代价函数就是一种合适的选择。

但是如果输出神经元是S型函数作用的结果,我们就最好考虑其他的代价函数。

交叉熵代价函数的定义

那么我们如何解决这个问题呢?研究表明,我们可以通过使用交叉熵函数来替换二次代价函数。为了理解什么是交叉熵,我们稍微改变一下之前的简单例子。假设,我们现在要训练一个包含若干输入变量的的神经元,x_1, x_2, \ldots 对应的权重为 w_1,w_2, \ldots 和偏置 b

深度学习必须熟悉的损失函数:交叉熵损失函数

神经元的输出就是 a = \sigma(z),其中 z = \sum_j w_j x_j+b 是输入的带权和。我 们如下定义这个神经元的交叉熵代价函数:

C = -\frac{1}{n} \sum_x \left[y \ln a + (1-y ) \ln (1-a) \right]

其中 n 是训练数据的总数,求和是在所有的训练输入 x 上进行的,y 是对应的目标输出。

对于交叉熵代价函数,针对一个训练样本 x 的输出误差 \delta^L

\delta^L = a^L-y

关于输出层的权重的偏导数为

\frac{\partial C}{\partial w^L_{jk}} = \frac{1}{n} \sum_x
    a^{L-1}_k  (a^L_j-y_j)

这里 \sigma'(z^L_j) 就消失了,所以交叉熵避免了学习缓慢的问题。

那么我们应该在什么时候用交叉熵来替换二次代价函数?实际上,如果在输出神经元是S时,交叉熵一般都是更好的选择。为什么?考虑一下我们初始化网络的权重和偏置的时候通常使用某种随机方法。可能会发生这样的情况,这些初始选择会对某些训练输入误差相当明显,比如说,目标输出是 1,而实际值是深度学习必须熟悉的损失函数:交叉熵损失函数0,或者完全反过来。如果我们使用二次代价函数,那么这就会导致学习速度的下降。它并不会完全终止学习的过程,因为这些权重会持续从其他的样本中进行学习,但是显然这不是我们想要的效果。

交叉熵在分类问题中的应用

交叉熵损失函数应用在分类问题中时,不管是单分类还是多分类,类别的标签都只能是 0 或者 1。

交叉熵在单分类问题中的应用

这里的单类别是指,每一张图像样本只能有一个类别,比如只能是狗或只能是猫。交叉熵在单分类问题上基本是标配的方法

loss = -\sum_{i=1}^ny_i log(\hat{y}_i)

上式为一张样本的 loss 计算方法。式中 n 代表着 n 种类别。举例如下,

深度学习必须熟悉的损失函数:交叉熵损失函数

交叉熵在多标签问题中的应用

这里的多类别是指,每一张图像样本可以有多个类别,比如同时包含一只猫和一只狗和单分类问题的标签不同,多分类的标签是n-hot。

深度学习必须熟悉的损失函数:交叉熵损失函数

值得注意的是,这里的Pred采用的是sigmoid函数计算。将每一个节点的输出归一化到[0,1]之间。所有Pred值的和也不再为1。换句话说,就是每一个Label都是独立分布的,相互之间没有影响。所以交叉熵在这里是单独对每一个节点进行计算,每一个节点只有两种可能值,所以是一个二项分布。前面说过对于二项分布这种特殊的分布,熵的计算可以进行简化。

同样的,交叉熵的计算也可以简化,即

loss =-ylog(\hat{y})-(1-y)log(1-\hat{y})

注意,上式只是针对一个节点的计算公式。这一点一定要和单分类loss区分开来。

深度学习必须熟悉的损失函数:交叉熵损失函数

交叉熵代价函数对权重求导的证明

交叉熵代价函数的定义:

C = -\frac{1}{n} \sum_x \left[y \ln a + (1-y ) \ln (1-a) \right]

代价函数 Cw^L_{jk} 求偏导

\begin{aligned}
\frac{\partial C}{\partial w_{jk}^L} &= -\frac{1}{n} \sum_x \left(
  \frac{y^L_j }{\sigma(z^L_j)} -\frac{(1-y^L_j)}{1-\sigma(z^L_j)} \right)
  \frac{\partial \sigma(z^L_j)}{\partial w_{jk}^L} \\
  &= -\frac{1}{n} \sum_x \left(
  \frac{y^L_j }{\sigma(z^L_j)} -\frac{(1-y^L_j)}{1-\sigma(z^L_j)} \right)\sigma'(z^L_j) a_k^{L-1} \\
&=\frac{1}{n} \sum_x \frac{\sigma'(z^L_j)
    a_k^{L-1}}{\sigma(z^L_j) (1-\sigma(z^L_j))} (\sigma(z^L_j)-y_j)
\end{aligned}

其中\frac{\partial z^l_j}{\partial w^l_{jk}} = a_k^{l-1} 来自,根据 z_j^l 定义

z^l_j=\sum_k w^l_{jk} a^{l-1}_k+b^l_j

所以

\frac{\partial z^l_j}{\partial w^l_{jk}} = a_k^{l-1}

根据 \sigma(z) = 1/(1+e^{-z}) 的定义,

\begin{aligned}
\sigma'(z) &= (\frac{1}{1+e^{-z}})'
\\
&= \frac{e^{-z}}{(1+e^{-z})^{2}}
\\
&= \frac{1+e^{-z}-1}{(1+e^{-z})^{2}}  
\\
&= \frac{1}{(1+e^{-z})}(1-\frac{1}{(1+e^{-z})})
\\
&= \sigma(z)(1-\sigma(z))
\\
\end{aligned}

\sigma'(z) 带入 \frac{\partial C}{\partial w_j} 可得

\frac{\partial C}{\partial w^L_{jk}} = \frac{1}{n} \sum_xa^{L-1}_k  (a^L_j-y_j)

其向量形式是

\frac{\partial C}{\partial w^L} =  \frac{1}{n} \sum_x a_j^{L-1}(\sigma(z^L)-y)

对偏置用同样的方法可得

\frac{\partial C}{\partial b^L_{j}} = \frac{1}{n} \sum_x (a^L_j-y_j)

交叉熵的含义和来源

我们对于交叉熵的讨论聚焦在代数分析和代码实现。这虽然很有用,但是也留下了一个未能回答的更加宽泛的概念上的问题,如:交叉熵究竟表示什么?存在一些直觉上的思考交叉熵的方法吗?我们如何想到这个概念?

让我们从最后一个问题开始回答:什么能够激发我们想到交叉熵?假设我们发现学习速度下降了,并理解其原因是因为对于二次代价函数,输出层的权重的偏导数为

\frac{\partial C}{\partial w^L_{jk}} = \frac{1}{n}
   \sum_x a^{L-1}_k  (a^L_j-y_j) \sigma'(z^L_j)

\sigma'(z^L_j) 会在一个输出神经元困在错误值时导致学习速度的下降。在研究了这些公式后,我们可能就会想到选择一个不包含 \sigma'(z) 的代价函数。所以,这时候对一个训练样本 x,其代价 C = C_x 满足:

\frac{\partial C}{\partial w_j} = a_j^{L-1}(a^L_j-y)
\frac{\partial C}{\partial b } = (a-y)

如果我们选择的损失函数满足这些条件,那么它们就能以简单的方式呈现这样的特性:初始误差越大,神经元学习得越快。这也能够解决学习速度下降的问题。实际上,从这些公式开始,现在我们就看看凭着我们数学的直觉推导出交叉熵的形式是可行的。我们来推一下,由链式法则,我们有

\frac{\partial C}{\partial b} = \frac{\partial C}{\partial a}
  \sigma'(z)

使用 \sigma'(z) = \sigma(z)(1-\sigma(z)) = a(1-a),上个等式就变成

\frac{\partial C}{\partial b} = \frac{\partial C}{\partial a}a(1-a)

对比等式,我们有

\frac{\partial C}{\partial a} = \frac{a-y}{a(1-a)}

对此方程关于 a 进行积分,得到

C = -[y \ln a + (1-y) \ln (1-a)]+ {\rm constant}

其中 constant 是积分常量。这是一个单独的训练样本 x 对损失函数的贡献。为了得到整个的损失函数,我们需要对所有的训练样本进行平均,得到了

C = -\frac{1}{n} \sum_x [y \ln a +(1-y) \ln(1-a)] + {\rm constant}

而这里的常量就是所有单独的常量的平均。所以我们看到方程

\frac{\partial C}{\partial w_j} = a_j^{L-1}(a^L_j-y)
\frac{\partial C}{\partial b } = (a-y)

唯一确定了交叉熵的形式,并加上了一个常量的项。这个交叉熵并不是凭空产生的。而是一种我们以自然和简单的方法获得的结果。

那么交叉熵直觉含义又是什么?我们如何看待它?深入解释这一点会将我们带到一个不大愿意讨论的领域。然而,还是值得提一下,有一种源自信息论的解释交叉熵的标准方式。粗略地说,交叉熵是“不确定性”的一种度量。特别地,我们的神经元想要计算函数 x \rightarrow y = y(x)。但是,它用函数x\rightarrow a = a(x) 进行了替换。假设我们将 a 想象成我们神经元估计为 y = 1 的概率,而 1-a 则是 y=0 的概率。那么交叉熵衡量我们学习到 y 的正确值的平均起来的不确定性。 如果输出我们期望的结果,不确定性就会小一点;反之,不确定性就大一些。当然,我这里没有严格地给出“不确定性”到底意味着什么,所以看起来像在夸夸其谈。但是实际上,在信息论中有一种准确的方式来定义不确定性究竟是什么。详细内容请看交叉熵(cross-entropy)的数学历史。

交叉熵(cross-entropy)的数学历史

通用的说,熵(Entropy)被用于描述一个系统中的不确定性(the uncertainty of a system)。在不同领域熵有不同的解释,比如热力学的定义和信息论也不大相同。

先给出一个”不严谨”的概念表述:

  • 熵:可以表示一个事件A的自信息量,也就是A包含多少信息。
  • KL散度:可以用来表示从事件A的角度来看,事件B有多大不同。
  • 交叉熵:可以用来表示从事件A的角度来看,如何描述事件B。

一句话总结的话:KL散度可以被用于计算代价,而在特定情况下最小化KL散度等价于最小化交叉熵。而交叉熵的运算更简单,所以用交叉熵来当做代价。

信息量

首先是信息量。假设我们听到了两件事,分别如下:
事件A:巴西队进入了2018世界杯决赛圈。
事件B:中国队进入了2018世界杯决赛圈。
仅凭直觉来说,显而易见事件B的信息量比事件A的信息量要大。究其原因,是因为事件A发生的概率很大,事件B发生的概率很小。所以当越不可能的事件发生了,我们获取到的信息量就越大。越可能发生的事件发生了,我们获取到的信息量就越小。那么信息量应该和事件发生的概率有关。

假设 X 是一个离散型随机变量,其取值集合为 \chi ,概率分布函数 p(x)=Pr(X=x),x\in\chi ,则定义事件 X=x_0 的信息量为:

I(x_0)=-log(p(x_0))

由于是概率所以p(x_0)的取值范围是[0,1], 绘制为图形如下:

深度学习必须熟悉的损失函数:交叉熵损失函数

什么是熵(Entropy)?

放在信息论的语境里面来说,就是一个事件所包含的信息量。我们现在有了信息量的定义,而熵用来表示所有信息量的期望,即:

因此熵被定义为 S(x)=-\sum_{i}P(x_{i})log_{b}P(x_{i})

如何衡量两个事件/分布之间的不同:KL散度

我们上面说的是对于一个随机变量x的事件A的自信息量,如果我们有另一个独立的随机变量x相关的事件B,该怎么计算它们之间的区别?

此处我们介绍默认的计算方法:KL散度,有时候也叫KL距离,一般被用于计算两个分布之间的不同。看名字似乎跟计算两个点之间的距离也很像,但实则不然,因为KL散度不具备有对称性。在距离上的对称性指的是A到B的距离等于B到A的距离。

KL散度的数学定义:

相对熵又称KL散度,如果我们对于同一个随机变量 x 有两个单独的概率分布 P(x) 和 Q(x),我们可以使用 KL 散度(Kullback-Leibler (KL) divergence)来衡量这两个分布的差异

维基百科对相对熵的定义

In the context of machine learning, DKL(P‖Q) is often called the information gain achieved if P is used instead of Q.

对于离散事件我们可以定义事件A和B的差别为:

D_{KL}(A||B) = \sum_{i}P_{A}(x_i) log\bigg(\frac{P_{A}(x_i)}{P_{B}(x_i)} \bigg) = \sum_{i}P_{A}(x_i)log(P_{A}(x_i ))- P_{A}(x_i)log(P_{B}(x_i))

对于连续事件,那么我们只是把求和改为求积分而已。

D_{KL}(A||B) = \int a(x) log\bigg(\frac{a(x)}{b(x)} \bigg)

从公式中可以看出:

  • 如果 P_A=P_B,即两个事件分布完全相同,那么KL散度等于0。
  • 观察公式,可以发现减号左边的就是事件A的熵,请记住这个发现。
  • 如果颠倒一下顺序求 D_{KL}(B||A),那么就需要使用B的熵,答案就不一样了。所以KL散度来计算两个分布A与B的时候是不是对称的,有“坐标系”的问题**,D_{KL}(A||B)\ne D_{KL}(B||A)

换句话说,KL散度由A自己的熵与B在A上的期望共同决定。当使用KL散度来衡量两个事件(连续或离散),上面的公式意义就是求 A与B之间的对数差 在 A上的期望值。

KL散度 = 交叉熵 – 熵?

如果我们默认了用KL散度来计算两个分布间的不同,那还要交叉熵做什么?

事实上交叉熵和KL散度的公式非常相近,其实就是KL散度的后半部分(公式2.1):A和B的交叉熵 = A与B的KL散度 – A的熵。 D_{KL}(A||B) = -S(A)+H(A,B)

对比一下这是KL散度的公式:

D_{KL}(A||B) = \sum_{i}P_{A}(x_i) log\bigg(\frac{P_{A}(x_i)}{P_{B}(x_i)} \bigg) = \sum_{i}P_{A}(x_i)log(P_{A}(x_i ))- P_{A}(x_i)log(P_{B}(x_i))

这是熵的公式:

S(A) = -\sum_{i}P_A(x_{i})logP_A(x_{i})

这是交叉熵公式:

H(A,B)= -\sum_{i}P_{A}(x_i)log(P_{B}(x_i))

此处最重要的观察是,如果 S(A)是一个常量,那么D_{KL}(A||B) = H(A,B) ,也就是说KL散度和交叉熵在特定条件下等价。

为什么交叉熵可以用作代价?

接着上一点说,最小化模型分布 P(model) 与 训练数据上的分布 P(training) 的差异 等价于 最小化这两个分布间的KL散度,也就是最小化 KL(P(training)||P(model))

比照第四部分的公式:

  • 此处的A就是数据的真实分布: P(training)
  • 此处的B就是模型从训练数据上学到的分布: P(model)

巧的是,训练数据的分布A是给定的。那么根据我们在第四部分说的,因为A固定不变,那么求 D_{KL}(A||B)等价于求 H(A,B) ,也就是A与B的交叉熵。得证,交叉熵可以用于计算“学习模型的分布”与“训练数据分布”之间的不同。当交叉熵最低时(等于训练数据分布的熵),我们学到了“最好的模型”。

但是,完美的学到了训练数据分布往往意味着过拟合,因为训练数据不等于真实数据,我们只是假设它们是相似的,而一般还要假设存在一个高斯分布的误差,是模型的泛化误差下线。

因此在评价机器学习模型时,我们往往不能只看训练数据上的误分率和交叉熵,还是要关注测试数据上的表现。如果在测试集上的表现也不错,才能保证这不是一个过拟合或者欠拟合的模型。交叉熵比照误分率还有更多的优势,因为它可以和很多概率模型完美的结合。

所以逻辑思路是,为了让学到的模型分布更贴近真实数据分布,我们最小化 模型数据分布 与 训练数据之间的KL散度,而因为训练数据的分布是固定的,因此最小化KL散度等价于最小化交叉熵。

因为等价,而且交叉熵更简单更好计算,当然用它。


参考文献

[1] Michael Nielsen.CHAPTER 3 Improving the way neural networks learn[DB/OL]. http://neuralnetworksanddeeplearning.com/chap3.html, 2018-06-21.

[2] Zhu Xiaohu. Zhang Freeman.Another Chinese Translation of Neural Networks and Deep Learning[DB/OL].https://github.com/zhanggyb/nndl/blob/master/chap3.tex, 2018-06-21.

[3] 微调. 为什么交叉熵(cross-entropy)可以用于计算代价?[DB/OL]. https://www.zhihu.com/question/65288314/answer/244557337. 2018-06-21.

[4] 史丹利复合田. 一文搞懂交叉熵在机器学习中的使用,透彻理解交叉熵背后的直觉[DB/OL]. https://blog.csdn.net/tsyccnh/article/details/79163834. 2018-06-22.

今天的文章深度学习必须熟悉的损失函数:交叉熵损失函数分享到此就结束了,感谢您的阅读。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
如需转载请保留出处:https://bianchenghao.cn/21503.html

(0)
编程小号编程小号

相关推荐

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注