4. 版本控制:Git高级操作、数据版本管理(DVC)、模型版本管理(MLflow Model Registry)
4.1 核心原理:AI项目中的“三轨版本控制”
传统软件版本控制只管理代码,而AI/ML项目还包含数据与模型两类大型二进制资产。代码、数据、模型三者之间存在复杂的依赖关系:某次实验的模型A由数据集B在代码提交C下训练产生。若仅用Git管理代码,数据与模型的变更将完全失控。
因此,AI项目需要“三轨版本控制”:
- 代码轨:使用Git管理源代码、配置文件、测试脚本,粒度到行级。
- 数据轨:使用DVC(Data Version Control)管理数据集、中间特征文件,通过哈希指针将大文件存储在本地或远程对象存储中,Git仅记录元数据。
- 模型轨:使用MLflow Model Registry管理模型生命周期,记录模型的版本、阶段(Staging/Production/Archived)、参数、指标及血缘关系。
三者通过提交哈希与实验ID建立关联,形成可复现的完整快照。
4.2 Git高级操作:超越add/commit
在AI项目中,Git的高级操作主要解决协作效率与历史清晰度问题。
4.2.1 交互式暂存与部分提交
当一次改动涉及多个实验参数时,使用 git add -p 将不同hunk分别暂存,保持提交原子性:
# 将 config.yaml 中的不同参数修改拆分为两个提交
git add -p config.yaml
# 按 y/n/s 选择暂存哪些块
4.2.2 使用reflog找回丢失的提交
执行 git reset --hard 或 git rebase 后,旧提交不会立即被GC回收,可通过reflog找回:
git reflog
# 输出示例:
# a3f9c2e HEAD@{0}: reset: moving to HEAD~2
# 7b8f1a0 HEAD@{1}: commit: 调整学习率实验
git cherry-pick 7b8f1a0 # 恢复该提交
4.2.3 使用cherry-pick精准移植提交
当需要将某个分支上的特定提交(而非整个分支)合并到当前分支时:
git cherry-pick 7b8f1a0
# 若发生冲突,解决后 git cherry-pick --continue
4.3 DVC数据版本管理:让数据集可追踪
DVC的核心思想是将大文件从Git仓库中移出,仅保留一个指向实际存储位置的指针文件(.dvc文件)。该指针文件包含目标文件的MD5哈希值,当数据变化时,哈希值变化,Git便能感知数据版本变更。
4.3.1 DVC基本工作流
- 初始化:
dvc init创建 .dvc 目录。 - 添加数据:
dvc add data/raw生成 data/raw.dvc 指针文件。 - 配置远程存储:
dvc remote add -d myremote s3://bucket/dvc-store或使用本地路径。 - 推送数据:
dvc push将实际数据上传至远程存储。 - 版本切换:切换Git分支后执行
dvc checkout同步对应数据版本。
# 典型流程
dvc init
dvc add data/images
git add data/images.dvc .gitignore
git commit -m "添加训练图片数据集 v1"
dvc remote add -d storage s3://ml-bucket/dvc
dvc push
4.3.2 DVC管道(Pipeline)追踪数据血缘
DVC不仅能管理数据文件,还能通过 dvc.yaml 定义数据处理管道,记录依赖与输出的哈希关系:
# dvc.yaml
stages:
preprocess:
cmd: python preprocess.py --input data/raw --output data/processed
deps:
- data/raw
- preprocess.py
outs:
- data/processed
当输入数据或脚本变化时,dvc repro 会重新执行对应阶段,并自动更新输出文件的版本。
4.4 MLflow Model Registry:模型生命周期管理
MLflow Model Registry 提供了集中式模型存储库,支持模型版本注册、阶段转换与描述更新。它解决了“哪个模型在生产环境?”、“如何回滚到上一版本?”等关键问题。
4.4.1 注册模型版本
import mlflow
from mlflow.tracking import MlflowClient
client = MlflowClient()
# 注册新版本
result = client.create_registered_model("iris_classifier")
# 或直接通过 run_id 注册
client.create_model_version(
name="iris_classifier",
source="runs:/8f3a2b1c/model",
run_id="8f3a2b1c"
)
4.4.2 模型阶段转换
模型版本通常经历 Staging(预发布)→ Production(生产)→ Archived(归档) 的阶段流转:
# 将版本1从Staging转为Production
client.transition_model_version_stage(
name="iris_classifier",
version=1,
stage="Production"
)
| 阶段 | 用途 | 可写权限 | 典型操作 |
|---|---|---|---|
| Staging | 预发布验证 | 数据科学家 | 运行A/B测试、影子部署 |
| Production | 线上服务 | ML平台管理员 | 在线推理、监控 |
| Archived | 历史保留 | 只读 | 审计、复盘 |
4.5 案例:端到端可复现实验
假设你正在训练一个图像分类模型,需要完整记录“代码+数据+模型”三者的版本关系。
- 代码提交:修改 train.py 后执行
git commit -m "使用ResNet50替换VGG16",记录提交哈希a3f9c2e。 - 数据更新:新增1000张标注图片,执行
dvc add data/images,生成新的 .dvc 指针并提交Git。 - 模型训练:运行实验,MLflow自动记录参数、指标及模型文件,生成 run_id
8f3a2b1c。 - 注册模型:将效果最好的run注册为模型版本 v1,并转入Staging阶段。
- 复现实验:切换Git到
a3f9c2e,执行dvc checkout恢复对应数据,MLflow中run_id关联的代码哈希与数据哈希完全匹配。
# 复现命令
git checkout a3f9c2e
dvc checkout
mlflow run . --experiment-id 3 # 使用MLflow Projects复现
4.6 误区与复盘
后果:仓库体积膨胀,clone速度极慢,且Git无法有效处理二进制差异。正确做法是使用DVC或Git LFS管理大文件。
后果:模型已部署,但无法追溯其训练代码与数据,出现问题时无法复现。正确做法是在MLflow中记录代码提交哈希与数据哈希,形成完整血缘。
后果:生产环境模型变更无审计记录,回滚困难。正确做法是每次阶段转换时添加描述(如“修复数据泄漏问题”),并关联对应的实验run_id。
4.6.1 复盘清单
- 是否所有大文件(>100MB)都已从Git中移出?
- 每个模型版本是否能追溯到确切的代码提交与数据版本?
- 模型从Staging到Production的转换是否有审批记录?
- 是否定期清理Archived模型版本以节省存储?
- 团队成员是否都熟悉
git reflog与dvc checkout的恢复操作?
通过Git、DVC与MLflow Model Registry的协同使用,AI项目实现了从数据准备到模型部署的全链路版本可追溯,为后续的CI/CD流水线与模型监控奠定了坚实基础。