跑通一个项目,不等于得到了可信的评估。最值得反复检查的问题是:测试数据是否以某种方式参与了训练流程的决定?
对讲义流程的一处修正
课程的第二次实操强调按步骤理解流程,但不能把“编码、缺失处理在划分前;标准化在划分后”当成通用规则。判断依据应是:这个步骤是否需要从样本中学习信息。
| 操作 | 需要注意的边界 |
|---|---|
| 依据事先确定的格式规则解析日期、修正单位 | 可对所有样本使用同一套固定规则 |
| 根据中位数补缺失、学习类别词表、计算缩放参数 | 只在训练数据上拟合 |
| 特征选择、PCA、过采样 | 同样应置于训练或交叉验证折内部 |
| 调整异常值阈值、选模型、选超参数 | 不使用最终测试集做决定 |
固定的数据质量规则和“看完全部数据才决定的清洗方案”不是一回事。scikit-learn 明确将插补、缩放和特征选择等列为可能发生泄漏的环节,建议先划分并使用流水线。参见 数据泄漏说明。
一个独立编写的最小实验
下面用鸢尾花数据演示技术流程,不使用课程中的临床示例,也不涉及实际医疗判断。需要安装 NumPy 和 scikit-learn。
import numpy as np
from sklearn.datasets import load_iris
from sklearn.impute import SimpleImputer
from sklearn.linear_model import LogisticRegression
from sklearn.metrics import accuracy_score
from sklearn.model_selection import StratifiedKFold, cross_val_score, train_test_split
from sklearn.pipeline import Pipeline
from sklearn.preprocessing import StandardScaler
X, y = load_iris(return_X_y=True)
X = X.copy()
X[::17, 0] = np.nan
X_train, X_test, y_train, y_test = train_test_split(
X, y, test_size=0.2, random_state=7, stratify=y
)
model = Pipeline([
("imputer", SimpleImputer(strategy="median")),
("scaler", StandardScaler()),
("classifier", LogisticRegression(max_iter=1000)),
])
cv = StratifiedKFold(n_splits=5, shuffle=True, random_state=7)
scores = cross_val_score(model, X_train, y_train, cv=cv, scoring="accuracy")
model.fit(X_train, y_train)
prediction = model.predict(X_test)
assert prediction.shape == y_test.shape
assert model.named_steps["scaler"].n_samples_seen_ == len(X_train)
assert np.allclose(
model.named_steps["imputer"].statistics_, np.nanmedian(X_train, axis=0)
)
print("CV mean:", round(float(scores.mean()), 4))
print("Test accuracy:", round(float(accuracy_score(y_test, prediction)), 4))
这里交叉验证接收的是整条流水线,因此每一折会重新拟合自己的预处理。最终模型再在完整训练集上拟合,测试集只接受转换和预测。Pipeline 官方接口说明了各步骤的串联与拟合方式。
验收与限制
- 能说明每个
fit看到了哪些样本。 - 能解释为什么不能先对全量数据做特征选择,再交叉验证。
- 不根据测试准确率反复修改模型后,仍把它称为一次独立测试。
- 有重复对象或时间顺序时,重新设计划分方式;Pipeline 本身不会替你解决对象泄漏、未来信息或标签泄漏。
课程对应与整理边界
对应疏锦行《机器学习 26 考/保研基础班》的第二次实操讲义与“渐进式按流程提问”“一次性提问思路”视频目录。本文以流程核验和纠错为主,代码为独立编写;不声称已完整核验这些视频的口头讲解。
原创
机器学习实操:把预处理放进训练边界
本文采用 CC BY-NC-SA 4.0 许可协议,转载请注明出处。
评论交流
欢迎留下你的想法