流水线 Stages
DVC 使用 dvc run
创建 Stages。 这些表示形成流水线步骤(Steps)的过程(使用 Git 跟踪的源代码)。同时,Stages还将代码连接到对应的数据输入和输出。
下面我们将 Python 脚本转换为 Stage :
首先,我们需要先获取样例代码。
$ mkdir get-started $ cd get-started $ wget https://code.dvc.org/get-started/code.zip $ unzip code.zip $ rm -f code.zip $ tree . ├── params.yaml └── src ├── evaluate.py ├── featurization.py ├── prepare.py ├── requirements.txt └── train.py 复制代码
接下来,我们安装依赖库(强烈建议预先创建一个虚拟环境)。
$ pip install -r src/requirements.txt 复制代码
此时,先使用 Git 添加或提交源代码目录。
增加第一个 Stage
然后,使用 dvc run
创建 Stages 。
$ dvc run -n prepare \ -p prepare.seed,prepare.split \ -d src/prepare.py -d data/data.xml \ -o data/prepared \ python src/prepare.py data/data.xml 复制代码
运行之后,将会生成了一个 dvc.yaml
文件。 它包括有关我们运行的命令(python src/prepare.py data/data.xml
)、其依赖(dependencies) 和 输出(outputs)信息。其中:
- 依赖 为可能由DVC跟踪的文件或目录,记录在 Stage(在 dvc.yaml 中)或
.dvc
文件的deps
部分。当任何依赖项发生变化时,Stage 就会失效(被认为已过时)。 - 输出(outputs)信息由 DVC 跟踪的文件或目录,记录在 Stage(在 dvc.yaml 中)或
.dvc
文件的outs
部分。 输出信息通常是Stage的结果。
上面使用的命令(dvc run)具体参数的含义如下:
-n prepare
:指定stage的名称。 如果您打开dvc.yaml
文件,您将看到一个名为prepare
的部分。-p prepare.seed,prepare.split
:定义了指定类型的依赖项——parameters。 其想法是该阶段可以依赖于参数文件(默认为params.yaml
)中的字段值:
prepare: split: 0.20 seed: 20170428 复制代码
-d src/prepare.py
和-d data/data.xml
:表示 Stage 依赖于这些文件来工作。 注意:源代码本身被标记为依赖项。如果这些文件中的任何一个稍后进行了更改,DVC 将知道此阶段需要复现。-o data/prepared
:指定此脚本的输出目录,写入了两个文件。 这就是项目的工作空间现在的样子:
. ├── data │ ├── data.xml │ ├── data.xml.dvc +│ └── prepared +│ ├── test.tsv +│ └── train.tsv +├── dvc.yaml +├── dvc.lock ├── params.yaml └── src ├── ... 复制代码
python src/prepare.py data/data.xml
:表示这个Stage要运行的命令,保存到dvc.yaml
中,如下所示:
stages: prepare: cmd: python src/prepare.py data/data.xml deps: - src/prepare.py - data/data.xml params: - prepare.seed - prepare.split outs: - data/prepared 复制代码
prepare
Stage 最终包含了上述所有信息。
DVC 不需要使用 dvc add
来跟踪 Stage 的输出(在当前指定的输出目录为data/prepared
的情况下)。 因为 dvc run
已经解决了这个问题。如果您想将它们保存到远程存储库,您只需要运行 dvc push
即可(通常,与 git commit
一起为 dvc.yaml
文件进行版本管理)。
依赖图 (DAG)
通过多次使用 dvc run
,并将一个 Stage 的输出指定为另一个 Stage 的依赖项,我们可以描述一系列获得所需结果的命令。这就是我们所说的数据流水线或依赖图。
增加第二个 Stage
接下来,我们创建第二个 Stage 链接到prepare
Stage 的输出,以执行特征提取:
$ dvc run -n featurize \ -p featurize.max_features,featurize.ngrams \ -d src/featurization.py -d data/prepared \ -o data/features \ python src/featurization.py data/prepared data/features 复制代码
dvc.yaml
文件会自动更新,现在应该包括两个 Stage 了。具体结果如下所示:
stages: prepare: cmd: python src/prepare.py data/data.xml deps: - data/data.xml - src/prepare.py params: - prepare.seed - prepare.split outs: - data/prepared + featurize: + cmd: python src/featurization.py data/prepared data/features + deps: + - data/prepared + - src/featurization.py + params: + - featurize.max_features + - featurize.ngrams + outs: + - data/features 复制代码
添加更多的 Stage
让我们添加训练Stage。这次没有什么新鲜的事情,只是相同的dvc run
命令且具有同样的参数选项:
$ dvc run -n train \ -p train.seed,train.n_est,train.min_split \ -d src/train.py -d data/features \ -o model.pkl \ python src/train.py data/features model.pkl 复制代码
下面,我们再次检查 dvc.yaml
,它现在应该又有一个新的 Stage 了。
这应该是使用 Git 提交更改的好时机。 其中包括 .gitignore
、dvc.lock
和 dvc.yaml
文件,它们描述了我们的数据流水线。
复现流水线(dvc repro
)
创建 dvc.yaml
文件的重点是能够轻松重现流水线。
$ dvc repro 复制代码
修改模型训练的参数,重新运行
接下来,我们进行更多的模型训练实验尝试。首先,让我们尝试更改训练阶段的参数之一,首先,打开 params.yaml
文件,并将 n_est
更改为 100
。 然后,(重新)运行 dvc repro
。你将看到如下结果:
$ dvc repro Stage 'prepare' didn't change, skipping Stage 'featurize' didn't change, skipping Running stage 'train' with command: ... 复制代码
DVC 检测到应该只运行 train
Stage,并跳过其他所有内容!所有中间结果(prepare
和featurize
Stage 产生的结果)都被重用。
改回修改之前模型的参数,并重新运行
现在,让我们将n_est
改回 50
,并再次运行 dvc repro
:
$ dvc repro Stage 'prepare' didn't change, skipping Stage 'featurize' didn't change, skipping 复制代码
和以前一样,不需要重新运行prepare
,featurize
等 Stage 。但是这次它也没有重新运行train
Stage !先前使用相同输入参数和数据集的运行结果保存在 DVC 的运行缓存中,并在此处重用。
dvc repro
依赖于 dvc.yaml
中 DAG 的定义,并使用 dvc.lock
来确定究竟需要运行什么。
dvc.lock
文件类似于 .dvc
文件,它获取我们所使用的依赖项和参数值的哈希(在大多数情况下是 MD5 )。它可以被认为是流水线的一种状态:
schema: '2.0' stages: prepare: cmd: python src/prepare.py data/data.xml deps: - path: data/data.xml md5: a304afb96060aad90176268345e10355 - path: src/prepare.py md5: 285af85d794bb57e5d09ace7209f3519 params: params.yaml: prepare.seed: 20170428 prepare.split: 0.2 outs: - path: data/prepared md5: 20b786b6e6f80e2b3fcf17827ad18597.dir 复制代码
DVC 流水线(dvc.yaml
文件、dvc run
和 dvc repro
命令)解决了几个重要问题:
- 自动化:以“智能”的方式运行一系列步骤(Step),使您的项目迭代更快。 DVC 自动确定需要运行项目的哪些部分,并缓存“运行”及其结果以避免不必要的重新运行。
- 可重现性:
dvc.yaml
和dvc.lock
文件描述了要使用的数据以及哪些命令来生成流水线结果(例如, ML 模型)。 将这些文件存储在 Git 中可以轻松进行版本控制和共享。 - 机器学习的持续交付和持续集成 (CI/CD):以可复制构建的方式描述项目是引入 CI/CD 系统之前第一个必要的步骤。
可视化
建立了我们的流水线之后,我们需要一种很好的方法来理解它的结构。 查看连接 Stages 的图表会对你理解它的结构有所帮助。 DVC 让您无需离开终端即可完成操作!
$ dvc dag +---------+ | prepare | +---------+ * * * +-----------+ | featurize | +-----------+ * * * +-------+ | train | +-------+ 复制代码
如果你想探索此命令可视化管道的其他方式,请查看官网 dvc dag
。