MLOps 架构图:从训练数据到受监控的模型

生产模型的 MLOps 架构图:特征存储、训练流水线、模型注册表、在线服务,以及触发重新训练的监控闭环。

· 创始人兼开发者

发布于

MLOps 架构图:从训练数据到受监控的模型

笔记本里的模型并不是一个系统。Hidden Technical Debt in Machine Learning Systems(Sculley 等,NeurIPS 2015)里那张著名的图用方框说明了这一点:在真实的机器学习系统中,机器学习代码只占很小一部分。其余部分是数据采集、特征提取、模型服务、监控,以及连接它们的各种管道,而生产环境中的问题正是从这些地方冒出来的。

MLOps 架构图画的就是这“其余部分”。本文以一个欺诈评分模型为例绘制这样一张图,讲解每个生产模型都有的两个闭环,并列出需要标注的内容,让这张图能回答模型出问题时人们会提出的那些疑问。

两个闭环和一个触发器

每个生产模型都有一个训练闭环和一个服务闭环:

  • 训练闭环。 采集数据,把数据转换为特征,用来训练候选模型,与当前模型比较,然后注册。
  • 服务闭环。 请求到达,查询特征,由模型打分,并把预测记录下来。
  • 触发器把两者连接起来。对服务闭环的监控、定时计划或新数据,都会让训练闭环重新开始。
组件 职责 回答的问题
特征存储 每个特征只有一个定义,离线供训练使用,在线供评分使用 训练和服务用的是同一个特征吗?
流水线编排器 按顺序执行训练步骤,并记录每次运行 能重新构建出这个模型吗?
模型注册表 每个模型的版本、指标和审批状态 线上是哪个模型?之前是哪个?
模型服务 在线端点或批处理作业 多快、多频繁、为谁服务?
监控 输入、预测和结果随时间的变化 模型现在还准吗?

Google 的 MLOps 指南描述了三个成熟度级别:第 0 级是手动流程,第 1 级为持续训练实现训练流水线的自动化,第 2 级再为流水线本身加上 CI/CD。画出你现在所处的级别,而不是计划中的级别,并标出手动步骤。

训练与服务不一致

MLOps 架构图最常防住的 bug,是训练与服务不一致(training-serving skew):同一个特征在训练 SQL 里用一种方式计算,在服务代码里又用另一种方式计算。模型离线看起来不错,上线后却变差,而且没人说得清原因。上面提到的 Google 指南建议把特征存储作为实验、持续训练和在线服务的唯一数据源,让每个特征只有一个定义。

第二个经典 bug 是跨时间的数据泄漏。一笔支付的训练数据行,必须使用该笔支付发生时的特征值,而不是今天的特征值。把这个时间点(point-in-time)要求写在从特征存储指向训练流水线的连线上。

示例:银行卡支付的欺诈评分

支付 API 在授权一笔银行卡支付之前,会向模型请求一个欺诈评分。设计如下:

  1. 事件。 支付 API 把每一笔支付发布到 Kafka。一个流处理作业在在线存储中维护滚动特征,比如每张卡过去一小时内的支付次数。同样的事件也会进入数据仓库。
  2. 标签。 一笔支付是否属于欺诈,要通过数周甚至数月后才到达的拒付(chargeback)才能知道。拒付数据被加载到数据仓库,并与原始支付关联。
  3. 特征。 特征存储为每个特征只定义一次,从数据仓库计算离线值,并把最新值写入在线存储。
  4. 训练。 编排好的流水线按时间点构建训练集,校验数据,训练候选模型,在同一评估集上与线上模型比较,然后连同指标一起注册。
  5. 发布。 经批准的版本部署到评分端点:先以影子模式运行,对线上流量的副本打分而不影响决策;然后承接一小部分流量;最后承接全部流量。
  6. 监控。 每一个评分都连同特征一起被记录。监控把输入分布和评分分布与训练数据对比,并在标签陆续到达时计算精确率和召回率。漂移告警或质量告警会启动重新训练。
支付事件经由 Kafka 流入数据仓库和在线特征存储。特征存储为训练流水线和模型注册表提供数据,注册表把模型部署到支付 API 调用的评分端点。预测结果与迟到的标签一起进入监控,告警触发重新训练。

13 个组件 · 16 个连接

在 Archboard 中打开
图表内容
  • Card network disputes
  • Warehouse
  • Feature store
  • Training pipeline
  • Model registry
  • Drift alert
  • Payments API
  • Kafka
  • Online features
  • Fraud scoring
  • Prediction log
  • Model monitoring
  • chargebacks, later
  • payment events
  • event history
  • stream features
  • batch features
  • materialize
  • point-in-time set
  • candidate + metrics
  • approved version
  • features
  • score(payment)
  • scores
  • scores + features
  • late labels
  • drift, quality drop
  • retrain
欺诈评分模型的 MLOps 架构:支付事件和迟到的拒付标签进入特征存储,训练流水线注册候选模型,经批准的版本在线提供评分,对预测和标签的监控会触发重新训练。

这张图的读法如下:

  • 上排,训练。 拒付标签和事件历史在数据仓库中汇合。特征存储为流水线构建训练集,流水线再把候选模型注册到模型注册表。
  • 下排,服务。 支付 API 把事件发布到 Kafka,并同步调用评分端点。端点从在线存储读取特征,并把每个评分写入预测日志。
  • 注册表的连线是模型进入生产环境的唯一途径:永远是经批准的版本,绝不是从笔记本里复制出来的文件。
  • 右侧,回流闭环。 监控读取预测结果和迟到的标签。出现漂移或质量下降时会产生告警,进而启动训练流水线。

需要标注什么

  • 训练集连线上的时间点规则。
  • 端点和注册表上的模型版本和阶段。
  • 特征查询和评分的延迟预算,因为支付在等待它们。
  • 标签延迟。 如果标签要几周后才到,就写出来:它决定了你能多快衡量模型质量。
  • 重新训练的触发条件:定时计划、漂移阈值、数据量。
  • 负责人。 数据、特征、模型和端点往往归不同的团队负责。

常见错误

  • 只画一个叫“机器学习模型”的方框。 它把特征存储、注册表和监控闭环都藏了起来,而故障恰恰是从这些地方开始的。
  • 没有反馈路径。 如果标签从不回流,就没人知道模型是什么时候变差的。
  • 生产路径上有笔记本。 模型只能通过流水线和注册表进入服务。
  • 同一个特征有两种实现。 训练 SQL 和服务代码用不同方式计算“同一个”值,就会导致不一致。
  • 无法回滚。 在注册表中保留上一个版本,并画出端点如何切换回去。
  • 只监控基础设施。 模型出错时,延迟和错误率可能依然完美;输入、评分和结果也都要监控。

服务这一侧属于常规的分布式系统工作。事件驱动架构图介绍了 Kafka 部分;对于带检索的语言模型,RAG 架构图介绍了索引和服务。

在 Archboard 中构建

  1. 使用 Google 或 GitHub 登录,并新建一张图。
  2. 添加 ML 节点包中的 特征存储、一个表示注册表的 模型,以及一个用于评分的 端点。
  3. 添加数据节点包中的 Kafka、一个 数据仓库、一个作为在线存储的 Redis,以及一个作为预测日志的 主题。
  4. 添加 DevOps 节点包中的一个 流水线 用于训练、一个 指标 节点用于模型监控,以及一个 告警 作为重新训练的触发器。
  5. 添加 C4 模型节点包中的一个 容器 表示支付 API,以及一个 外部系统 表示卡组织的拒付数据。
  6. 把它们连接起来,在每条连线上标注所传输的数据,并把迟到的标签和重新训练触发器设为虚线。再添加一个基础节点包中的 Markdown 块,写明发布步骤。

这个示例共用 13 个图表节点,在 Free 套餐的限制之内。借助通过 MCP 连接的 AI 智能体,你可以描述这条流水线,让它摆放节点,然后再调整标签。

常见问题

我需要特征存储吗? 第一天不需要。你需要的是每个特征只有一个定义,并且训练和服务都使用它。当多个模型共享特征,或者你需要在线获取新鲜特征时,特征存储是实现这一点的常见方式。

模型注册表和制品存储有什么区别? 制品存储只保存文件。注册表在此基础上增加了版本、指标、血缘关系和审批状态,这样部署步骤就能请求经批准的版本,而不是某个文件路径。

模型应该多久重新训练一次? 数据发生实质变化有多频繁,就多久训练一次。先从定时计划开始,监控就绪后再加上漂移和质量触发条件,并记录每次重新训练的原因。

标签迟到时,如何监控模型? 先监控眼下就能看到的东西,比如输入分布、评分分布和被标记支付的占比;等标签到达后再计算精确率和召回率。两条路径都要画出来。

训练和服务应该共享基础设施吗? 它们可以共享特征定义和注册表,但负载特征不同。把它们画成两条独立的路径,在特征存储和注册表处汇合。

免费开始 — 1 个席位,无需信用卡。

相关文章

← 返回博客

一分钟打开画布

使用 Google 或 GitHub 登录。单席位免费,团队加入后再升级。