第 6 章 · 02 互信息特征选择


文档摘要

第 6 章 · 02 互信息特征选择 本节摘要:本节讲一种能捕捉非线性依赖的特征选择工具——互信息(Mutual Information, MI)。相关系数只能衡量线性关系,但金融里因子和收益的关系常常是非线性的(如 U 型、阈值效应),相关系数会漏掉这类强信号。互信息基于信息论的熵,衡量「知道一个变量后,对另一个变量的不确定性的减少量」,对任意依赖关系都有效。本节讲三件事:熵与互信息的定义、MI 与相关系数的本质区别、用 sklearn 的 / 在金融特征面板上做特征筛选,并画出归一化 MI 热力图定位最有预测力的因子。 内容来源:原项目 ,汉化并套用体系化模板。 ⚠️ 学习提示:互信息是无模型的(非参数),不需要假设关系形态,但也因此对样本量要求更高。

第 6 章 · 02 互信息特征选择

本节摘要:本节讲一种能捕捉非线性依赖的特征选择工具——互信息(Mutual Information, MI)。相关系数只能衡量线性关系,但金融里因子和收益的关系常常是非线性的(如 U 型、阈值效应),相关系数会漏掉这类强信号。互信息基于信息论的熵,衡量「知道一个变量后,对另一个变量的不确定性的减少量」,对任意依赖关系都有效。本节讲三件事:熵与互信息的定义、MI 与相关系数的本质区别、用 sklearn 的 mutual_info_classif / mutual_info_regression 在金融特征面板上做特征筛选,并画出归一化 MI 热力图定位最有预测力的因子。

内容来源:原项目 ch06/02_mutual_information.ipynb,汉化并套用体系化模板。

⚠️ 学习提示:互信息是无模型的(非参数),不需要假设关系形态,但也因此对样本量要求更高。小样本下估计噪声大,务必配合交叉验证使用。

学习目标

阅读完本节,你应当能够:

  1. 写出 H(X) 和互信息 I(X;Y) 的定义。
  2. 说清 MI 与相关系数的本质区别(线性 vs 任意依赖)。
  3. 用 sklearn 的 mutual_info_classif 对金融特征做筛选。
  4. 归一化 MI 热力图横向比较因子对不同期限目标的预测力。
  5. 知道 MI 估计的离散/连续处理差异。

一、为什么相关系数不够用

相关系数(Pearson ρ)衡量的是两个变量的线性关系强度。但金融里很多强依赖是非线性的:

  • U 型:低估价和高估价都容易反弹,中间价不动——ρ ≈ 0 但 MI 很高。
  • 阈值效应:换手率超过某阈值才有信号,阈值以下全是噪音——ρ 很低但 MI 高。
  • 异步相关:今天成交量与三天后收益相关,但与同期收益无关——必须先对齐再看。

如果只用相关系数筛因子,会漏掉所有非线性信号——而这些往往是 alpha 的主要来源。

二、熵与互信息

(entropy)量化一个随机变量包含的信息量(不确定性):

H(X) = -\sum_i p(x_i) \log p(x_i)

分布越均匀,熵越大(越不确定);越集中,熵越小。

互信息(mutual information)衡量「知道 X 后,Y 的不确定性减少了多少」:

I(X; Y) = H(Y) - H(Y | X)
  • I = 0 表示 X 和 Y 独立。
  • I 越大,依赖越强——不限于线性

💡 核心心法:相关系数回答「X 和 Y 是否同向/反向走?」,互信息回答「知道 X 是否能减少对 Y 的不确定性?」。后者范围更广,任何形式的依赖都能被捕捉。

三、MI vs 相关系数

维度 Pearson 相关系数 ρ 互信息 I
关系类型 仅线性 任意依赖
取值范围 [-1, 1] [0, ∞)
方向信息 有(正/负) 无(只看强度)
计算成本 中(需估计分布)
样本量要求
假设 近似正态更好 无分布假设

实务建议:先用 MI 做宽筛(把所有可能有信号的留下),再用 ρ 看方向、剔共线性高的特征

四、sklearn 实现

sklearn 提供两个函数:

  • mutual_info_regression:目标连续(回归)。
  • mutual_info_classif:目标离散(分类)。

金融里常常把「未来 N 月收益」二分类成「涨/跌」,用 mutual_info_classif:

from sklearn.feature_selection import mutual_info_classif target_labels = [f'target_{i}m' for i in [1, 2, 3, 6, 12]] targets = data.dropna().loc[:, target_labels] features = data.dropna().drop(target_labels, axis=1) features.sector = pd.factorize(features.sector)[0] # 类别编码 cat_cols = ['year', 'month', 'msize', 'age', 'sector'] discrete_features = [features.columns.get_loc(c) for c in cat_cols] mutual_info = pd.DataFrame() for label in target_labels: mi = mutual_info_classif(X=features, y=(targets[label] > 0).astype(int), # 涨跌二分类 discrete_features=discrete_features, random_state=42) mutual_info[label] = pd.Series(mi, index=features.columns)

⚠️ discrete_features 参数:必须告诉 sklearn 哪些列是离散的(如 sector、month),否则它会把它们当连续估计,结果失真。这是新手常踩的坑。

五、归一化 MI 热力图

原始 MI 的绝对值难解读(随单位变化),通常按目标列归一化:每个 MI 除以该列 MI 之和,看「这个因子占该期限总 MI 的比例」。

import seaborn as sns import matplotlib.pyplot as plt fig, ax = plt.subplots(figsize=(15, 4)) sns.heatmap(mutual_info.div(mutual_info.sum()).T, ax=ax, cmap='Blues');

热力图行是不同期限(1m/3m/6m/12m),列是因子。颜色越深,因子对该期限的预测力越强。典型发现:

  • 短期限(1m)受动量、波动类因子驱动。
  • 长期限(12m)受估值、规模类因子驱动。
  • 类别变量(sector、month)在某些期限贡献突出。

六、对类别变量的处理

mutual_info_classif 内部用基于 k 近邻的估计器(Ross, 2014),要求显式声明哪些特征离散。如果用 pd.get_dummies 把类别独热编码,则所有列都是 0/1 离散:

dummy_data = pd.get_dummies(data, columns=['year','month','msize','age','sector']) dummy_features = dummy_data.dropna().drop(target_labels, axis=1) cat_cols = [c for c in dummy_features.columns if c not in features.columns] discrete_features = [dummy_features.columns.get_loc(c) for c in cat_cols]

两种做法(因子化 vs 独热)结果接近,独热更细但维度更高。

本节要点回顾

  1. 相关系数只看线性:U 型、阈值效应这类非线性强信号会被 ρ 漏掉,但 MI 能捕捉。
  2. 熵 H(X) 量化不确定性;互信息 I(X;Y) = H(Y) - H(Y|X) 衡量知道 X 后 Y 不确定性的减少。
  3. sklearn:mutual_info_regression(连续目标)、mutual_info_classif(离散目标),必须声明 discrete_features
  4. 归一化热力图:MI 除以列和,横向比较因子对不同期限目标的预测力,指导宽筛。
  5. 实务流程:MI 宽筛 → 相关系数看方向和共线性 → 交叉验证最终确认。

下一节,我们讲偏差方差权衡——理解欠拟合和过拟合的根本动因,以及如何用学习曲线诊断。


发布者: 作者: 灏天文库 转发
评论区 (0)
U