MLOps Zoomcamp 2024 实验跟踪作业实战:用 MLflow 完成出租车时长预测、超参调优与模型注册全流程
2026/9/14 17:37:25 网站建设 项目流程

MLOps Zoomcamp 2024 实验跟踪作业实战:用 MLflow 完成出租车时长预测、超参调优与模型注册全流程

【免费下载链接】mlops-zoomcampFree MLOps course from DataTalks.Club. Register here 👇🏼 to get notified about the next cohort项目地址: https://gitcode.com/GitHub_Trending/ml/mlops-zoomcamp

本篇基于 2024 届第 2 周作业文档 展开,完整覆盖从安装 MLflow、预处理 Green Taxi 数据、autolog 训练 RandomForest,到本地部署 tracking server、hyperopt 超参调优和将最优模型推送到模型注册表的全部 6 个练习。读完本篇,你可以按照仓库中的脚本独立完成整个实验跟踪(Experiment Tracking)与模型管理(Model Registry)闭环,并理解每个练习背后对应的仓库源码实现。

1. 作业目标与 Q1:安装 MLflow

该作业的官方目标是:熟悉 MLflow——一个用于实验跟踪与模型管理的工具。整个作业围绕一个真实的回归任务展开:使用Green Taxi Trip Records数据集预测每次行程的时长(duration)。

Q1 要求安装 MLflow 的 Python 包并验证版本:

  • 文档建议创建一个独立的 Python 环境(例如使用 conda 环境),再通过pipconda在其中安装 MLflow;
  • 安装完成后执行mlflow --version查看输出,并在交卷时报告自己的版本号。

这是一个刻意设置的入门步骤:后续所有脚本(训练、调参、注册)都依赖mlflow包提供的autologstart_runMlflowClient等 API,版本差异也可能影响 UI 展示与注册表行为,因此先固定并记录版本。

2. Q2:下载与预处理数据(preprocess_data.py 源码解析)

Q2 要求下载 2023 年 1 月、2 月、3 月的 Green Taxi Trip Records parquet 数据(来源于 NYC TLC 官方发布页),然后运行作业脚本:

python preprocess_data.py --raw_data_path <TAXI_DATA_FOLDER> --dest_path ./output

文档提示:执行前先进入02-experiment-tracking/homework/目录(即本仓库的 homework 目录),并把<TAXI_DATA_FOLDER>替换为你实际存放数据的位置。该脚本会完成三件事:从<TAXI_DATA_FOLDER>加载数据、在训练集(2023 年 1 月)上拟合一棵DictVectorizer、把预处理后的数据集与DictVectorizer保存到磁盘。

结合 preprocess_data.py 源码,可以看到脚本的具体行为:

  • 数据加载与清洗read_dataframe函数):读取 parquet 后,用lpep_dropoff_datetime - lpep_pickup_datetime计算 duration 并换算为分钟,只保留时长在[1, 60]分钟之间的记录;同时将PULocationIDDOLocationID转为字符串;
  • 特征工程preprocess函数):把上下车地点拼成组合特征PU_DO = PULocationID + '_' + DOLocationID,与数值特征trip_distance一起构造成 dict 记录,再通过DictVectorizer转为稀疏特征矩阵。注意fit_dv参数:只对训练集调用fit_transform,验证/测试集只做transform,避免数据泄漏;
  • 月份划分run_data_prep按文件名约定加载green_tripdata_2023-01/02/03.parquet,分别作为 train / val / test;
  • 落盘dump_pickle把 4 个对象保存到dest_path——dv.pkl(向量器)、train.pklval.pkltest.pkl(每个数据集是(X, y)元组)。

由此可以直接回答 Q2 的选择题:“OUTPUT_FOLDER 保存了多少个文件?”——从源码的 4 处dump_pickle调用看,答案是4

3. Q3:用 autolog 训练模型(train.py 的改造方式)

Q3 要求用 Scikit-Learn 的RandomForestRegressor在预处理好的数据上训练,并改造训练脚本启用 MLflow autologging,运行后启动 MLflow UI 确认 run 被正确跟踪。

作业版 train.py 目前是“裸”训练代码:加载train.pkl/val.pkl,用RandomForestRegressor(max_depth=10, random_state=0)训练,在验证集上计算mean_squared_error(..., squared=False)得到 RMSE,但没有任何 MLflow 调用。

对照 solution/train.py,官方答案的改造点只有四处:

import mlflow mlflow.set_tracking_uri("sqlite:///mlflow.db") mlflow.set_experiment("random-forest-train") # 在 run_train 内部: mlflow.sklearn.autolog() # 开启 sklearn 自动日志 with mlflow.start_run(): # 文档 Tip 1 强调:用 start_run 包裹训练代码 rf = RandomForestRegressor(max_depth=10, random_state=0) ...

从源码结构看,这正是 autologging 的标准用法:mlflow.sklearn.autolog()会拦截RandomForestRegressor的构造与fit调用,自动记录超参数(如max_depthrandom_state等);再配合start_run()把日志归属到当前 run。不要修改模型超参数(文档 Tip 2),以保证训练快速完成且结果可比。

Q3 的选择题问 run 中记录的min_samples_split是多少。由于脚本只显式指定了max_depth=10random_state=0,其余参数取 Scikit-Learn 默认值,因此 UI 中看到的min_samples_split2(默认值)。

4. Q4:本地启动 tracking server(含模型注册表)

Q4 要求在本地启动一个 tracking server——这样不仅能跟踪实验,还能访问model registry。具体任务:

  • 在本地启动 tracking server;
  • 使用SQLite作为 backend store,使用名为artifacts的文件夹作为 artifacts store;
  • 保持 server 持续运行,因为后续两个练习(Q5、Q6)都要连接它。

对应的标准启动命令(与课程 模块 2 的 notebook 中的本地 server 用法一致)为:

mlflow server --backend-store-uri sqlite:///mlflow.db --default-artifact-root ./artifacts --serve-artifacts

参数含义:

  • --backend-store-uri sqlite:///mlflow.db:元数据(实验、run、参数、指标)存到本地 SQLite 文件mlflow.db
  • --default-artifact-root ./artifacts:指定 artifacts(模型文件等)的默认存储目录;
  • --serve-artifacts:让 server 自身负责 artifacts 的上传/下载代理,客户端无需直连文件系统。

Q4 的选择题问“除了backend-store-uri,还需要传什么才能正确配置 server”。从上面命令与选项看,核心答案是default-artifact-root(配套示例中同时携带--serve-artifacts;选项中artifacts-onlyartifacts-destination并非该版本的配置项)。

5. Q5:用 hyperopt 调超参并逐次记录(hpo.py 的改造方式)

Q5 要求hyperopt调优RandomForestRegressor,改造 hpo.py,确保每次调参迭代都把验证 RMSE 记录到 tracking server(即在objective函数中加几行代码),然后不带任何参数直接运行脚本,最后在 UI 中查看实验random-forest-hyperopt的所有 run。注意文档明确:本练习不要使用 autologging,只手动记录回答问题所需的信息——传给objective的超参数列表,以及验证集(2023 年 2 月数据)上的 RMSE。

作业版脚本中objective只返回{'loss': rmse, 'status': STATUS_OK}给 hyperopt,没有任何 MLflow 日志。对照 solution/hpo.py,改造点在objective内:

def objective(params): with mlflow.start_run(): # 每次迭代一个 run mlflow.log_params(params) # 记录本次采样的超参 rf = RandomForestRegressor(**params) rf.fit(X_train, y_train) y_pred = rf.predict(X_val) rmse = mean_squared_error(y_val, y_pred, squared=False) mlflow.log_metric("rmse", rmse) # 记录验证集 RMSE return {'loss': rmse, 'status': STATUS_OK}

脚本其余部分保持不变,其调参配置值得注意:

  • 顶部mlflow.set_tracking_uri("http://127.0.0.1:5000")指向 Q4 启动的本地 server,实验名为random-forest-hyperopt
  • 搜索空间(scope.int(hp.quniform(...)))为:max_depth ∈ [1, 20]n_estimators ∈ [10, 50]min_samples_split ∈ [2, 10]min_samples_leaf ∈ [1, 4],且random_state固定为 42;
  • fmin使用tpe.suggest算法,max_evals=num_trials(CLI 默认 15 次),并用rstate = np.random.default_rng(42)固定随机数,保证搜索结果可复现。

Q5 的选择题问“你得到的最优验证 RMSE 是多少”,选项为 4.817 / 5.335 / 5.818 / 6.336。由于random_staterstate均已固定,15 次 TPE 采样的轨迹是确定的,运行后在 UI 中按metrics.rmse排序即可从上述四个选项里选出最接近的值。

6. Q6:把最优模型推送到模型注册表(register_model.py)

Q6 要求把表现最好的模型提升到模型注册表。仓库提供的 register_model.py 已经实现了前半段逻辑:

  • 通过MlflowClient().search_runs从实验random-forest-hyperopt中按order_by=["metrics.rmse ASC"]取出 top 5 的 run(--top_n默认 5);
  • 对每个 run,用其超参数重新训练,在新实验random-forest-best-models中记录val_rmsetest_rmse(测试集为 2023 年 3 月数据);
  • 顶部调用了mlflow.sklearn.autolog(),因此模型工件(modelartifact)会被自动记录到每个 run 中,为后续注册提供model_uri

作业留空的部分(源码中注释掉的client.search_runs(...)mlflow.register_model(...)),对照 solution/register_model.py 的完整实现:

# 选出 test_rmse 最低的 run experiment = client.get_experiment_by_name(EXPERIMENT_NAME) best_run = client.search_runs( experiment_ids=experiment.experiment_id, run_view_type=ViewType.ACTIVE_ONLY, max_results=top_n, order_by=["metrics.test_rmse ASC"] )[0] # 注册最优模型 run_id = best_run.info.run_id model_uri = f"runs:/{run_id}/model" mlflow.register_model(model_uri, name="rf-best-model")

这里有两个文档 Tip 对应的关键点:

  • Tip 1:用MlflowClientsearch_runs配合order_by=["metrics.test_rmse ASC"]取排序第一的 run;
  • Tip 2mlflow.register_model需要形如"runs:/<RUN_ID>/model"model_uri字符串和一个模型名(示例答案取名rf-best-model)。

Q6 的选择题问最优模型的测试 RMSE,选项为 5.060 / 5.567 / 6.061 / 6.568——运行脚本后在 UI 的random-forest-best-models实验中查看注册模型的test_rmse即可作答。

另外需要注意版本相关事实:课程 模块 2 README 明确指出,从 MLflow 2.9 起模型注册表的 stages 已被弃用,应改用模型版本 tags 与 aliases(例如用set_registered_model_alias替代transition_model_version_stage);同时list_experiments已被search_experiments取代。如果你的 MLflow 版本较新,后续操作注册表时应使用这些新 API。

7. 关键文件与操作速查

练习脚本核心操作仓库路径
Q2preprocess_data.pypython preprocess_data.py --raw_data_path <TAXI_DATA_FOLDER> --dest_path ./output,产出 4 个 pickle 文件homework/preprocess_data.py
Q3train.pymlflow.sklearn.autolog()+with mlflow.start_run():包裹训练homework/train.py、solution/train.py
Q4mlflow server --backend-store-uri sqlite:///mlflow.db --default-artifact-root ./artifacts --serve-artifacts本地终端
Q5hpo.pyobjective内加mlflow.log_paramsmlflow.log_metric,连接http://127.0.0.1:5000homework/hpo.py、solution/hpo.py
Q6register_model.pysearch_runs(order_by=["metrics.test_rmse ASC"])+mlflow.register_model("runs:/<RUN_ID>/model", ...)homework/register_model.py、solution/register_model.py

整份作业的提交入口与答题规则见 homework.md 的 “Submit the results” 一节:答案与选项不完全一致时,选择最接近的一项。整套练习串起来,恰好演示了 MLOps 中实验跟踪到模型治理的最小完整闭环:本地记录单模型训练 → 远程 server 记录调参过程 → 注册表沉淀可复用的最优模型,也为后续模块(编排、部署、监控)提供了可部署的模型来源。

【免费下载链接】mlops-zoomcampFree MLOps course from DataTalks.Club. Register here 👇🏼 to get notified about the next cohort项目地址: https://gitcode.com/GitHub_Trending/ml/mlops-zoomcamp

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询