上周团队里出了个事故:训练集上一个准确率98%的模型,在生产环境里掉到了72%。排查了两天,发现训练时用的数据版本和推理服务加载的数据预处理代码对不上——有人改了预处理逻辑但没更新版本标记,另一个同事用老标记重新训练了模型。这种问题在传统软件工程里早就有成熟方案,但在AI项目里却反复出现。今天我们就聊聊怎么用MLOps的思路和工具链解决这类问题。

一、MLOps到底是什么?

很多人把MLOps简单理解为“机器学习版的DevOps”,这个说法对了一半。更准确地说,MLOps要解决的是机器学习项目特有的三个矛盾:实验的灵活性与生产的稳定性之间的矛盾数据迭代与模型迭代的耦合问题跨角色协作(数据科学家/算法工程师/运维工程师)的标准化问题

传统软件工程中,代码是唯一的核心资产;而在ML项目里,我们至少需要管理四类资产:代码、数据、模型、环境。这四者的任意组合都可能影响最终效果。MLOps就是让这四者的变更可追踪、可复现、可协作的一套工程实践。

二、工具链核心三件套

Git:代码版本管理的底线

别以为Git只是存代码的——在ML项目里,Git要管的东西多了去了。

# 错误示范:把数据文件直接塞进Git仓库
# big_data.csv  # 这个文件2.3GB,push一次半小时,还会把同事clone卡死

# 正确姿势:用.gitignore隔离数据,用配置文件记录数据来源
# .gitignore里写:
*.csv
*.h5
models/*.pkl

# configs/train_config.yaml里写:
data:
  source: s3://our-bucket/v1.2/processed/train_202304/
  version: "v1.2"  # 这里一定要打版本标签,吃过亏的都知道

Git分支策略也要调整。我们团队现在用:experiment/*分支做算法实验,feature/*分支开发工程功能,model/*分支管理模型迭代。合并到main分支时必须包含完整的版本信息文件。

DVC:数据与模型的版本管家

Git管不了大文件,DVC(Data Version Control)就是专门干这个的。它把大文件存到云存储(S3、OSS、本地NAS都行),在Git里只留一个指针文件。

# 初始化DVC(假设已经在Git项目中)
dvc init
dvc remote add -d myremote s3://mybucket/dvc-store  # 设置远程存储

# 把数据文件交给DVC管理
dvc add datasets/train.csv
git add datasets/train.csv.dvc  # 这个文件很小,存的是元数据和哈希值
git commit -m "Add training dataset v1.0"

# 需要切换数据版本时
git checkout another-branch
dvc checkout  # 自动拉取对应版本的数据文件

最实用的功能是数据流水线(pipeline):

# dvc.yaml
stages:
  prepare:
    cmd: python src/prepare.py
    deps:
      - src/prepare.py
      - data/raw
    outs:
      - data/prepared

  train:
    cmd: python src/train.py
    deps:
      - src/train.py
      - data/prepared
    outs:
      - models/model.pkl
    metrics:
      - metrics/accuracy.json  # DVC能跟踪指标变化

dvc repro就能完整复现整个流程,谁动了哪个环节、产出什么结果,一目了然。

MLflow:实验跟踪与模型注册中心

模型训练不是一次性的,我们得记录每次实验的参数、指标、环境、模型。MLflow的Tracking组件就是干这个的。

import mlflow

def train_model(params):
    mlflow.set_experiment("recommendation_v2")
    
    with mlflow.start_run():
        # 记录超参数
        mlflow.log_params(params)
        
        # 训练代码...
        model = train(params)
        accuracy = evaluate(model)
        
        # 记录指标
        mlflow.log_metric("accuracy", accuracy)
        
        # 记录整个conda环境
        mlflow.log_artifact("conda.yaml")
        
        # 保存模型(自动记录框架版本)
        mlflow.sklearn.log_model(model, "model")
        
        # 打个标签方便查找
        mlflow.set_tag("stage", "production_candidate")

生产环境需要模型版本管理时,用MLflow Model Registry:

# 注册模型
mlflow.register_model(
    "runs:/<run_id>/model",
    "recommendation_system"
)

# 生产环境加载指定版本
model = mlflow.pyfunc.load_model(
    "models:/recommendation_system/Production"
)

这样就能在UI界面上看到模型从Staging到Production的流转过程,还能做A/B测试。

三、实战中的坑与经验

  1. 版本对齐要强制:我们定了个规矩——任何模型文件必须包含生成它的代码版本、数据版本、环境版本三元组。缺少任何一个就不允许上线。

  2. 环境复现越早做越好:项目第一天就要写Dockerfile或conda环境文件。等换了显卡驱动才发现CUDA版本对不上,已经晚了。

  3. 指标跟踪要统一:团队所有人用同一套指标计算脚本,避免“你的准确率和我算的不一样”这种低级问题。

  4. 流水线不是越复杂越好:刚开始用DVC pipeline时,我们把每个数据清洗步骤都拆成一个stage,结果调试起来像走迷宫。后来改成:数据预处理一个stage、特征工程一个stage、训练评估一个stage,清晰多了。

  5. 模型注册中心要有权限控制:实习生不小心把实验模型推成生产版本的事故,我们可不想再来一次。

四、给新手的起步建议

如果你刚开始接触MLOps,别想着一次性把整套工具链全上齐。按这个顺序来:

第一周先把Git规范定好,数据文件一律不进仓库,用README明确数据存放位置。

第二周引入DVC,只用来管数据文件版本。先体验dvc adddvc checkout的基本操作。

第三周在训练脚本里加MLflow跟踪,哪怕只是记录loss和accuracy。

等这些成为肌肉记忆了,再考虑DVC pipeline和MLflow Model Registry。

最后说个真心话:工具是辅助的,关键还是团队要形成“版本意识”。每次开会有人问“这个结果怎么来的”,理想答案应该是“git commit id是xxx,数据版本是v1.2,模型运行在mlflow experiment yyy里”——而不是“我上周跑的,好像是那台GPU服务器”。

Logo

AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。

更多推荐