互信息(MI值)计算入门,从概念到公式再到实践,一文搞懂
这是一篇面向信息论、数据分析新手的互信息(MI)入门文章,紧扣“从概念到实践搞懂MI值”,一文搞定。,互信息是核心工具,比协方差灵活,能精准捕捉两个随机变量的线性/非线性依赖关系:非负值,越高关联越强,趋近0则接近独立,文中拆解熵→条件熵→差值的核心逻辑,清晰梳理离散、连续变量的实用计算公式,附简单快速上手的思路。
在数据分析、机器学习、自然语言处理等领域,我们常常需要衡量两个变量之间的关联程度——除了常见的皮尔逊相关系数,MI值(Mutual Information,互信息) 是一个更“全能”的选择:它能捕捉非线性关联,也能处理离散变量,甚至连续变量的相关性也不在话下。
我们就从基础概念、公式推导,一步步走到代码实践,彻底搞懂MI值的计算逻辑。

先搞懂:MI值到底是什么?
MI值的核心定义是:两个变量共享的信息量,换句话说,知道了变量X之后,能减少多少关于变量Y的不确定性?
举个简单的例子:
- 变量X是“今天是否下雨”,变量Y是“今天地面是否湿”。
- 如果不知道X,我们对Y的“不确定性”(用熵衡量)可能很高;但如果知道X(比如今天下雨了),那Y的不确定性几乎为0——此时X和Y的MI值就很大。
- 反过来,如果X是“今天是否喝牛奶”,Y是“明天股市是否涨跌”,知道X几乎不减少Y的不确定性,那它们的MI值就接近0。
基础铺垫:先理解“熵”
MI值的计算离不开“熵(Entropy)”——熵是衡量一个变量不确定性的指标,记为( H(X) )。
离散变量的熵
对于离散变量X,假设它有( k )个可能的取值( x_1, x_2,..., x_k ),每个取值的概率为( p(xi) ),那么熵的公式是: [ H(X) = -\sum{i=1}^k p(x_i) \log_2 p(x_i) ] (注:对数以2为底时,熵的单位是“比特”;以自然对数e为底时,单位是“奈特”,两者可互相转换)
联合熵
两个变量X和Y的联合熵( H(X,Y) ),衡量的是X和Y同时发生时的总不确定性: [ H(X,Y) = -\sum{x} \sum{y} p(x,y) \log_2 p(x,y) ] p(x,y) )是X取x、Y取y的联合概率。
条件熵
条件熵( H(Y|X) ),表示知道X之后,Y剩下的不确定性: [ H(Y|X) = H(X,Y) - H(X) ]
MI值的公式推导与计算
有了熵的铺垫,MI值就很好理解了:MI值 = Y的原始熵 - 已知X后Y的条件熵,也就是共享的信息量。
离散变量的MI值公式
根据上面的定义,离散变量X和Y的MI值( I(X;Y) )可以写成: [ I(X;Y) = H(Y) - H(Y|X) = H(X) + H(Y) - H(X,Y) ]
用联合概率和边缘概率展开的话(更方便计算): [ I(X;Y) = \sum{x} \sum{y} p(x,y) \log_2 \frac{p(x,y)}{p(x)p(y)} ] 这个展开式也很直观:如果X和Y独立, p(x,y)=p(x)p(y) ),对数部分为0,MI值就是0,符合我们的认知。
举个小例子:手动计算离散变量的MI值
假设我们有一组数据,统计“是否吃早餐”(X,取值:吃=1,不吃=0)和“上午是否饿肚子”(Y,取值:饿=1,不饿=0)的联合分布:
| X\Y | Y=1(饿) | Y=0(不饿) | 边缘概率p(X) |
|---|---|---|---|
| X=1(吃) | 1 | 4 | 5 |
| X=0(不吃) | 3 | 2 | 5 |
| 边缘概率p(Y) | 4 | 6 | 0 |
我们一步步算:
- 计算H(X): [ H(X) = -0.5\log_20.5 -0.5\log_20.5 = 1 \text{ 比特} ]
- 计算H(Y): [ H(Y) = -0.4\log_20.4 -0.6\log_20.6 \approx 0.971 \text{ 比特} ]
- 计算H(X,Y): [ H(X,Y) = -0.1\log_20.1 -0.4\log_20.4 -0.3\log_20.3 -0.2\log_20.2 \ \approx -0.1\times(-3.322) -0.4\times(-1.322) -0.3\times(-1.737) -0.2\times(-2.322) \ \approx 0.332 + 0.529 + 0.521 + 0.464 = 1.846 \text{ 比特} ]
- 计算MI值: [ I(X;Y) = H(X)+H(Y)-H(X,Y) \approx 1 + 0.971 - 1.846 = 0.125 \text{ 比特} ] 这个结果说明,“是否吃早餐”和“上午是否饿肚子”之间有一定的共享信息,关联程度不算特别强但确实存在。
连续变量的MI值怎么算?
对于连续变量,我们需要把“概率”换成“概率密度函数”,求和换成积分: [ I(X;Y) = \int\int p(x,y) \log_2 \frac{p(x,y)}{p(x)p(y)} dxdy ] 但实际计算中,我们很难直接得到连续变量的概率密度,通常的做法是:
- 离散化:把连续变量分成多个区间(比如用分位数分箱),然后按离散变量的方式计算;
- 非参数估计:比如用核密度估计(KDE)来近似概率密度函数,再进行数值积分。
代码实践:用Python计算MI值
在Python中,我们可以用scikit-learn库快速计算离散/连续变量的MI值,非常方便。
安装必要库
如果没安装的话,先装一下:
pip install scikit-learn numpy pandas
离散变量的MI值计算(基于我们的小例子)
import numpy as np
from sklearn.metrics import mutual_info_score
# 构造样本数据(根据联合分布生成1000个样本)
np.random.seed(42) # 固定随机数
X = np.random.choice([0,1], size=1000, p=[0.5,0.5])
Y = np.zeros_like(X)
# 按条件概率生成Y
for i in range(1000):
if X[i] == 1:
Y[i] = np.random.choice([0,1], p=[0.8,0.2]) # 0.4/0.5=0.8不饿,0.1/0.5=0.2饿
else:
Y[i] = np.random.choice([0,1], p=[0.4,0.6]) # 0.2/0.5=0.4不饿,0.3/0.5=0.6饿
# 计算MI值
mi = mutual_info_score(X, Y)
print(f"离散变量的MI值:{mi:.3f}") # 结果接近0.125,和手动计算一致
连续变量的MI值计算
用sklearn.feature_selection.mutual_info_regression(Y是连续变量)或mutual_info_classif(Y是离散变量):
from sklearn.feature_selection import mutual_info_regression
import matplotlib.pyplot as plt
# 构造有非线性关联的连续数据
np.random.seed(42)
X_cont = np.linspace(0, 10, 1000).reshape(-1,1)
Y_cont = np.sin(X_cont[:,0]) + np.random.normal(0, 0.1, 1000) # Y = sin(X) + 噪声
# 计算连续变量的MI值
mi_cont = mutual_info_regression(X_cont, Y_cont, random_state=42)[0]
print(f"连续变量的MI值:{mi_cont:.3f}")
# 可视化一下
plt.scatter(X_cont, Y_cont, s=5)
plt.xlabel("X_cont")
plt.ylabel("Y_cont = sin(X) + noise")
plt.show()
这里Y和X是非线性的正弦关系,皮尔逊相关系数会很低,但MI值能捕捉到它们的关联。
MI值的应用场景
- 特征选择:在机器学习中,用MI值筛选和目标变量关联最强的特征,去除冗余特征;
- 自然语言处理:计算词语之间的互信息,发现搭配词(番茄”和“炒蛋”的MI值很高);
- 因果推断:作为初步探索,判断变量之间是否存在潜在关联;
- 图像处理:衡量图像不同区域之间的信息共享程度。
- MI值衡量的是两个变量共享的信息量,能捕捉非线性、离散/连续变量的关联;
- 计算核心是熵:( I(X;Y)=H(X)+H(Y)-H(X,Y) );
- 实际应用中,用Python的scikit-learn可以快速实现计算。
掌握MI值,能帮你在数据分析中更全面地理解变量关系,赶紧试试吧!


还没有评论,来说两句吧...