条件熵,相对熵,交叉熵,联合熵,信息增益
给定的条件下, 的条件概率分布的熵对 的期望;
条件熵 表示在已知随机变量 的条件下随机变量 的不确定性。
因为条件熵中 也是一个变量,意思是在一个变量 的条件下(变量 的所有值都会取),另一个变量 熵对 的期望;
设 ={嫁,不嫁},统计“嫁”的概率6/12,“不嫁”的概率6/12;
计算 的熵
为了引入条件熵,我们现在还有一个变量 ,代表长相是“帅”还是“不帅”。
不帅的情况有4个,有1个不愿嫁,3个愿意;
帅的情况有8个,不愿意嫁5个,愿意嫁的为3个;
条件熵 相当于联合熵 ,减去单独的熵 ,即:
证明过程参考 [1] 。
从以上的推导可以看出: 。
定义:
设 , 是离散随机变量 中取值的两个概率分布,则 对 的相对熵是:
相对熵可以从来衡量两个概率分布之间的差异,上面公式的意义就是求 与 之差在 上的期望;
有两个概率分布 和 ,其中 是真实分布, 是非真实分布,如果用真实分布 来衡量一个样本所需要编码长度的期望(平均编码长度)为:
如果使用非真实分布 来表示来自真实分布 的平均编码长度,则是:
这就是 交叉熵 。
对于变长编码(如哈夫曼码),必须保证任何编码不是其他编码的前缀,符合这一特性的编码叫做 前缀码(prefix codes) 。
前缀码的意义在于解码简单,但是会带来个问题,就是编码损失(不是所有的组合都可以)。如当前编码为"01",长度 ,那 开始的其他编码如("010","011")(总长度为3举例)就不能再使用。
损失的长度为 。
所以为了对信息进行***编码的目的,往往需要对短编码和短编码损失进行权衡;
将短编码带来的损失称为编码代价,通常根据 出现的概率 来分配编码代价,假设 的编码长度为 :
平均编码长度则为:
如现在有另一个序列服从 分布,但是它仍然使用 分布的***编码方式,那它的平均编码长度即为:
上式称为 分布相对 分布的交叉熵,衡量了 分布使用 分布的***编码方式时的平均编码长度。
交叉熵根据相对熵的公式可以得出:
可以理解为用其他方式的***编码( )和自己方式的***编码( )之差。
定义 联合熵 如下:
根据条件熵定义:
定义 互信息(Mutual Entropy) 如下:
定义 差异信息(Variation of Information) :
信息增益 :
参考1:通俗理解条件熵
参考2:信息论与机器学习
[损失函数]——交叉熵
在了解交叉熵之前我们需要关于熵的一些基本知识,可以参考我的上一篇 博客 [1] 。
信息熵的定义为离散随机事件的出现概率 [2] 。当一个事件出现的概率更高的时候,我们认为该事件会传播的更广,因此可以使用信息熵来衡量信息的价值。
当一个信源具有多种不同的结果,记为:U1,U2,...,Un,每个事件相互独立,对应的概率记为:P1,P2,...,Pn。信息熵为各个事件方式概率的期望,公式为:
对于二分类问题,当一种事件发生的概率为p时,另一种事件发生的概率就为(1-p),因此,对于二分类问题的信息熵计算公式为:
相对熵(relative entropy),又被称为Kullback-Leibler散度(Kullback-leibler divergence),是两个概率分布间差异的一种度量 [3] 。在信息论中,相对熵等于两个概率分布的信息熵的差值。
相对熵的计算公式为:
其中 代表事件的真实概率, 代表事件的预测概率。例如三分类问题的标签为 ,预测标签为 。
因此该公式的字面上含义就是真实事件的信息熵与理论拟合的事件的香农信息量与真实事件的概率的乘积的差的累加。[4]
当p(x)和q(x)相等时相对熵为0,其它情况下大于0。证明如下:
KL散度在 Pytorch 中的使用方法为:
在使用过程中, reduction 一般设置为 batchmean 这样才符合数学公式而不是 mean ,在以后的版本中 mean 会被替换掉。
此外,还要注意 log_target 参数,因为在计算的过程中我们往往使用的是log softmax函数而不是softmax函数来避免underflow和overflow问题,因此我们要提前了解target是否经过了log运算。
torch.nn.KLDivLoss() 会传入两个参数 (input, target) , input 是模型的预测输出, target 是样本的观测标签。
下面我们用一个例子来看看 torch.nn.KLDivLoss() 是如何使用的:
输出结果如下:
相对熵可以写成如下形式:
等式的前一项为真实事件的熵,后一部分为 交叉熵 [4] :
在机器学习中,使用KL散度就可以评价真实标签与预测标签间的差异,但由于KL散度的***项是个定值,故在优化过程中只关注交叉熵就可以了。一般大多数机器学习算法会选择交叉熵作为损失函数。
交叉熵在pytorch中可以调用如下函数实现:
其计算方法如下所示 [5] :
假设batch size为4,待分类标签有3个,隐藏层的输出为:
经过 softmax 激活函数之后得到预测值:
softmax函数的输出结果每一行相加为1。
假设这一个mini batch的标签为
根据交叉熵的公式:
代表真实标签,在真实标签中,除了对应类别其它类别的概率都为0,实际上,交叉熵可以简写为:
所以该mini batch的loss的计算公式为(别忘了除以batch size,我们最后求得的是mini batch的平均loss):
因此,我们还需要计算一次对数:
计算结果为:
根据交叉熵的计算公式,loss的最终计算等式为:
运算结果和pytorch内置的交叉熵函数相同:
结果为:
除了 torch.nn.CrosEntropyLoss() 函数外还有一个计算交叉熵的函数 torch.nn.BCELoss() 。与前者不同,该函数是用来计算二项分布(0-1分布)的交叉熵,因此输出层只有一个神经元(只能输出0或者1)。其公式为:
在pytorch中的函数为:
用一个实例来看看如何使用该函数:
输出结果为:
它是如何计算的呢,我们接下来一步步分析:
首先输入是:
需要经过 sigmoid 函数得到一个输出
输出结果为:
然后我们根据二项分布交叉熵的公式:
得到 loss 的如下计算公式:
和pytorch的内置函数计算结果相同。
另外,需要注意的是, 当使用交叉熵作为损失函数的时候,标签不能为onehot形式,只能是一维的向量 ,例如,当batch size是5时,这一个batch的标签只能时[0,1,4,2,6]这样的形式。
交叉熵(Cross Entropy)
其中x表示事件,p(x)表示事件发生的概率。
信息熵具有以下性质:单调性,即发生概率越高的事件,其所携带的信息熵越低。极端案例就是“太阳从东方升起”,因为为确定事件,所以不携带任何信息量。从信息论的角度,认为这句话没有消除任何不确定性。非负性,即信息熵不能为负。这个很好理解,因为负的信息,即你得知了某个信息后,却增加了不确定性是不合逻辑的。累加性,即多随机事件同时发生存在的总不确定性的量度是可以表示为各事件不确定性的量度的和。信息熵是用来衡量信源不确定性的。信息熵越大,信源越具不确定性,信源越复杂。
通过公式可以看出,q分布与p分布越接近,KL散度越小,相对熵越小。
Pytorch-交叉熵
一条信息的信息量大小和它的不确定性有很大的关系 。一句话如果需要很多外部信息才能确定,我们就称这句话的信息量比较大。比如你听到“云南西双版纳下雪了”,那你需要去看天气预报、问当地人等等查证(因为云南西双版纳从没下过雪)。相反,如果和你说“人一天要吃三顿饭”,那这条信息的信息量就很小,因为这条信息的确定性很高。
那我们就能将事件 的信息量定义如下(其中 表示事件 发生的概率):
信息量是对于单个事件来说的 ,但是实际情况一件事有很多种发生的可能,比如掷骰子有可能出现6种情况,明天的天气可能晴、多云或者下雨等等。 熵是表示随机变量不确定的度量,是对所有可能发生的事件产生的信息量的期望 。公式如下:
的曲线如下:
结合熵的公式(2)以及 曲线,当这些所有可能发生事件的概率比较小(接近0)或者比较大(接近1)时,熵的值会比较小;如果事件发生的概率既远离0也远离1时,熵的值就会比较大。
例如,如下三组事件比较:
1)事件概率均等,[0.2500, 0.2500, 0.2500, 0.2500],熵为2;
2)事件概率比较靠近0或者1,[0.1, 0.1, 0.1, 0.7],熵为1.3568;
3)事件概率极其靠近0或者1,[0.001, 0.001, 0.001, 0.999],熵为0.0313.
熵的一种比较特殊的情况就是掷硬币 ,只有正、反两种情况,该种情况(二项分布或者0-1分布)熵的计算可以简化如下:
其中, 表示正面概率。
相对熵又称KL散度,用于衡量对于同一个随机变量 的两个分布 和 之间的差异 。在机器学习中, 常用于描述样本的真实分布 ,例如[1,0,0,0]表示样本属于***类,而 则常常用于表示预测的分布 ,例如[0.7,0.1,0.1,0.1]。显然使用q(x)来描述样本不如 准确, 需要不断地学习来拟合准确的分布 。
KL散度的公式如下:
KL散度的值越小表示两个分布越接近。
我们将KL散度的公式进行变形,得到:
前半部分就是 的熵,后半部分就是我们的交叉熵:
机器学习中,我们常常使用KL散度来评估predict和label之间的差别,但是由于KL散度的前半部分是一个常量,所以我们常常将后半部分的交叉熵作为损失函数,其实二者是一样的。
交叉熵代价函数(Cross-entropy cost function)是用来衡量人工神经网络(ANN)的预测值与实际值的一种方式。与二次代价函数相比,它能更有效地促进ANN的训练。在介绍交叉熵代价函数之前,本文先简要介绍二次代价函数,以及其存在的不足。
ANN的设计目的之一是为了使机器可以像人一样学习知识。人在学习分析新事物时,当发现自己犯的错误越大时,改正的力度就越大。比如投篮:当运动员发现自己的投篮方向离正确方向越远,那么他调整的投篮角度就应该越大,篮球就更容易投进篮筐。同理, 我们希望:ANN在训练时,如果预测值与实际值的误差越大,那么在反向传播训练的过程中,各种参数调整的幅度就要更大,从而使训练更快收敛。 然而,如果使用二次代价函数训练ANN,看到的实际效果是,如果误差越大,参数调整的幅度可能更小,训练更缓慢。
以一个神经元的二类分类训练为例,进行两次实验(ANN常用的激活函数为sigmoid函数,该实验也采用该函数):输入一个相同的样本数据x=1.0(该样本对应的实际分类y=0);两次实验各自随机初始化参数,从而在各自的***次前向传播后得到不同的输出值,形成不同的代价(误差):
在实验1中,随机初始化参数,使得***次输出值为0.82(该样本对应的实际值为0);经过300次迭代训练后,输出值由0.82降到0.09,逼近实际值。而在实验2中,***次输出值为0.98,同样经过300迭代训练,输出值只降到了0.20。
从两次实验的代价曲线中可以看出: 实验1的代价随着训练次数增加而快速降低,但实验2的代价在一开始下降得非常缓慢;直观上看,初始的误差越大,收敛得越缓慢。
其实,误差大导致训练缓慢的原因在于使用了二次代价函数。二次代价函数的公式如下:
其中, 表示代价, 表示样本, 表示实际值, 表示输出值, 表示样本的总数。为简单起见,同样一个样本为例进行说明,此时二次代价函数为:
目前训练ANN最有效的算法是反向传播算法 。简而言之,训练ANN就是通过反向传播代价,以减少代价为导向,调整参数。参数主要有:神经元之间的连接权重 ,以及每个神经元本身的偏置 。调参的方式是采用梯度下降算法(Gradient descent),沿着梯度方向调整参数大小。 和 的梯度推导如下:
其中, 表示神经元的输入, 表示激活函数。从以上公式可以看出, 和 的梯度跟激活函数的梯度成正比,激活函数的梯度越大, 和 的大小调整得越快,训练收敛得就越快。而神经网络常用的激活函数为sigmoid函数,该函数的曲线如下所示:
如图所示, 实验2的初始输出值(0.98)对应的梯度明显小于实验1的输出值(0.82),因此实验2的参数梯度下降得比实验1慢。这就是初始的代价(误差)越大,导致训练越慢的原因。 与我们的期望不符,即:不能像人一样,错误越大,改正的幅度越大,从而学习得越快。
可能有人会说,那就选择一个梯度不变化或变化不明显的激活函数不就解决问题了吗?那样虽然简单粗暴地解决了这个问题,但可能会引起其他更多更麻烦的问题。而且,类似sigmoid这样的函数(比如tanh函数)有很多优点,非常适合用来做激活函数,具体请自行google之。
换个思路,我们不换激活函数,而是换掉二次代价函数,改用交叉熵代价函数:
其中, 表示样本, 表示样本的总数。那么,重新计算参数 的梯度:
因此, 的梯度公式中原来的 被消掉了;另外,该梯度公式中的 表示输出值与实际值之间的误差。所以,当误差越大,梯度就越大,参数 调整得越快,训练速度也就越快。 实际情况证明,交叉熵代价函数带来的训练效果往往比二次代价函数要好。
在实际分类任务中,要先将输出层的输出值经过Softmax函数,再经过log函数,最后才用交叉熵损失函数计算损失。
pytorch中有计算交叉熵损失的接口,即 F.cross_entropy() ,不过该接口包含了Softmax函数、log函数、交叉熵损失函数。也就是说 F.cross_entropy() = F.softmax() + torch.log() + F.nnl_loss() 。即使如此,也要使用 F.cross_entropy() ,不仅是因为它简单,更因为它能保证数值稳定。
机器学习的过程就是希望在训练数据熵 模型学到的分布 和 真实的分布 越近越好,我们知道KL散度可以表示两个分布之间的不同。
但我们没有真实数据的分布,那么只能退而求其次,希望模型学到的分布和训练数据的分布 ,也就是把训练数据当做模型和真实数据之间的代理人 。假设训练数据是从总体中独立同步分布采样(Independent and identically distributed sampled)而来,那么我们可以利用最小化训练数据的经验误差来降低模型的泛化误差。简单说:
由此非常理想化的看法是如果 模型(左) 能够学到 训练数据(中) 的分布,那么应该近似的学到了 真实数据(右) 的分布: 近似于 近似于
简单的交叉熵,你真的懂了吗?
交叉熵损失函数
TensorFlow的四种交叉熵
一种信息化的描述方法,用来定义信息中不确定因素的多少。机器学习结果的好坏评判标准就是两类信息之间的熵最小,由此引发了评判结果好坏的标准。
交叉熵(Cross Entropy)是Loss函数的一种(也称为损失函数或代价函数),用于描述模型预测值与真实值的差距大小,常见的Loss函数就是均方平方差(Mean Squared Error),定义如下。
![][matrix]
[matrix]: frac{(y-a)^2}{2}
平方差表示预测值与真实值直接相减,为了避免得到负数取绝对值或者平方,再做平均就是均方平方差。注意这里预测值需要经过sigmoid激活函数,得到取值范围在0到1之间的预测值。
平方差可以表达预测值与真实值的差异,但在分类问题种效果并不如交叉熵好,原因可以参考 这篇博文 。
交叉熵的定义如下,
当神经元函数为![][fact]这里
[fact]: sigma(z)
01: ![][01]
02: ![][02]
03: ![][03]
04: ![][04]
05: ![][05]
06: ![][06]
07: ![][07]
[00]: ?begin{bmatrix}1xx 21yy 21zz^2\end{bmatrix}
[01]: frac{e x+e {-x}}{2}}
[02]: ^k=frac{n(n-1)ldots(n-k+1)}{k!}
[03]: ?begin{align}sqrt{37}=sqrt{frac{73 2-1}{12 2}}=sqrt{frac{73 2}{12 2}cdotfrac{73 2-1}{73 2}}=sqrt{frac{73 2}{12 2}}sqrt{frac{73 2-1}{73 2}}=frac{73}{12}sqrt{1-frac{1}{73 2}}\approxfrac{73}{12}left(1-frac{1}{2cdot73 2}right)end{align}
[04]: ?begin{arr***}{c|lcr}ntext{Left}text{Center}text{Right}\hline10.2411252-1189-83-2020001+10i\end{arr***}
[05]: ?math***{N,Z,Q,R,C}
[06]: ?left{begin{arr***}{ll}a_1x+b_1y+c_1z=d_1+e_1a_2x+b_2y=d_2a_3x+b_3y+c_3z=d_3end{arr***}right.
[07]: left(left[frac{1+left{x,yright}}{left(frac{x}{y}+frac{y}{x}right)left(u+1right)}+aright]^{3/2}right)
如何理解交叉熵(Cross Entory)?
对于事件x,它的自信息(self-information)定义为:
当log的底数为e,