在 GitHub 上编辑

repro

根据需要按正确顺序运行 流水线阶段,以复现完整或部分流水线。

概要

usage: dvc repro [-h] [-q | -v] [-f] [-i]
                 [-s] [-p] [-P] [-R]
                 [--downstream] [--force-downstream]
                 [--pull] [--allow-missing] [--dry]
                 [--glob] [--no-commit] [--no-run-cache]
                 [-k] [--ignore-errors]
                 [targets [<target> ...]]

positional arguments:
  targets       Stages to reproduce. 'dvc.yaml' by default.

详见 targets

描述

通过恢复在 dvc.yaml 中列出的阶段之间定义的 依赖关系图,提供一种重新生成数据流水线结果的方法。然后检查各个阶段,确定哪些需要运行(参见 dvc status)。最后执行 它们的命令

这类似于软件构建自动化中的 make,但 DVC 会捕获“构建需求”(阶段的依赖项),并在过程中缓存流水线的输出

注意事项

在执行生成某个阶段输出的命令之前,该阶段的输出会被从 工作区 中删除(除非在 dvc.yaml 中使用了 persist: true)。

对于包含多个命令的阶段(即 cmd 字段为列表的情况),命令将按照定义的顺序依次执行。任一命令失败都会停止该阶段剩余命令的执行并抛出错误。

没有依赖项也没有输出的阶段被视为始终变更,因此 dvc repro 总是会运行这些阶段。

通常在定义一个或多个阶段后(参见 dvc.yamldvc stage add),或者当代码或其他依赖项发生更改或缺失时执行此操作。请注意,除非使用 --pull 选项,否则 dvc repro 不会尝试 dvc checkoutdvc pull 数据。

为了方便起见,DVC 提供了一个 Git 钩子,在执行 git commit 后提醒你是否需要运行 dvc repro。详见 dvc install

请记住,一个 dvc.yaml 文件不一定对应一条流水线(尽管通常是这样)。因此 DVC 会读取 工作区 内所有的 dvc.yaml 文件来重建流水线。

不过,有几种方法可以限制需要重新生成的内容:通过指定复现的 targets,或使用某些命令 选项,例如 --single-item--all-pipelines

所有数据文件、中间结果或最终结果都会被缓存(除非使用了 --no-commit 选项),并且根据需要在 dvc.lock.dvc 文件中更新已更改的依赖项和输出的哈希值。

并行执行阶段

如果你需要并行执行阶段,可以同时多次启动 dvc repro(例如,在多个独立终端中运行)。例如,假设你的 流水线 图结构如下所示:

$ dvc dag
+--------+          +--------+
|   A1   |          |   B1   |
+--------+          +--------+
     *                   *
     *                   *
     *                   *
+--------+          +--------+
|   A2   |          |   B2   |
+--------+          +--------+
          *         *
           **     **
             *   *
        +------------+
        |    train   |
        +------------+

该流水线包含两个并行分支(AB),以及在最后合并这两个分支的 train 阶段。如果此时运行 dvc repro,DVC 会按顺序依次重现实现两个分支,然后执行 train。若要同时重现实现两个分支,可以同时运行 dvc repro A2dvc repro B2。当两个分支都成功完成后,再运行 dvc repro train:DVC 会识别到两个分支均已是最新的状态,仅执行最终阶段。

选项

  • targets(可选命令参数)— 指定需要重现实验的内容(默认为 ./dvc.yaml 中的所有流水线)。根据所用标志的不同,可以提供不同类型的目标(详见各选项说明)。例如:

  • -R, --recursive — 在作为 targets 提供的目录及其子目录中递归查找 dvc.yaml 文件并进行重现实验。如果目标中不包含任何目录,则此选项无效。

  • --glob — 将 targets 解释为通配符 模式,以匹配阶段名称。例如:train-*(特定阶段名)或 models/dvc.yaml:train-*(特定 dvc.yaml 文件中的阶段)。注意:该选项仅匹配阶段名称,不匹配路径。

  • -s, --single-item — 关闭对依赖项变更的递归检查,仅重现实验单个阶段。如果提供了多个阶段名称作为 targets,则这些阶段将被非递归地依次执行。

  • -f, --force — 即使未检测到任何更改,也强制重现实验流水线并重新生成结果。默认情况下会执行所有阶段,但可通过 targets 参数或 -s-p 选项限制范围。

  • --no-commit — 不将本次执行的输出保存到缓存中(仍会创建或更新 dvc.yamldvc.lock);在探索不同数据或阶段时,可用于避免缓存不必要的中间数据。使用 dvc commit 可完成后续提交操作。

  • --dry — 仅打印将要执行的命令,而不实际运行这些命令。

  • -i, --interactive — 在重现实验每个阶段前提示用户确认。只有当用户输入 "y" 时,该阶段才会被执行。

  • -p--pipeline - 重新执行包含指定 targets 的完整管道。使用 dvc dag <target> 查看某个目标的父级管道。

  • -P--all-pipelines - 重新执行 DVC 项目中所有 dvc.yaml 文件定义的全部管道。此选项下指定 targets 无效,因为所有可能的目标都会被包含。

  • --no-run-cache - 即使阶段命令及其依赖项和输出此前已运行过,仍强制执行该命令(参见运行缓存)。例如当阶段命令具有非确定性行为时有用(不推荐)。

  • --force-downstream - 在类似 ... -> A (已更改) -> B -> C 的情况下,会先重新执行 A,然后继续执行 B,即使 B 此前已使用来自 A 的相同输入执行过(已被缓存)。准确地说,它会重新执行所有变更阶段的下游阶段,即使这些阶段的直接依赖项未发生变化。

    当所有阶段共享一个公共依赖时,这种方式非常有用,可仅在第一个相关阶段(如本例中的 A)声明该依赖,避免重复定义。例如,若已知所有阶段(A 及其后续阶段)都依赖于 requirements.txt,则只需在 A 中声明,在 BC 中可省略。

    这是一种强制执行未变更阶段的方法。对于包含生成非确定性(半随机)输出的阶段的管道也很有用,因为每次执行输出都可能不同,因此无法信任此类阶段的缓存。

  • --downstream - 仅在其对应管道中执行给定 targets 之后的阶段,包括目标阶段本身。如果未提供 targets,此选项无效。

  • --pull - 尝试按需下载缺失的数据。包括:(1) 即将运行的阶段的依赖项;(2) 其他未变更但需跳过的阶段的输出;(3) 即将从缓存检出的阶段的运行缓存(除非传入了 --no-run-cache)。

  • --allow-missing - 跳过仅有数据缺失而无其他变更的阶段。

    在 DVC>=3.0 版本中,--allow-missing 不会跳过由 DVC<3.0 保存的数据,因为在 DVC 3.0 中哈希类型发生了变化,DVC 将其视为数据变更。要将数据迁移到新的哈希类型,请运行 dvc cache migrate --dvc-files。更多关于 从 DVC 2.x 升级到 3.0 的信息请参阅相关文档。

  • -k--keep-going - 继续执行,跳过依赖于失败阶段的那些阶段。目标的其他依赖项仍将被执行。

  • --ignore-errors - 执行阶段时忽略所有错误。与 --keep-going 不同,即使阶段依赖于失败的阶段,也会继续执行。

  • -h, --help - 打印使用说明/帮助信息,然后退出。

  • -q--quiet - 不向标准输出写入任何内容。如果所有阶段均已最新或全部成功执行,则以退出码 0 结束;否则以退出码 1 结束。阶段中定义的命令仍可自由输出信息,不受此标志影响。

  • -v, --verbose - 显示详细的跟踪信息。

示例

要动手实践数据科学和机器学习管道,请参阅 入门:数据管道

让我们构建并重新执行一个简单的管道。它从这个 text.txt 文件开始:

dvc
1231
is
3
the
best

并进行几次简单的转换来过滤和统计数字:

$ dvc stage add -n filter -d text.txt -o numbers.txt \
           "cat text.txt | egrep '[0-9]+' > numbers.txt"

$ dvc stage add -n count -d numbers.txt -d process.py -M count.txt \
           "python process.py numbers.txt > count.txt"

其中 process.py 是一个脚本,为简化起见,仅打印行数:

import sys
num_lines = 0
with open(sys.argv[1], 'r') as f:
    for line in f:
        num_lines += 1
print(num_lines)

执行 dvc repro 的结果应如下所示(cat 用于显示文件内容,tree 用于显示工作目录的内容):

$ dvc repro
Running stage 'filter':
> cat text.txt | egrep '[0-9]+' > numbers.txt
Generating lock file 'dvc.lock'
Updating lock file 'dvc.lock'

Running stage 'count':
> python process.py numbers.txt > count.txt
Updating lock file 'dvc.lock'
Use `dvc push` to send your updates to remote storage.

$ cat count.txt
2

$ tree
.
├── count.txt      <---- result: "2"
├── dvc.lock       <---- file to record pipeline state
├── dvc.yaml       <---- file containing list of stages.
├── numbers.txt    <---- intermediate result of the first stage
├── process.py     <---- code that implements data transformation
└── text.txt       <---- text file to process

你可以检查一下 dvc.lockcount.txt 的内容,以便后续参考。

现在,假设我们想要打印一段描述信息,并将以下这行代码添加到 process.py 中:

...
print('Number of lines:')
print(num_lines)

此时如果我们运行 dvc repro,应该会看到如下输出:

$ dvc repro
Stage 'filter' didn't change, skipping
Running stage 'count' with command:
        python process.py numbers.txt > count.txt
Updating lock file 'dvc.lock'

你现在可以验证 dvc.lockcount.txt 是否已更新为新信息:依赖/输出文件的哈希值已更新,以及生成了新的结果。

示例:从目标阶段向下游执行

本示例延续前面的例子。

当与某个 target 阶段一起使用时,--downstream 选项允许我们仅重新执行该特定阶段之后的命令。为了演示其工作方式,我们先修改 text.txt(即第一个阶段的输入文件,由前一个示例创建):

...
The answer to universe is 42
- The Hitchhiker's Guide to the  Galaxy

假设我们还想在描述中打印文件名,因此我们将 process.py 更新为:

print(f'Number of lines in {sys.argv[1]}:')
print(num_lines)

现在,在 dvc repro 中使用 --downstream 选项,只会执行目标阶段(count)及其后续阶段(本例中无后续阶段):

$ dvc repro --downstream count
Running stage 'count' with command:
        python process.py numbers.txt > count.txt
Updating lock file 'dvc.lock'

text.txt 的更改被忽略,因为该文件是 filter 阶段的依赖项,而上述 dvc repro 并未执行该阶段。这是因为在管道中,filter 发生在目标阶段(count)之前(参见 dvc dag),如下所示:

$ dvc dag

  +--------+
  | filter |
  +--------+
      *
      *
      *
  +-------+
  | count |
  +-------+

请注意,在上述示例中,如果不使用 --downstream 而直接运行 dvc repro,则不仅会执行目标阶段(count),还会执行其前面的所有阶段(本例中只有 'filter')。

示例:仅按需拉取管道数据

你可以结合使用 --pull--allow-missing 标志,在重现实验管道的同时,仅拉取实际需要的数据来运行已更改的阶段。

基于 example-get-started-experiments 中使用的管道:

$ dvc dag
      +--------------------+
      | data/pool_data.dvc |
      +--------------------+
                 *
                 *
                 *
          +------------+
          | data_split |
          +------------+
           **         **
         **             **
        *                 **
  +-------+                 *
  | train |*                *
  +-------+ ****            *
      *         ***         *
      *            ****     *
      *                **   *
+-----------+         +----------+
| sagemaker |         | evaluate |
+-----------+         +----------+

如果我们处于一台所有数据均缺失的机器上:

$ dvc status
data_split:
        changed deps:
                deleted:            data/pool_data
        changed outs:
                not in cache:       data/test_data
                not in cache:       data/train_data
train:
        changed deps:
                deleted:            data/train_data
        changed outs:
                not in cache:       models/model.pkl
                not in cache:       models/model.pth
                not in cache:       results/train
evaluate:
        changed deps:
                deleted:            data/test_data
                deleted:            models/model.pkl
        changed outs:
                not in cache:       results/evaluate
sagemaker:
        changed deps:
                deleted:            models/model.pth
        changed outs:
                not in cache:       model.tar.gz
data/pool_data.dvc:
        changed outs:
                not in cache:       data/pool_data

我们可以修改 evaluate 阶段,DVC 将仅拉取运行该阶段所需的必要数据(models/model.pkldata/test_data/),并跳过其余阶段:

$ dvc repro --pull --allow-missing
'data/pool_data.dvc' didn't change, skipping
Stage 'data_split' didn't change, skipping
Stage 'train' didn't change, skipping
Running stage 'evaluate':
...

更多详情请参阅用户指南中的 拉取缺失数据

内容

🐛 发现问题?告诉我们!或者修复它:

在 GitHub 上编辑

有疑问?加入我们的聊天,我们会为您提供帮助:

Discord 聊天