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的协作流程
我总结了一套比较顺手的流程,分享给你:
- 准备数据:把数据集放到
datasets/目录 - DVC跟踪:
dvc add datasets/ - Git提交:
git add datasets.dvc && git commit -m "数据集v1.0" - 推送远端:
dvc push && git push - 开始训练:记录当前数据集版本到训练日志
- 迭代数据:修改数据集后,重复步骤2-4
这套流程我用了两年多,团队里再也没出现过“数据找不到了”或者“版本对不上”的问题。
4.8 小结
DVC不是什么高大上的技术,但它解决的是嵌入式AI开发中最基础也最容易被忽视的问题——数据管理。你想想看,模型再牛,数据不对也是白搭。
下一章我会讲模型版本管理,到时候DVC和Git的知识会继续用到。嗯,先把数据集管好,后面的路就好走了。