张春成

V2

2022/10/13阅读:41主题:默认主题

信息论中的各种熵

信息论中的各种熵

信息论中有各种熵的定义,本文用一组例子说明熵的计算方式。以及通过熵对信号进行排序,我们可能会得到怎样的结果。


Shannon Entropy

这是最基本的熵,它从概率的方式定义了一个符号可能提供的“信息量”

信息量的期望就是信息熵,也以它的提出者 Shannon 命名

当我们有了两个变量,这两个变量就有了联合概率

对于联合概率,我们同样可以依定义求它的信息熵,称为联合熵

这两个变量同样可以有条件概率

从条件概率求得的信息熵称为条件熵

由于它显得过于复杂,我们引入所谓的互信息的概念

这里不加证明地给出结论

不难发现,互信息是一个变量提供的熵,减去它在已知另一个变量的值时,它还能够提供的熵。前者永远大于后者,二者有包含关系如下

Untitled
Untitled

KL Divergence

由于熵的计算方式可知,它是对信息量的度量。但机器学习问题往往是这样的问题

已知某个变量的分布,它能否用于预测另外的变量

在这种情况下,如果仅仅用条件熵或互信息来约束的话,会遇到一些困难,比如不方便计算梯度,再比如不方便获取条件概率等等。

另外,在真实场景中,我们也往往并不关心模型在整个空间上表现,而只关心它在特定范围内的表现。因此交叉熵应运而生

不难发现,它的上限是信号 p 的 Shannon Entropy。因此将它们的差值定义为 KL 散度,散度越小代表两个分布越接近。

熵的比较

下面我将提供一段可用的代码,用于直观说明熵的意义和计算方式。

首先,用 Perlin 噪声生成一组随机信号,波形图以及任意两个信号的联合概率密度函数如下图所示。可以看到,联合概率密度函数很少能够覆盖整个空间,因为你不能指望 2n 个点覆盖 n平方的范围。

newplot (32).png
newplot (32).png
newplot (33).png
newplot (33).png

之后,计算它们的各种熵,其中熵最大和最小的信号以及它们的数值分布如下图所示,熵越大,代表数值越难以预测。

newplot (17).png
newplot (17).png
newplot (18).png
newplot (18).png

接下来,选择熵最高的信号,将它他其他信号画在一起,为了方便展示,分别用热度图和空间曲线分别展示这些信号,从而直观地观察这些信号之间的差异。

信号排序原则分别是联合熵、互信息和交叉熵。不难发现,通过交叉熵排序找到的交叉熵更高的信号,它们之间的“相似性”也更高。

newplot (27).png
newplot (27).png
Untitled
Untitled
newplot (29).png
newplot (29).png
Untitled
Untitled
newplot (31).png
newplot (31).png
Untitled
Untitled

计算三种熵的代码如下,值得说明的是,计算概率和联合概率的方法是网格法,它的精度受限于 bins 的选择,本文的数值是 100。

另外,为了避免信号差异过大,将信号的范围限制在 0 和 1 之间。

# Compute probability
pdata = []

for d in tqdm(data, 'Prob.'):
    a, b = np.histogram(d, bins=bins)
    a = a.astype(np.float32) / len(d)
    pdata.append(a)
    
pdata = np.array(pdata)
px.imshow(pdata, title='Prob.').show()

# Compute joint probability
p2data = []
for j in tqdm(range(repeat), 'Prob.2'):
    p2data.append([e for e in range(repeat)])
    for k in range(repeat):        
        a, b, c = np.histogram2d(data[j], data[k], bins=bins)
        a /= np.sum(a)
        p2data[j][k] = a

p2data = np.array(p2data)
px.imshow(p2data[0][1], title='Prob.2', x=bins[:-1], y=bins[:-1], color_continuous_scale='dense').show()
p2data.shape

# Compute entropy
entropy = []

for p in tqdm(pdata, 'Entropy'):
    a, b = np.histogram(p, bins=bins)
    e = scipy.stats.entropy(a)
    entropy.append(e)
    
px.scatter(entropy, title='Entropy').show()

# Compute joint entropy
joint_entropy = np.zeros((repeat, repeat))

for j in tqdm(range(repeat), 'Joint Entropy'):
    for k in range(repeat):
        p = p2data[j][k].flatten()
        e = scipy.stats.entropy(p)
        joint_entropy[j][k] = e
        pass

px.imshow(joint_entropy, title='Joint Entropy').show()

# Compute mutual information
mutual_information = np.zeros((repeat, repeat))

for j in tqdm(range(repeat), 'Mutual Information'):
    for k in range(repeat):
        p1 = pdata[j][:, np.newaxis]
        p2 = pdata[k][np.newaxis, :]
        pxy = np.matmul(p1, p2)
        pp = p2data[j, k]
        
        m = pp != 0
        pxy = pxy[m]
        pp = pp[m]
        
        s = pp * np.log(pxy / pp)
        mutual_information[j][k] = -np.sum(s)
        
px.imshow(mutual_information, title='Mutual Information').show()

# Compute cross entropy
cross_entropy = np.zeros((repeat, repeat))

for j in tqdm(range(repeat), 'Cross Entropy'):
    for k in range(repeat):
        p1 = pdata[j]
        p2 = pdata[k]
        
        m = p2 != 0
        p1 = p1[m]
        p2 = p2[m]
        
        s = p1 * np.log(p2)
        cross_entropy[j][k] = -np.sum(s)
        
px.imshow(cross_entropy, title='Cross Entropy').show()

分类:

后端

标签:

后端

作者介绍

张春成
V2