mutual_info_score仅适用于离散变量,需先对连续变量分箱;mutual_info_regression适用于连续特征与连续目标变量,内部用knn估计密度。

用 sklearn.metrics.mutual_info_score 计算离散变量间的互信息
互信息(Mutual Information)是衡量两个变量非线性依赖程度的通用指标,不假设线性或单调关系,适合分类变量或已分箱的连续变量。但注意:mutual_info_score 只接受整数或字符串标签,不能直接喂入浮点数组。
常见错误是把原始连续数据直接传进去,报错 ValueError: Found array with 0 sample(s) 或 TypeError: ufunc 'isnan' not supported for the input types——本质是它底层调用的是直方图计数,要求输入是离散类别。
- 对连续变量,先用
pd.cut或KBinsDiscretizer(n_bins=5, encode='ordinal')分箱(建议 5–10 箱,太少会丢失信息,太多易过拟合) - 确保两组变量长度一致,且无 NaN:用
np.isfinite()掩码过滤再传入 - 结果无量纲,但受 bin 数量影响明显;可除以
np.log2归一化到 [0,1] 区间(需手动计算联合/边缘熵)
用 sklearn.feature_selection.mutual_info_regression 处理“连续 X → 连续 y”
这是更贴近你场景的选项:当一组是连续特征(如温度、时间),另一组也是连续响应(如销量、误差),mutual_info_regression 内部自动用 KNN 估计密度,避免人工分箱失真。
容易踩的坑是忽略参数 random_state 和 n_neighbors:默认 n_neighbors=3 在小样本(max(3, len(X)//10);不设 random_state 会导致每次运行结果微小波动(KNN 搜索有随机性)。
- 输入 X 必须是二维:即使单变量也要写成
X.reshape(-1, 1) - y 是一维数组,自动处理缺失值(跳过 NaN 对应的样本)
- 返回的是数组,每个元素对应 X 的一列与 y 的互信息;若只有一列,取
[0]
警惕 scipy.stats.kendalltau 和 spearmanr 的“伪非线性”陷阱
很多人误以为这两个是“非线性相关系数”,其实它们只捕获单调关系(上升或下降趋势),对抛物线、正弦等非单调模式完全不敏感。比如 x = [-2,-1,0,1,2], y = x²,kendalltau 返回接近 0,但互信息能稳定检出强依赖。
使用场景很明确:当你真正关心的是“x 增大时 y 是否倾向于增大/减小”,而不是“x 和 y 是否存在任意形式的统计依赖”——此时选它们更快更稳健(O(n log n) 时间);否则别用。
-
kendalltau对异常值鲁棒,适合小样本(n -
spearmanr实际计算的是秩次的 Pearson 相关系数,结果范围仍是 [-1,1],但解释不能套用线性假设 - 两者都要求至少 10 个有效配对,少于该数时 p 值不可靠
性能与精度权衡:小数据用互信息,大数据考虑近似
当样本量超过 10⁵,mutual_info_regression 的 KNN 密度估计会明显变慢(默认 brute-force 搜索)。这时可切换为 algorithm='kd_tree'(需数据维度不高)或改用 minepy.MINE 库的 mic()(最大信息系数),它基于自适应分箱,对大样本更友好,但安装需额外编译(pip install minepy)。
真正容易被忽略的是:所有互信息类指标对样本分布极度敏感。同一组数据,训练集和测试集若分布偏移(如时间序列前后段),互信息值可能差 30% 以上——别把它当绝对标尺,更适合做特征筛选的相对排序。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!











