4. MLflow 进阶:嵌套运行、标签与描述、搜索与比较实验

基础功能摸熟了,咱们来点进阶的。说实话,MLflow 真正好用的地方,是它处理复杂实验场景的能力。今天聊的这几个功能——嵌套运行、标签描述、搜索比较——是我在实际项目中用得最多的。

4.1 嵌套运行:把实验组织成树

先说说嵌套运行。你想想看,一个完整的 ML 项目,往往不是单次实验就能搞定的。比如我调参时,先跑一组基线,再基于基线结果做细化。如果每次都是独立的 run,那它们之间的关系就丢了。

嵌套运行(Nested Runs)就是为了解决这个问题。它允许你在一个父 run 内部创建多个子 run,形成树状结构。

核心概念:父 run 代表一个实验任务,子 run 代表该任务下的具体尝试。

代码实现其实很简单,用 with mlflow.start_run() 嵌套就行:

import mlflow

# 创建父 run
with mlflow.start_run(run_name="调参实验_v3") as parent_run:
    mlflow.log_param("base_model", "ResNet50")
    mlflow.log_param("dataset", "CIFAR-10")
    
    # 子 run 1:学习率 0.001
    with mlflow.start_run(nested=True, run_name="lr_0.001") as child1:
        mlflow.log_param("learning_rate", 0.001)
        mlflow.log_metric("accuracy", 0.852)
    
    # 子 run 2:学习率 0.0005
    with mlflow.start_run(nested=True, run_name="lr_0.0005") as child2:
        mlflow.log_param("learning_rate", 0.0005)
        mlflow.log_metric("accuracy", 0.873)
    
    # 父 run 记录总结指标
    mlflow.log_metric("best_accuracy", 0.873)

我的习惯:父 run 只记录公共参数和最终结论,子 run 记录每次尝试的细节。这样查看时一目了然。

嵌套运行在 UI 里会显示为可展开的树形结构。我个人觉得,这在做超参网格搜索时特别有用——每个参数组合是一个子 run,父 run 就是整个搜索任务。

4.2 标签与描述:给实验打上标记

实验多了以后,光靠 run_name 根本不够用。我记得有一次,团队三个人同时跑实验,结果跑出来几十个 run,谁是谁的都分不清。后来我强制要求所有人必须加标签和描述。

标签(Tags)是键值对,可以用来标记实验的版本、状态、负责人等信息。描述(Description)是一段文本,用来记录实验的背景和结论。

import mlflow

with mlflow.start_run(run_name="BERT_finetune_v2") as run:
    # 设置标签
    mlflow.set_tag("model_type", "BERT")
    mlflow.set_tag("status", "completed")
    mlflow.set_tag("author", "张三")
    mlflow.set_tag("experiment_version", "v2.1")
    
    # 设置描述
    mlflow.set_tag("mlflow.note.content", 
                   "基于BERT-base在IMDb上微调。\n"
                   "学习率从5e-5降到2e-5后效果更好。\n"
                   "结论:2e-5 + warmup 10% 是最优组合。")

避坑指南:我曾经犯过一个错误——把描述写在 mlflow.set_tag("description", "...") 里。结果 UI 里不显示。后来才发现,MLflow 的笔记功能必须用 mlflow.note.content 这个 key。记住了,这是硬规定。

标签的另一个妙用是过滤。你可以给实验打上 "good"、"bad"、"to_review" 这样的标签,然后在 UI 里一键筛选。我团队现在的工作流是:跑完实验先打标签,每周五统一 review 所有 "to_review" 的实验。

4.3 搜索实验:用 API 精准定位

UI 搜索虽然方便,但自动化场景下,你得用 API。MLflow 的搜索语法类似 SQL 的 WHERE 子句,支持按参数、指标、标签过滤。

先看个简单例子:

import mlflow
from mlflow.tracking import MlflowClient

client = MlflowClient()

# 搜索所有准确率大于 0.85 的实验
runs = client.search_runs(
    experiment_ids=["1"],
    filter_string="metrics.accuracy > 0.85"
)

for run in runs:
    print(f"Run ID: {run.info.run_id}, Accuracy: {run.data.metrics['accuracy']}")

更复杂的搜索,可以组合多个条件:

# 搜索 learning_rate=0.001 且 accuracy > 0.85 且状态为 completed 的实验
runs = client.search_runs(
    experiment_ids=["1", "2"],
    filter_string="params.learning_rate = '0.001' and "
                  "metrics.accuracy > 0.85 and "
                  "tags.status = 'completed'",
    order_by=["metrics.accuracy DESC"],
    max_results=10
)

搜索语法要点:

  • 参数值必须用单引号括起来,比如 params.lr = '0.001'
  • 指标值用数字,不需要引号
  • 支持 >、<、=、!=、LIKE 操作符
  • 可以用 AND、OR 组合条件
  • order_by 支持 ASC 和 DESC

说实话,这个搜索功能我每天都在用。比如上线前,我会搜 "tags.status = 'candidate' and metrics.f1 > 0.9",把候选模型全找出来做对比。

4.4 比较实验:用 UI 和 API 做决策

找到候选实验后,下一步就是比较。MLflow 的 UI 提供了并排对比功能,但 API 层面也有办法。

先看 UI 操作:在实验列表里勾选多个 run,点击 "Compare" 按钮。你会看到参数和指标的并排表格,还有可视化图表。我个人最喜欢的是平行坐标图,能一眼看出哪些参数组合效果好。

API 层面的比较,其实就是把多个 run 的数据拉下来自己分析:

import pandas as pd

# 获取多个 run 的数据
run_ids = ["run_id_1", "run_id_2", "run_id_3"]
runs_data = []

for run_id in run_ids:
    run = client.get_run(run_id)
    data = {
        "run_id": run_id,
        "run_name": run.info.run_name,
        **run.data.params,
        **run.data.metrics
    }
    runs_data.append(data)

# 转成 DataFrame 做分析
df = pd.DataFrame(runs_data)
print(df[["run_name", "learning_rate", "accuracy", "f1_score"]])

我的做法:把比较结果自动生成报告。写个脚本,每天凌晨跑一次,把前一天所有实验拉出来对比,把最优的模型自动打上 "champion" 标签。这样早上来一看就知道该用哪个模型。

比较实验时,有几个坑要注意:

  • 指标对齐:确保比较的 run 用的是同一个评估集,否则指标没有可比性
  • 参数类型:MLflow 把所有参数存成字符串,比较时记得做类型转换
  • 时间戳:用 run.info.start_time 可以按时间排序,看实验的演进过程

4.5 本章知识体系

下面这张图总结了本章的核心内容,我建议你保存下来,用的时候对照着看:

MLflow 进阶功能知识体系 MLflow 进阶功能 嵌套运行 标签与描述 搜索与比较 父 run 子 run 键值对标签 笔记描述 API 搜索 UI 比较 核心价值 • 嵌套运行:把实验组织成树状结构,保留实验间的父子关系 • 标签与描述:给实验打上可搜索的标记,记录实验背景和结论 • 搜索与比较:用 API 精准定位实验,用 UI 直观对比结果

这三个功能配合起来用,效果最好。我一般的工作流是:用嵌套运行组织实验结构,用标签标记状态和结论,最后用搜索和比较选出最优模型。这套流程在团队协作中特别管用,每个人都能快速找到自己需要的实验。