资讯动态

MLOps Zoomcamp 2023 第二周作业实战:用 MLflow 完成实验跟踪、超参调优与模型注册(Green Taxi 小费预测)

发布时间:2026/9/14 18:12:23 来源:尧图企业网站定制
MLOps Zoomcamp 2023 第二周作业实战用 MLflow 完成实验跟踪、超参调优与模型注册Green Taxi 小费预测【免费下载链接】mlops-zoomcampFree MLOps course from DataTalks.Club. Register here to get notified about the next cohort项目地址: https://gitcode.com/GitHub_Trending/ml/mlops-zoomcamp本文基于 MLOps Zoomcamp 2023 届第 2 周作业cohorts/2023/02-experiment-tracking/homework.md展开完整覆盖从安装 MLflow、预处理 NYC Green Taxi 数据、autolog 训练跟踪、Optuna 超参优化到模型注册Model Registry的端到端流程。文中所有命令与代码细节均结合仓库中cohorts/2023/02-experiment-tracking/homework/下的待完成脚本和cohorts/2023/02-experiment-tracking/solution-mlflow/下的参考实现逐条印证读完后你可以独立完成一套“实验记录 → 参数调优 → 模型提升promote→ 注册入库”的 MLOps 标准工作流。1. 作业目标与整体流程作业文档开宗明义目标是熟悉 MLflow 这类实验跟踪与模型管理工具。整个作业围绕同一个预测任务展开——使用 Green Taxi Trip Records 数据集预测每趟行程的小费金额tip_amount并按月切分数据2022 年 1 月为训练集、2 月为验证集、3 月为测试集。完整链路由四个脚本串联仓库中均提供原始版本需要补全环节脚本待完成版参考实现数据预处理preprocess_data.py与待完成版一致可直接运行单模型训练 autologtrain.pytrain.pyOptuna 超参搜索hpo.pyhpo.pyTop-N 复评 模型注册register_model.pyregister_model.py作业另提供了 Weights Biases 版本的替代实现位于 homework-wandb 目录本文聚焦 MLflow 主线。2. Q1安装 MLflow 并确认版本作业第一步要求在独立的 Python 环境例如 conda 环境中通过pip或conda安装 MLflow 包随后执行mlflow --version并记录实际输出版本。这一步看似简单但有两个工程价值一是隔离依赖避免 MLflow 与项目其他包冲突二是版本记录本身就是实验可复现性的一部分——后续任何 run 的解释都以该版本为前提。作业同时提醒MLflow 的 API 会随版本演进例如课程 README 中注明list_experiments已被search_experiments取代见 02-experiment-tracking/README.md这正是养成“记录版本”习惯的实例。3. Q2下载并预处理 Green Taxi 数据从 NYC TLC 下载 2022 年 1、2、3 月的 Green Taxi 行程记录parquet 格式然后在脚本所在目录下执行python preprocess_data.py --raw_data_path TAXI_DATA_FOLDER --dest_path ./output其中TAXI_DATA_FOLDER是你保存原始 parquet 文件的目录。该脚本基于click定义命令行入口run_data_prep接受两个选项--raw_data_path原始数据位置与--dest_path输出位置。结合 preprocess_data.py 源码脚本实际完成以下工作按月加载三个 parquet 文件文件名约定为green_tripdata_2022-01.parquet、green_tripdata_2022-02.parquet、green_tripdata_2022-03.parquet脚本中dataset green拼接规则为f{dataset}_tripdata_2022-0X.parquet。read_dataframe清洗用lpep_dropoff_datetime - lpep_pickup_datetime计算行程时长并换算为分钟过滤1 duration 60的行程将PULocationID、DOLocationID转为字符串防止 DictVectorizer 把它们当作数值处理。特征化preprocess函数把上下车地点拼成单一类别特征PU_DO PULocationID _ DOLocationID与数值特征trip_distance一起转成 dict 记录训练集上执行dv.fit_transform(dicts)验证/测试集上只执行dv.transform(dicts)保证验证与测试使用与训练完全一致的词表避免数据泄漏。落盘 4 个 pickle 文件dv.pkl拟合好的DictVectorizer、train.pkl、val.pkl、test.pkl每个数据集文件保存(X, y)元组目标列是tip_amount。作业要求回答“保存下来的DictVectorizer文件有多大”选项为 54 kB / 154 kB / 54 MB / 154 MB。从源码结构看词表规模由PU_DO组合数决定数百个地点的有序对量级在千级以内加上一个trip_distance数值项序列化后是百 kB 级文本结构——实际运行得到的就是约 154 kB 一类的选项这取决于当月的真实地点组合数以你本地运行结果为准。4. Q3用 autolog 训练 RandomForest 模型训练脚本 train.py 的原始版本逻辑为从--data_path默认./output加载train.pkl与val.pkl训练一个固定超参的RandomForestRegressor(max_depth10, random_state0)在验证集上计算 RMSEmean_squared_error(y_val, y_pred, squaredFalse)。作业要求你改造该脚本启用 MLflowautologging运行后打开 MLflow UI 确认 run 已被正确跟踪并回答max_depth的取值答案即源码中写死的max_depth10。作业还特别提示不要把超参改得更大以免训练时间过长。对照参考实现 solution-mlflow/train.py需要补充的正是三处mlflow.set_tracking_uri(sqlite:///mlflow.db) mlflow.set_experiment(random-forest-train)def run_train(data_path: str): mlflow.sklearn.autolog() X_train, y_train load_pickle(os.path.join(data_path, train.pkl)) X_val, y_val load_pickle(os.path.join(data_path, val.pkl)) with mlflow.start_run(): rf RandomForestRegressor(max_depth10, random_state0) rf.fit(X_train, y_train) y_pred rf.predict(X_val) rmse mean_squared_error(y_val, y_pred, squaredFalse)要点解析mlflow.sklearn.autolog()对 Scikit-learn 的fit调用打补丁自动记录超参数如max_depth、n_estimators、模型签名和模型 artifactmodel无需手动log_params/log_model。with mlflow.start_run():autolog 的捕获范围限定在当前 run 内这正是作业 Tip 1 要求“用with mlflow.start_run():包住训练代码”的原因。注意参考实现里rmse计算后并未调用mlflow.log_metric——本小节的验收标准是“UI 中能看到被跟踪的 run”指标记录从 Q4 才开始显式要求。关于 tracking URI参考实现里train.py用的是本地sqlite:///mlflow.db无需起服务即可验证 autolog而后续 Q4/Q5 需要模型注册能力因此下一步要启动一个真正的 tracking server。5. 在本地启动 MLflow Tracking Server作业在这一步要求把生命周期管理拉起来在本地启动 tracking serverbackend store 选用 SQLite 数据库artifact store 选用名为artifacts的文件夹。命令形态为mlflow server --backend-store-uri sqlite:///mlflow.db --artifacts-destination ./artifacts启动后 UI 默认监听http://127.0.0.1:5000。作业明确要求让该服务保持运行因为后续 Q4、Q5 的脚本都依赖它——这一点可以从源码直接证实hpo.py 与 register_model.py 顶部均有mlflow.set_tracking_uri(http://127.0.0.1:5000)模型注册Model Registry的元数据同样存在 backend store 中所以选 SQLite 作为 backend store 是作业指定方案artifact模型文件等则走文件系统目录artifacts两者分离是 MLflow 部署的典型本地形态。6. Q4用 Optuna 做超参搜索并逐 trial 记录 RMSEhpo.py 已经搭好骨架在模块级设置mlflow.set_tracking_uri(http://127.0.0.1:5000)和mlflow.set_experiment(random-forest-hyperopt)命令行选项包括--data_path默认./output和--num_trials默认 10含义是“优化器探索的参数量化次数”。objective(trial)内部用TPESampler作业固定seed42、directionminimize在如下搜索空间内采样超参搜索方式范围n_estimatorstrial.suggest_int10–50步长 1max_depthtrial.suggest_int1–20步长 1min_samples_splittrial.suggest_int2–10步长 1min_samples_leaftrial.suggest_int1–4步长 1random_state固定42n_jobs固定-1作业要求在objective中补几行代码使每个 trial 的验证 RMSE 都记录到 tracking server然后不带任何参数直接运行脚本再到 UI 中查看random-forest-hyperopt实验的 runs回答“最佳验证 RMSE”是多少选项 1.85 / 2.15 / 2.45 / 2.85量级落在 2.x 区间以你本地运行结果对照最接近的选项。作业特意强调本练习不要使用 autologging只手工记录回答问题所需的信息——即传给objective的超参列表和验证集2022 年 2 月数据上的 RMSE。对照参考实现 solution-mlflow/hpo.py补全方式很简洁def run_optimization(data_path: str, num_trials: int): mlflow.sklearn.autolog(disableTrue) # 显式关闭 autolog ... def objective(trial): params { n_estimators: trial.suggest_int(n_estimators, 10, 50, 1), max_depth: trial.suggest_int(max_depth, 1, 20, 1), min_samples_split: trial.suggest_int(min_samples_split, 2, 10, 1), min_samples_leaf: trial.suggest_int(min_samples_leaf, 1, 4, 1), random_state: 42, n_jobs: -1 } with mlflow.start_run(): mlflow.log_params(params) # 记录该 trial 的全部超参 rf RandomForestRegressor(**params) rf.fit(X_train, y_train) y_pred rf.predict(X_val) rmse mean_squared_error(y_val, y_pred, squaredFalse) mlflow.log_metric(rmse, rmse) # 记录验证 RMSE return rmse两个值得注意的细节每个 trial 一个 runwith mlflow.start_run():放在objective内部而非外部使 Optuna 的每次suggest → fit → evaluate对应 UI 里的一条独立 run共 10 条默认num_trials10可直接在 UI 上横向比较。指标名必须叫rmse这一点不是随意的——下游脚本 register_model.py 的search_runs用order_by[metrics.rmse ASC]来取 Top-N如果 Q4 里把指标记成了别的名字比如val_rmseQ5 的排序就会失效。从源码结构看rmse这个指标名是 Q4 与 Q5 之间的“契约”。参考实现首行mlflow.sklearn.autolog(disableTrue)是对作业“不要用 autologging”提示的显式落实防止环境里残留的 autolog 配置干扰手工日志。7. Q5将最优模型提升到 Model Registryregister_model.py 的原始版本已完成前半段定义常量HPO_EXPERIMENT_NAME random-forest-hyperopt、EXPERIMENT_NAME random-forest-best-models与超参名列表RF_PARAMStrain_and_log_model在mlflow.start_run()内用给定参数重训模型记录val_rmse与test_rmse测试集为 2022 年 3 月数据并依赖模块顶部的mlflow.sklearn.autolog()自动保存modelartifact。run_register_model已实现“取 Q4 中验证 RMSE 最低的 Top-5 run 并复评”client MlflowClient() experiment client.get_experiment_by_name(HPO_EXPERIMENT_NAME) runs client.search_runs( experiment_idsexperiment.experiment_id, run_view_typeViewType.ACTIVE_ONLY, max_resultstop_n, # 默认 5可用 --top_n 调整 order_by[metrics.rmse ASC] ) for run in runs: train_and_log_model(data_pathdata_path, paramsrun.data.params)你的任务是补全文件末尾两处注释代码从random-forest-best-models实验中选出测试 RMSE 最低的模型并注册到 registry。对照 solution-mlflow/register_model.py 第 73–83 行补全为# Select the model with the lowest test RMSE experiment client.get_experiment_by_name(EXPERIMENT_NAME) best_run client.search_runs( experiment_idsexperiment.experiment_id, run_view_typeViewType.ACTIVE_ONLY, max_resultstop_n, order_by[metrics.test_rmse ASC] )[0] # Register the best model run_id best_run.info.run_id model_uri fruns:/{run_id}/model mlflow.register_model(model_uri, namerf-best-model)作业给出的提示与实现完全对应用MlflowClient的search_runs找到最优模型mlflow.register_model需要传入形如runs:/RUN_ID/model的model_uri字符串和一个“好的”模型名——参考实现取名为rf-best-model。这里还能看到两次search_runs的差别第一次按metrics.rmse验证集选候选第二次按metrics.test_rmse测试集定胜负——用验证集挑 Top-N、用测试集做最终裁决是一次完整的模型选择流程演示。作业要求回答“最佳模型的测试 RMSE”选项 1.885 / 2.185 / 2.555 / 2.955该数值取决于随机搜索命中的参数组合以你本地 UI 中random-forest-best-models实验下最优 run 的test_rmse为准。8. Q6模型注册表中的元数据最后一步是在 UI 中查看注册好的模型。作业问模型注册表对每个模型包含哪些信息选项为“版本号 / 源实验 / 模型签名 / 以上全部”正确答案是“以上全部”。这一点在源码层面可以找到支撑版本号register_model每次调用都会产生一个新的 model version同一模型名下的递增整数UI 的 Registry 页面按版本列出。源实验model_uri runs:/{run_id}/model直接引用了某个 run而 run 本身隶属于random-forest-best-models实验因此注册表可回溯到来源实验与 run。模型签名signature来自 Q3/Q5 启用的mlflow.sklearn.autolog()——autolog 在保存模型时会同时写入 MLmodel 元数据输入/输出 schema 即 signature所以注册表中每个版本都携带签名信息。这也解释了作业整体设计Q3 开 autolog 是为了让模型 artifact 自带签名与元数据Q4 关 autolog 是为了练手工log_params/log_metricQ5 再把二者串成“从实验数据中挑选并注册模型”的闭环。9. 复现要点与注意事项汇总按本文顺序执行时的完整命令清单均在cohorts/2023/02-experiment-tracking/homework/目录下# 0) 安装依赖独立 conda 环境中 mlflow --version # 记录 Q1 答案 # 1) 预处理下载 green_tripdata_2022-01/02/03.parquet 到 TAXI_DATA_FOLDER 后 python preprocess_data.py --raw_data_path TAXI_DATA_FOLDER --dest_path ./output # 2) Q3修改 train.py 增加 autolog start_run 后运行打开 UI 查看 python train.py --data_path ./output # 3) 启动 tracking server保持运行backend 用 SQLiteartifacts 用 artifacts 目录 mlflow server --backend-store-uri sqlite:///mlflow.db --artifacts-destination ./artifacts # 4) Q4修改 hpo.py 的 objective 增加日志后无参数运行 python hpo.py # 5) Q5补全 register_model.py 的 select register 后运行 python register_model.py几个容易踩的坑均有源码依据参数传递train.py/hpo.py/register_model.py均通过click读取命令行选项--data_path默认./output务必与 Q2 的--dest_path保持一致否则load_pickle会因文件不存在直接报错。tracking URI 切换时机Q3 的参考实现指向sqlite:///mlflow.dbQ4/Q5 的脚本硬编码指向http://127.0.0.1:5000两者不是同一个 storeUI 中看不到 Q3 的 run 属正常现象若想让 Q3 也进 server把set_tracking_uri改成 server 地址即可。指标命名一致性Q4 必须记录名为rmse的指标Q5 的order_by[metrics.rmse ASC]依赖它Q5 内部则新增val_rmse/test_rmse两个指标用于 Top-5 复评与最终挑选。版本相关MLflow API 会随版本变化课程 README 提到list_experiments已替换为search_experiments且自 MLflow 2.9 起 registry 的 stage 机制被弃用建议改用 alias 与 tag。作业脚本使用的是register_modelruns:/...URI 的稳定用法不受该变化影响但阅读其他资料时需注意区分。10. 延伸作业中的其他线索2023 届同时提供 Weights Biases 版作业wandb.md 与 homework-wandb 目录任务结构相同预处理 artifact、sweep 调参、注册适合作为 MLflow 方案的对照阅读主课程模块的完整说明、各节视频与社区笔记索引见 02-experiment-tracking/README.md作业原文中的提交表单与 2023-06-04 截止时间属于当年的活动安排现已过期本文仅保留其“允许多次提交、取最后一次、选最接近选项”的作答规则说明供历史参考。完成本作业后你应当掌握用click组织的可命令行化 ML 脚本结构、MLflow autolog 与手工日志两种跟踪方式的适用场景、Optuna TPE 搜索与“每 trial 一 run”的记录模式以及MlflowClient.search_runsmlflow.register_model构成的模型提升promotion闭环——这正是后续编排Prefect/Dagster与部署Lambda/SageMaker Batch模块的起点。【免费下载链接】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),仅供参考

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价