3、版本控制:Git与DVC(数据版本控制)集成、模型注册表概念、MLflow Model Registry实战
好,咱们进入第三个章节。版本控制这件事,做软件开发的兄弟都不陌生。但模型部署不一样——你不仅要管代码,还得管数据、管模型、管实验配置。我见过太多团队,代码用Git管得挺好,模型文件却散落在各个文件夹里,命名方式千奇百怪:model_final_v3_really_final.pth,你懂的。
这一章,咱们就聊聊怎么把版本控制这件事做透。说白了,就是让Git管代码,让DVC管数据,让MLflow管模型。各司其职,清清楚楚。
3.1 Git与DVC的集成:代码和数据分开管
Git本身不适合管大文件。一个预训练模型动辄几百MB,甚至几个GB。你把它塞进Git仓库,每次clone都像在下载电影。而且Git的diff机制对大文件毫无意义——你改了一个权重参数,Git会认为整个文件都变了。
DVC(Data Version Control)就是来解决这个问题的。它的核心思路很简单:用Git管理元数据,用远程存储管理实际文件。
核心思想:DVC会在你的仓库里生成一个 .dvc 文件,这个文件很小,记录了原始文件的哈希值和存储位置。你把这个 .dvc 文件提交到Git,实际的大文件则推送到S3、GCS或者本地NAS上。
我在项目中遇到过一种情况:团队里有人直接把模型文件用Git LFS管理,结果每次拉取代码都要等半小时。后来换成DVC,配合S3存储,速度提升很明显。嗯,这里要注意,DVC不是替代Git,而是Git的补充。
3.1.1 快速上手DVC
安装很简单,一行命令搞定:
pip install dvc
初始化DVC,它会创建一个 .dvc 目录:
cd your-project
git init
dvc init
然后配置远程存储。我个人习惯用S3,但MinIO或者本地路径也行:
dvc remote add -d myremote s3://my-bucket/dvc-store
接下来,把你需要版本控制的数据文件加进来:
dvc add data/raw_dataset.csv
dvc add models/bert_finetuned.pth
这时候你会发现,仓库里多了两个 .dvc 文件。把这两个文件提交到Git:
git add data/raw_dataset.csv.dvc models/bert_finetuned.pth.dvc .dvc/config
git commit -m "Add dataset and model with DVC tracking"
最后,把实际文件推送到远程存储:
dvc push
别人要拉取你的数据时,只需要:
git pull
dvc pull
你看,整个过程跟Git的体验几乎一致。这就是DVC设计得好的地方——学习成本很低。
小技巧:我建议把 dvc push 和 dvc pull 写到CI/CD流水线里。每次模型训练完,自动推送新版本的数据和模型。这样团队其他人永远能拿到最新版本。
3.2 模型注册表概念:给模型一个「身份证」
模型注册表,说白了就是一个中心化的模型管理平台。它解决什么问题?你想想看,一个项目跑下来,可能产生几十个模型版本。哪个版本效果最好?哪个版本部署到了生产环境?哪个版本有严重的过拟合?如果没有注册表,这些信息全靠口口相传,迟早出乱子。
模型注册表的核心功能包括:
- 版本管理:每个模型都有唯一的版本号,支持回滚
- 元数据记录:训练参数、数据集版本、评估指标、创建时间等
- 阶段标记:标记模型处于哪个阶段——Staging、Production、Archived
- 权限控制:谁可以注册新模型,谁可以部署到生产
我曾经在一个金融项目里吃过亏。当时模型迭代很快,一周更新两三次。没有注册表,生产环境用的模型版本全靠运维手动记录。有一次回滚,运维搞错了版本号,把还没验证的模型推了上去,结果线上出了半小时的异常。从那以后,我再也不敢不用模型注册表了。
避坑指南:模型注册表不是数据库,它更强调「可追溯」和「可复现」。你注册一个模型,应该能追溯到它对应的代码commit、数据集版本、训练超参数。缺少任何一个环节,这个模型就是「孤儿模型」,出了问题你根本查不到原因。
3.3 MLflow Model Registry实战
MLflow是目前最流行的机器学习生命周期管理工具之一。它的Model Registry模块,正好实现了我们刚才说的模型注册表功能。而且它跟MLflow Tracking天然集成,用起来很顺手。
3.3.1 环境准备
先安装MLflow:
pip install mlflow
启动MLflow服务,我建议用SQLite做后端存储,简单够用:
mlflow server --backend-store-uri sqlite:///mlflow.db --default-artifact-root ./mlruns --host 0.0.0.0 --port 5000
嗯,这里要注意,生产环境建议用PostgreSQL或者MySQL,并发性能更好。
3.3.2 训练并注册模型
咱们用一个简单的例子演示。假设你训练了一个XGBoost模型:
import mlflow
import mlflow.xgboost
from xgboost import XGBClassifier
from sklearn.metrics import accuracy_score
# 设置MLflow Tracking URI
mlflow.set_tracking_uri("http://localhost:5000")
# 创建一个实验
mlflow.set_experiment("churn_prediction")
with mlflow.start_run() as run:
# 训练模型
model = XGBClassifier(n_estimators=100, max_depth=5)
model.fit(X_train, y_train)
# 记录参数和指标
mlflow.log_param("n_estimators", 100)
mlflow.log_param("max_depth", 5)
accuracy = accuracy_score(y_test, model.predict(X_test))
mlflow.log_metric("accuracy", accuracy)
# 记录模型
mlflow.xgboost.log_model(model, "model")
# 注册模型到Model Registry
mlflow.register_model(
model_uri=f"runs:/{run.info.run_id}/model",
name="ChurnPredictionModel"
)
运行这段代码后,打开MLflow UI(http://localhost:5000),你会看到:
- 在「Experiments」页面,能看到这次运行的参数和指标
- 在「Models」页面,能看到新注册的
ChurnPredictionModel,版本号为1
3.3.3 管理模型版本和阶段
模型注册了,接下来要管理它的生命周期。MLflow支持给每个版本打上阶段标签:
| 阶段 | 说明 | 典型用途 |
|---|---|---|
| None | 未指定阶段 | 刚注册的模型,还没评估 |
| Staging | 预发布阶段 | 通过单元测试,准备集成测试 |
| Production | 生产阶段 | 已通过所有验证,部署到线上 |
| Archived | 归档阶段 | 已下线,保留历史记录 |
你可以通过MLflow UI手动调整阶段,也可以用API:
from mlflow.tracking import MlflowClient
client = MlflowClient(tracking_uri="http://localhost:5000")
# 将版本1提升到Staging
client.transition_model_version_stage(
name="ChurnPredictionModel",
version=1,
stage="Staging"
)
# 将版本1提升到Production
client.transition_model_version_stage(
name="ChurnPredictionModel",
version=1,
stage="Production"
)
重要提醒:MLflow默认允许同一个模型有多个版本处于Production阶段。我个人建议在CI/CD脚本里加一个检查——把旧版本自动降级为Archived,确保生产环境只有一个活跃版本。否则部署时容易搞混。
3.3.4 从注册表加载模型进行推理
部署的时候,直接从注册表加载模型,不用关心模型文件存在哪里:
import mlflow.pyfunc
# 加载Production阶段的模型
model = mlflow.pyfunc.load_model(
model_uri="models:/ChurnPredictionModel/Production"
)
# 进行推理
predictions = model.predict(new_data)
你看,代码里只写了模型名称和阶段。至于模型文件存在S3还是本地,版本号是1还是5,这些细节都被MLflow封装好了。这就是注册表的价值——解耦。
3.3.5 实战中的最佳实践
根据我的经验,有几点值得注意:
- 命名规范:模型名称用驼峰命名,比如
ChurnPredictionModel、FraudDetectionModel。别用中文,也别用空格。 - 版本号策略:每次注册自动递增,不要手动指定版本号。MLflow会自动处理。
- 描述信息:注册模型时,用
mlflow.register_model的description参数写上关键信息,比如「基于2024年Q1数据训练,AUC=0.92」。 - 自动化:把模型注册和阶段转换集成到CI/CD里。比如,模型评估通过阈值后,自动从Staging提升到Production。
一个小技巧:我习惯在模型注册时,同时记录数据集的DVC版本号。这样,如果生产环境模型出了问题,我可以快速回滚到对应的数据集版本,重新训练。这个信息可以写在模型的description里,或者用MLflow的 log_param 记录下来。
好,这一章的内容就到这里。Git管代码,DVC管数据,MLflow管模型——这三者配合起来,你的模型部署工具链就有了坚实的基础。下一章,咱们聊聊容器化,把模型打包成Docker镜像,让它能在任何地方跑起来。