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。它生成一个 .dvc 文件,里面只存了文件的哈希值。真正的数据放在 .dvc/cache 里,或者推到远程存储上。
举个例子。假设你有一个 data/train.csv 文件,500MB。你执行:
dvc add data/train.csv
DVC 会做三件事:
- 把
train.csv复制到.dvc/cache,按哈希值命名 - 生成
data/train.csv.dvc文件,内容就是哈希值和元信息 - 把
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 的日常协作流程。假设你和同事小明在同一个项目里:
- 你:修改了代码,更新了数据集
- 你:
dvc add data/new_dataset.csv - 你:
git add data/new_dataset.csv.dvc - 你:
git commit -m "更新数据集" - 你:
dvc push(把数据推送到远程存储) - 你:
git push(把代码和 .dvc 指针推送到 Git 远程) - 小明:
git pull(拉取代码和 .dvc 指针) - 小明:
dvc pull(拉取实际数据)
整个过程,小明不需要手动下载任何数据文件。一个 dvc pull 就搞定了。