使用 mlflow.log_params() 记录 pipeline 参数时需手动构造扁平字典,避免直接传 pipeline.get_params();保存模型前须确保 pipeline 已 fit 并用 assert 验证;应使用 mlflow.sklearn.log_model() 进行版本管理,并记录预处理逻辑以保障线上一致性。

用 mlflow.log_params() 记录 Pipeline 参数时,别直接传 pipeline.get_params()
因为 sklearn.pipeline.Pipeline 的 get_params() 返回的是嵌套字典,含大量重复键(比如多个 __ 开头的内部属性)和不可序列化对象(如函数、类),mlflow.log_params() 会直接报错或静默丢弃。
实操建议:
- 只提取你真正关心的、可复现的参数:比如
StandardScaler的with_mean、LogisticRegression的C和solver - 手动构造扁平字典,键名带前缀避免冲突:
{"scaler_with_mean": True, "lr_C": 1.0, "lr_solver": "liblinear"} - 如果 Pipeline 步骤名不固定,用
pipeline.named_steps安全遍历,而不是硬编码索引
joblib.dump() 保存模型前,先确认 pipeline 已 fit
未训练的 Pipeline 保存后加载会报 AttributeError: 'Pipeline' object has no attribute 'steps' 或更隐蔽的 NotFittedError —— 这不是路径或权限问题,是状态问题。
常见错误现象:
- 本地能跑通,CI 环境里
joblib.load()后调predict()报错 - 保存时没报错,但加载后
pipeline.steps[0][1].mean_是None
实操建议:
- 保存前加断言:
assert hasattr(pipeline.named_steps["classifier"], "classes_")(按实际步骤名和属性调整) - 统一用
pipeline.fit(X_train, y_train)后再joblib.dump(pipeline, "model.joblib"),别分开 fit 和 dump - 避免在保存前对 pipeline 做
copy.deepcopy(),某些 transformer 在 deepcopy 后会丢失 fitted 状态
模型版本管理别只靠文件名,用 mlflow.sklearn.log_model() + run_id
单纯把 model_v1.joblib、model_v2.joblib 存进 Git 或共享目录,无法追溯它对应哪次数据、哪个超参组合、在哪台机器上训练——等于没版本。
使用场景:
- 需要回滚到上周效果最好的模型
- 业务方问“这个预测结果是用哪个版本模型算的”,你能立刻给出
run_id和完整实验快照
实操建议:
- 用
mlflow.sklearn.log_model(pipeline, "model"),它自动记录 sklearn 版本、Python 版本、甚至 pip 依赖(需配合conda_env) - 每次训练都开新 run:
with mlflow.start_run() as run:,后续所有log_param/log_metric/log_model都绑定这个run_id - 别手动改
mlflow.set_tracking_uri()到本地文件路径,团队协作时优先用mlflow server,否则别人 load 不到你的 run
实验记录漏掉预处理逻辑,上线后 predict 结果全乱
很多同学 log 了模型和参数,但忘了记录 fit 时用的 X_train 的列顺序、缺失值填充策略、类别编码映射表——导致线上 inference 用 pandas read_csv() 默认列序读入,或没做 fillna(),输入张量结构已变。
性能 / 兼容性影响:
- 测试集 AUC 0.92,线上 A/B 测试只有 0.61,查半天发现是训练时用了
df.fillna(-999),而线上没做 - OneHotEncoder 保存时没存
categories_,加载后 transform 报ValueError: Found unknown categories
实操建议:
- 把预处理逻辑封装进自定义 transformer(继承
BaseEstimator+TransformerMixin),这样joblib.dump()能一并保存状态 - 用
mlflow.log_artifact("preprocessor.pkl")单独存一份预处理器,别只信 pipeline 里的引用 - 上线前必做一致性校验:用原始训练数据走一遍线上 infer pipeline,输出和本地
pipeline.predict()对齐
最麻烦的不是记不住 log 哪些东西,而是以为 pipeline 里包了全部,结果漏掉外部数据清洗脚本里的一个 df.drop_duplicates() —— 这种隐式依赖,必须写进 README.md 或用 mlflow.log_text() 存一份摘要。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!











