QCon北京「鸿蒙专场」火热来袭!即刻报名,与创新同行~ 了解详情
写点什么

Uber 机器学习在线服务及模型的持续集成和部署实践

  • 2021-08-05
  • 本文字数:3374 字

    阅读完需:约 11 分钟

Uber机器学习在线服务及模型的持续集成和部署实践

本文最初发表于 Uber 官方博客,经授权由 InfoQ 中文站翻译并发布。

前言


在过去几年,Uber 各种组织和用例中的机器学习应用明显增多。我们的机器学习模型实时为用户提供了更好的体验,帮助预防安全事故并确保市场效率。


图 1:模型和服务二进制 CI/CD 的高级视图


需要注意的一点是,我们对模型和服务进行了持续集成(CI)和持续部署(CD),如上图所示。因为训练和部署的模型增长迅速,我们在经过多次迭代后,终于找到了解决 MLOps 挑战的解决方案。


具体来说,主要有四大挑战。第一个挑战是每天要支持大量模型部署,同时保持实时预测服务的高度可用。在模型部署一节,我们将讨论这项挑战的解决方案。


第二个挑战是,在部署新的重新训练的模型时,与实时预测服务实例相关的内存占用增加了。许多模型还增加了实例(重新) 启动时下载和加载模型所需的时间。在实施新模型时,我们发现,很大一部分旧模型没有收到流量。在模型自动退役一节中,我们将讨论这项挑战的解决方案。


第三个挑战涉及到模型推出策略。机器学习工程师可以通过不同的阶段推出模型,如遮蔽、测试或实验。我们注意到了一些模型推出策略的常见模式,并决定把它纳入实时预测服务中。对于这项挑战,我们将在自动遮蔽一节中对其进行讨论。


我们管理的是一个实时预测服务的集群,因此不可以选择人工服务软件部署。最后一项挑战是为实时预测服务软件制定一个 CI/CD 故事。在模型部署期间,模型部署服务通过对样本数据的预测调用对候选模型进行验证。但是,它不会检查部署到实时预测服务的现有模型。即便模型通过了验证,也不能保证在部署到生产实时预测服务实例时,该模型可以被使用或表现出相同的行为(用于特征转换和模型评估)。


出现这种情况的原因是,两个实时预测服务版本之间可能会有依赖关系的改变,或者服务构建脚本改变。在持续集成和部署一节中,我们将讨论这项挑战的解决方案。

模型部署


要管理在实时预测服务中运行的模型,机器学习工程师可以通过模型部署 API 来部署新的模型和退役未使用的模型。他们可以通过 API 跟踪模型的部署进度和运行状态。在图 2 中,你可以看到系统的内部架构:


图 2:模型部署工作流和运行状况检查工作流

动态模型加载


过去,我们将模型构件封入实时预测服务的 Docker 镜像,并与服务一起部署模型。由于模型的快速部署,这一繁重的过程成为模型迭代的瓶颈,并导致模型和服务开发者之间的中断。


针对这一问题,我们实现了动态模型的加载。模型构件和配置存储保存了生产环境中应该为哪些模型提供服务的目标状态。一个实时预测服务会定期检查这个存储,比较它与本地状态,从而触发对新模型加载和删除退役模型。动态模型加载将模型与服务器的开发周期解耦,从而加快生产模型的迭代速度。

部署模型工作流


并非简单地将训练好的模型推送到模型构件和配置存储中,它通过多个步骤创建独立的、已验证的模型包:


  • 构件验证:确保所训练的模型包含服务和监控所必需的所有构件。

  • 编译:将所有模型构件和元数据打包到一个自包含的可加载包中,并将其打包到实时预测服务中。

  • 服务验证:在本地加载编译好的模型 jar,并用训练数据集中的样本数据进行模型预测——这一步确保了模型能够运行,并且与实时预测服务兼容。


之所以这样做,主要是为了保证实时预测服务的稳定性。因为在同一个容器中加载了多个模型,一个错误的模型可能会导致预测请求失败,并且有可能中断同一个容器上的模型。

模型部署跟踪


要帮助机器学习工程师管理他们的生产模型,我们可以对部署模型进行跟踪,如上图 2 所示。该方案由两部分组成:


  • 部署进度跟踪:部署工作流将发布部署进度更新到一个集中式元数据存储中以便跟踪。

  • 运行状况检查:模型在完成其部署工作流之后,将成为模型运行状况检查的候选对象。这个检查定期进行,以跟踪模型的健康状况和使用信息,并将更新信息发送到元数据存储。

模型自动退役


有一个 API 可以让未使用的模型退役。但是,在很多情况下,人们忘记了这样做,或者没有将模型清理纳入他们的机器学习工作流中,这样会造成不必要的存储成本和增加内存占用。大量的内存占用会导致 Java 垃圾收集暂停和内存不足,这两种情况都会影响服务质量


为解决这一问题,我们建立了一个模型自动退役流程,所有者可以为模型设定一个到期时间。若模型在到期后未使用,则上图 1 中的自动退役工作流会为相关用户触发警告,并使模型退役。当启用该特性之后,我们看到了资源占用率的显著下降。

自动遮蔽


随着机器学习工程师选择采用不同的策略推出模型,他们经常需要设计一种在一组模型中分配实时预测流量的方法。我们看到了它们的流量分配策略中的一些常见模式,比如渐进式推出和遮蔽。


通过渐进式推出,用户复制流量,并逐步在一组模型中改变流量分布。对于遮蔽过程,客户端复制初始(主) 模型的流量,并将其应用于另一个(遮蔽)模型。图 3 显示了一组模型之间典型的流量分布,其中模型 A、 B、 C 参与渐进式推出,而模型 D 则对模型 B 进行遮蔽。


图 3:一组模型之间的实时流量预测分布


为减少对常见模式开发重复实现的工程时间,实时预测服务提供了用于流量分布的内置机制。接下来我们关注的是自动遮蔽模型的情况。


虽然不同团队采用不同的模型遮蔽策略,但具有共性:


  • 来自生产数据的模型预测结果并不用于生产,而是为了分析收集。

  • 遮蔽模型与其主模型共享大部分特征,这在定期重新训练和更新模型的用户工作流中尤其如此。

  • 在遮蔽停下来之前,通常要持续数天或数周的时间窗。

  • 一个主模型可以被多个遮蔽模型所影射;一个遮蔽模型可以影射多个主模型。

  • 遮蔽流量可以是 100% 的,也可以根据主要模型流量的一些标准来挑选。

  • 为了比较结果,对主模型和遮蔽模型都收集了相同的预测。

  • 一个主模型可能要为数百万次的预测提供服务,预测日志可能会被采样。


在模型部署配置中,自动隐藏配置只是其中的一项工作。实时预测服务可以检查自动遮蔽的配置,并相应地分配流量。用户仅需通过 API 端点设定遮蔽关系和遮蔽标准(遮蔽内容,遮蔽时间长短),并确保增加遮蔽模型所需的功能,而非主模型。


我们发现内置的自动遮蔽功能带来了额外的好处:


  • 大部分的主模型和遮蔽模型具有一套共同的特征,实时预测服务只能从在线的特征库提取主模型中未使用的特征,从而用于遮蔽模型。

  • 通过结合内置的预测日志逻辑和遮蔽采样逻辑,实时预测服务可以将遮蔽流量减少到那些注定要被记录的流量。


如果服务受到压力,可以将遮蔽模型看作是一个二级模型,并暂停 / 恢复,以缓解负载压力。

持续集成和部署


我们依靠 CI/CD 为一个实时预测服务的集群进行服务发布部署。由于我们支持关键的业务用例,除了在模型部署期间进行验证之外,我们还需要确保对自动持续集成和部署过程的高度信任。


我们的解决方案尝试通过新版本解决下列问题:


  • 代码变化不兼容:这个问题可能有两个症状 —— 模型无法加载或用新的二进制文件进行预测,或者其行为会随着新版本的发布而改变。后一种方法难以识别和修正,对模型的正确性也至关重要。

  • 依赖关系不兼容:由于基础依赖关系的改变,服务无法启动。

  • 构建脚本不兼容:由于构建脚本的改变,版本无法构建。


针对以上问题,我们采用了三个阶段的策略来验证和部署二进制文件的最新实时预测服务:staging 集成测试、金丝雀集成测试以及产品发布。


staging 集成测试和金丝雀集成测试将运行于非生产环境。staging 集成测试用于验证基本功能,当 staging 集成测试通过后,我们将运行金丝雀集成测试来确保所有产品模型的服务性能。在确保生产模型的行为不变后,以滚动部署的方式,将该版本部署到所有实时预测服务的生产实例上。

最后的想法


我们已经分享了我们针对一些 MLOps 挑战的解决方案。随着我们发展 Uber 的机器学习基础设施和平台并支持新的机器学习用例,我们看到新的 MLOps 挑战出现。其中,有几个方面是:几乎实时地监测推理的准确性、特征质量和业务指标;部署和维护多任务学习和混合模型;进行特征验证;改进模型回归机制;模型可追溯性和可调试性等。敬请关注。


作者介绍:


Joseph Wang,Uber 机器学习平台团队软件工程师。住在旧金山。致力于特征存储、实时模型预测服务、模型质量平台和模型性能。


Jia Li,Uber 机器学习平台团队高级软件工程师。致力于模型部署、实时预测和模型监控。


Yi Zhang,Uber 机器学习平台团队高级软件工程师。在解决从数据基础设施到数据应用层的大数据问题方面表现出色。


Yunfeng Bai,Uber 机器学习平台团队的 TLM 成员。他领导团队在模型管理和实时预测方面作出了相关努力。


原文链接:


https://eng.uber.com/continuous-integration-deployment-ml/

2021-08-05 14:342684

评论

发布
暂无评论
发现更多内容

TarsBenchmark | 服务性能压测利器

TARS基金会

微服务 压力测试 TARS

案例集锦|科技赋能,华为云GaussDB助千行百业数字化转型

华为云开发者联盟

数据库 华为云 企业应用

Soul网关源码阅读番外篇(一) HTTP参数请求错误

Java 源码阅读 网关

我所认为的产品经理能力模型

day day up

热情空前,家长纷纷变身“寒假规划师”,如何抓住这波热潮?

ZEGO即构

AI 在线教育 在线课堂

阿里架构师深入讲解Android开发!教你一种更清晰的Android架构!BAT大厂面试总结

欢喜学安卓

android 程序员 面试 移动开发

怎么提升写代码的能力

阿里巴巴云原生

程序员 个人成长 方法论 云原生 自我思考

SpringCloud 从入门到精通 12---Nacos配置中心

Felix

惊喜来袭!253页全彩免费电子书《Python 编程参考》正式上线发布

穿甲兵

Python redis 程序设计 Go 语言

COCO聊天挖矿系统开发|COCO聊天挖矿软件APP开发

系统开发

2020中国ToB独角兽:估值逆势起飞,寡头效应加剧

ToB行业头条

阿里巴巴2021年最新开源十亿级Java高并发系统设计手册

Java架构追梦

Java 阿里巴巴 架构 并发 系统架构设计手册

redis持久化怎么选?成年人从来不做选择...

moon聊技术

Java 程序经验小结:返回零长度的数组或集合,而不是null

后台技术汇

28天写作

从根上理解高性能、高并发(五):深入操作系统,理解高并发中的协程

JackJiang

网络编程 高并发 协程 高性能 即时通讯

架构师 3 期 3 班 -week8- 作业

zbest

作业 week8

iOS音视频--视频合集

程序员 音视频 OpenGL ES GPUImage Metal

Kubernetes安装篇(上):基于Minikube方式部署本地环境

xcbeyond

Kubernetes 安装 minikube 28天写作 Kubernetes从入门到精通

QA为什么转换角色

BY林子

软件测试 QA 职业发展

使用Apollo升级一下yml文件管理和发布

Sky彬

springboo

是找茬?还是装B?阿里面试每轮必问的“Spring Boot”意义何在?

比伯

Java 编程 架构 面试 计算机

盘点2020 | 百度AI的2020

百度大脑

盘点2020

dubbo-go 白话文 | 从零搭建 dubbogo 和 dubbo 的简单用例

阿里巴巴云原生

Java 云原生 dubbo 中间件 dubbogo

新年Flag 中奖名单公布|如何科学的从55人中随机选出11个中奖名额

InfoQ写作社区官方

话题讨论 热门活动

SpringCloud 从入门到精通 11---Nacos负载均衡

Felix

WebRTC 的现状和未来:专访 W3C WebRTC Chair Bernard Aboba

阿里云CloudImagine

阿里云 WebRTC 视频云

安装Android系统 missing operating system

mengxn

android

《我想进大厂》之分布式事务篇

艾小仙

Java 面试 后端

阿里架构师经验分享!Android面试知识点总结宝典助你通关!顺利通过阿里Android岗面试

欢喜学安卓

android 程序员 面试 移动开发

【有奖调研】中国人工智能开发者调研

百度大脑

云原生 DevOps 的 5 步升级路径

阿里巴巴云原生

Serverless 容器 DevOps 微服务 云原生

Uber机器学习在线服务及模型的持续集成和部署实践_文化 & 方法_Uber Engineering_InfoQ精选文章