在 fit 中学习,在 transform 中应用
变换器是有第二项任务的估计器。fit(X) 从数据中学出一些数(均值、分位数、词表),存入以下划线结尾的属性并返回 self。transform(X) 再把这些存下的数应用到任何数据(新的或旧的)上,而不会看这些数据来决定任何事。这种分离就是全部意义所在:数只在训练行上学一次,测试行只被变换。缩尾处理器(winsorizer)是个好的第一个例子。fit 为每列学一个下分位数和一个上分位数,transform 用 np.clip 在二者之间截断。如果 transform 在收到的数据上重新计算分位数,每个数据集都会被截到自己的范围,训练信息就永远到不了测试集。继承 TransformerMixin 和 BaseEstimator,你还免费得到 fit_transform 和参数机制。
真实的表格混合数值和类别,所以 scikit-learn 提供 ColumnTransformer([(名称, 变换器, 列), ...]):每个分支处理自己的列,输出并排拼接。这里数值分支是 make_pipeline(Winsorizer(0.02, 0.98), StandardScaler()),类别分支是 OneHotEncoder(handle_unknown='ignore'),它把未见过的类别变成一行零而不是报错。sparse_threshold=0 强制输出稠密数组。要给输出列命名,每一步都必须能回答 get_feature_names_out,所以你的缩尾处理器也要实现它:直接返回收到的名字。黄金法则是:对训练行调用 fit_transform,对测试行只调用 transform。在股票面板(26 个代码、10,296 行)上,以 2023 年 1 月 1 日划分得到 5,564 行训练和 4,732 行测试,约 2.2% 的测试动量值落在训练 2%–98% 范围之外,被截到训练边界。
- 学一次,到处用:
fit在训练行上存下数值,transform只负责应用。 - 一个预处理器,两个分支:
ColumnTransformer把数值和类别送入各自的步骤;handle_unknown="ignore"能应对新类别。 - 完整实现约定:不能给输出列命名的变换器会让整条管道的
get_feature_names_out失效。
实验:评分内容
- 构造函数5 分
- fit 与 transform20 分
- 特征名与管道10 分
- 双分支预处理器15 分
- 按日期划分10 分
- 只在过去上拟合10 分
- 面板研究30 分