Python 特征工程的版本控制

2次阅读

特征版本控制需锁定数据快照、代码逻辑、依赖参数、列结构四要素:硬编码feature_version、嵌入路径、禁用时间戳;封装transformer并固化pipeline;外部数据带as_of_date锚点并落地静态文件;用onehotencoder替代get_dummies并固化categories。

Python 特征工程的版本控制

特征工程代码没版本号,改完就跑不回退

特征工程脚本一旦被修改,旧模型复现就会失败——这不是“代码没注释”的问题,而是缺少显式版本标识。你不能靠 git commit hash 当特征版本,因为同一份代码在不同数据上产出的特征可能不同。

实操建议:

立即学习Python免费学习笔记(深入)”;

  • 在特征生成函数里硬编码 FEATURE_VERSION 变量,比如 FEATURE_VERSION = "v2.1.0",所有下游模型训练必须显式读取并记录这个值
  • 把版本号嵌入特征保存路径,例如 "features/train_v2.1.0.parquet",而不是 "features/train.parquet"
  • 避免用时间戳(如 "v20240521")当版本号:它不表达语义变更,且并发训练时易冲突

sklearn Pipeline 里 fit_transform 和 transform 混用导致特征不一致

你在训练时对数值列用 StandardScaler().fit_transform(),预测时却直接用 scaler.transform() ——这本身没错,但若 Pipeline 没固化、或中间步骤被重写(比如加了新列),transform() 就会悄悄改变行为。

实操建议:

立即学习Python免费学习笔记(深入)”;

  • 所有特征处理逻辑必须封装进自定义 transformer 类,并在 __init__ 中声明 version 属性,和外部 FEATURE_VERSION 对齐
  • 训练完立刻用 joblib.dump(pipeline, f"pipeline_{FEATURE_VERSION}.pkl") 保存完整 pipeline,别只存 transformermodel
  • 禁止在 pipeline 外部手动调用 fit_transform;统一走 pipeline.fit(X_train) + pipeline.transform(X_test)

特征依赖外部数据源(如数据库、API)时版本失控

你的 get_user_features() 函数每次运行都查最新用户标签,但昨天训练的模型用的是上周的标签快照——模型上线后效果漂移,根本没法归因是模型还是特征变了。

实操建议:

立即学习Python免费学习笔记(深入)”;

  • 所有外部依赖必须带明确时间锚点,比如 as_of_date="2024-05-20" 参数,且该参数要参与 FEATURE_VERSION 计算(如 v2.1.0_20240520
  • 查询结果必须落地为静态文件(user_features_20240520.parquet),特征脚本只读这个文件,不直连数据库
  • CI 流程中加入校验:若检测到 as_of_date 超过 7 天未更新,中断构建并报错 "External feature snapshot stale"

特征名动态生成(如 one-hot 后缀)导致下游列顺序错乱

pd.get_dummies(df, columns=["city"]) 在不同批次数据上生成的列名顺序可能不同,模型加载时 X.shape[1] 对不上,直接报 ValueError: X has 123 features, but StandardScaler is expecting 125 features

实操建议:

立即学习Python免费学习笔记(深入)”;

  • 永远不用 pd.get_dummies,改用 sklearn.preprocessing.OneHotEncoder(drop="first", sparse_output=False, handle_unknown="ignore"),它能保证输出列名和顺序稳定
  • 对所有类别型字段,提前固化 categories_ 到配置文件(如 categories/city.json),训练前强制加载,避免 encoder 自动 infer
  • 特征生成后立刻执行 assert list(X.columns) == EXPECTED_FEATURE_NAMES,断言失败即终止,不留给下游擦屁股

特征版本控制最难的不是记版本号,而是让“特征”这个概念本身可锁定:数据快照、代码逻辑、依赖参数、列结构,四者缺一不可。漏掉任意一个,所谓版本就是假象。

text=ZqhQzanResources