深度学习中的信息论——交叉熵

本文深入探讨信息量、熵和交叉熵的概念,它们在数据编码和分类任务中的作用。信息量是衡量信息不确定性的度量,熵则表示系统的混乱程度,交叉熵用于评估两个概率分布的差异,常用于分类问题的损失函数。在机器学习中,交叉熵损失函数与最大似然估计等价,有助于优化模型性能。同时,文章还提及KL散度作为衡量分布差异的指标,并讨论了熵与基尼不纯度之间的关系。
摘要由CSDN通过智能技术生成

信息量

信息量是在将信息量化。可以直观地感觉到信息的多少和概率是有关的,概率大的信息也相对低一些(概率大到可以预测了,那么就意味着这件事情带来的信息很少)。

为了量化信息,就要找到一个单位,

为了简化起见,事件A是某次多次抛掷硬币的结果。所有结果的可能性数目为n=m^l,m=2,而知道可能性数目n的话可以求出长度l=log_m n,又因为是等概率的,p=1/n,所以l=log_m \frac{1}{p}=log_2 \frac{1}{p}

可以看到,概率和编码长度是负相关的,和我们对信息量的直觉是一样的。事实上,不管是是不是等概率分布,只要知道概率,就可以这样求取信息量。

现在我们知道信息量中log取2为底和概率取导数的真正含义了。那么熵是什么呢?既然信息量是衡量一件事的不确定程度,那么熵就是衡量一个系统的混乱程度。它综合了所有可能发生类别的不确定性,其实就是信息量的期望:

从编码的角度,熵指的是对随机变量编码所需的最小比特数。有一种编码的种类就叫作熵编码,属于无损编码。因为熵就是平均信息量,而信息量是以01编码进行量化的,那么为了不损失信息,我们最少也需要这么多的bit进行编码。同时可以看到,概率越小出现的符号,允许使用更长的编码,这样整体的编码效率才更高。

关于不等概情况的理解:比如把骰子的2改为1,那么转到1那一面的概率为\frac{2}{6},我们以“”转到1的一面“”这件事件为单位对概率1重新划分,因为概率总和为1,那么所有的类的数目就是1/p。

交叉熵

从熵的公式中可以看到,有两个位置使用了概率分布。求和位置使用概率是为了计算期望,是对编码结果的权重求和;对数部分使用概率意味着根据概率分布确定编码方式。

对于两个信源,他们有各自不同的概率分布,分别求熵可以得到各自平均每个字符对应的最小的编码长度。那么如果两个信源互换编码方式呢?从公式上看,变化就是取对数的对象换成了编码对象的概率分布,而加权所使用的概率仍然是自己的概率。因为两个位置的概率不统一,所以被称作交叉熵:

可以预见,互换编码方式之后求出的“熵”会增大,当且仅当两个分布相等时交叉熵取最小值。所以交叉熵可以用来衡量两个分布的差异。

在分类任务中,预测值和真实值都是一个几维的向量,都可以看作是一个分布。所以可以使用交叉熵来做损失函数。在二分类时,写作:

计算交叉熵损失函数时,大部分人直接使用torch.nn.functional中提供的函数,把网络输出和label作为参数传进去就行。但其实cross_entropy函数是通过log_softmax 和 nll_loss计算得到的。

正如之前提到的,计算交叉熵必须知道概率,而网络输出是向量。log_softmax就是把概率归一化,并且求对数,等效于先F.softmax,然后torch.log。NLL损失全称为Negative Log-Likelihood Loss,其含义是负对数似然损失。

PyTorch-损失函数-CrossEntropyLoss_crossentropyloss函数pytorch-CSDN博客

这样,在cross_entropy内部自动计算softmax得到概率,并且最终输出交叉熵。CE=\sum_x{p(x)log\frac{1}{q(x)}}=-\sum_x{p(x)log(q(x))}

注意n.softmax在计算概率的时候要指定好维度,从而保证不同互斥类别的概率之和为1.

torch_softmax = F.softmax(output, dim=1)

KL散度

熵的一个重要意义是编码对应的最短码字。交叉熵因为改变了信源的概率,所以码字是要长一点。为了衡量长度增加了多少,和原来的编码方式相减就可以得到。减号右边的式子表示的是信源匹配的情况:

D_p(p)=\sum_xp(x)log_2\frac{1}{q(x)}-\sum_xp(x)log_2\frac{1}{p(x)}=\sum_xp(x)log_2\frac{p(x)}{q(x)}

这个“差值”也可以看作是“距离”,称为KL散度。不过不是真正的“距离”,因为该“距离”不具有对称性。

经过变换,可以写成比例关系的形式。所以KL散度也叫做相对熵。取值范围就是0~正无穷。

KL散度经常被用来衡量两个信源,或者说两个分布的差异性,因为差异越大,编码的适用性越差,编码长度变化量也越大。因为KL散度的一部分是恒定不变的,另外一部分就是交叉熵,所以还是更经常使用交叉熵作为损失函数。

交叉熵作为损失函数还有一个好处是使用sigmoid函数在梯度下降时能避免均方误差损失函数学习速率降低的问题,因为学习速率可以被输出的误差所控制。

和其他的联系

再深究一点,其实最小化交叉熵和最大似然估计也是等价的。因为最大似然的目的其实是最小化取负对数,取对数的目的是防止连乘过程中的溢出。这就造成了二者首先在格式上是相似的。最大似然是求取模型的参数分布,使得输出的值是已知样本的概率最大,本质上也是让二者的分布最接近。

在决策树中,除了使用基于熵的信息增益,常见的还有基尼不纯度。从名字上看,不纯度和熵的混乱程度是类似的;实际上,二者确实也是类似的,基尼不纯度其实是熵的近似值(log泰勒展开,忽略高阶项)。基于近似后得到的新公式,也可以有新的解释:一个随机事件变成它的对立事件的概率/分错的概率。

在网上的资料中提到,熵与基尼不纯度还有一个区别是熵到达峰值的过程相对慢一些,并且由此造成熵对于混乱程度的判罚要重一些。这里我不太明白,基尼不纯度是通过舍弃高阶项来近似熵,所以基尼不纯度是要比熵值低一些的,二者都是在等概时取最大值,所以二者的关系是熵的曲线段在不纯度上方,二者端点相同。因为熵值更大,所以作为损失函数时的惩罚力度更大。

scipy中实现了KL散度的计算,当参数中只有一个序列时,计算的是熵,并且可以指定以e为底还是以2为底:

>>>entropy([1/2, 1/2], base=2)
1.0

当有两个序列时,以第一个序列为先验分布计算二者的KL散度:

>>>entropy([1/2, 1/2], qk=[9/10, 1/10])
0.5108256237659907

而我在这里计算的时候返回的值是inf,即便输入的是两个完全一致的序列也是这样,问题出在哪里呢?我这里犯了一个错,输入的序列应该是各个事件发生的概率,即应该是一个离散的概率密度序列,而不能直接输入两个取值的集合。尤其是取值可能出现负数,这样把它当做概率进行求对数,就会出错,返回inf。

对应做法是利用scipy中的norm.pdf估计概率密度。还有就是手动统计两个序列在各个区间内数值的频率。比如可以利用np.percentile得到四分位数。

Reference:

https://zhuanlan.zhihu.com/p/59550047

https://www.zhihu.com/question/65288314

https://zhuanlan.zhihu.com/p/40024110

https://www.cnblogs.com/arkenstone/p/10524720.html

https://zhuanlan.zhihu.com/p/76667156

近似关于“熵”家族的那些事_熵和概率十分相近,但又不同。概率是真实反映变化到某状态的确信度。而熵反映的是-CSDN博客

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值