测试集是否应参与到预处理阶段?
Forester’s Notebook
精耕笔记:自然搞懂深度学习(基于Pytorch)
测试集是否应参与到预处理阶段?
这是一个关于机器学习实践中数据泄露 (Data Leakage) 的核心问题。
一、明确含义
这里提到的测试集,是指起到验证模型效果作用的数据集,如有验证集也应包含。
预处理阶段可分为清洗和预处理两部分:

清洗阶段:将”脏“数据清洗干净。存在的问题对后续所有流程都造成困扰,是工作进行的基础。
预处理阶段:面向具体问题及应用模型,对数据集做必要处理。
二、答案
简短的回答是:
原则上,测试集(Test Set) 不应该 参与到任何需要从数据中“学习”或“估算”的预处理步骤中。
依次来看,每个操作都会对数据集原本“真实性”进行削减。
换句话说,这些操作仅是为用到的模型服务的,希望模型能达到最优效果;而训练完成后,进行验证(选取哪个模型/超参数最优)和测试(看看最终模型效果如何)追求的是模拟最真实的应用场景。
三、详细解释与例外情况
1、不允许测试集参与预处理的情况 (关键)
任何基于数据集统计量(均值、标准差、分位数等)的预处理步骤,都只能在**训练集(Training Set)**上进行计算和拟合,然后将拟合好的参数应用到训练集、验证集和测试集上。
| 预处理操作 | 原则 | 说明 |
|---|---|---|
| 标准化 (Standardization) | 只用训练集的均值 ( μ ) (\mu) (μ) 和标准差 ( σ ) (\sigma) (σ)。 | 错误做法: 用整个数据集(包括测试集)计算 μ \mu μ 和 σ \sigma σ,然后进行转换。这会导致模型在训练过程中“偷窥”到了测试数据的分布。 |
| 归一化 (Normalization) | 只用训练集的最大值 ( max ) (\max) (max) 和最小值 ( min ) (\min) (min)。 | 错误做法: 用测试集的 max \max max 和 min \min min 来缩放测试集。 |
| 缺失值填充 (Imputation) | 只用训练集的中位数、均值或众数来填充。 | 错误做法: 用整个数据集的中位数来填充测试集中的缺失值。 |
| 特征选择 (Feature Selection) | 只在训练集/验证集上评估特征重要性。 | 错误做法: 在所有数据上运行特征选择算法(如相关性分析),然后只用选定的特征训练模型。 |
| 编码 (Encoding) | 通常允许,但需注意。 | 如果是 One-Hot 编码等简单的转换,测试集可以进行。但如果是基于频率或目标变量的复杂编码,则必须严格在训练集上学习映射。 |
2、允许测试集参与预处理的情况 (一般转换)
对于不涉及从数据中学习统计信息的简单、确定性的转换,测试集可以参与:
- 确定性的格式转换:
- 将日期字符串转换为日期时间对象。
- 将文本转换为小写或去除标点符号。
- 简单的特征工程:
- 将两个特征相加、相乘等,只要转换的规则是事先确定的,不依赖于数据的分布。
- 重新整形和清理:
- 删除明显的重复行(但更好的做法是在划分之前就进行)。
三、推荐的预处理工作流 (Pipeline)
为了避免数据泄露,最佳实践是遵循以下步骤:
-
原始数据 (Raw Data)
-
划分数据集
将数据划分为:
- 训练集 (Training Set)
- 验证集 (Validation Set) (可选,用于调参)
- 测试集 (Test Set) (严格保留,绝不动用!)
-
拟合预处理器 (在训练集上)
使用sklearn.preprocessing中的变换器(如StandardScaler或SimpleImputer)在训练集上调用fit()方法。 -
转换数据 (在所有集合上)
使用步骤 3 中拟合好的变换器,在训练集、验证集和测试集上调用transform()方法。
这种工作流确保了测试集是真正“盲测”的,从而得到对模型泛化能力最公正的评估。
更多推荐


所有评论(0)