A38

模型部署

点击正文段落选定收藏或划线位置;未选定时使用屏幕内第一段。

课内目录

训练脚本打印出较高的 F1,并不意味着模型已经能够稳定地帮助使用者。别人送来的字段可能缺失,服务机器上的库版本可能不同,预测结果还可能在没有报错的情况下发生变化。模型部署要把训练中的假设变成运行中的约定:什么输入可以接收,哪个版本负责计算,怎样知道它正常,以及发现问题后怎样恢复。

本课围绕公开 Adult 收入分类数据集构造教学服务,预测收入是否超过数据集规定的阈值。这个任务适合观察数值特征、类别特征和分类指标,但数据有历史与人群局限,只用于学习部署流程,不据此进行个人资格判断。所有延迟、流量比例及验收数值都是示例,需要在实际任务中重新确定。

1 模型部署要回答什么

模型部署首先回答“交付的到底是什么”。模型文件通常只保存参数与计算结构,而最终预测还依赖缺失值处理、类别编码、字段顺序和分类阈值。如果训练时把教育程度编码为固定位置的特征,线上却按另一种顺序拼接向量,模型可能照常返回分数,含义却已经错位。因此,可发布对象应是能够还原完整预测过程的发布包,并为它分配唯一的 release_id。

以 Adult 为例,输入可以包括年龄、每周工作时长、教育程度和职业类别。训练阶段把数值缺失值替换为训练集统计量,把类别字段转换为模型接受的向量。线上必须使用已经拟合好的处理器,不能根据当前请求重新计算均值,也不能随着新类别到来随意增加向量维度。输入契约要写明字段名称、类型、单位、允许范围、必填性,以及未知类别的处理办法。

部署还要回答“预测何时交付”。每天集中计算 1 次并写出结果,属于批量推理;收到请求后立即计算并返回,属于在线推理。前者关心整批完成时间、失败重跑和结果去重,后者更关心响应延迟、并发与超时。本课采用在线服务方便观察版本切换,但同样的制品管理与一致性检查也适用于批量任务。不要因为模型可以提供接口,就把所有场景都改成实时调用。

评估目标需要在上线前讲清。precision 表示被预测为正类的样本中真正为正的比例,recall 表示真实正类中被找出的比例,F1 综合这 2 项;AUC 衡量分数对正负样本的排序能力,通常指 ROC-AUC。AUC 较高不保证固定阈值下的 recall 足够,类别不平衡时还应关注正类数量和 PR 曲线。服务返回成功只能证明完成了计算,不能证明预测正确。

模型部署同时管理输入、发布包、执行环境和观测
模型部署同时管理输入、发布包、执行环境和观测

还需要确定责任边界:谁定义输入,谁批准质量门槛,谁处理服务故障,谁决定回滚。可恢复性不能依赖“记得上次用了哪个文件”。发布包、运行环境和入口路由都应留下记录,使值班者能够在不了解训练细节时恢复到已验证状态。部署完成的标志,是这些问题已有明确答案并经过演练。

2 导出、运行时与硬件后端

导出是把训练工具中的模型转换为适合保存和执行的表示。可以保留框架原生格式,也可以使用 ONNX 等交换格式。交换格式有利于跨工具执行,但支持范围受算子、格式版本和运行时实现约束。导出工具没有报错,只说明生成了制品;还要检查目标运行时是否支持所需操作,以及输入输出名称、形状、数据类型是否符合预期。

运行时负责加载制品并执行推理,硬件后端决定计算实际落在 CPU、GPU 或其他设备上。对规模较小的表格模型,CPU 可能已经满足需求;图像分类模型在足够批量下可能从 GPU 获益。选择要依据完整请求的实测延迟、吞吐、内存与成本,不能只看某段矩阵运算的速度。传输、解码、预处理和排队都可能占用主要时间。

导出前先冻结训练结果和输入处理。将数据按标签比例划分为训练集 70%、验证集 15%、测试集 15%,保存随机种子与样本标识。填补器、缩放器和类别编码器只在训练集拟合,验证集用于选择阈值与配置,测试集在配置确定后用于最终评估。如果存在同人多条记录或时间关系,应按人分组或按时间划分,避免相互关联的记录进入不同集合造成泄漏。

导出后用固定参考样本同时运行原模型与候选制品。比较输出形状、分数差异和最终类别,并特别查看决策阈值附近的样本。浮点计算可能出现小差异,容限要根据任务和数值表示预先设定;不能看到差异后不断放宽条件。分数差很小也可能让阈值附近的标签翻转,因此既要看数值误差,也要看 precision、recall 和 F1 是否出现不可接受的变化。

输入契约与预处理共同确定模型实际收到的特征
输入契约与预处理共同确定模型实际收到的特征

图像任务还要固定颜色通道、缩放尺寸和归一化方式,短文本任务要固定分词器、词表、截断长度及特殊符号。表格任务中常见的单位差异同样危险:年龄以年计,每周时长以小时计,字段顺序不由 JSON 键的排列决定。预处理若未随模型封装,就必须作为独立版本被清单严格绑定,避免只升级模型文件。

是否使用量化或更低数值精度,属于后续优化决定。入门部署先建立可靠基线,再比较候选方案的质量与资源表现。格式转换和硬件加速都不是必选项,更不能代替输入检查与回归评估。本课只需要理解执行链条,复杂算子优化与设备内部调度留到后续学习。

3 版本、回滚与灰度边界

模型版本不能单独代表线上行为。相同模型配上不同编码器、阈值或运行时,可能产生不同预测。发布清单至少应绑定模型摘要、预处理摘要、输入契约版本、类别映射、阈值、依赖锁和启动配置。release_id 标识这组不可变内容,摘要帮助核对文件是否相同;二者作用不同,名称相同不能代替内容核验。

回滚应切回已经验证过的完整发布包。仅把模型文件替换为旧文件,却保留新预处理,可能把故障变得更隐蔽。旧包需要能够重新启动,输入接口也要与当前调用方兼容。如果新版本增加了必填字段,旧版本不认识调用方的新格式,入口切换未必能恢复服务。发布前应检查契约兼容性,并在需要时提供明确的过渡安排。

灰度是让有限比例的真实流量进入候选版本,再决定是否扩大。可以先分配 5%,检查达到约定的时间窗口和请求数量后,再增加到 25% 与 100%。这些比例只是演示;低流量场景可能需要更长观察时间。按稳定请求标识或用户标识分流,能够减少同类请求来回切换;但分组方式也要检查是否造成候选组的人群偏差。

入口按稳定标识分流,异常时把候选流量降为 0
入口按稳定标识分流,异常时把候选流量降为 0

灰度必须说明能证明什么。几分钟内可以观察错误率、延迟和输入分布,真实标签若要几天后才产生,就不能宣布 F1 已经通过。此时质量判断依赖发布前的固定评估、及时可得的代理信号,以及之后的标签回收。影子推理可把相同请求复制给候选模型并比较输出,但候选结果不影响用户;它能检查一致性与资源消耗,却不能直接证明业务效果。

上线前写出停止条件,例如连续 5 分钟错误率超过 1%,或候选版本 p95 延迟超过约定预算便暂停扩流。p95 是 95% 请求延迟不超过的值,不能用平均值替代。质量门槛需要同时规定样本数、标签成熟时间和比较口径。回滚由谁执行、入口多久生效、在途请求如何结束,都应提前演练,并保留失败版本供排查。

4 动手:部署一次可回滚推理服务

这次练习的交付物是本地运行的 2 个推理进程、固定参考样本、发布清单,以及能够切回旧进程的入口配置。准备 Adult 的固定快照,记录来源、获取日期、文件摘要和标签映射。把“超过收入阈值”定义为正类,统一原始文件中可能存在的空白、缺失标记与标签后缀。先做小规模数据检查,确认清洗规则没有把标签或样本标识混入特征。

按前述比例固定划分后,训练带预处理的简单分类流水线,例如类别独热编码加逻辑回归。验证集用来选择业务可解释的分类阈值,测试集只用于最终报告。记录各集合的样本数、正类比例,以及测试集上的 precision、recall、F1、AUC 和混淆矩阵。若你为了调阈值反复查看测试集,就需要另外保留未参与选择的数据,不能继续把原测试结果当作独立证据。

接着生成 v1 发布包。包内保存已拟合流水线、契约、阈值配置、完整依赖锁和清单;使用原生格式也可以,不强求格式转换。若序列化格式能加载可执行对象,只接受可信构建流程产生的制品。挑选正常样本、含缺失字段样本、未知类别样本和阈值附近样本作为参考集合,保存预期的接受或拒绝行为。类别不在词表中是否继续预测,必须按契约决定。

服务提供 POST /predict、GET /ready 和 GET /version。启动时加载固定发布包,核验摘要并执行预热;全部成功后 /ready 才返回就绪。/predict 接受命名字段,校验成功后按固定顺序转换并返回 score、predicted_label、release_id 和 request_id。score 的含义应写入契约,不默认它是经过校准的真实概率。非法类型、缺失必填字段或超出请求上限时,返回明确错误,避免悄悄填入 0。

可以用如下请求检查输入和版本是否贯通。实际契约应列出全部字段;本练习让流水线只使用示例中的 4 个字段,保持调用可复现。

POST /predict
Content-Type: application/json

{
  "request_id": "adult-demo-017",
  "features": {
    "age": 42,
    "hours_per_week": 40,
    "education": "Bachelors",
    "occupation": "Tech-support"
  }
}

启动 v1 后重放参考集合,确认响应携带版本信息,合法输入能得到预期输出,非法输入得到契约规定的错误。再用固定并发和固定输入大小进行短时负载检查,记录吞吐、p95 延迟、错误率及内存。负载生成端也可能成为瓶颈,因此要记录生成方式和测试机器。先预热再测量,并区分进程启动时间与稳定服务延迟。

构建候选 v2 时只改变明确记录的内容,例如使用验证集选出的新阈值,其余内容保持可追踪。把 v1、v2 放在不同本地端口,入口通过配置按稳定标识分流,候选比例从 0 调整为 5%。演练时可以使用预先构造的请求集合模拟流量;这只能证明流程可操作,不能冒充真实生产灰度的质量证据。观察结果要按 release_id 分开保存。

可回滚部署从冻结输入开始,到入口切换结束
可回滚部署从冻结输入开始,到入口切换结束

最后主动让候选进程不可用,检查入口是否停止给未就绪节点分配新请求,并将候选比例降为 0。随后确认新请求都由 v1 回应、版本标记正确、错误率恢复,在途请求按约定完成或失败。保留 v2 的日志与配置后再修复。只有实际走通“发现异常—切换入口—确认恢复”,才能把“支持回滚”写入练习结论。

5 灵活性与稳定性取舍

部署方式没有脱离约束的最优解。直接用训练框架运行,通常更容易保留已有处理逻辑,代价是依赖较多、包体可能较大;转换为通用格式,可能简化目标环境,却增加算子兼容和一致性验证工作。应该先问目标机器允许什么、发布频率多高、谁负责维护,再决定格式。为了追求形式统一而拆散原本可靠的流水线,可能增加出错位置。

批量大小是另一个常见取舍。把多个输入合并执行,可能摊薄固定开销、提高吞吐,但需要等待更多请求到齐。低到达率下,等待可能比计算更久。交互中采用固定到达率和简化计算时间,显示批量增大时吞吐容量上升,平均等待也增加。它解释方向,实际验收仍需测量 p95 等尾延迟;真实系统通常设置最大等待时间,避免一直凑批。

稳定性也不等于“永远不改”。完全冻结依赖有利于复现,但仍需要安排兼容性与维护更新;在每次启动时自动安装最新版则会让节点状态难以预测。可行做法是固定每次发布的完整环境,把更新作为新候选包进行评估,保留经过验证的旧包。这样既能变化,又能知道变化发生在哪里。

资源冗余同样需要依据目标。保留旧版本进程会占用内存,却能缩短回滚时间;临时重新加载旧包节约平时资源,却增加恢复等待。小型教学服务可以直接保留 2 个进程,实际服务则按恢复时间目标和容量限制选择。不要为入门任务堆叠复杂平台,先证明输入一致、结果可追溯和故障可恢复,再逐步增加自动化。

6 常见坑:导出成功却线上精度漂移

精度漂移常被混成“模型变差了”,但至少有几类不同原因。第 1 类是执行不一致:线上使用了错误的特征顺序、颜色通道、分词器或类别映射。第 2 类是数据本身变化:同样的处理程序收到不同人群、设备或表达方式的数据。第 3 类是评价口径变化,例如真实标签尚未成熟就被当成负类。排查要先固定比较对象,不能同时改模型、阈值和数据清洗。

输入契约的问题通常表现为接口成功而预测异常。训练时缺失值用中位数补齐,线上却用 0;训练时每周时长是数值,线上传入带单位字符串;文本训练时保留标点,线上先删除所有符号。服务若宽松接受这些输入,错误不会自动暴露。除了类型检查,还要观察字段缺失率、未知类别比例和数值范围,发现异常时保留可重放的脱敏样本。

服务健康、输入变化和带标签质量需要分别观测
服务健康、输入变化和带标签质量需要分别观测

数据泄漏会让发布前的高分失去参考价值。若在全部数据上计算缩放统计量后再划分集合,评估过程已经接触了测试分布;若把与结果直接相关的事后字段放入特征,模型可能学到上线时根本拿不到的信息。短文本分类还可能出现同段文本的轻微改写跨集合重复,图像分类可能把同源图片的裁剪版本分到不同集合。部署前应核对特征可获得时间与样本关联关系。

类别不平衡也容易造成误读。假设流失预测中正类仅占 5%,全部预测“不流失”就能得到 95% accuracy,recall 却为 0。上线后应按同样的正类定义、阈值和标签窗口比较 precision、recall、F1,并记录正类支持数。正类比例变化时,precision 可能在排序能力近似不变的情况下变化,因此要结合 AUC、分组结果及数据分布判断,不能凭单个数值定位原因。

分布变化不自动意味着必须重训。输入缺失率突然上升可能来自采集故障,修复数据管道比重训更合适;某个新类别大量出现则可能需要更新编码与训练样本。先用固定参考集合验证执行链条,再检查线上样本特征和标签关系。即使特征分布看似稳定,输入与标签之间的关系仍可能变化;分布告警是调查线索,不能直接当作质量结论。

7 案例:依赖未锁定导致节点不一致

下面是可在教学环境构造的故障案例,不是对某个真实系统事故的描述。团队发布了相同摘要的模型文件,节点 A 和节点 B 都能启动,平均延迟也接近,但相同输入在节点 B 偶尔报错或产生不同分数。初步检查只比较了模型文件,因此有人怀疑硬件计算存在随机问题。真正缺少的是完整发布环境的证据。

排查先固定原始请求、模型与预处理摘要、release_id、节点标识及运行时版本,再把完全相同的请求分别送到 2 个节点。若无法复现,应检查此前比较的是否真是相同输入、相同阈值与相同时间窗口。对于可复现差异,先对比模型实际收到的特征向量,再对比分数。这样可以把输入转换差异与数值执行差异分开。

案例中,A 使用构建时验证过的依赖组合,B 在启动时按宽泛版本范围重新解析了库。我们故意构造了预处理兼容性差异,使未知类别在 B 上触发不同处理结果。具体行为取决于库与配置,并非所有升级都会改变输出。修复环境后,在相同请求和参考集合上重新比较,差异消失,才形成支持依赖问题的证据。

从固定请求出发,逐层区分执行差异与数据变化
从固定请求出发,逐层区分执行差异与数据变化

恢复时先把流量切回经过验证的旧发布包,将故障节点退出入口,再制作锁定直接依赖和传递依赖的新包。清单还要记录解释器、运行时与必要的系统环境信息,设备驱动约束也应在适用时写清。不能只在 B 上现场升级几个库并宣布完成,因为这样难以保证重启或扩容后的节点一致。所有节点通过同样的摘要检查与参考样本检查后,才重新进入灰度。

8 把部署清单写进发布方案

发布清单要让另一个人能够判断“这个版本是什么、为什么能上线、出了问题怎么办”。身份部分写 release_id、制品存放位置、内容摘要、构建来源和负责人;执行部分写输入契约、预处理版本、阈值、类别映射、依赖锁与目标运行环境。不要用“当前最新版”指代任何需要复现的对象,配置也应有可核对的版本。

证据部分应写数据来源、划分方法、泄漏检查、各集合的标签比例与固定评估结果。报告除了整体指标,还要给出重要人群或输入类别的样本量与结果,避免整体改善掩盖局部退化。样本不足的分组要注明证据有限。对导出模型还应附参考集合标识、分数容限、标签翻转情况和目标硬件上的检查结论。

发布清单把模型、环境、评估和回滚证据连成记录
发布清单把模型、环境、评估和回滚证据连成记录

运行部分写资源限制、超时、请求大小上限、就绪条件和观测位置。p95 延迟要注明并发、请求形状、预热条件与统计窗口,否则不同报告无法比较。预测日志只保留排查所需信息,对可能涉及个人的数据做脱敏与访问控制。需要回收真实标签时,预先约定关联标识、标签定义、成熟时间及保存期限,避免上线后才发现无法评价。

最后把灰度与恢复写成可执行条件:初始比例、扩流门槛、最短观察时间、最小样本数、暂停条件、回滚目标和执行人。区分立即可见的服务指标与延迟到达的质量指标,并注明后者何时复查。验收不是清单全部打勾就结束,而是证据能对应到具体发布包,且回滚演练确实恢复了请求。下面的“放进方案里”会将这些要求压缩成可直接改写的发布段落。

9 从模型部署走向MLOps 基础(A39)

完成这次部署后,我们能够管理某个已知版本,但真实项目会持续产生新数据、新标签和新候选模型。人工逐次整理清单、比较结果和切换版本,容易遗漏条件。MLOps 关注把数据、训练、评估、发布与监控连接为可追踪的持续流程,让每次变化都有来源、门槛和责任人。下一课会从这些协作与自动化问题开始。

部署与 MLOps 的连接点是可比较的记录。同一套固定参考样本帮助检查执行一致性,新的带标签样本帮助评价当前任务表现,二者不能相互替代。固定集合可能逐渐不代表现实,而持续变化的评估集合又不便直接比较历史版本。因此需要保留评估集合版本和数据时间范围,让“比上次好”有明确的比较基础。

自动化也需要边界。输入分布告警可以自动通知负责人、暂停扩大候选流量,却不应未经判断就启动重训并直接覆盖线上模型。新模型仍要经过相同的输入契约、独立评估、一致性和灰度检查。服务质量突然下降时,先恢复可用性,再调查数据或模型原因,比在故障窗口内同时修改多项内容更容易保留证据。

可以先把部署检查做成只读的自动关卡。例如 Adult 的候选包声明使用某版教育程度词表,检查程序就核对词表摘要,重放包含未知职业的参考请求,并把输出与该候选包的评估报告关联。若模型摘要改变而报告仍指向旧包,即使报告中的 F1 达标,也应阻止发布;否则自动化只是更快地重复使用过期证据。

标签回收也要保留预测发生时的版本。假设同一请求在灰度期间由 v1 处理,几天后才补齐标签,应把标签关联到当时保存的分数、阈值与 release_id,再计算质量。若改用当前 v2 重新预测后记到 v1 名下,就无法判断旧版本的真实表现。缺失关联标识的记录应单独统计,避免只评价容易匹配的样本而产生选择偏差。

进入 A39 前,可以用 3 个问题检查准备程度:拿到 release_id 能否找到完整环境;相同请求能否重放并解释输出;旧版本能否在约定时间内重新承接请求。如果答案仍依赖某个人的记忆,就先补齐发布与恢复记录。可复现、可观察、可恢复的部署,是进一步建立自动化流程的基础。

放进方案里

本次发布使用 Adult 公开数据快照进行教学验证,以年龄、每周工作时长、教育程度和职业类别为输入,预测数据集定义的收入类别。记录来源、获取日期与文件摘要,按标签分层划分训练集 70%、验证集 15%、测试集 15%。预处理仅在训练集拟合,阈值在验证集确定,测试报告同时列出 precision、recall、F1、AUC、混淆矩阵和正类样本数。该服务仅用于部署练习。

发布包以唯一 release_id 标识,绑定模型、预处理、输入契约、阈值、类别映射、完整依赖锁及运行时信息,并核验内容摘要。启动后先执行预热和参考样本检查,通过后才进入就绪状态。非法类型或缺失必填字段按契约拒绝;未知类别按固定规则处理。响应携带版本与请求标识,日志保存必要的脱敏证据,以便重放定位。

发布前在目标机器测量固定并发下的错误率、p95 延迟和内存,并记录输入大小、测试窗口与预热条件。候选流量按稳定标识从 5% 起步,满足约定观察时间、请求数量和服务门槛后,再扩至 25% 与 100%。例如连续 5 分钟错误率超过 1% 即停止扩流;实际项目应在发布前补齐延迟预算和质量门槛,不能上线后临时调整。

真实标签未成熟前,报告仅陈述服务表现、输入分布与候选输出差异;标签回收后按统一口径复查分类质量。保留已验证的旧发布包和可用容量,演练候选失效时将其流量降为 0,确认新请求由旧版本响应。发布负责人执行切换,数据负责人核查分布及标签问题,所有恢复记录关联 release_id。任何修复都生成新候选包,并重新经过一致性检查与灰度。

10 小结:下一步MLOps 基础(A39)

模型部署把预测过程变成可交付、可观测、可恢复的服务。模型、预处理、阈值与运行环境共同决定结果;导出成功需要一致性证据,服务健康需要质量证据,回滚需要完整旧版本和实际演练。

自测时试着解释:为什么相同模型文件仍可能输出不同结果?为什么灰度运行 5 分钟不能证明 F1 达标?为什么切回旧模型却保留新编码器不算可靠回滚?如果能把答案对应到输入契约、标签时间与发布包,你就具备进入 A39、学习持续管理模型生命周期的基础。

同阶段相关课

AI 答疑

默认关闭。启用后,只发送本课标题、最近阅读的屏幕内正文摘录(最多 6000 字)与本次问题。

配置自己的服务