4、数据集版本控制:使用DVC管理训练数据集

做嵌入式AI的兄弟都知道,模型迭代最头疼的不是改网络结构,而是数据集管理。我见过太多团队,模型训好了,回头想复现,发现训练数据找不到了——要么是硬盘坏了,要么是同事误删了,要么是版本搞混了。嗯,这问题我踩过坑。

今天聊的DVC(Data Version Control),说白了就是给数据集装个Git。但它不是存数据本身,而是存数据的“指针”。你想想看,一个数据集动辄几十GB,Git根本扛不住。DVC的做法很聪明——它只记录文件的哈希值和存储位置,真正的数据放在远端。

4.1 为什么需要DVC?

我刚开始做STM32CubeAI项目时,数据集管理全靠手动。文件夹命名“v1_final”、“v2_final_final”、“v3_真的不改了”……结果呢?训出来的模型A用的是v1数据,模型B用的是v2数据,对比效果时根本说不清差异在哪。

DVC能解决三个核心痛点:

  • 版本可追溯:每次训练用的数据集版本,一查就知道
  • 存储不爆炸:只存差异文件,不是全量复制
  • 协作不打架:团队共享数据集,不会出现“你改了我不知道”的情况

核心思想:DVC + Git = 代码版本控制 + 数据版本控制。两者配合,才能做到真正的可复现。

4.2 DVC的安装与初始化

安装很简单,一行命令搞定:

pip install dvc

然后在你项目的Git仓库里初始化:

cd your_project
git init
dvc init

注意,dvc init会在项目根目录生成一个.dvc文件夹。这个文件夹里存的是配置信息,别手欠删了。我有个同事就干过这事,结果所有数据版本信息全丢了……

4.3 添加数据集到DVC

假设你的数据集在datasets/目录下:

dvc add datasets/

执行后你会看到:

  • 生成了一个datasets.dvc文件(这是数据集的元信息)
  • 原来的datasets/目录被替换成了缓存链接
  • 真正的数据被移到了.dvc/cache

这时候别忘了提交到Git:

git add datasets.dvc .gitignore
git commit -m "添加训练数据集 v1.0"

小技巧:我习惯在提交信息里写清楚数据集的内容,比如“添加了1000张室内场景图片,包含光照变化”。这样以后翻Git log,一眼就知道数据集长什么样。

4.4 配置远程存储

本地管理只是第一步。真正的价值在于把数据存到远端,团队共享。DVC支持多种远程存储:

存储类型 配置命令 适用场景
本地目录 dvc remote add myremote /path/to/storage 单机多项目
SSH服务器 dvc remote add myremote ssh://user@host/path 小团队内部
S3兼容 dvc remote add myremote s3://bucket/path 云端协作
阿里云OSS dvc remote add myremote oss://bucket/path 国内团队常用

配置好后,推送数据:

dvc push

拉取数据:

dvc pull

注意dvc push只会上传当前版本的数据。如果你有多个版本,每个版本都需要单独push。我曾经因为忘了push新版本,导致同事拉到的还是旧数据,模型训了一晚上才发现不对……

4.5 版本切换与回滚

这是DVC最爽的地方。假设你训了一个模型,效果不错。后来改了数据集,训出来的模型反而变差了。你想回到之前的数据集版本,怎么做?

# 查看历史版本
git log --oneline

# 切换到某个commit
git checkout <commit_hash>

# 恢复对应的数据集
dvc checkout

就这么简单。DVC会根据datasets.dvc文件里的哈希值,从缓存里恢复出对应的数据。

我个人习惯的做法是:每次训练前,先dvc checkout确认数据集版本,再开始训练。这样能保证训练日志里记录的数据集版本和实际使用的完全一致。

4.6 在STM32CubeAI项目中的实战

拿我最近做的一个手势识别项目举例。数据集结构是这样的:

datasets/
├── train/
│   ├── gesture_0/  (1000张)
│   ├── gesture_1/  (1000张)
│   └── gesture_2/  (1000张)
├── val/
│   ├── gesture_0/  (200张)
│   ├── gesture_1/  (200张)
│   └── gesture_2/  (200张)
└── test/
    ├── gesture_0/  (100张)
    ├── gesture_1/  (100张)
    └── gesture_2/  (100张)

我用DVC管理后,每次数据增强、清洗、扩充,都生成一个新版本。比如:

  • v1.0:原始采集数据,共3600张
  • v1.1:增加了随机旋转和亮度调整,数据量翻倍到7200张
  • v1.2:去除了模糊和重复的图片,剩下6800张

每个版本对应一个Git commit。训练时,我在训练脚本里加了一行:

import subprocess
dataset_version = subprocess.check_output(['git', 'log', '--oneline', '-1']).decode().strip()

这样训练日志里自动记录了数据集版本。以后复盘时,一眼就能看出哪个模型用了哪个数据集。

避坑指南:我曾经犯过一个错误——在数据增强脚本里直接修改了原始数据集。结果DVC检测到文件变化,但没提交新版本。后来想回退,发现原始数据已经被覆盖了。正确的做法是:数据增强生成新目录,用DVC管理新目录,保留原始数据不动。

4.7 DVC与Git的协作流程

我总结了一套比较顺手的流程,分享给你:

  1. 准备数据:把数据集放到datasets/目录
  2. DVC跟踪dvc add datasets/
  3. Git提交git add datasets.dvc && git commit -m "数据集v1.0"
  4. 推送远端dvc push && git push
  5. 开始训练:记录当前数据集版本到训练日志
  6. 迭代数据:修改数据集后,重复步骤2-4

这套流程我用了两年多,团队里再也没出现过“数据找不到了”或者“版本对不上”的问题。

4.8 小结

DVC不是什么高大上的技术,但它解决的是嵌入式AI开发中最基础也最容易被忽视的问题——数据管理。你想想看,模型再牛,数据不对也是白搭。

下一章我会讲模型版本管理,到时候DVC和Git的知识会继续用到。嗯,先把数据集管好,后面的路就好走了。