信息量

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

$$
I(x_0)=−log(p(x_0))
$$

可以理解为,一个事件发生的概率越大,则它所携带的信息量就越小,而当$p(x_0)=1$​ 时,熵将等于 0,也就是说该事件的发生不会导致任何信息量的增加。

举个例子,小明平时不爱学习,考试经常不及格,而小王是个勤奋学习的好学生,经常得满分,所以我们可以做如下假设:
事件 A:小明考试及格,对应的概率$P(x_A)=0.1$​,信息量为$I(x_A)=−log(0.1)=3.3219$​
事件 B:小王考试及格,对应的概率$P(x_B)=0.999$​​​,信息量为$I(x_B)=−log(0.999)=0.0014$
​​​
可以看出,结果非常符合直观:小明及格的可能性很低(十次考试只有一次及格),因此如果某次考试及格了(大家都会说:XXX 竟然及格了!),必然会引入较大的信息量,对应的$I$ 也较高。而对于小王而言,考试及格是大概率事件,在事件 B 发生前,大家普遍认为事件 B 的发生几乎是确定的,因此当某次考试小王及格这个事件发生时并不会引入太多的信息量,相应的$I$ 也非常的低。

那么什么又是熵呢?还是通过上边的例子来说明,假设小明的考试结果是一个 0-1 分布。 $\chi_A$ 只有两个取值{0:不及格,1:及格},在某次考试结果公布前,小明的考试结果有多大的不确定度呢?你肯定会说:十有八九不及格!因为根据先验知识,小明及格的概率仅有 0.1,90%的可能都是不及格的。怎么来度量这个不确定度?求期望!不错,我们对所有可能结果带来的额外信息量求取均值(期望),其结果不就能够衡量出小明考试成绩的不确定度了吗。即:

$$
H_A(x)=−[p(x_A)log(p(x_A))+(1−p(x_A))log(1−p(x_A))]=0.4690
$$

对应小王的熵:

$$
H_B(x)=−[p(x_B)log(p(x_B))+(1−p(x_B))log(1−p(x_B))]=0.0114
$$

虽然小明考试结果的不确定性较低,毕竟十次有 9 次都不及格,但是也比不上小王(1000 次考试只有一次才可能不及格,结果相当的确定)。我们再假设一个成绩相对普通的学生小东,他及格的概率是$P(x_C)=0.5P(x_C)=0.5$,即及格与否的概率是一样的,对应的熵:

$$
H_C(x)=−[p(x_C)log(p(x_C))+(1−p(x_C))log(1−p(x_C))]=1
$$

其熵为 1,他的不确定性比前边两位同学要高很多,在成绩公布之前,很难准确猜测出他的考试结果。

熵其实是信息量的期望值,它是一个随机变量的确定性的度量。熵越大,变量的取值越不确定,反之就越确定

对于一个随机变量$X$ 言,它的所有可能取值的信息量的期望$E[I(x)]$ 称为

$X$ 熵定义为:

$$
H(X)=E_plog\frac{1}{p(x)}=−∑_{x∈X}p(x)logp(x)
$$

$p(x)$ 的值在 0-1 之间,取对数后小于零

如果$p(x)$ 连续型随机变量的 pdf,则熵定义为:

$$
H(X)=−\int _{x∈X}p(x)logp(x)dx
$$

为了保证有效性,这里约定当$p(x)\to0$ ,有$p(x)logp(x)\to0$

当 $X$ 为 0-1 分布时,熵与概率 $p$ 的关系如下图:

image-20210827104845876

可以看出,当两种取值的可能性相等时,不确定度最大(此时没有任何先验知识),这个结论可以推广到多种取值的情况。在图中也可以看出,当$p$=0 或 1 时,熵为 0,即此时 $X$ 完全确定。
熵的单位随着公式中 log 运算的底数而变化,当底数为 2 时,单位为“比特”(bit),底数为 e 时,单位为“奈特”。

互信息 (Mutual Information)

无监督学习中常用的损失函数,作用于标签时,最大化预测标签和真实标签的信息熵,可以促使预测标签 certain 且 diverse,

$$
\begin{align} I(X;Y)&=\sum_{x,y}p(x,y)·\text{log}\ \frac {p(x, y)} {p(x),p(y)}\ &=-\sum_y p(y)\log p(y) - \sum_xp(x)H(Y|X=x)\ &=H(Y)-H(Y|X) \end{align}
$$

直观地说,如果把熵 $H(Y)$ 看作一个随机变量于不确定度的量度,那么 **$H(Y|X)$ 就是 在已知 $X$ 事件后 $Y$ 事件会发生*的不确定度。互信息为 $Y$ 的熵减去条件熵。

KL 散度

相对熵(relative entropy)又称为 KL 散度(Kullback-Leibler divergence),KL 距离,是两个随机分布间距离的度量。记为$D_{KL}(p\parallel q)$​。它度量当真实分布为 $p$ 时,假设分布 $q$ 的无效性。

某个随机变量的编码长度怎么算?

首先要知道什么是编码长度,这个其实很简单的,比如我们有一个数字 $x$ ,服从某个 $P$ 的分布。如果使用霍夫曼编码,出现概率越低的数字需要的编码长度越长,概率越高的数字需要的编码长度越短。这个只要学过计算机的都懂,不提。霍夫曼树是二叉树,你就简单理解编码长度就是二叉树中某个节点的高度,概率越高越靠近根节点,所以编码长度是:

$$log(\frac{1}{P(x)})$$

你看概率越大的 $x$ 编码长度越短,概率越小的编码长度越长。

平均编码长度怎么算?

如果根据每个$x$ 的概率把他们的编码长度平均一下,就得到了平均编码长度:

$$\sum{P(x)log(\frac{1}{P(x)})}$$

如果我们搞错情况了,以为$x$ 的分布是 $Q$ ,那么使用霍夫曼编码的时候使用的编码长度就变成了:

$$log(\frac{1}{Q(x)})$$

于是就会基于错误的分布 $Q$ 对 $x$ 进行霍夫曼编码,但他的真实分布却是 $P$ ,那么这种情况的平均编码长度就变成了:

$$\sum{P(x)log(\frac{1}{Q(x)})}$$

KL散度怎么算

霍夫曼编码是最优编码,但如果你对 $x$ 的分布估计错误,那就不优了,额外会浪费很多比特数用来编码,浪费的这些比特数直接用两个平均编码长度相减就有了:

$$\sum{P(x)log(\frac{1}{Q(x)})}-\sum{P(x)log(\frac{1}{P(x)})}$$

也就是:

$$\sum{P(x)log(\frac{P(x)}{Q(x)})}$$

这就是KL散度

所以KL散度其实是利用最优编码这个代理量去衡量两个分布之间有多大的区别。

对了,为什么是比特数,因为霍夫曼是二叉树,左0右1,故为比特

以上摘自 KL散度衡量的是两个概率分布的距离吗? 刘斯坦回答部分

数学推导

$$
\begin{split}D_{KL}(p\parallel q)
&=E_p[log\frac{p(x)}{q(x)}]\
&=\sum_{x\in\chi}p(x)log\frac{p(x)}{q(x)}\
&=\sum_{x\in\chi}[p(x)logp(x)-p(x)logq(x)]\
&=\sum_{x\in\chi}p(x)logp(x)-\sum_{x\in\chi}p(x)logq(x)\
&=-H(p)-\sum_{x\in\chi}p(x)logq(x)\
&=-H(p)+E_p[-logq(x)]\
&=H_p(q)-H(p)
\end{split}
$$

并且为了保证连续性,做如下约定:

$0log\frac00=0$​,$0log\frac0q=0$​​,$plog\frac{p}{0}=\infty$​

显然,当$p=q$ ,两者之间的相对熵$D_{KL}(p\parallel q)=0$​

上式最后的$H_p(q)$ 示在 $p$ 分布下,使用 $q$ 进行编码需要的 bit 数,而$H(p)$ 示对真实分布$p$ 需要的最小编码 bit 数。

基于此,相对熵的意义就很明确了:$D_{KL}(p||q)$​ 表示在真实分布为$p$ 前提下,使用$q$ 布进行编码相对于使用真实分布$p$ 行编码(即最优编码)所多出来的 bit 数。

注意

  • 如果继续用 2 为底的对数计算,则 KL 散度值表示信息损失的二进制位数。

  • 如果 $p$ 和 $q$ 是同分布的,则 KL 散度为 0。

  • KL散度不是距离,因为不符合对称性,所以用 KL 散度度量分布差异时需设计成对称的,$D_{KL}(p||q)+D_{KL}(q||p)$
    Specializing to Gaussian measures $P\sim\mathcal{N}(\mu_1, \Sigma_1)$ and $Q\sim\mathcal{N}(\mu_2, \Sigma_2)$, then the KL divergence is given by

    $$
    \text{KL}(P||Q)=\frac 1 2 [(\mu_2-\mu_1)^{\top}\Sigma_2^{-1}(\mu_2-\mu_1)+\text{trace}(\Sigma_2^{-1}\Sigma_1)-\text{ln}(\frac {det(\Sigma_1)} {det(\Sigma_2)})-K]
    $$

条件熵 (Conditional Entropy)

条件熵是在已知随机变量 $X$ 的条件下,$Y$ 的条件概率分布的熵对随机变量 $X$ 的数学期望

$$
\begin{align} H(Y|X) &=\sum_{x\in\mathcal{X}} p(x) H(Y|X=x) \ &=-\sum_{x\in\mathcal{X}} p(x) \sum_{y\in\mathcal{Y}} p(y|x) \log p(y|x)\ &=-\sum_{x\in\mathcal{X}}\sum_{y\in\mathcal{Y}} p(x,y)\log p(y|x)\ &=-\sum_{x\in\mathcal{X},y\in\mathcal{Y}}p(x,y)\log p(y|x)\ \end{align}
$$

最小化条件熵让模型远离决策边界,可以应用在无监督数据上,以利用其数据分布信息。

JS 散度(Jensen-Shannon)

JS 散度度量了两个概率分布的相似度,基于 KL 散度的变体,解决了 KL 散度非对称的问题。一般地,JS 散度是对称的,其取值是 0 到 1 之间。定义如下:

$$
JS(p||q)=\frac 1 2 KL(p||\frac {p+q} 2)+\frac 1 2 KL(q||\frac {p+q} 2)
$$

KL 散度和 JS 散度度量的时候有一个问题: 如果两个分布 p, q 离得很远,完全没有重叠的时候,那么 KL 散度值是没有意义的,而 JS 散度值是一个常数。这在学习算法中是比较致命的,这就意味这这一点的梯度为 0,梯度消失了。

Maximum Mean Discrepancy (MMD)

定义和特点
MMD是通过比较两个分布的样本均值的差异来衡量它们之间的距离。具体地,它通过特征空间中的核函数来度量分布之间的差异,通常使用正定核如高斯核。

优点

简单直观,易于实现和计算。
在一些实验中表现良好,特别是当分布差异较为显著时效果较好。

缺点

对于高维和复杂的数据分布,可能会出现较高的误差。
对于较小的样本量可能表现不稳定。

适用条件

适合用于比较较为简单的数据分布和特征空间。
在计算资源有限的情况下表现较为出色。

代码

MMD 是通过核方法来度量两个分布之间的距离,这里以高斯核为例实现 MMD 的计算:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
import numpy as np

def gaussian_kernel(x, y, sigma=1.0):
return np.exp(-np.linalg.norm(x - y)**2 / (2 (sigma *2)))

def mmd(X, Y, kernel=gaussian_kernel):
m = len(X)
n = len(Y)

K_xx = np.zeros((m, m))
K_yy = np.zeros((n, n))
K_xy = np.zeros((m, n))

for i in range(m):
for j in range(m):
K_xx[i, j] = kernel(X[i], X[j])

for i in range(n):
for j in range(n):
K_yy[i, j] = kernel(Y[i], Y[j])

for i in range(m):
for j in range(n):
K_xy[i, j] = kernel(X[i], Y[j])

return np.mean(K_xx) + np.mean(K_yy) - 2 np.mean(K_xy)

# Example usage:
X = np.random.randn(100, 2) # Sample from distribution X
Y = np.random.randn(100, 2) # Sample from distribution Y

distance_mmd = mmd(X, Y)
print(f"MMD distance between X and Y: {distance_mmd}")

Correlation Alignment (CORAL)

定义和特点
CORAL通过最小化两个分布之间的协方差矩阵的差异来进行域自适应。它试图通过特征之间的协方差来对齐两个域的特征分布。

优点

考虑了特征之间的相关性,能够更加准确地度量分布的差异。
对于特征之间存在较强关联的数据集有较好的适应性。

缺点

受限于协方差矩阵的计算,当特征空间较大时可能计算代价较高。
只考虑了二阶统计量,可能忽略了高阶的分布差异。

适用条件

适合于特征之间具有较强相关性的数据集。
对于计算资源充足的情况下,可以有效地对齐分布。

代码

CORAL 通过最小化协方差矩阵的差异来进行域自适应:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
from sklearn.covariance import LedoitWolf

def coral(X, Y):
cov_X = LedoitWolf().fit(X).covariance_
cov_Y = LedoitWolf().fit(Y).covariance_

return np.linalg.norm(cov_X - cov_Y)

# Example usage:
X = np.random.randn(100, 2) # Sample from distribution X
Y = np.random.randn(100, 2) # Sample from distribution Y

distance_coral = coral(X, Y)
print(f"CORAL distance between X and Y: {distance_coral}")

Central Moment Discrepancy (CMD)

定义和特点

CMD通过比较高阶中心矩来度量两个分布之间的差异。它不仅考虑了均值和方差,还考虑了数据分布的更高阶统计信息。

优点

能够更全面地捕捉数据分布的差异,尤其是对于非高斯分布和高阶统计信息的敏感性较好。

缺点

需要计算和比较高阶统计量,计算复杂度可能较高。
对于样本量较少时,估计高阶统计量的稳定性可能较差。

适用条件

适合用于捕捉高阶统计信息对分布差异影响显著的情况。
当数据分布复杂且不服从正态分布时表现较为突出。

代码

CMD 通过比较高阶中心矩来度量两个分布之间的差异,这里演示计算方差和偏度的差异:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
from scipy.stats import moment

def cmd(X, Y):
var_X = np.var(X)
var_Y = np.var(Y)

skew_X = moment(X, moment=3)
skew_Y = moment(Y, moment=3)

return np.abs(var_X - var_Y) + np.abs(skew_X - skew_Y)

# Example usage:
X = np.random.randn(100) # Sample from distribution X
Y = np.random.randn(100) # Sample from distribution Y

distance_cmd = cmd(X, Y)
print(f"CMD distance between X and Y: {distance_cmd}")

Maximum Density Divergence (MDD)

定义和特点
MDD通过比较两个分布的密度函数的差异来度量它们之间的距离。通常使用KL散度来作为分布差异的度量标准。

优点

直接基于密度函数比较,能够较为准确地捕捉分布之间的差异。
在分布有明显差异时效果较好。

缺点

对于高维和复杂分布的密度估计可能存在困难。
KL散度可能会受到样本稀疏性的影响。

适用条件

适合用于直接比较密度函数的场景。
当能够准确估计密度函数时表现较为优越。

代码

MDD 通过比较两个分布的密度函数的差异来

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
from scipy.stats import entropy
from sklearn.neighbors import KernelDensity

def mdd(X, Y):
kde_X = KernelDensity(bandwidth=0.5).fit(X[:, np.newaxis])
kde_Y = KernelDensity(bandwidth=0.5).fit(Y[:, np.newaxis])

log_dens_X = kde_X.score_samples(X[:, np.newaxis])
log_dens_Y = kde_Y.score_samples(Y[:, np.newaxis])

return entropy(np.exp(log_dens_X), np.exp(log_dens_Y))

# Example usage:
X = np.random.randn(100) # Sample from distribution X
Y = np.random.randn(100) # Sample from distribution Y

distance_mdd = mdd(X, Y)
print(f"MDD distance between X and Y: {distance_mdd}")

Reference