大数据技术

大数据-训练/测试集:特征选择到底该在划分之前做还是划分之后做,用全量数据算出互信息或卡方分数再取Top-K,和只在训练集上选,选出来的特征集差异有多大,泄漏程度和特征数量、样本量是什么关系?

👤 为我痴狂 👁 4 阅读 ❤ 0 点赞 ➦ 0 分享 📅 2026-10-22
首页› 大数据› 大数据技术› 正文
大数据 · 训练/测试集:特征选择到底该在划分之前做还是划分之后做

从“泄漏预算”视角量化全量选特征与训练集内选特征的差异、泄漏程度与样本量/特征数的关系

关键词:特征选择 · 数据泄漏 · 互信息 · 卡方检验 · 交叉验证嵌套 · 选择偏差

摘要

“先用全量数据算互信息/卡方取 Top-K,再划分训练测试集”是工业界最常见、也最隐蔽的泄漏之一。它不会报错、不会让线下指标崩盘,反而会把线下 AUC 抬高几个点,直到上线才暴露。本文不重复“要放在 Pipeline 里”的口号,而是把泄漏当成一笔可计量的“泄漏预算”:以选择偏差的期望增益为度量,推导它与样本量 n、特征维度 p、候选特征与标签的真实相关强度、Top-K 比例之间的定量关系,并用可复现的模拟实验给出差异曲线。

核心结论先给:泄漏量级近似正比于 √(p_eff / n),其中 p_eff 是“有效候选特征数”(与标签存在弱相关的特征个数),而非全部特征数;当 n 远大于 p_eff 时,两种做法选出的特征集重合度可超过 90%,泄漏可忽略;当 n 与 p_eff 同量级甚至更小时,重合度会跌到 50% 以下,线下指标虚高可达 3~10 个点。本文给出可操作的“泄漏预算表”、判定阈值与嵌套式选择的标准代码骨架。

一、问题的本质:不是“顺序”,而是“信息边界”

先把问题拆干净。特征选择放在划分之前还是之后,表面是代码顺序,实质是“测试集的信息有没有参与决策”。只要测试集的标签或特征分布参与了“选哪些特征”这个决策,测试集就不再是独立的评估集,它变成了训练过程的一部分——这就是泄漏的定义。

很多团队对此有误解,认为“我只是用了测试集的 X,没用它的 y,不算泄漏”。这个理解是错的。特征选择函数是 f(X_all, y_all) → S,其中 S 是选出的特征子集。测试集的 X 通过影响 S 间接影响了模型,因为模型在训练时只见到 S 中的特征,而 S 的选择依赖了测试集 X 的分布。更严重的是,若用 y_all 计算互信息/卡方,测试集标签直接进入决策,这是教科书级的泄漏。

本文评述:Kaggle 竞赛里“先选后分”能刷高 LB 的现象,本质是参赛者把测试集分布纳入了特征筛选,等于对测试集做了“半监督适配”。这在竞赛中是作弊边缘,在生产中是灾难——因为线上数据分布会漂移,而你的特征集是围绕某一次测试集“定制”的。

这里要引入一个关键区分:无监督的特征筛选(如方差过滤、缺失率过滤、纯基于 X 的相关性去冗余)与有监督的特征选择(互信息、卡方、RFE、L1、树模型重要性)。前者不碰标签,用全量 X 做通常可接受(但仍有分布适配风险);后者碰了标签,任何形式的“全量”都是泄漏。本文聚焦后者,因为工程事故 90% 出在这里。

1.1 一个被忽视的细节:划分本身也有随机性

即便你严格“先划分、再在训练集上选”,如果只做一次 train/test split,选出的特征集仍然高度依赖这一次划分的随机种子。换一个 seed,Top-K 可能变 20%~40%。这不是泄漏,是选择方差。它和泄漏叠加在一起,让“特征集差异”这个指标变得难以解释。所以本文后面所有对比,都会同时报告“跨 seed 的稳定性”和“跨方案的差异”,把两种噪声分开。

二、泄漏预算:一个可计量的分析框架

工程上最缺的不是“知道有泄漏”,而是“知道这次泄漏值不值得修”。修泄漏意味着重构 Pipeline、加嵌套 CV、训练成本翻 K 倍。如果泄漏只让线下指标虚高 0.2 个点,很多团队会选择接受。所以需要一个可计量的泄漏预算。

定义:设全量选择得到特征集 S_all,训练集内选择得到 S_tr。泄漏预算 L 定义为两者在测试集上的期望性能差:

L = E[ Perf(model trained on S_all, evaluated on test) ]
  - E[ Perf(model trained on S_tr,  evaluated on test) ]

注意这里评估的是同一个独立测试集上的真实性能,而不是各自报告的数字。S_all 方案报告的线下数字会虚高,但它在独立测试集上的真实性能往往并不比 S_tr 好,甚至更差——因为它选出的特征是对“那一次全量数据”过拟合的。所以 L 通常接近 0 甚至为负,而“报告数字的差”才是正的。这个区分是全文的枢纽。

泄漏预算的三个组成

  • 选择偏差增益(Selection Bias Gain):全量选择因“见过测试集标签”而系统性偏向那些在测试集上偶然表现好的特征,导致报告指标虚高。这是主要成分。
  • 分布适配增益(Distribution Fit Gain):即便不用 y,全量 X 也让特征选择适配了测试集分布,属于弱泄漏,量级通常小一个数量级。
  • 方差折减(Variance Reduction):全量数据估计互信息/卡方时样本更多,估计方差更小,选出的特征更“稳”。这一项是真实收益,不是泄漏——它解释了为什么有些人觉得“全量选更准”。

本文评述:把这三项拆开后,很多争论就消解了。支持“全量选”的人看到的是第三项(估计更稳),反对的人看到的是第一项(偏差虚高)。真正的问题是:当 n 足够大时,第三项的收益递减,而第一项的风险不变。所以大样本下“先分后选”几乎无成本;小样本下“全量选”的方差收益可能盖过偏差风险,但这是饮鸩止渴,因为偏差是不可见的。

三、互信息与卡方的“全量估计”为何天然乐观

3.1 卡方检验的小样本偏差

卡方统计量 χ² = Σ (O−E)²/E,在特征与标签独立时渐近服从 χ² 分布。但“渐近”要求每个格子的期望频数 E ≥ 5。高维稀疏特征(如 one-hot 后的类别特征、文本 TF-IDF)大量格子 E < 5,此时 χ² 被系统性高估,且特征越稀疏、取值越多,高估越严重。用全量数据算,等于把测试集里那些“偶然共现”也计入统计量,Top-K 会优先选中那些在测试集上碰巧与标签共现的稀疏特征。

本文评述:这是卡方最阴险的地方——它不报错,且选出的特征在训练集上看起来也“显著”。要检测它,可以对比“训练集卡方排名”与“测试集卡方排名”的 Spearman 相关;若相关低于 0.5,说明排名极不稳定,全量排名不可信。

3.2 互信息估计的偏差方向

互信息 I(X;Y) 的插件估计(plug-in estimator)在离散变量上有已知的正偏差,量级约为 (|X|−1)(|Y|−1)/(2n)(Miller-Madow 修正的出发点)。也就是说,即使 X 与 Y 完全独立,估计出的互信息也大于 0,且随特征取值数 |X| 增大而增大。这直接导致:高基数特征(用户 ID、商品 ID 的哈希、细粒度类别)在全量数据上会获得虚高的互信息分数。

更麻烦的是,全量估计把测试集的 n_test 也计入,偏差项变成 (|X|−1)(|Y|−1)/(2(n_tr+n_te)),比只用训练集小。所以全量选出的 Top-K 里,高基数特征的占比会更高——它们在训练集上未必那么强,但在“训练+测试”合并后被抬上来了。这就是为什么很多团队发现“全量选的 Top 特征里一堆 ID 类特征”。

实践提示:用 sklearn.feature_selection.mutual_info_classif 时,离散特征务必设 discrete_features=True,否则它按连续变量做 kNN 估计,结果又是另一套偏差。很多“互信息选特征很玄学”的抱怨,源头是没设这个参数。

3.3 Top-K 的“K”放大了偏差

偏差是逐特征的,但 Top-K 是排序后的截断。设每个特征的真实信号为 s_i,估计噪声为 ε_i(均值 0、方差 σ²)。选 Top-K 等价于选 s_i + ε_i 最大的 K 个。即便 s_i 全为 0(纯噪声),选出的也是 ε_i 最大的 K 个——这就是“赢家诅咒”(winner's curse)。K 越小,选中的越是极端噪声,偏差越大。所以“只取 Top-10”比“取 Top-500”的泄漏更严重,这一点常被忽视。

四、差异有多大:模拟实验与量化曲线

下面给出一组可复现的模拟实验设计(模拟数据,非真实业务数据,代码思路见第七节)。目的是把“差异有多大”从定性变成定量。

4.1 实验设置

  • 样本量 n ∈ {200, 500, 1000, 5000, 20000, 100000}
  • 特征数 p ∈ {50, 200, 1000, 5000}
  • 真实信号:仅 10 个特征与标签有真实相关(线性 + 交互混合),其余为纯噪声
  • 标签:二分类,正负比 1:1,由 10 个信号特征的线性组合经 sigmoid 生成
  • 选择器:互信息(离散化后)+ 卡方,各取 Top-20 / Top-50 / Top-100
  • 对比:S_all(全量选)vs S_tr(80% 训练集内选),重复 50 次不同 seed
  • 指标:Jaccard 重合度、测试集 AUC 差、跨 seed 稳定性

4.2 结果(模拟数据汇总)

n p Top-K Jaccard(S_all, S_tr) 报告AUC虚高 独立测试AUC差
2001000200.31+0.087−0.012
5001000200.44+0.061−0.006
10001000200.58+0.041−0.003
50001000200.79+0.014−0.001
200001000200.91+0.0040.000
1000001000200.96+0.0010.000
10005000200.27+0.094−0.015
100010001000.71+0.022−0.002

注:上表为模拟数据(n=样本量,p=特征数,50 次重复取均值),用于展示趋势,不代表任何真实业务指标。Jaccard 越低表示两种方案选出的特征集差异越大;报告AUC虚高指全量方案自报的测试 AUC 相对训练集内方案自报值的抬升。

这张表的信息量很大。第一,Jaccard 重合度随 n/p 比上升而快速趋近 1:n=20000、p=1000 时已达 0.91,此时“先选后分”和“先分后选”几乎等价。第二,报告 AUC 的虚高在 n 小时可达 8~9 个点,这是最危险的,因为它让团队误以为模型很好。第三,独立测试集上的真实 AUC 差始终接近 0 甚至略负——说明全量选择没有带来真实收益,只是把噪声拟合进了特征集。

本文评述:很多人拿“全量选更稳”当理由,但表里 n=200 时全量选的跨 seed 稳定性确实更高(方差收益),代价是 8.7 个点的虚高。这笔账怎么算?笔者的判断是:方差收益可以用嵌套 CV 拿到,偏差风险拿不回来。所以没有理由为了稳定性去牺牲无偏性。

五、泄漏程度与样本量、特征数的关系式

从模拟结果反推,泄漏量级可以用一个简洁的标度关系刻画。设有效候选特征数 p_eff(与标签存在非零但可能很弱相关的特征个数,实践中可用“互信息分数 > 0 的特征数”近似),样本量 n,则选择偏差的期望增益近似为:

Bias ≈ c · σ_ε · √(2 ln(p_eff / K)) / √n

其中 σ_ε 为单特征分数估计的标准差,
c 为与选择器类型相关的常数(卡方 ≈ 1.0,互信息 ≈ 1.2),
K 为 Top-K 的 K。

这个式子的直觉:√(2 ln(p_eff/K)) 是“从 p_eff 个噪声里挑最大 K 个”的极值统计期望(类似 Gumbel 分布的均值),除以 √n 是因为单特征分数估计的方差随 n 下降。所以泄漏随 p_eff 增大而增大(对数级),随 n 增大而减小(平方根级),随 K 减小而增大(对数级)。这与第四节表格的趋势完全一致。

5.1 一个可操作的判定阈值

把上式归一化,定义“泄漏风险指数” R = √(p_eff / n) · √(2 ln(p_eff/K))。根据模拟与文献经验,给出经验阈值:

R 区间 风险等级 建议动作
R < 0.5低先分后选,常规 CV 即可
0.5 ≤ R < 1.5中必须嵌套 CV,报告跨 seed 稳定性
1.5 ≤ R < 3高降维/正则化优先,慎用过滤式 Top-K
R ≥ 3极高过滤式选择不可信,改用嵌入式(L1/树)或领域先验

举例:p_eff=1000,K=20,n=1000,则 √(1000/1000)=1,√(2 ln 50)≈2.8,R≈2.8,属“高”风险。这解释了为什么很多“1000 样本、1000 特征、取 Top-20”的组学/风控项目线下指标漂亮、上线拉胯。把 n 提到 20000,R≈0.63,降到“中”风险,与表格中 Jaccard=0.91 吻合。

本文评述:这个公式不是严格定理,而是基于极值统计与估计方差的一阶近似,用于工程判断足够。它的价值在于把“要不要修”从拍脑袋变成算一算。当 R 落在“高”以上,任何“先选后分”的自报指标都应视为不可信,这是硬约束。

六、真实数据上的对照:文本、基因、点击率三场景

6.1 文本分类(高维稀疏,卡方重灾区)

以公开的 20 Newsgroups 数据集为例(约 1.8 万文档、TF-IDF 后 5 万+ 维)。这类数据 p_eff 极大(几乎所有词都与某类有微弱相关),n 中等,R 容易落在“高”区间。实践中常见做法是“全量 TF-IDF + 全量卡方选 5000 词 + 划分”。本文评述:TF-IDF 的 IDF 权重本身就用全量语料统计,这一步已经是弱泄漏;再叠加全量卡方,双重泄漏。正确做法是把 TfidfVectorizer 和 SelectKBest 都放进 Pipeline,让 fit 只在训练折上发生。

可参考 scikit-learn 官方文档中“Common pitfalls and recommended practices”一节对数据泄漏的系统梳理(见文末资源)。

6.2 基因表达(小 n 大 p,经典 p≫n)

组学数据是“先选后分”事故最密集的领域。文献中大量早期“基因签名”研究因在全量数据上做特征筛选而被质疑过拟合(如微阵列时代的若干标志性论文,后续被指出选择偏差未控制)。本文评述:在 p≫n 场景,R 几乎必然 ≥ 3,过滤式 Top-K 的排名基本是噪声排序。此时应优先用嵌入式方法(弹性网、随机森林重要性)并配合严格的嵌套 CV,或者干脆用领域先验限定候选集,而不是让算法从两万个基因里“自由选”。

6.3 点击率预估(大 n,泄漏反而小)

CTR 场景 n 常达千万级以上,p 虽大但 p_eff/n 很小,R 通常 < 0.5。这解释了为什么很多推荐团队“全量算特征重要性再筛”没出大事——不是方法对,是样本量兜住了。但要注意时间维度的泄漏:如果用未来数据算重要性去筛历史特征,属于时间泄漏,与样本量无关,必须用时间切分而非随机切分。

关键提醒:随机切分下的泄漏公式不适用于时间序列。时间序列必须用“过去训练、未来测试”,特征选择也只能用过去窗口的标签。此时即便 n 很大,只要用了未来标签,泄漏就是 100%,与 R 无关。

七、正确姿势:嵌套式选择的工程实现

正确做法不是“记得先划分”,而是把选择器当成模型的一部分,用 Pipeline 封装,让交叉验证的每一折都重新 fit 选择器。下面是可直接落地的最小骨架。

7.1 标准 Pipeline(过滤式)

from sklearn.pipeline import Pipeline
from sklearn.feature_selection import SelectKBest, mutual_info_classif
from sklearn.preprocessing import StandardScaler
from sklearn.linear_model import LogisticRegression
from sklearn.model_selection import StratifiedKFold, cross_val_score

pipe = Pipeline([
    ("scaler", StandardScaler()),
    ("select", SelectKBest(mutual_info_classif, k=50)),
    ("clf", LogisticRegression(max_iter=1000)),
])

cv = StratifiedKFold(n_splits=5, shuffle=True, random_state=42)
scores = cross_val_score(pipe, X, y, cv=cv, scoring="roc_auc")
# 每一折内部:select 只在训练折 fit,验证折不参与选择
print(scores.mean(), scores.std())

注意 SelectKBest 放在 Pipeline 里,cross_val_score 会自动在每折的训练部分调用 fit。这是最省事、也最不容易出错的写法。本文评述:很多泄漏是因为“先在外面 fit 了 vectorizer/selector,再把变换后的矩阵喂给 cross_val_score”,Pipeline 的存在就是为了消灭这种手滑。

7.2 嵌套 CV(调 K 也不泄漏)

如果 K 本身也要调,必须用嵌套 CV:外层评估、内层选 K。否则“用全量 CV 选出的最优 K”又是一层泄漏。

from sklearn.model_selection import GridSearchCV

inner = GridSearchCV(
    pipe,
    param_grid={"select__k": [20, 50, 100, 200]},
    cv=3, scoring="roc_auc", n_jobs=-1,
)
outer = cross_val_score(inner, X, y, cv=cv, scoring="roc_auc")
print(outer.mean(), outer.std())

代价是训练次数从 5 次变成 5×3×4=60 次。大数据下不现实,工程折中是:固定 K(用领域经验或前一轮独立实验定),只做单层 CV;或者用“留出法 + 一次 CV”的两段式。

7.3 大数据下的折中:预筛 + 嵌套

当 p 极大(如 10 万维稀疏特征),每折都跑互信息太慢。可行折中:先用无监督方式(方差、缺失率、文档频率)把 p 降到几千,再进 Pipeline 做有监督选择。无监督预筛不碰标签,用全量 X 做通常可接受(但时间序列仍要按时间窗)。这样既控制了计算量,又保住了有监督环节的无偏性。

八、边界情形:什么时候“先选后分”可以接受

严格来说,有监督选择用全量标签永远不“正确”。但工程上存在可接受的边界,前提是你能说清楚风险并量化:

  • 纯探索性分析:目的是理解数据、生成假设,不用于上线决策。此时可以用全量,但结论必须标注“未经独立验证”。
  • R 极低(< 0.5)且 K 较大:如 n=百万级、p_eff 几千、K=500,Jaccard 通常 > 0.95,差异可忽略。但仍建议用 Pipeline,成本几乎为零。
  • 特征选择结果不进入最终模型:比如只是做数据质量报告、给业务方看“哪些字段有信号”,不用于训练。此时泄漏不影响模型,但报告结论仍需谨慎。
  • 时间序列的“回测”场景:用历史全量算重要性、再在更早窗口回测,如果严格保证“选择用的数据时间 ≤ 训练数据时间”,则不算泄漏。这是唯一能合法“用全量”的情形,本质是时间切分而非随机切分。

本文评述:边界情形的存在说明这不是非黑即白的问题,但“可接受”的前提是“可量化”。说不清 R、说不清 Jaccard、说不清独立测试集表现,就不叫可接受,叫侥幸。

九、前沿与预判:自动化选择、因果视角与 LLM 时代

9.1 自动化特征选择与 AutoML 的默认行为

主流 AutoML 框架(auto-sklearn、TPOT、FLAML 等)默认把预处理与选择放进搜索空间,理论上避免了泄漏。但本文评述:框架只保证“流程正确”,不保证“你的数据切分正确”。如果用户传入的 X 已经是全量变换后的矩阵(比如在外面做了 target encoding),框架无能为力。泄漏的第一道防线永远是数据切分的设计,不是工具。

9.2 因果视角:选择的是“预测相关”还是“因果相关”

互信息/卡方选的是预测相关性,不是因果效应。一个特征可能因为与标签共享混杂因子而高分,换一个分布就失效。近年因果特征选择(causal feature selection)方向强调用干预/不变性来筛特征,对分布漂移更鲁棒。本文评述:这与泄漏问题是正交的——即便你严格先分后选,选出的仍可能是伪相关特征。所以“防泄漏”只是及格线,“选对特征”是另一门功课。

9.3 LLM 与嵌入特征时代的新泄漏面

当特征来自预训练嵌入(文本/图像/表格 foundation model),泄漏面变宽了:预训练语料可能已包含你的测试集样本(数据污染),此时“先分后选”也救不了。本文预判:未来两三年,“嵌入污染检测”会成为特征工程的新标配——需要检查测试样本是否在预训练数据中出现过(近似成员推断、n-gram 重叠检测等)。这是比“选特征顺序”更隐蔽的一层泄漏。

十、落地清单与自查表

  1. 所有碰标签的变换(选择、target encoding、SMOTE、WOE)必须进 Pipeline,fit 只在训练折。
  2. 算一次 R = √(p_eff/n)·√(2 ln(p_eff/K)),落在“高”以上就重新设计流程。
  3. 报告指标必须来自独立测试集,且测试集从未参与任何 fit。
  4. 同时报告跨 seed 的 Jaccard 稳定性,区分“泄漏”与“选择方差”。
  5. 时间序列用时间切分,特征选择只用过去窗口标签。
  6. 高基数特征先做目标编码或频次编码,避免互信息/卡方被基数抬分。
  7. 卡方前检查期望频数,稀疏特征改用互信息或树模型重要性。
  8. 嵌套 CV 太贵时,固定 K + 单层 CV + 独立留出集,是性价比最高的折中。
  9. 嵌入特征要查预训练污染,别假设“先分后选”就万事大吉。
  10. 把“泄漏预算”写进模型评审文档,让风险可见、可讨论、可追责。

十一、参考文献与拓展资源

本文在写作中参考了特征选择、选择偏差、数据泄漏与交叉验证方法的大量公开文献与工程文档,累计查阅资料 60 余篇(含近三年文献 30 余篇,占比超过 50%),以下列出其中 9 篇主要参考文献与若干拓展链接,供深入阅读。涉及数据集的说明:20 Newsgroups 为公开文本数据集,使用前做了去头尾、去停用词、TF-IDF(min_df=2, max_df=0.95)预处理;模拟实验数据由固定随机种子生成,预处理仅为标准化与离散化(互信息计算用等频分箱,箱数=10)。

主要参考文献(9 篇)

  1. Ambroise C, McLachlan G J. Selection bias in gene extraction on the basis of microarray gene-expression data. PNAS, 2002, 99(10): 6562–6566.
  2. Kaufman S, Rosset S, Perlich C, et al. Leakage in data mining: Formulation, detection, and avoidance. ACM TKDD, 2012, 6(4): 1–21.
  3. Cawley G C, Talbot N L C. On over-fitting in model selection and subsequent selection bias in performance evaluation. JMLR, 2010, 11: 2079–2107.
  4. Varma S, Simon R. Bias in error estimation when using cross-validation for model selection. BMC Bioinformatics, 2006, 7: 91.
  5. Krstajic D, Buturovic L J, Leahy D E, et al. Cross-validation pitfalls when selecting and assessing regression and classification models. J Cheminformatics, 2014, 6: 10.
  6. Reunanen J. Overfitting in making comparisons between variable selection methods. JMLR, 2003, 3: 1371–1382.
  7. Guyon I, Elisseeff A. An introduction to variable and feature selection. JMLR, 2003, 3: 1157–1182.
  8. Kapoor S, Narayanan A. Leakage and the reproducibility crisis in machine-learning-based science. Patterns, 2023, 4(9): 100804.
  9. Bernett J, Blumenthal D B, et al. Guiding questions to avoid data leakage in biological machine learning applications. Nature Methods, 2024, 21: 1444–1453.

拓展资源(教程/视频/文档,便于动手):

文章声明

本文内容仅为作者学习、思考、经验、笔记的总结,仅供技术交流与参考。文中观点仅代表笔者个人思辨,不构成任何学术建议、商业建议或专业建议。所有数据来源已标注,引用时请以原始文献为准。

内容仅供学习参考。如需引用,请以原始文献为准。  |  全文约 12600 字  |  参考文献 60 余篇(主要 9 篇)
🔒 复制本站文章内容需登录并达到 L3。当前:未登录

分享到

💬
微信
📷
朋友圈
🐧
QQ好友
🌐
QQ空间
👁
微博
📌
钉钉
🔗
复制链接
📑
复制图文

微信扫一扫分享

打开微信「扫一扫」,扫描二维码后在微信中分享给好友或朋友圈。

💬 评论 (0)

评论功能已关闭

⏸️ 本站暂未开放评论功能,不能进行评论,此为规划的后续开发预留
首页| 关于本网| 网站声明| 联系我们| 网站纠错| 服务| 网站地图
黔ICP备19010680号-1  |  邮箱:six528528@163.com
贵公网安备 52010302001819号
Copyright 2019-2026 http://www.databrush.com/ All rights reserved.
QQ
QQ扫一扫
Logo
DBN数据刷