互信息(Mutual Information, MI)
起源
互信息(Mutual Information, MI)这一概念最早由克劳德·香农在信息论的开创性工作中引入,主要用来量化两个随机变量之间的相互依赖程度。它是一种衡量变量间统计相关性的非参数度量,不仅能够捕捉线性关系,还能反映非线性关系。
原理与定义
互信息测量了知道一个随机变量的值后,我们能获得的关于另一个随机变量的信息量。换句话说,它衡量了两个变量联合分布相比于它们各自独立分布的额外信息量。如果两个变量完全独立,它们的互信息为0;如果一个变量完全确定另一个变量,互信息达到最大。
公式
给定两个离散随机变量X和Y,它们的联合概率分布为P(X,Y),各自的边缘概率分布为P(X)和P(Y),互信息I(X;Y)定义为:
对于连续随机变量,上述求和变为积分:
引申义
互信息可以视为一种非对称度量,尽管通常在实践中视作对称使用,它还能够推广到多变量情况,形成多变量互信息,以及条件互信息,用于评估三个或更多变量间的相互依赖关系。
异同点
- **与相关系数**:互信息不限于线性关系,而皮尔逊相关系数主要衡量线性关系;斯皮尔曼等级相关系数虽能捕捉非线性关系,但不如互信息一般化。
- **与熵**:互信息是两个变量联合熵与各自熵的差,体现了信息增益或减少。
优缺点
**优点**:
- 非参数性,适用于任何类型的变量关系,包括非线性关系。
- 能够检测变量间的复杂依赖结构。
- 信息论基础,具有坚实的理论支持。
**缺点**:
- 计算量大,尤其是对于高维或连续变量,可能需要复杂的估计技术。
- 对于高维空间,互信息可能过估计变量间的相关性。
- 对于离散变量,结果受变量划分(离散化)影响。
应用场景
- 特征选择:在机器学习中,用于挑选与目标变量最相关的特征。
- 数据挖掘:发现数据集中隐藏的关联规则。
- 信息检索:评估查询词和文档的相关性。
- 神经科学:分析神经元活动间的相互作用。
数据示例
假设有两个离散随机变量 (X) 和 (Y),分别代表某地区的天气情况(晴天、雨天)和是否适合户外活动(适合、不适合)。我们有以下联合概率分布表:
从上表中,我们可以提取出边缘概率分布:
计算互信息 I(X;Y))
按照这个公式,我们需要对所有组合进行计算:
具体计算
总和
将上述计算结果相加得到互信息 (I(X;Y)):
因此,在这个例子中,随机变量 (X)(天气)和 (Y)(是否适合户外活动)之间的互信息大约为 0.466 nats(自然单位的信息量)。这表明这两个变量之间存在一定的相关性,即知道其中一个变量的值可以提供关于另一个变量的信息。
Java代码实现
import java.util.HashMap; import java.util.Map; public class MutualInformationExample { public static void main(String[] args) { // 定义联合概率分布 Map<String, Double> jointProbabilities = new HashMap<>(); jointProbabilities.put("晴天_适合", 0.6); jointProbabilities.put("晴天_不适合", 0.1); jointProbabilities.put("雨天_适合", 0.1); jointProbabilities.put("雨天_不适合", 0.2); // 计算边缘概率分布 Map<String, Double> marginalX = new HashMap<>(); Map<String, Double> marginalY = new HashMap<>(); for (Map.Entry<String, Double> entry : jointProbabilities.entrySet()) { String key = entry.getKey(); Double prob = entry.getValue(); String x = key.split("_")[0]; String y = key.split("_")[1]; marginalX.put(x, marginalX.getOrDefault(x, 0.0) + prob); marginalY.put(y, marginalY.getOrDefault(y, 0.0) + prob); } // 计算互信息 double mutualInfo = 0.0; for (Map.Entry<String, Double> entry : jointProbabilities.entrySet()) { String key = entry.getKey(); Double probXY = entry.getValue(); Double probX = marginalX.get(key.split("_")[0]); Double probY = marginalY.get(key.split("_")[1]); if (probX != 0 && probY != 0) { mutualInfo += probXY * (Math.log(probXY / (probX * probY)) / Math.log(2)); // 使用2为底的对数转换为比特 } } System.out.printf("互信息 (I(X;Y)): %.3f bits%n", mutualInfo); } }
这段Java代码首先定义了联合概率分布,然后从这些联合概率中计算出每个变量的边缘概率分布。之后,它遍历联合概率分布,根据互信息的公式计算每一对状态的贡献,并累加这些贡献来得到总的互信息值。注意,这里使用了自然对数(以e为底)转换为以2为底的对数来表示结果为比特。
常见的相似度计算方法
余弦相似度(Cosine Similarity)
皮尔逊相关系数
曼哈顿距离(Manhattan Distance)
欧氏距离(Euclidean Distance)
修正余弦相似度(Adjusted Cosine Similarity)
皮尔逊χ²检验(Pearson's Chi-squared Test)
Tanimoto系数(Tanimoto Coefficient)