4. DVC 入门:安装、初始化与协作模式

数据集版本管理,说白了就是给数据也上个「Git」。但 Git 本身不是为大数据设计的——你想想看,一个 10GB 的模型权重文件,push 到 GitHub 得等到天荒地老。DVC(Data Version Control)就是来解决这个问题的。

我最早接触 DVC 是在一个 NLP 项目里。那时候团队还在用百度网盘传数据,版本全靠文件名后缀「_v2_final_真的不改了」。后来实在受不了了,才引入了 DVC。嗯,今天我们就从最基础的开始讲。

4.1 安装 DVC

安装方式很简单,我推荐用 pip,干净利落。

pip install dvc

如果你想用其他方式,也可以:

  • conda:conda install -c conda-forge dvc
  • brew(macOS):brew install dvc
  • apt(Ubuntu/Debian):sudo apt install dvc

小提示:如果你要用 S3、GCS、Azure 等远程存储,记得装对应的扩展包。比如 pip install dvc[s3]。我一开始没装,折腾了半天才发现是少了个依赖。

装完之后,验证一下:

dvc --version

看到版本号,就说明装好了。

4.2 初始化 DVC 项目

假设你已经有 Git 仓库了。没有的话先建一个:

git init my-dvc-project
cd my-dvc-project

然后在项目根目录执行:

dvc init

你会看到类似这样的输出:

Initialized DVC.

You can now commit the changes to git.

这时候项目里会多出几个文件:

  • .dvc/ 目录——DVC 的配置和缓存都在这里
  • .dvc/.gitignore——自动生成的,把缓存目录排除在 Git 之外

注意:dvc init 必须在 Git 仓库内执行。我见过有人直接在普通文件夹里跑,结果 DVC 报错说找不到 Git 仓库。DVC 是寄生在 Git 上的,没有 Git 它没法工作。

初始化之后,记得提交一下:

git add .dvc .dvc/.gitignore
git commit -m "初始化 DVC"

4.3 DVC 与 Git 的协作模式

这是最核心的部分。很多人一开始会搞混:DVC 到底存了什么?Git 又存了什么?

我画了一张图,帮你理清关系:

DVC + Git 协作模式 Git 仓库 代码文件(.py, .yaml, .json) .dvc 文件(数据指针) dvc.lock(依赖锁定) .gitignore(排除缓存) DVC 缓存(.dvc/cache) 实际数据文件(二进制) 按哈希值存储 不进入 Git 历史 远程存储(S3 / GCS / 本地路径) 数据备份与共享 dvc push / dvc pull 核心思想:Git 管代码 + 指针,DVC 管实际数据。两者各司其职。

说白了,DVC 不直接把大文件塞进 Git。它生成一个 .dvc 文件,里面只存了文件的哈希值。真正的数据放在 .dvc/cache 里,或者推到远程存储上。

举个例子。假设你有一个 data/train.csv 文件,500MB。你执行:

dvc add data/train.csv

DVC 会做三件事:

  1. 把 train.csv 复制到 .dvc/cache,按哈希值命名
  2. 生成 data/train.csv.dvc 文件,内容就是哈希值和元信息
  3. 把 train.csv 加入 .gitignore,防止 Git 跟踪它

然后你只需要把 .dvc 文件提交到 Git:

git add data/train.csv.dvc
git commit -m "添加训练数据集"

其他人拉取代码后,执行 dvc pull,就能把实际数据下载下来。

我的习惯:每次 dvc add 之后,我都会立刻 git add 对应的 .dvc 文件并提交。这样版本是原子性的,不会出现「代码更新了但数据指针没更新」的情况。

4.4 .dvc 文件结构

我们打开一个 .dvc 文件看看:

# data/train.csv.dvc
md5: 3a7c8f9b1e2d4f6a8b0c1d2e3f4a5b6c
outs:
- md5: a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6
  size: 524288000
  path: train.csv
  hash: md5
  cloud: null

结构很简单:

  • md5:这个 .dvc 文件本身的哈希值
  • outs:输出文件列表,每个文件包含:
    • md5:实际数据文件的哈希值
    • size:文件大小(字节)
    • path:相对于项目根目录的路径
    • hash:哈希算法(默认 md5)

这个文件很小,几 KB 而已。Git 跟踪它毫无压力。

4.5 缓存机制

DVC 的缓存设计很巧妙。默认缓存目录是 .dvc/cache,结构是这样的:

.dvc/cache/
├── a1/
│   └── b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6
├── b3/
│   └── c4d5e6f7a8b9c0d1e2f3a4b5c6d7e8
└── ...

每个文件按哈希值的前两位分目录存储。这样做的好处:

  • 去重:同一个文件不管被 dvc add 多少次,只存一份
  • 完整性校验:每次读取都会校验哈希,数据损坏能及时发现
  • 增量更新:只修改过的文件才会生成新缓存

我曾经踩过的坑:有一次我手动删了 .dvc/cache 目录,以为 DVC 会自动重建。结果所有 .dvc 文件都变成了「孤儿指针」,指向不存在的缓存。最后只能重新 dvc add 所有数据。所以,千万别手贱删缓存目录。想清理的话,用 dvc gc 命令。

4.6 设置远程存储

本地缓存只能自己用。要跟团队协作,得配一个远程存储。我以 S3 为例:

dvc remote add myremote s3://my-bucket/dvc-store
dvc remote default myremote

然后推送数据:

dvc push

其他人拉取:

dvc pull

支持的远程存储类型很多:

类型 命令示例 适用场景
Amazon S3 dvc remote add myremote s3://bucket/path AWS 用户,生产环境
Google Cloud Storage dvc remote add myremote gs://bucket/path GCP 用户
Azure Blob Storage dvc remote add myremote azure://container/path Azure 用户
本地路径 dvc remote add myremote /mnt/shared/dvc 内网共享存储
SSH dvc remote add myremote ssh://user@host/path 自建服务器

我的建议:小团队先用本地路径或 SSH 远程存储,成本低、配置简单。等数据量上来了,再迁移到 S3 或 GCS。别一开始就上云,容易把简单问题复杂化。

4.7 日常协作流程

最后,总结一下 DVC + Git 的日常协作流程。假设你和同事小明在同一个项目里:

  1. 你:修改了代码,更新了数据集
  2. 你:dvc add data/new_dataset.csv
  3. 你:git add data/new_dataset.csv.dvc
  4. 你:git commit -m "更新数据集"
  5. 你:dvc push(把数据推送到远程存储)
  6. 你:git push(把代码和 .dvc 指针推送到 Git 远程)
  7. 小明:git pull(拉取代码和 .dvc 指针)
  8. 小明:dvc pull(拉取实际数据)

整个过程,小明不需要手动下载任何数据文件。一个 dvc pull 就搞定了。