在数据科学项目中,模型部署可能是整个生命周期中最关键和复杂的部分。
运营或关键任务的ML需要彻底的设计。你必须考虑工件的脉络和跟踪,自动部署以避免人为错误,测试和质量检查,模型在线时的功能可用性......以及其他许多事情。
在这篇文章中,我们汇编了一个通常发生在生命周期终端阶段的常见错误清单。这些更多的是与软件架构有关,但在处理推理服务时却起着非常重要的作用*。*
错误1:手动部署你的模型
手动部署推理服务是一个很大的风险。大多数ML服务需要执行多个命令才能得到部署。让我们想象一下,我们正在部署一个FastAPI网络服务,这是在线推理的标准。这些是你为成功部署而执行的典型步骤。
- 1执行测试套件并获得代码覆盖率
- 2获取Docker注册表的凭证
- 3建立推理服务镜像
- 4调用Kubernetes从Docker注册中心获取镜像并部署服务
想象一下,手动完成这些步骤(以及你需要的所有设置)。人为错误很有可能发生--你可能忘记从模型注册中心更新模型路径,你可能忘记运行测试,你可能没有先进入预生产环境就直接部署到生产中,等等。
你可以尝试:自动持续集成与部署


模型部署--CI/CD管线I来源
持续集成工具
幸运的是,有各种工具可以用来自动完成这些步骤。Github Actions、Jenkins和Gitlab CI/CD是非常好的例子。你可以在这篇文章中阅读更多关于它们的信息。
这些工具允许你定义工作流程,根据你的服务代码库上发生的某些事件来触发。你可以在将一个分支合并到开发中时部署到集成环境中,在新功能到达主分支时部署到生产中。
持续部署工具
对于持续部署步骤,有一些工具,如ArgoCD、Jenkins-X或Flux,它们是基于GitOps的Kubernetes pods部署器(如果你不知道那是什么,Gitlab在这里提供了一篇非常全面的文章来解释它是什么)。这些工具将负责把你的改动释放到生产中。
从本质上讲,这些CI/CD管道是一组UNIX命令,可以自动完成上面定义的所有步骤,并且总是在容器化环境中执行。这保证了每一次部署都是可重复的和确定性的。
错误2:忽视了部署策略的使用
最简单的ML模型部署策略基本上是通过更新运行API的容器镜像,将旧服务换成新服务。这通常被称为 重现部署模式 这是一个非常老式的策略,很少有公司还在使用。这种部署的主要缺点是,它可能会导致服务 在特定时间内停机 (只要服务需要启动),这在某些应用中是不可接受的。除此之外,如果你没有一个更复杂的策略,你将无法利用一些强大的技术来提高可靠性、跟踪和实验。
你可以尝试的是:使用其中一种部署策略
蓝绿部署


蓝绿模式部署|来源
这种部署策略包括在生产中同时部署2个版本的服务(包括新的和旧的)。当新版本被部署时,消费者的流量通过负载均衡器逐渐被重定向到这个版本。如果新服务产生任何类型的错误,流量负载将立即被重定向到旧版本(作为一种自动回滚)。
蓝绿色部署的好处是,你会在很早的阶段发现错误,同时仍然为你的大多数消费者提供服务。它有一个嵌入式的灾难恢复功能,可以切换到以前的工作版本。在ML领域,这种技术特别有用,因为模型很容易由于各种原因产生错误。
看看Martin Fowler对蓝绿部署的解释,了解更多关于这个策略的信息。
金丝雀部署
金丝雀部署与蓝绿部署类似。主要区别在于,新旧版本之间的流量平衡不是按百分比进行的,而是逐步增加对新用户的模型释放。


金丝雀模型部署|来源
基本上,模型首先发布给特定的生产用户群,以便在早期捕捉错误和问题(你甚至可以在向公众推广之前向内部员工发布)。在确认该服务对他们来说运行良好后,该服务将逐步推广到越来越多的用户。密切监测部署情况,以捕捉潜在的问题,如错误、不希望出现的行为、高延迟、CPU或RAM的过度使用等等。这通常是一个缓慢的过程,但比其他类型的部署风险要小。如果有问题,回滚是相当容易的。
影子部署
这种部署并不像前几种那样常见,它被低估了。它有一个很大的好处,就是不必直接将模型发布到野外。
它的工作方式是将传入的请求复制到另一个包含ML模型新版本的sidecar服务。这个新模型不会对消费者产生任何影响,也就是说,响应来自唯一存在的稳定版本。


影子模型部署|来源
例如,如果你刚刚为在线交易建立了一个新的欺诈检测模型,但你有点不愿意在没有用真实数据做测试的情况下将其发布到生产中,你可以将其作为一个影子服务部署。旧的服务将仍然与不同的系统互动,但你将能够评估新的版本。如果你有一个定义明确的ML监控架构(做ML模型监控的最佳工具),你将能够通过引入一个与地面真实的反馈回路来评估模型的准确性。对于这个用例,这将意味着知道交易最终是否是欺诈性的。
这种类型的部署还需要配置负载均衡器,使其一次重复向两个版本的请求。根据用例,也可以将生产负载流量异步重放至影子版本,以避免影响负载均衡器的性能。
错误3:没有启用自动(预测)服务回滚
想象一下,你有一个生产模型,负责你的应用程序的主要服务的动态定价。一些高度依赖这种类型的模型的公司有Uber、Bolt AirBnB、Amazon、Shopify等等。
然后,假设数据科学团队创建了一个新的改进版本的ML模型。但部署失败(由于任何原因)。应用程序将不得不切换到后备价格,因为模型的API不会有反应。现在,价格不是个性化的(在最好的情况下),当然也不是动态的。
这个问题有可能导致收入大幅下降,直到服务得到解决,新模型得到部署。
你可以尝试:为你的部署启用自动回滚功能
如果你的ML模型为你的应用程序的一个非常重要的功能服务,拥有一个强大的回滚系统是至关重要的。回滚系统允许将服务切换回以前的版本,并减少应用程序表现不佳的时间。正如我们之前已经看到的,这是蓝绿部署的一个重要部分。如果新版本在渐进式发布过程中没有出现任何错误,那么它只接收100%的流量。


Kubernetes部署|来源
手动回滚触发器
回滚到以前版本的另一个方便的方法是启用**手动回滚触发器。**这对部署在生产中的ML模型特别有用。有时,ML服务不会失败,但它们可能开始返回异常的输出,由于模型编译效率低下而需要太长的时间来响应,以及更多的原因。这些类型的问题通常不会被自动检测到,它们在一段时间后被确认。通常,客户支持票开始到达,你会被告知问题。
手动回滚触发器可以通过几种方式部署。例如,Github允许设置 工作流调度事件。这些允许你从你的服务库中手动运行Github工作流程,提供一些输入。你可以设置你想回滚的提交、标签或分支。
错误4:在你的推理服务中忽略了负载测试!
ML服务往往比典型的后端服务要慢。ML模型在进行预测时并不总是很快。这真的取决于你所建立的模型的种类。例如,如果你使用Transformer模型进行文本分类,推理时间可能需要一些时间,取决于输入序列的长度。一般来说,神经网络也是高度CPU密集型的,在某些情况下,它们也会吃掉大量的RAM内存。
你可以尝试一下:考虑一下流量高峰期做压力测试并制定自动伸缩策略
由于这些潜在的性能问题,设计一个有效的硬件基础设施对于及时返回响应是至关重要的。有必要知道哪个是基于硬件使用的自动扩展系统的最佳配置策略,设置服务主机的基本内存和CPU能力,设置服务主机的初始数量,等等。
如果你部署的是网络服务,所有这些都可以在你的Kubernetes配置YAML中定义,如果你在AWS中部署的是无服务器架构,则可以在Lambda配置中定义。(GCP和Azure的无服务器功能也有类似的选项)。得出这些数字的最好方法是进行压力和负载测试。你也可以跳过这一步,在服务已经投入生产的情况下校准配置,但这样做的风险更大。


AKS集群|来源
什么是负载测试?
负载测试包括针对分期环境模拟真实世界的流量负载。也就是说,试图估计服务每秒会收到多少个请求(也包括高峰期),并从本地、外部主机或云端执行测试。有几个开源和付费的工具可以用于此,如Locust(如果你用Python工作,很容易使用)或Apache JMeter。你可以在这里找到更多的选择。
你将不得不定义请求/秒和以一定速度产生的用户数量来模拟你的服务。这些工具也允许你定义自定义负载。例如,你将能够模拟在一天的高峰时段有较高的流量,在周末有较少的负载。
负载测试结果将显示服务以何种速度返回503错误或以高延迟返回响应。你甚至可以用你自己的监控系统(Datadog、Grafana等)仔细检查这一行为。


k6概述|来源
负载测试的结果将如何帮助你优化你的架构?
这些测试结果将允许你定义在正常请求/秒的速率下,你需要有多少个pod在线,并估计你的服务需要扩展多少。然后,你将能够设置CPU和RAM的阈值来触发水平自动缩放策略。它还将为你提供一个延迟分布的感觉,并决定它是否足以满足手头的用例,或者是否有任何必要的优化需要在进入生产之前应用。
然而,模拟真实的行为总是很困难的,极端的流量高峰并不总是可以预测的。这就引出了下一个问题,拥有一个强大的、定义明确的监控系统将使团队能够及早得到任何问题的通知。你需要有警报来监测延迟、错误、日志模式的异常等。
错误5:不监控你的ML系统!
很明显,在你的生产模型上没有一个适当的监控层是一个大错误。在过去的这些年里,技术堆栈与云环境变得越来越分层,这一点更加重要。许多不同的组件相互作用,使得根本原因分析更加困难。当这些组件之一出现故障时,非常有必要确切地知道这个问题是如何发生的。
此外,在处理ML系统时,我们有一个额外的挑战。机器学习模型依赖于它们所训练的数据,但它们在生产中使用的是它们从未见过的数据。这带来了一个明显的问题,ML模型本质上是错误的, 但正如常见的统计谚语所说,"......*有些是有用的"。*因此,监测我们的模型在不同时期的错误程度是至关重要的。
你可以尝试:实现一个监控层
ML系统的监控是非常复杂的。有几个监控层次,你需要建立一个完整的可观察层。这些是硬件和服务监控,反馈环路和模型退化。
硬件和服务监控
硬件和服务监控是绝对必须实施的,包括。CPU和RAM的使用,网络吞吐量,响应延迟,完整的端到端跟踪,以及日志记录。这些将允许快速补救技术问题,以避免对用户体验产生负面影响,从而对公司的最终收入产生影响。前面提到的一些工具可以很好地解决这个问题,比如Datadog、 Grafana, 或者其他工具,比如New Relic或Dynatrace。


Datadog中的监控仪表板 |来源
还值得一提的是,Neptune可以帮助监测训练指标和硬件消耗(在文档中阅读更多内容)。如果你的模型需要定期重新训练,或者是你的生产服务的一部分(例如:训练+预测发生在同一个工作中),这就特别有用。
奈普图恩的硬件监控
反馈环路
在离线评估中使用的传统ML指标也可以在生产中进行评估,但只有在有地面真实数据的情况下。这通常被称为 反馈环路.计算这些非常依赖于地面真实数据出现的方式。
在一些用例中,你需要等待一段特定的时间,直到你得到预测的真正结果(欺诈检测),在其他一些情况下,你有一个模糊的结果(语法错误纠正),在其他一些情况下,他们甚至没有。但大多数时候,你可以得出一个用户行为的结果,作为检查模型是否支持你试图优化的业务指标的代理。


反馈回路|来源
模型降级
除了这两个(硬件、服务和反馈回路),ML模型暴露了一个新的基本的复杂情况。这就是所谓的 模型退化.这种影响不会在系统中产生错误,但意味着逐渐地,预测的质量会越来越低,如果你没有一个复杂的ML友好的监控层,那就很难发现。
模型退化主要是由以下原因造成的 数据漂移*.这* 意味着你喂给在线算法的数据相对于训练数据发生了某种变化。这通常是通过比较生产数据与训练数据的分布来进行统计测试。在 失败的声音 论文中,你可以读到关于这种影响的更多细节。


数据漂移 |来源
由于MLOps是关于自动化的,检测这种类型的问题对公司提出了巨大的工程挑战。大多数提供MLOps工具的公司已经解决了监测训练阶段的问题,但生产模型退化监测仍然是一个难以普遍解决的概念(SageMaker、Whylabs和Aporia是少数已经为普通用例提出解决方案的工具)。
将Web服务日志转移到可以批量提取和分析的数据存储中,通常是通过使用 流式管道来解决的,将记录放入流中,然后写入对象存储中。例如,你可以使用一个Kafka主题和一个Lambda函数来接收特征和预测记录,并将它们保存在S3中。后来,你可以设置一个定期的Airflow作业,在S3中提取所有这些数据,并与训练数据进行比较。如果有很大的差异,你可以向ML工程团队发送一个Slack通知。而如果退化对你的系统至关重要,你可以触发模型训练并自动部署新模型。
总结
在这篇文章中,我们介绍了ML工程师在部署他们的第一个模型时犯的一些关键错误。所有这些对于一个基于ML的生产系统的长期成功至关重要。而且,作为一个提示,要小心过度的工程设计!迭代是解决ML项目的最好方式,因为实施所有这些建议的成本和努力都很高。你的模型用例ROI需要支持它。
