4. 版本控制:代码版本控制(Git)、数据版本控制(DVC)、模型版本控制
在MLOps体系中,版本控制是支撑可重复性、可追溯性与团队协作的基石。传统软件开发中,Git已能很好地管理代码;但机器学习项目不仅包含代码,还涉及不断演进的数据集、预训练模型权重、超参数配置以及评估指标。若仅用Git管理整个ML项目,仓库会迅速膨胀,且无法有效追踪数据与模型的“血缘关系”。本章将系统拆解三层版本控制:面向代码的Git、面向数据的DVC(Data Version Control)以及面向模型产物的模型注册与版本管理,并厘清它们各自解决的问题与协作边界。
4.1 核心原理:三层版本控制的职责划分
MLOps版本控制的核心思想是“按对象类型分层管理”。代码变化频繁且逻辑性强,适合用Git的提交历史记录;数据集文件体积大、更新方式多为整体替换或增量追加,不适合直接放入Git;模型文件则是训练产物,需要与代码、数据版本精确对应,同时还要记录评估指标与部署状态。下图展示了这三层控制在一个典型ML项目中的协作关系:
Git负责管理代码仓库中的源文件与配置文件,DVC通过轻量级指针文件(.dvc文件)记录数据集的元信息与存储位置,而模型版本控制(通常借助MLflow或Seldon等工具)则维护模型产物的生命周期。三者通过提交哈希或版本号互相引用,形成一条完整的血缘链。
4.2 方法流程:从Git到DVC再到模型注册
下面以一个典型的“房价预测”项目为例,演示三层版本控制的具体操作流程。
4.2.1 代码版本控制(Git)
代码版本控制遵循常规Git工作流,但ML项目建议在仓库中明确区分代码与数据目录,并通过.gitignore排除所有大型数据文件与模型输出:
# .gitignore 关键片段
/data/raw/
/data/processed/
/models/checkpoints/
*.h5
*.pt
*.pkl
.mlflow/
每次实验前,先创建功能分支并提交代码变更:
git checkout -b experiment/feature-engineering-v2
git add src/ configs/
git commit -m "添加特征:房屋周边POI密度"
git push origin experiment/feature-engineering-v2
代码提交的粒度应保持“一次提交对应一个逻辑变更”,便于后续通过git bisect定位问题。
4.2.2 数据版本控制(DVC)
DVC的核心机制是将数据文件替换为指向远程存储的指针。初始化并添加数据目录:
dvc init
dvc add data/processed/train.csv
git add data/processed/train.csv.dvc .gitignore
git commit -m "添加训练数据集 v3(含POI特征)"
执行dvc add后,DVC会计算文件哈希,生成一个.dvc文件,并将实际数据复制到本地缓存(默认.dvc/cache)。随后将缓存推送到远程存储(如S3、MinIO):
dvc remote add -d storage s3://ml-bucket/dvc-store
dvc push
当需要切换数据版本时,只需git checkout到对应提交,再执行dvc checkout即可恢复匹配的数据文件。DVC还支持定义流水线(dvc.yaml),将数据处理、特征工程、训练等步骤串联,实现一键复现。
4.2.3 模型版本控制(MLflow Model Registry)
模型训练完成后,使用MLflow记录参数、指标与模型产物,并注册到Model Registry:
import mlflow
from mlflow.tracking import MlflowClient
with mlflow.start_run(run_name="xgb_v2_poi"):
mlflow.log_param("max_depth", 6)
mlflow.log_metric("rmse", 45210.3)
mlflow.log_artifact("models/xgb_model.pkl")
# 注册模型
mlflow.register_model(
model_uri="runs:/<run_id>/models/xgb_model.pkl",
name="HousePricePredictor"
)
注册后的模型会获得版本号(如v1、v2),并可在Stage中流转:Staging → Production → Archived。每次部署前,需确认模型版本对应的Git提交哈希与DVC数据版本,确保三者一致。
4.3 案例/场景:一次完整的可复现实验
假设数据科学家小张完成了一次实验,提交记录如下:
| 对象 | 版本标识 | 说明 |
|---|---|---|
| 代码 | Git commit 7f3a9e2 |
特征工程v2 + XGBoost调参 |
| 数据 | DVC md5 a1b2c3d4e5 |
train.csv 含POI密度特征 |
| 模型 | MLflow v3 (Production) | RMSE 45210,AUC 0.87 |
当需要回滚或复现该实验时,只需执行:
git checkout 7f3a9e2
dvc checkout
mlflow models serve -m "models:/HousePricePredictor/3" --port 5001
系统会从Git恢复代码、从DVC缓存拉取对应数据、从MLflow加载模型v3,三者精确匹配,杜绝“代码新、数据旧”或“模型与特征不一致”的混乱。
4.4 误区/复盘:版本控制中的常见陷阱
误区一:将大文件直接提交到Git。这会导致仓库体积膨胀、克隆缓慢,且无法利用Git的差异比较功能。正确做法是使用DVC或Git LFS管理大文件。
误区二:只记录模型文件,不记录数据版本。模型与训练数据强相关,若数据更新后未同步更新DVC指针,模型评估将失去意义。每次训练前必须确认dvc.lock文件与当前数据一致。
最佳实践:在训练脚本中自动记录当前Git commit与DVC文件哈希,写入MLflow run的tag中,形成不可篡改的血缘信息。
import subprocess
git_sha = subprocess.check_output(["git", "rev-parse", "HEAD"]).decode().strip()
dvc_hash = subprocess.check_output(["dvc", "data", "status"]).decode().strip()
mlflow.set_tag("git_commit", git_sha)
mlflow.set_tag("dvc_status", dvc_hash)
另一个常见问题是模型注册表与部署环境脱节。模型在Staging阶段表现良好,但推送到Production后因数据分布漂移导致效果下降。此时应通过模型版本的回滚机制快速切换至上一版本,同时利用DVC回溯训练数据分布,分析漂移原因。
最后,团队应建立统一的版本命名规范。建议采用“语义化版本+实验序号”的方式,例如v2.1.0-exp4,并在模型注册表的描述字段中注明实验目标与关键结论,避免版本号混乱。
通过Git、DVC与模型注册表的协同工作,MLOps平台能够实现从数据准备到模型上线的全链路可追溯、可回滚与可复现,为自动化运维提供坚实基础。