自鸣得意了半天,发现这篇文章基本就是维基百科 Quantities of Information 词条英文版的翻译。但是对应的中文词条没有覆盖英文版那么多的内容,所以也不完全是无用功。
信息和概率
一条信息由一个命题来表达。(这一个命题可以是对多个命题进行逻辑演算的一个表达式。)
而这个命题解答了人心中的某个疑问。既然这是个疑问,那么在得到确切的信息之前,有众多其他命题,和这条消息一样有可能是问题的答案。既然是有可能,那就是概率论可以派上用场的对方。所有这些可能成为答案的命题一起,构成一个随机变量空间。
比如说一道有 ABCD 四个选项的选择题,如果是单选题,那么答案的随机变量空间就是 {A, B, C, D},如果是多选题,则是 {A, B, C, D, AB, AC, AD, BC, BD, CD, ABC, ABD, ACD, BCD, ABCD},如果是排序题、不定项排序题、答案出错了的题……
描述一个概率分布的信息量
自信息:Self Information
自信息是一个随机事件的性质,也就是针对一个随机变量的某一个可能取值而言的。表达式为
这是一个无量纲量,但是公式中指数的底数可以任意选择——
- n = 2 的时候自信息的单位是 bit,也叫香农 (shannon), 这里的 bit 和二进制位 bit 不完全相同,一个香农是一个二进制位所能表示信息的上限:当一个二进制位完全取决于其它位时,这个位不包含任何额外信息,香农数为 0,但这个二进制位依然物理上存在;
- n = e 的时候单位是 nat, 因为 叫做自然对数;
- n = 10 的时候单位叫 hartley
——单位之间的换算关系由对数的换底公式给出。
这个量在信息论中的意义是,这条消息作为一个不方便问的问题的答案,最少可以用多少个 n 个选项的单选题套出答案。当 n=2 的时候,每个问题就是一个是非题,也就是一般疑问句。
码农面试的时候经常问一类问题:一堆看起来相同的东西里面有一个不一样,你有一种不能直接测出答案的测量工具,最少需要测量几次才能辨别出来……但是自信息的计算不能提供具体的辨别方法,具体方法还是需要你自己去凑,而面试刷人很多都是在刷这种细枝末节。
当然了,前提是你的面试官懂他自己在问什么,而不是相信美剧《硅谷》里压缩算法可以突破信息论极限的计算机民科~
当 p = 0 时,自信息发散为无穷大。不过问题不大,原因在下一节。
信息熵:Entropy
信息熵是一个随机变量的概率分布的整体性质。
算法很简单,就是自信息的概率期望,也就是按照随机变量每个取值的概率加权平均:
当 p = 0 时,自信息发散,但是概率为零,强行定义两者的积也为零,对信息熵不构成贡献。
当我们只对某一特定的随机事件信息感兴趣,除此以外的所有事件合并为目标事件的补集,就得到二项信息熵 binary entropy:
沿着自信息的意义往下走,信息熵在信息论中的意义是,一个将众多信息/命题的集合作为备选答案的问题,最少可以用多少道 n 个选项的单选题的集合来等价替代。
当这些最优的单选题确定之后,原问题的每一个选项,可以用单选题的答案序号来进行编码。指数的不同底数/信息量的不同单位就是数字的 n 进制,信息量就是相应进制下最大压缩编码后的位数。
当然要讨论压缩的话,还需要另找地方记录各个单选题和选项,也就是压缩字典。
比较两个概率分布的信息量
而如何选择单选题,使之成为针对给定问题最优的问题集,会因为各个选项概率分布的不同而变化。即便是同一组信息/备选答案,两套不同的概率分布,各自会给出一套对自己最优的问题集,一套概率分布下的最优问题集不见得是另外一套概率分布下的最优问题集。
下面的表达式都只写出了离散变量的形式,连续随机变量需要将求和写成对应的积分。
相对熵:Kullback–Leibler (K-L) Divergence
英文里也叫 relative entropy 或者 I-divergence
这里的两个概率分布映射自同一个随机变量空间。
这个量描述了当 p(X) 作为各选项的正确概率分布的情况下,用对 q(X) 最优的单选题去提问,没问出来的信息所需要的额外的单选题数目/编码数。
在科学应用中,p(X) 一般是从实验中测量出来的概率分布,q(X) 是理论模型的预测。
下面的例子计算了一个单选题,选 C、选 B、假想中一群学生的答案统计、胡猜四种概率分布 p, q ,r , φ 之间的 KL divergence。因为概率为零会出现发散问题,所以我们取 eps = 10^(-10) 把这些概率值截断:
import numpy as np
def kl_div(p,q,eps=1e-10):
p = np.clip(p,eps,1-eps)
q = np.clip(q,eps,1-eps)
return np.sum(p*np.log2(p/q))
p = np.array([ 0, 0, 1, 0])
q = np.array([ 0, 1, 0, 0])
r = np.array([1/6, 1/6, 1/2, 1/6])
phi = np.array([1/4, 1/4, 1/4, 1/4])
results = np.empty((4,4))
for i,v1 in enumerate([p,q,r,phi]):
for j,v2 in enumerate([p,q,r,phi]):
results[i,j] = kl_div(v1,v2)
KL-div(行, 列)/bit | p | q | r | φ |
---|---|---|---|---|
p = [0,0,1,0] | 0 | 33.219 | 1 | 2 |
q = [0,1,0,0] | 33.219 | 0 | 2.585 | 2 |
r = [1/6, 1/6, 1/2, 1/6] | 14.817 | 25.890 | 0 | 0.208 |
φ = [1/4,1/4,1/4,1/4] | 22.914 | 22.914 | 0.189 | 0 |
从结果中我们可以看到:
- 对角线为 0,符合其意义。
- 和 都应该是 +∞,这里的有限值是 eps 截断的结果
- 除个别巧合,对称位置的值一般不相等。这个量不同于两点之间的距离。
交叉熵:Cross Entropy
这里的两个概率分布映射自同一个随机变量空间 X。
概率分布 q 相对于 p 的交叉熵 cross entropy
这个量描述了当 p(X) 作为各选项的正确概率分布的情况下,用对 q(X) 最优的单选题去提问,所需要的总共的单选题数目/编码数。
类似于二项熵,p 和 q 之间的 binary cross entropy:
def cross_entropy(p,q,eps=1e-10):
p = np.clip(p,eps,1-eps)
q = np.clip(q,eps,1-eps)
return -np.sum(p*np.log2(q))
results = np.empty((4,4))
for i,v1 in enumerate([p,q,r,phi]):
for j,v2 in enumerate([p,q,r,phi]):
results[i,j] = cross_entropy(v1,v2)
Cross Entropy(行, 列)/bit | p | q | r | |
---|---|---|---|---|
p = [0,0,1,0] | 0 | 33.219 | 1 | 2 |
q = [0,1,0,0] | 33.219 | 0 | 2.585 | 2 |
r = [1/6, 1/6, 1/2, 1/6] | 16.610 | 27.683 | 1.792 | 2 |
= [1/4,1/4,1/4,1/4] | 24.914 | 24.914 | 2.189 | 2 |
- 对角线上不一定为零,而是自己的信息熵
- 其他位置和 KL divergence 相差大约为第一个输入分布的信息熵,误差 eps 的截断
互信息:Mutual Information
这里的两个概率分布一般来说映射自不同的随机变量空间。
从后一个等号可以看出,这一性质衡量的是 X, Y 两个随机变量的联合分布在多大程度上不同于“X 和 Y 相互独立”的零假设。两个随机变量相互独立时,互相不反映对方的信息,互信息 MI = 0。
当从 X 所在的随机变量空间取样的难度比较大的时候,我们需要用容易取样的另一个变量空间的随机变量 Y 来推测 X 的情况,互信息就可以用来论证我们这种选择的合理性。
扯点闲篇
PyTorch 中以此为基础的 loss functions
torch.nn
中有如下几个和今天的文章相关的 loss functions:
torch.[nn.KLDivLoss](https://pytorch.org/docs/stable/generated/torch.nn.KLDivLoss.html#torch.nn.KLDivLoss)
torch.[nn.CrossEntropyLoss](https://pytorch.org/docs/stable/generated/torch.nn.CrossEntropyLoss.html#torch.nn.CrossEntropyLoss)
torch.[nn.BCELoss](https://pytorch.org/docs/stable/generated/torch.nn.BCELoss.html#torch.nn.BCELoss)
torch.[nn.BCEWithLogitsLoss](https://pytorch.org/docs/stable/generated/torch.nn.BCEWithLogitsLoss.html#torch.nn.BCEWithLogitsLoss)
之所以没直接用这些函数计算上面的例子,是因为 KLDivLoss
是按元素计算,随后需要自己求和;CrossEntropyLoss
又是按类别的,还不需要归一化,而且文档的解释很复杂,我到现在也没看明白;而且还要注意这些函数的设计输入是不是 logit,这是机器学习里的概念,在此不展开了。
玻尔兹曼的墓志铭
其中 S 是(微正则系综中的)热力学熵,k 是玻尔兹曼常数 ,W 是因为刻碑的师傅不会写 Ω。
W 或 Ω 是处于相同能量的热力学状态的数量。因为你都需要统计物理了,显然是只知道能量,没办法知道所考虑的微观粒子究竟处于哪一个热力学状态。那此时的零假设就是处于所有状态的可能性相等,p = 1/Ω,信息熵
和热力学熵只相差一个玻尔兹曼常数。这是因为信息熵是无量纲的,熵和温度的量纲相乘之后需要得到能量的量纲,只能由 把量纲凑齐,而数值是自由能相关的实验里测出来的。
好像这就是高中物理里熵的定义式是吧。
上了大学以后,正则系综和巨正则系综中的熵也分别就是各自体系中各状态的概率分布的信息熵,乘上玻尔兹曼常数。(我也忘得差不多了,试图萌混过关)
善卜者无先见之明
公元 451 年,阿提拉 Attila 率领匈人攻入罗马领土,横扫有大量其他民族居住的高卢地区。西罗马帝国将军艾提乌斯 Aetius 联络了众多畏惧匈人的民族组成联军,其中包括西哥特人的王狄奥多里克 Theodoric,两军会战于卡塔隆 Catalaunian 平原。
本来想用这个故事举例子来着,因为我记得阿提拉在战前找了个大师算了一卦,说是一位国王将战死,一个国家将崩塌。于是阿提拉很高兴,以为哥特人和狄奥多里克要玩完了,结果战斗打响,狄奥多里克确实死于乱军,但是罗马和哥特等族的联军击败了匈人,阿提拉的霸业雨打风吹去。
于是试图说明算命的魅力就在于,用文字游戏表达一个自信息比较低的命题,同时误导对方相信一个自信息高得多的命题,在心理疏导之外,赚一个信息熵的差价。
结果查证的时候发现好像不是这么回事,Barbarian Rising 故事片里的预言内容不一样;维基百科上没给出处,说算命的很准,于是阿提拉推迟到下午作战,方便晚上跑路;其他地方甚至压根没有算命的情节。但是写都写了,需要积累高考作文素材的小朋友们还是可以假装被我误导了~
当然了,算命这个事还有一种情况,就是打着不确定的幌子,售卖确定但不方便承认自己确定的信息,那就是另一种生意,和另外的价格了~