实验追踪工具:MLflow 入门归纳总结

说到模型训练,很多新手朋友容易踩同一个坑:跑了一堆实验,最后分不清哪个超参数组合、哪个数据集版本、哪个代码 commit 产出的指标最好。我以前也吃过这个亏,笔记本里记满了参数列表,结果隔两周自己都看不懂。后来接触了 MLflow,才发现追踪实验其实可以很优雅。

MLflow 不是一个“大而全”的平台,它是一套轻量级的实验追踪、模型管理和部署工具。它的核心思想是:你只管写训练代码,剩下的记录、对比、复现全交给它。今天我把最常用的部分——Tracking——给你拆开揉碎讲清楚。

MLflow 的四个组件

先看一眼整体结构,心里有个地图。MLflow 分四块,但日常用到最多的就是 Tracking:

MLflow 核心组件结构图 MLflow 四组件 Tracking 实验记录 & 对比 Projects 可复现打包 Models 模型格式 & 版本 Registry 模型注册 & 阶段 实际入门阶段:70% 的时间只与 Tracking 打交道 实验次数 < 1000 时,完全不需要 Models/Registry

说白了,Tracking 帮你把每一次实验的参数、指标、代码版本、环境信息、模型文件都存起来,还能用一个 Web UI 对比多条实验曲线。我问你,没有追踪工具之前,你是不是靠手工复制文件夹来保存不同模型?嗯,我以前也是。

安装与初始化

安装特别简单,一条命令搞定:

pip install mlflow

要是想用 UI 查历史记录,再装个扩展存储:

pip install mlflow[extras]

我个人习惯用 file:// 本地存储起步,等实验多了再切到 MySQL 或者 S3。你只要记住:一个 MLflow 服务可以跑在单机上,也能跑在集群里。我们先用本地模式试起来。

启动 UI 也很简单:

mlflow ui --port 5000

然后浏览器访问 http://localhost:5000,就能看到一个空白的实验列表。别急,马上就有内容了。

核心概念:实验 & 运行

MLflow 里两个最基本的概念:

  • 实验(Experiment):一个项目主题,比如“BERT fine-tune on IMDB”、“ResNet50 on CIFAR-10”。每个实验可以包含很多次运行。
  • 运行(Run):一次具体的训练尝试,记录下这次的所有元数据。

我建议一开始就给每个项目建一个实验,这样不同方向的结果不会混在一起。我自己踩过坑:所有实验都放在默认 “Default” 实验里,半个月后里面混了十几个不同项目的跑分,看曲线的时候头都大了。

基本使用流程(代码实战)

我们写一段典型的训练代码,把 MLflow 加进去。假设你正在训练一个 PyTorch 分类模型:

import mlflow
import mlflow.pytorch

# 1. 设置实验名称(不存在就自动创建)
mlflow.set_experiment("CIFAR10_ResNet18")

# 2. 开始一次运行
with mlflow.start_run(run_name="exp_lr_0.001"):
    # 记录超参数
    mlflow.log_param("learning_rate", 0.001)
    mlflow.log_param("batch_size", 64)
    mlflow.log_param("optimizer", "Adam")
    mlflow.log_param("epochs", 10)

    # 模拟训练过程(实际你放自己的训练循环)
    for epoch in range(10):
        train_loss = 1.2 - 0.1 * epoch  # 假数据
        val_acc = 0.3 + 0.06 * epoch

        # 记录每个 epoch 的指标
        mlflow.log_metric("train_loss", train_loss, step=epoch)
        mlflow.log_metric("val_accuracy", val_acc, step=epoch)

    # 记录最终的模型(保存为 MLflow 格式)
    mlflow.pytorch.log_model(model, artifact_path="model")

关键点:mlflow.log_metric 可以传 step 参数,这样 UI 里就会自动画折线图,效果跟在 TensorBoard 里看一样直观。

跑完一次后,打开 UI 就能看到这次运行的所有信息。你可以在左侧「Experiments」栏选中你的实验,右侧会列出所有运行,点击任意一条就能看到详细参数、指标曲线和 artifact 列表。

我还常用哪些命令?

API 用途 注意的点
log_param(key, value) 记录超参数或配置(不可修改) 一个运行中 key 只能设一次,设第二次会报错
log_metric(key, value, step=None) 记录数值指标(可多次写入) 同一 key 可以写多次,UI 按 step 画曲线
log_artifact(local_path) 上传本地文件/文件夹到 artifact 存储 常用于上传 best_model.pth、config.yaml、confusion_matrix.png
log_artifacts(local_dir) 上传整个目录 递归上传,注意文件量大时可能慢
set_tag(key, value) 给运行打标签 我习惯打“status: finished”或“description: baseline”

💡 实用小技巧:如果你想对比两次运行在同一个指标上的差异,可以在 UI 里“Compare Runs”选中多条,MLflow 会自动生成指标差异表和并行坐标图(Parallel Coordinates Plot),一眼看出哪个超参数影响最大。

避坑指南(我踩过的,你别再踩)

我曾经犯过一个低级错误: 在 Jupyter notebook 里反复执行 mlflow.start_run() 但忘了写 with 语句,导致每次运行之间嵌套了,所有指标都记录到了同一个 run 里面。后来我养成了习惯——永远用 with mlflow.start_run(): 上下文管理,而不是主动调用 start 和 end。

另一个常见的坑是:artifact 路径默认是当前目录下的 mlruns 文件夹。如果你在多个项目之间切换,或者用 Git 管理代码,千万别把 mlruns 提交到版本控制里。我建议在 .gitignore 里加上 mlruns/,或者显式指定存储位置:

# 设置 artifact 存储路径为你自己的目录
mlflow.set_tracking_uri("file:///home/user/mlflow_tracking")

⚠ 注意: 如果你在分布式训练(比如 PyTorch DDP)中使用 MLflow,不要在每个 worker 里都创建独立的 run。默认情况下,一个进程调用 mlflow.start_run() 就够。如果所有 worker 都写,你会得到一堆混乱的 run。正确做法是只让 rank 0 进程记录实验,其他 worker 跳过记录逻辑。

if dist.get_rank() == 0:
    mlflow.start_run()
    # ... 记录代码
    mlflow.end_run()

进阶:用 MLflow 做超参数搜索

当你用 Grid Search 或者 Optuna 跑一堆组合时,每个组合都应该是一个独立的 run。我的写法是这样:

for lr in [0.01, 0.001, 0.0001]:
    for bs in [32, 64]:
        with mlflow.start_run(nested=True):
            mlflow.log_param("learning_rate", lr)
            mlflow.log_param("batch_size", bs)
            # 训练并记录指标
            ...

加上 nested=True 会让这些 run 在 UI 里以“树状结构”展示,父 run 是主调,子 run 是每次搜索。这种模式特别适合一键拉平所有搜索空间的结果对比。

如何查看历史指标?

除了 Web UI,你也能用 Python 客户端查:

from mlflow.tracking import MlflowClient

client = MlflowClient()
experiment = client.get_experiment_by_name("CIFAR10_ResNet18")
runs = client.search_runs(experiment.experiment_id)

for run in runs:
    print(run.info.run_id, run.data.metrics.get("val_accuracy"))

这条代码把我从手动截图对比中解放出来了。以前我每次改参数都打开 Excel 手动输入,现在直接写个脚本导出所有指标,画对比图,省了至少 80% 的时间。

小结:MLflow 入门的三个关键

  1. 先解决记录问题:用 log_param 和 log_metric 把你的超参数和每步指标存下来。
  2. 再用 UI 做对比:本地起一个 mlflow ui,就能像刷博客一样看不同实验的曲线。
  3. 最后固化习惯:每次新实验前 set_experiment,每次运行用 with start_run,每次迭代结束时存好 artifact。

嗯,入门 MLflow 就这点东西。等你跑个几十次实验,开始觉得手动对比麻烦时,自然会想用它的 Search API 做自动化分析。到那时候,你已经是半个 MLflow 老手了。