DVC 给数据集做版本控制:数 GB 文件不进 git 也能 reproduce

起因

ML 项目的代码可以 git 管,但数据集(几百 MB / 几 GB / 几十 GB)不能进 git。
结果是"我两个月前那个 SOTA 实验用的是哪份数据?" 完全说不清。
git 只能 commit 一个 data.csv 指针 / README 描述,没法保证可复现。

DVC 把这个问题解了:在 git 里只 commit 一个"数据元信息文件"(指针 +
hash),实际数据存对象存储 / S3 / SSH 服务器。dvc pull 拉对应 hash 的
数据,整套实验完全可复现。

解决方案

uv add 'dvc[s3]'    # 后端用 S3;其它有 [gs] [azure] [ssh] [gdrive]
# 或 brew install dvc
dvc version

初始化

在已有 git 仓库里:

dvc init
git commit -m 'init dvc'

DVC 在 .dvc/ 建配置目录。

配远程存储

dvc remote add -d myremote s3://my-bucket/dvc-storage
dvc remote modify myremote endpointurl https://s3.example.com  # 兼容 minio
# AWS S3 凭据走 ~/.aws/credentials 或环境变量
git commit .dvc/config -m 'add s3 remote'

添加数据

dvc add data/train.parquet
# 输出:data/train.parquet.dvc + .gitignore 更新

git add data/train.parquet.dvc data/.gitignore
git commit -m 'add train dataset v1'

# 推送数据到 S3
dvc push

.dvc/cache/ 是本地缓存。data/train.parquet.dvc 文件长这样:

outs:
- md5: 6c7a3b8d9e2f4a1c5b8e7d6f3a2c4b5e
  size: 234567890
  path: train.parquet

只 28 行 YAML 进 git,原始几百 MB 数据进 S3。

别人 / 别机器拉

git clone my-project
cd my-project
dvc pull
# 自动拉所有 .dvc 文件对应的数据

切某个 git commit → dvc pull 自动拉那个版本的数据。

Pipeline(DAG)

DVC 的核心还在于 pipeline 定义 + 自动 cache。dvc.yaml

stages:
  prep:
    cmd: python src/prep.py
    deps:
      - src/prep.py
      - data/raw.parquet
    outs:
      - data/clean.parquet

  train:
    cmd: python src/train.py --data data/clean.parquet --out models/model.pt
    deps:
      - src/train.py
      - data/clean.parquet
    params:
      - lr
      - epochs
    outs:
      - models/model.pt
    metrics:
      - metrics.json

  eval:
    cmd: python src/eval.py
    deps:
      - models/model.pt
      - data/test.parquet
    metrics:
      - eval.json

跑:

dvc repro             # 跑全 pipeline,按依赖关系 + 自动跳过未变 stage
dvc repro train       # 只跑 train + 下游
dvc dag               # 看 DAG

params.yaml

lr: 0.001
epochs: 10

params.yaml 里某个值 → dvc repro 只重跑受影响 stage。
没改的 stage 命中 cache 秒级返回。

实验对比

dvc exp run -S lr=0.005 -S epochs=20
dvc exp run -S lr=0.001 -S epochs=30

dvc exp show
# 表格对比所有实验的 params + metrics

-S 临时改参数。每次 exp 产生独立分支,不污染 main。

效果

  • 数据从 git 中消失(仓库从 5 GB 降到 12 MB)
  • 切换数据版本 = git checkout + dvc pull,分钟级
  • 多人同时改不同 stage 不冲突(每人本地 cache 各自命中)
  • "上次 SOTA 用的是哪份数据" 永远答得清
  • CI 里 dvc pull + dvc repro 复现实验

与 git-lfs / DataLad 对比

git-lfs DVC DataLad
数据大文件
Pipeline
实验跟踪
多 backend 仅 GitHub LFS S3 / GCS / SSH / 多
学习曲线

只存数据用 git-lfs;要做 ML pipeline 用 DVC。

踩过的坑

  1. 第一次 dvc add 大文件慢:要算 md5 + 复制到 .dvc/cache/。
    dvc config cache.type symlink 用软链不复制,省时省空间但
    .dvc/cache/ 不能跨文件系统。

  2. 没 push 就 commit + push git:别人 git pull + dvc pull 拉不到
    数据。养成 dvc pushgit push 前的习惯。

  3. .dvc/cache 占满磁盘:本地保留所有版本 + 多分支切换累积。
    dvc gc --workspace 清掉工作区当前 commit 用不到的;
    dvc gc --all-commits 极致清。

  4. multiple users 写同一 stagedvc lock 防止并发 repro 撞车。
    或者 stage outputs 必须确定,random_seed 要固定。

  5. 大数据集多人 train:每人都 dvc pull 几十 GB 浪费带宽。可以
    配 dvc 远程在共享 NFS 上,所有人挂载到本地 .dvc/cache/ 共享,
    配 cache.type=symlink。

精确评价 共 0 人评价
可复现性
可复现 · 0 不可复现 · 0
文风
文风流畅 · 0 文风晦涩 · 0
立场
支持 · 0 反对 · 0

登录后即可对本帖作出评价。

评论区 0 条 · 所有人可在此交流

登录后参与评论。

还没有评论,来说两句。