8. 参数与指标管理

8.参数与指标管理

在机器学习项目中,参数和指标的管理往往比代码本身更复杂。调参、记录结果、对比实验,这些工作如果靠手动维护,很快就会变成一场噩梦。DVC 提供了一套完整的解决方案,让参数和指标的管理变得像代码版本控制一样自然。

参数文件 params.yaml

参数文件是 DVC 参数管理的核心。本质上,它就是一个普通的 YAML 文件,但 DVC 赋予了它特殊的意义。默认情况下,DVC 会寻找项目根目录下的 params.yaml 文件。

参数文件的结构非常灵活,可以采用任意层级。来看一个典型的例子:

seed: 20180226

train:
  lr: 0.0041
  epochs: 75
  layers: 9

processing:
  threshold: 0.98
  bow_size: 15000

这个文件定义了三个部分:全局的随机种子、训练参数和数据处理参数。DVC 支持 YAML 1.2 格式,通过 ruamel.yaml 库解析,这比传统的 PyYAML 支持更多特性。

参数文件的命名并不强制。虽然 params.yaml 是默认选择,但完全可以使用其他名称,比如 config.yaml、hyperparams.json 等。关键在于如何在流水线中引用它。

参数依赖管理

在流水线中定义参数依赖

参数依赖是 DVC 流水线中最精细的依赖类型。与普通文件依赖不同,参数依赖可以追踪到文件中的某个具体值。这意味着修改 params.yaml 中的一个参数,不会导致所有阶段都被重新执行。

在 dvc.yaml 中定义参数依赖有两种方式。第一种是手动编辑文件:

stages:
  train:
    cmd: python train_model.py
    deps:
      - train_model.py
      - matrix-train.p
    params:
      - seed
      - train.lr
      - train.epochs
    outs:
      - model.p

params 列表中的每个条目都对应 params.yaml 中的一个路径。点号表示层级关系,比如 train.lr 对应 YAML 中的 train 下的 lr 键。

第二种方式是使用 dvc stage add 命令:

$ dvc stage add -n train \
                -d train_model.py -d matrix-train.p \
                -o model.p \
                -p seed,train.lr,train.epochs \
                python train_model.py

-p 参数接受逗号分隔的参数路径列表。这种方式的优势在于,DVC 会立即验证参数路径的有效性,而手动编辑则要等到执行时才能发现问题。

使用自定义参数文件

如果参数不在 params.yaml 中,可以通过前缀指定文件路径:

$ dvc stage add -n train \
                -p params.json:learning_rate,batch_size \
                -p config.toml:threshold \
                python train.py

甚至可以使用 : 来追踪整个文件的所有参数:

$ dvc stage add -n train \
                -p myparams.toml: \
                python train.py

在代码中读取参数

定义了参数依赖后,代码需要能够读取这些值。DVC 提供了 Python API 来简化这个过程:

import dvc.api

params = dvc.api.params_show()

seed = params['seed']
lr = params['train']['lr']
epochs = params['train']['epochs']

dvc.api.params_show() 会自动解析默认的 params.yaml 文件。如果需要指定其他文件:

params = dvc.api.params_show('config.toml')

对于非 Python 项目,可以直接使用标准的 YAML/JSON/TOML 解析器读取文件。DVC 只关心文件内容是否变化,不关心如何读取。

参数依赖的工作机制

当执行 dvc repro 或 dvc exp run 时,DVC 会检查所有依赖的状态。对于参数依赖,DVC 会计算参数值的哈希值,而不是整个文件的哈希。这意味着:

  • 修改未使用的参数不会触发阶段重新执行
  • 多个阶段可以共享同一个参数文件,但依赖不同的参数子集
  • 参数变化会精确地反映在 dvc.lock 文件中
# dvc.lock 中的参数部分
stages:
  train:
    params:
      params.yaml:
        seed: 20180226
        train.lr: 0.0041
        train.epochs: 75

这种细粒度的追踪机制,让大规模参数调优变得高效。修改一个超参数不再需要重新运行整个流水线。

Metrics 指标定义

什么是 Metrics

Metrics 是描述模型性能的键值对数据。与参数不同,metrics 是阶段的输出,而不是输入。典型的 metrics 包括准确率、损失值、AUC 等。

Metrics 文件应该保持小巧且人类可读,通常使用 JSON、YAML 或 TOML 格式。DVC 对 metrics 文件有特殊处理:它们会被 Git 追踪,而不是 DVC 缓存。

定义 Metrics

在 dvc.yaml 中定义 metrics 有两种方式。第一种是顶级定义:

metrics:
  - metrics.json
  - eval/scores.yaml

这种方式适用于简单的项目,所有 metrics 文件都会被自动识别。

第二种方式是在阶段定义中指定:

stages:
  evaluate:
    cmd: python eval.py
    deps:
      - model.pkl
    outs:
      - metrics.json:
          cache: false

通过设置 cache: false,告诉 DVC 这个文件应该由 Git 管理。也可以使用 dvc stage add 的 -m 或 -M 选项:

$ dvc stage add -n evaluate \
                -d model.pkl \
                -m metrics.json \
                python eval.py

-m 表示 metrics 文件会被 DVC 追踪(类似普通输出),而 -M 表示不缓存(推荐用于 metrics)。

Metrics 文件格式

Metrics 文件必须包含键值对结构。可以是扁平的:

{
  "accuracy": 0.95,
  "loss": 0.12,
  "auc": 0.89
}

也可以是嵌套的:

{
  "train": {
    "accuracy": 0.98,
    "loss": 0.08
  },
  "test": {
    "accuracy": 0.95,
    "loss": 0.12
  }
}

DVC 会解析这种结构,并在对比时正确显示层级路径。

使用 DVCLive 自动记录 Metrics

手动写入 metrics 文件容易出错。DVCLive 提供了更优雅的方案:

from dvclive import Live

with Live() as live:
    live.log_metric("accuracy", 0.95)
    live.log_metric("loss", 0.12)

DVCLive 会自动创建 dvclive/metrics.json 文件,并在 dvc.yaml 中配置好 metrics 追踪。这种方式不仅简洁,还能与训练循环无缝集成。

Plots 可视化配置

Plots 与 Metrics 的区别

虽然 plots 和 metrics 都是阶段的输出,但用途不同。Metrics 是标量值,用于量化比较;plots 则是数据系列或图像,用于可视化分析。典型的 plots 包括 ROC 曲线、混淆矩阵、特征重要性图等。

Plots 文件格式

DVC 支持多种 plots 数据格式:

  1. 数据系列文件:JSON、YAML、CSV 或 TSV 格式,包含多个数据点
  2. 图像文件:JPEG、GIF、PNG 或 SVG 格式,直接渲染

对于数据系列,DVC 使用 Vega-Lite 规范生成交互式图表。例如,CSV 格式的训练日志:

epoch,train_loss,train_acc,val_loss,val_acc
1,0.45,0.82,0.38,0.85
2,0.32,0.89,0.29,0.91
3,0.28,0.92,0.25,0.93

在 dvc.yaml 中定义 Plots

Plots 的定义比 metrics 更灵活,支持丰富的配置选项:

plots:
  # 简单文件路径,使用默认配置
  - logs.csv

  # 自定义 plot ID 和坐标轴
  - ROC:
      template: simple
      x: fpr
      y:
        eval/train/roc.json: tpr
        eval/test/roc.json: tpr
      title: Train vs Test ROC

  # 混淆矩阵
  - Confusion-Matrix:
      template: confusion
      x: actual
      y:
        eval/train/cm.json: predicted
        eval/test/cm.json: predicted

  # 图像文件
  - eval/importance.png

  # 整个目录
  - eval/misclassified_examples

每个 plot 配置可以包含以下字段:

  • y:Y 轴数据来源,可以是单个字段或映射
  • x:X 轴字段名,默认为自动生成的索引
  • title:图表标题
  • template:模板名称(linear、simple、confusion 等)
  • x_label、y_label:坐标轴标签

使用 dvc stage add 定义 Plots

命令行方式同样支持 plots 定义:

$ dvc stage add -n evaluate \
                -d model.pkl \
                --plots roc_curve.json \
                --plots-no-cache confusion_matrix.png \
                python eval.py

--plots 会缓存输出文件,而 --plots-no-cache 不会。对于图像类 plots,通常不需要缓存。

高级配置技巧

当需要组合多个数据源时,可以使用自定义 plot ID:

plots:
  - precision_recall:
      x:
        prc_train.json: recall
        prc_test.json: recall
      y:
        prc_train.json: precision
        prc_test.json: precision
      title: Precision vs Recall

这种方式允许将不同文件中的数据绘制在同一张图上,便于直接对比。

差异对比 diff

参数和指标的价值在于对比。DVC 提供了一套完整的 diff 工具,让实验比较变得简单直观。

dvc params diff

比较参数变化是最常用的操作。默认比较工作区与最新提交:

$ dvc params diff
Path         Param           HEAD   workspace
params.yaml  lr              —      0.0041
params.yaml  train.epochs    —      70
params.yaml  train.layers    —      9

如果参数文件已提交过,会显示具体的变化:

$ dvc params diff
Path         Param         HEAD    workspace
params.yaml  lr            0.0041  0.0043
params.yaml  train.layers  9       7
params.yaml  train.epochs  70      110

常用选项包括:

  • --all:显示所有参数,包括未变化的
  • --deps:只显示作为阶段依赖的参数
  • --targets:指定参数文件路径

比较两个特定版本:

$ dvc params diff e12b167 HEAD^
Path         Param         e12b167  HEAD^
params.yaml  lr            0.0038   0.0041
params.yaml  train.layers  10       9
params.yaml  train.epochs  50       70

dvc metrics diff

Metrics diff 的工作方式类似,但会额外显示变化量:

$ dvc metrics diff
Path                  Metric    HEAD     workspace  Change
dvclive/metrics.json  AUC       0.78912  0.18114    -0.60798
dvclive/metrics.json  TP        215      768        553

对于数值型指标,Change 列显示差值;对于非数值,显示 -。可以通过 --precision 控制小数位数。

dvc plots diff

Plots diff 不是显示数值差异,而是将多个版本的 plots 叠加显示:

$ dvc plots diff HEAD HEAD^

这会生成一个 HTML 文件,其中包含所有指定版本的曲线。对于数据系列 plots,不同版本会用不同颜色区分。

常用选项:

  • --targets:指定 plots 文件
  • -x、-y:指定坐标轴字段
  • --template:指定模板
  • --open:生成后自动在浏览器打开

dvc exp diff

实验 diff 是最高层的对比命令,它结合了 params diff 和 metrics diff:

$ dvc exp diff
Path         Metric   HEAD      workspace  Change
scores.json  roc_auc  0.915363  0.93345    0.018087
scores.json  grade    B         B-         —

Path         Param         HEAD  workspace  Change
params.yaml  max_features  1500  3000       1500

默认比较 HEAD 与工作区,也可以指定两个实验:

$ dvc exp diff exp-1 exp-2

在 Python 中比较

所有 diff 功能都可以通过 Python API 访问:

import dvc.api

# 获取参数差异
params_diff = dvc.api.params_show(rev='HEAD')

# 获取指标差异
metrics_diff = dvc.api.metrics_show(rev='HEAD')

# 获取实验表格
exps = dvc.api.exp_show()
import pandas as pd
df = pd.DataFrame(exps)

这种方式便于在 Jupyter Notebook 中进行自定义分析。

实际工作流程示例

让我们看一个完整的工作流程,体会参数与指标管理的便利性。

初始状态,我们有如下 params.yaml:

train:
  lr: 0.001
  epochs: 10
  batch_size: 32

定义训练阶段:

$ dvc stage add -n train \
                -p train.lr,train.epochs,train.batch_size \
                -d train.py -d data \
                -m metrics.json \
                --plots curves.json \
                python train.py

训练脚本 train.py 读取参数并记录指标:

import dvc.api
from dvclive import Live

params = dvc.api.params_show()
lr = params['train']['lr']
epochs = params['train']['epochs']

with Live() as live:
    for epoch in range(epochs):
        # 训练逻辑...
        accuracy = train_one_epoch(lr)
        live.log_metric("accuracy", accuracy)
        live.next_step()

运行实验:

$ dvc repro

查看结果:

$ dvc metrics show
Path           accuracy
metrics.json   0.85

发现准确率不够理想,调整学习率:

$ dvc exp run --set-param train.lr=0.01

比较两次实验:

$ dvc metrics diff
Path           Metric     HEAD     workspace  Change
metrics.json   accuracy   0.85     0.89       0.04

可视化训练曲线:

$ dvc plots diff HEAD workspace --targets curves.json

这个流程展示了参数与指标管理的闭环:定义 → 执行 → 评估 → 调整 → 对比。所有操作都被 DVC 追踪,确保可重复性。

启下:迈向实验管理

掌握了参数与指标管理后,我们已经具备了进行系统化实验的基础。下一章将深入 DVC 的实验管理系统,学习如何批量运行实验、比较多个迭代、以及分享实验结果。参数与指标不再是孤立的数据点,而是构成实验故事的重要章节。

参数调优不再是盲目的尝试,而是有追踪、有对比、有分析的科学过程。当面对几十个实验版本时,这套系统将成为导航的罗盘。