深度学习模型服务:定义、挑战和设计

释放双眼,带上耳机,听听看~!
本章内容涵盖了深度学习模型服务的定义、常见挑战和方法,以及为不同用户场景设计模型服务系统的相关内容。通过阅读本章,您将对模型服务的工作原理有坚实的理解,并了解常见的设计模式,可以应对大多数模型服务用例。

本章内容包括:

  • 定义模型服务
  • 常见的模型服务挑战和方法
  • 为不同用户场景设计模型服务系统

模型服务是使用用户输入数据执行模型的过程。在深度学习系统中的所有活动中,模型服务与最终用户最为接近。在完成数据集准备、训练算法开发、超参数调整和测试结果等一系列工作后,这些模型通过模型服务服务向客户呈现出来。

以语音翻译为例。在为语音翻译训练了一个序列到序列模型之后,团队准备将其向世界展示。为了让人们能够远程使用这个模型,该模型通常托管在一个Web服务中,并通过Web API公开。然后,我们(作为客户)可以通过Web API发送我们的语音音频文件,并获得一个翻译后的语音音频文件。所有模型的加载和执行都发生在Web服务的后端。包括在这个用户工作流中的所有内容——服务、模型文件和模型执行——都被称为模型服务。

构建模型服务应用程序是另一个特殊的深度学习领域,软件工程师在这方面特别擅长。模型服务涉及请求延迟、可伸缩性、可用性和可操作性等各个方面,这些都是工程师们熟悉的领域。通过对深度学习模型服务概念的介绍,有一定分布式计算经验的开发人员可以在构建模型服务元素方面发挥重要作用。

将模型部署到生产环境中可能具有挑战性,因为模型是由各种不同的框架和算法进行训练的,因此执行模型的方法和库也各不相同。此外,模型服务领域使用的术语令人困惑,有太多的术语,例如模型预测和模型推断,在服务环境中听起来不同,但意思相同。此外,有许多可供选择的模型服务选项。一方面,我们有像TensorFlow Serving、TorchServe和NVIDIA Triton Inference Server等黑盒解决方案。另一方面,我们有定制化的方法,例如构建自己的预测器服务或直接将模型嵌入应用程序中。这些方法看起来非常相似和有能力,因此很难在它们之间进行选择。因此,如果您对这个领域还不熟悉,很容易迷失方向。

我们的目标是帮助您找到正确的方向。我们希望能够赋予您设计和构建最适合您情况的模型服务解决方案的能力。为了实现这个目标,我们有很多内容要涵盖,从对模型服务的概念理解和服务设计考虑因素,到具体的示例和模型部署工作流程。为了避免给您带来过长的章节,我们将这些内容分为两章:第6章聚焦于概念、定义和设计,第7章将这些概念付诸实践,包括构建一个示例预测服务,涉及开源工具的使用,以及模型的部署和监控。 在本章中,我们首先澄清术语并提供我们对模型服务中使用的元素的定义。我们还描述了模型服务领域面临的主要挑战。然后我们将转向设计方面,解释模型服务的三种常见策略,并设计一个适应不同用例的模型服务系统。

通过阅读本章,您不仅会对模型服务的工作原理有坚实的理解,还会了解常见的设计模式,可以应对大多数模型服务用例。掌握了概念和术语后,您应该能够轻松参与任何与模型服务相关的讨论,或阅读有关该主题的文章和论文。当然,本章为您打下了基础,以便您可以在接下来的实践工作中进行跟进。

解释模型服务

在模型服务的工程中,术语是一个主要问题。例如,模型、模型架构、推理图、预测和推理等术语被人们使用,但并没有明确定义,因此在不同的上下文中(模型服务或模型训练)它们可以具有相同的含义或指代不同的概念。当我们与数据科学家合作构建模型服务解决方案时,围绕模型服务术语的混淆会导致很多误解。在本节中,我们将解释模型服务的核心概念,并从工程的角度解释常用术语,帮助您避免陷入术语陷阱。

什么是机器学习模型?

在学术界对机器学习模型有多个定义,从对数据集学习的简化表示到用于识别特定模式或基于之前未见信息做出决策的数学表示。然而,作为模型服务开发人员,我们可以简单地将模型理解为在训练过程中生成的一组文件。

模型的概念很简单,但许多人误解模型只是静态文件。尽管模型保存为文件,但它们并不是静态的;它们本质上是可执行的程序。 让我们分解这个陈述并确定其含义。模型由机器学习算法、模型数据和模型执行器组成。模型执行器是机器学习算法的包装代码;它接收用户输入并运行算法以计算和返回预测结果。机器学习算法是指模型训练中使用的算法,有时也称为模型架构。再次以语音翻译为例,如果翻译模型是由序列到序列网络作为其训练算法进行训练的,那么模型中的机器学习算法就是相同的序列到序列网络。模型数据是运行机器学习算法所需的数据,例如神经网络的学习参数(权重和偏差)、嵌入和标签类别。图6.1展示了一个通用的模型结构。

深度学习模型服务:定义、挑战和设计

注意: 为简单起见,本章中我们经常将机器学习算法称为模型算法。

在本节中最重要的要点是,模型训练执行的输出——或者简单地说,模型——不仅仅是一组静态数据。相反,深度学习模型是可执行的程序,包括机器学习算法及其依赖的数据,因此模型可以根据输入数据在运行时进行预测。

注意: 模型不仅仅是权重和偏差。有时,数据科学家会将神经网络的训练参数(权重和偏差)保存到一个文件中,并命名为”模型文件”。这会让人们误以为模型只是包含权重和偏差的数据文件。权重和偏差是模型数据,但我们还需要算法和包装代码来运行预测。

模型预测和推断

学术界可能将模型推断和预测视为两个不同的概念。模型推断可以指了解数据生成方式、理解其原因和效应,而模型预测可能指预测未来事件。

一个样例的模型预测场景可以是使用销售记录训练模型,以预测哪些人可能会对下一个营销活动做出回应。而一个样例的模型推断场景可能包括使用销售记录训练模型,以了解产品价格和客户收入对销售效果的影响。在模型推断中,对于之前未见过的数据的预测准确性并不是非常重要,因为主要关注的是学习数据生成过程。模型训练旨在适应整个数据集。

从工程角度来看,模型预测和模型推断意味着相同的操作。尽管模型可以用于不同的目的,但在模型服务的上下文中,模型预测和模型推断指的是相同的操作:使用给定的数据点执行模型,得到一组输出值。如图6.2所示,模型服务的工作流程对于预测模型和推断模型是相同的,它们之间没有区别。

深度学习模型服务:定义、挑战和设计

为了简化本章中插图的文本,从图6.2开始,我们使用“模型”一词来代表模型数据、模型执行器和机器学习(模型)算法。这不仅是为了使文本更简洁,还强调了机器学习模型是一个可执行的程序。

什么是模型服务?

模型服务简单地意味着使用输入数据执行模型以进行预测,这包括获取预期的模型,设置模型的执行环境,使用给定的数据点执行模型以进行预测,并返回预测结果。最常用的模型服务方法是将模型托管在一个Web服务中,并通过Web API公开模型的预测函数。

假设我们构建了一个目标检测模型来检测海岸图片中的鲨鱼,我们可以建立一个Web服务来托管这个模型,并公开一个鲨鱼检测的Web API。然后,世界上任何一个海滩酒店都可以使用他们自己的海岸图片通过这个Web API来检测鲨鱼。传统上,我们将托管模型的Web服务称为预测服务。

在预测服务中,典型的模型预测工作流程包括四个步骤:接收用户请求;从存储库加载模型到内存或GPU;执行模型的算法;最后,返回预测结果。图6.3展示了这个工作流程。

深度学习模型服务:定义、挑战和设计

除了四步预测工作流程外,图6.3还提到了模型服务的三个主要组件:预测服务(A)、模型存储库(B)和预测Web API(C)。模型存储库(组件B)保存模型训练产生的所有模型。Web API(组件C)接收预测请求。预测服务(组件A)响应预测请求,从存储库加载模型,运行模型,并返回预测结果。

尽管预测工作流程的四个步骤通常适用于各种模型,但实际实现这些步骤取决于业务需求、模型训练算法和模型训练框架。我们将在第6.3节讨论预测服务的设计选项,并在第7章中介绍两个示例预测服务。

模型服务的挑战

在构建用于有效提供模型的Web服务时,与在本地计算机上运行模型相比,存在更多的复杂性。以下是在Web服务中提供模型时常见的六个挑战:

  1. 模型预测API因模型算法而异。不同的深度学习算法(如循环神经网络和卷积神经网络[CNN])需要不同的输入数据格式,它们的输出格式也可能不同。在设计Web预测API时,设计一个统一的Web API以满足每个模型算法的输入数据要求是相当具有挑战性的。
  2. 模型执行环境因训练框架而异。模型可以在不同的框架(如TensorFlow和PyTorch)中进行训练。每个训练框架都有其特殊的设置和配置来执行其模型。预测服务应该在其后端封装模型执行环境的设置,使客户可以专注于使用模型预测API,而不是与训练该模型的框架相关的事项。
  3. 有太多可供选择的模型服务工具、库和系统。如果我们决定使用现有的开源模型服务方法,那么立即面临的问题就是应该选择哪种方法。有20多种不同的选项,例如TorchServe、TensorFlow Serving、NVIDIA Triton Inference Server、Seldon Core和KFServing。我们如何知道哪种方法最适合我们的情况?
  4. 没有通用的、最经济的模型服务设计;我们需要根据自己的用例定制适合自己的模型服务方法。与模型训练和超参数调优服务不同,它们都采用一种适用于所有情况的方法,模型预测服务的设计在很大程度上取决于具体的用户场景。例如,设计一个仅支持一个模型(如花卉识别模型)的预测服务与设计一个支持10种不同类型模型(如PDF扫描、文本意图分类和图像分类)的预测服务是完全不同的。
  5. 在保持资源饱和度的同时降低模型预测延迟。从成本效益的角度来看,我们希望计算资源完全饱和用于模型预测工作负载。此外,我们希望为客户提供实时的模型预测体验,因此我们不希望预测延迟因为刚性的基础设施预算而下降。为了实现这一目标,我们需要在预测工作流的每个步骤中创新地减少时间成本,例如更快地加载模型或在提供服务之前预热模型。
  6. 模型部署和部署后模型监控是我们在一开始就应考虑的事情。模型部署——从训练到生产的进程对于成功的模型开发至关重要。我们希望迅速将模型推向生产,并且希望在生产中拥有多个版本的模型,以便快速评估不同的训练算法并选择最佳模型。部署后的模型监控可以帮助检测模型性能回归;对于欺诈检测和贷款审批等领域的模型来说,这是一种关键的保护机制。 好消息是,这些六个挑战都是工程问题,所以您一定能够应对!我们将在本章和下一章中讨论如何应对这些挑战。

模型服务术语

随着我们继续阅读本章,我们想要回顾一下模型服务的术语。许多术语在学术界有不同的定义,但在实践中,当涉及到模型服务时,它们可以互换使用。以下的定义应该可以帮助您和您的同事避免混淆。

  • 模型服务(Model serving)、模型评分(Model scoring)、模型推断(Model inference)和模型预测(Model prediction)在深度学习环境中是可以互换使用的术语。它们都指的是使用给定的数据点执行模型。在本书中,我们使用模型服务(Model serving)。

  • 预测服务(Prediction service)、评分服务(Scoring service)、推断服务(Inference service)和模型服务服务(Model serving service)是可以互换使用的术语;它们指的是允许远程模型执行的Web服务。在本书中,我们使用预测服务(Prediction service)。

  • 预测(Predict)和推断(Inference)在模型服务的上下文中是可以互换使用的;它们是与运行模型算法相关的入口函数。在本书中,我们使用预测(Predict)。

  • 预测请求(Prediction request)、评分请求(Scoring request)和推断请求(Inference request)是可以互换使用的;它们指的是执行模型进行预测的Web API请求。在本书中,我们使用预测请求(Prediction request)。

  • 机器学习算法(Machine learning algorithm)、训练算法(Training algorithm)和模型算法(Model algorithm)是可以互换使用的,正如我们在6.1.3节中所述;它们指的是在模型训练和模型推断中运行的算法是相同的机器学习算法(相同的神经网络),只是处于不同的执行模式下。

  • 模型部署(Model deployment)和模型发布(Model release)是可以互换使用的;它们表示将训练好的模型(文件)部署/复制到业务运行的生产环境中的过程,以便客户可以从这个新模型中获益。通常情况下,这指的是将模型文件加载到预测服务中。

常见的模型服务策略

在我们详细讨论模型服务使用案例和预测服务设计之前,请让我们先了解三种常见的模型服务策略:直接模型嵌入、模型服务和模型服务器。无论你的具体用例需要做什么,通常你可以采用以下三种方法之一来构建你的预测服务。

直接模型嵌入

直接模型嵌入指的是在用户应用程序的进程中加载模型并运行模型预测。例如,一个花卉识别移动应用程序可以直接在本地进程中加载图像分类模型,并从给定的照片中预测植物身份。整个模型加载和服务过程都在应用程序本地(手机上)进行,而无需与其他进程或远程服务器通信。

大多数用户应用程序(如移动应用程序)都是用强类型语言编写的,如Go、Java和C#,但大多数深度学习建模代码是用Python编写的。因此,将模型代码嵌入应用程序代码是困难的,即使这样做,过程也可能需要一些时间。为了方便在非Python进程中进行模型预测,PyTorch和TensorFlow等深度学习框架提供了C++库。此外,TensorFlow还提供了Java(github.com/tensorflow/…)和JavaScript(github.com/tensorflow/…)库,可以直接从Java或JavaScript应用程序中加载和执行TensorFlow模型。

直接嵌入的另一个缺点是资源消耗。如果模型在客户端设备上运行,性能较低的设备用户可能无法获得良好的体验。运行大型深度学习模型需要大量计算,这可能导致应用程序运行缓慢。

最后,直接嵌入涉及将模型服务代码与应用程序业务逻辑混合,这对于向后兼容性构成了挑战。因此,由于很少使用,我们只简要介绍了该方法。

模型服务

模型服务是指在服务器端运行模型服务。针对每个模型、每个模型的每个版本或每种类型的模型,我们都为其构建了一个专用的 Web 服务。这个 Web 服务通过 HTTP 或 gRPC 接口公开了模型预测 API。

模型服务管理模型服务的完整生命周期,包括从模型存储库获取模型文件、加载模型、针对客户请求执行模型算法,并卸载模型以回收服务器资源。以文档分类为例,自动根据内容对图像和 PDF 中的文档进行排序,我们可以训练一个用于光学字符识别(OCR)的 CNN 模型,从文档图像或 PDF 中提取文本。为了以模型服务方式提供此模型,我们为该 CNN 模型构建一个专用的 Web 服务,并且该 Web API 仅设计用于该 CNN 模型的预测功能。有时,我们为每个主要模型版本更新构建一个专用的 Web 服务。

模型服务的常见模式是将模型执行逻辑构建为一个 Docker 镜像,并使用 gRPC 或 HTTP 接口公开模型的预测函数。对于服务设置,我们可以托管多个服务实例,并使用负载均衡器将客户的预测请求分配到这些实例上。

模型服务方法的最大优点是简单性。我们可以轻松将模型的训练容器转换为模型服务容器,因为本质上,模型预测执行涉及运行训练好的模型神经网络。通过添加 HTTP 或 gRPC 接口,并将神经网络设置为评估模式,模型训练代码可以快速转变为一个预测 Web 服务。我们将在第6.3.1节和6.3.2节中看到模型服务的设计和使用案例,并在第7章中提供一个具体的代码示例。

由于模型服务针对模型算法具体化,我们需要为不同的模型类型或版本构建单独的服务。如果您有多个不同的模型需要提供服务,采用每个模型一个服务的方式可能会产生许多服务,并且对这些服务的维护工作(如修补、部署和监控)可能会很繁重。如果您面临这种情况,模型服务器方法就是正确的选择。

模型服务器 (Model server)

模型服务器 (Model server) 方法旨在以黑盒的方式处理多种类型的模型。无论模型算法和模型版本如何,模型服务器都可以通过统一的网络预测 API 操作这些模型。模型服务器是下一阶段的发展,我们不再需要对新类型的模型或新版本的模型进行代码更改或部署新服务。这样可以节省模型服务方法中的重复开发和维护工作。

然而,模型服务器方法比模型服务方法更加复杂,实施和管理起来更具挑战性。在一个服务和一个统一的 API 中处理多种类型的模型是复杂的。模型算法和模型数据是不同的,它们的预测函数也不同。例如,图像分类模型可以使用卷积神经网络 (CNN) 进行训练,而文本分类模型可以使用长短期记忆 (LSTM) 网络进行训练。它们的输入数据不同(文本 vs. 图像),算法也不同(CNN vs. LSTM)。它们的模型数据也各不相同;文本分类模型需要嵌入文件来编码输入文本,而 CNN 模型不需要嵌入文件。这些差异给寻找一种低维护、低成本和统一的服务方法带来了许多挑战。

虽然构建模型服务器方法很困难,但确实是可行的。许多开源的模型服务器库和服务(例如 TensorFlow Serving、TorchServe 和 NVIDIA Triton Inference Server)提供模型服务器解决方案。我们只需要构建定制化的集成逻辑,将这些工具整合到我们现有的系统中,以解决业务需求,例如将 TorchServe 集成到我们的模型存储、监控和警报系统中。

从模型部署的角度来看,模型服务器是一种黑盒方法。只要我们按照模型服务器的标准保存模型文件,在通过其管理 API 将模型上传到模型服务器时,模型预测就应该正常工作。模型服务的实施和维护的复杂性可以大大降低。在第 6.3.3 节中,我们将看到一个模型服务器的设计和应用案例,而在第 7 章中,我们将介绍使用 TorchServe 的代码示例。

注意:我们是否总是应该考虑使用模型服务器方法?并非总是如此。如果我们不考虑服务开发成本和维护成本,模型服务器方法是最强大的,因为它设计用于涵盖所有类型的模型。但是,如果我们关心模型服务的成本效益(我们应该关心!),那么最佳方法取决于具体的用例。在下一节中,我们将讨论常见的模型服务用例和相应的设计。

设计一个预测服务

在软件系统设计中,一个常见的错误是追求构建一个无所不能的系统,而忽视了具体的用户场景。过度设计会使我们的注意力从即时的客户需求转移到可能在未来有用的特性上。结果,系统要么花费不必要的时间来构建,要么很难使用。这在模型服务领域尤其如此。

深度学习是一项昂贵的业务,无论是在人力资源还是计算资源方面。我们应该只构建必要的功能,尽快将模型投入生产,并尽量减少运营成本。为了做到这一点,我们需要从用户场景开始。

在本节中,我们将介绍三个典型的模型服务场景,从简单到复杂。对于每个用例,我们解释场景并说明一个合适的高级设计。通过按顺序阅读以下三个小节,您将了解当用例变得越来越复杂时,预测服务设计是如何发展的。

注意,预测服务设计的目标不是构建一个适用于各种模型的强大系统,而是以成本效益的方式构建一个适合具体情况的系统。

单模型应用

想象一下构建一个可以在两张图片之间交换人脸的移动应用程序。用户期望应用程序的用户界面能够上传照片、选择源图片和目标图片,并执行深度伪造模型(arxiv.org/abs/1909.11…)来交换所选图片之间的人脸。对于这种只需要使用一个模型的应用程序,服务方法可以选择模型服务(6.2.2)或直接模型嵌入(6.2.1)。

模型服务方法

根据6.2.2节的讨论,模型服务方法涉及为每个模型构建一个网络服务。因此,我们可以通过以下三个组件构建人脸交换模型应用程序:一个运行在手机上的前端用户界面应用程序(组件A);一个处理用户操作的后台应用程序(组件B);一个后端服务或预测器(组件C),用于托管深度伪造模型并通过网络API执行每个人脸交换请求。

当用户在移动应用程序上上传源图片和目标图片,并点击人脸交换按钮时,移动应用程序的后台应用程序将接收到请求,并调用预测器的网络API进行人脸交换。然后,预测器对用户请求数据(图片)进行预处理,执行模型算法,并对模型输出(图片)进行后处理,然后将结果传递给应用程序的后台应用程序。最终,移动应用程序将显示源图片和目标图片中交换了人脸的结果。图6.4展示了适用于人脸交换的通用设计示意图。

深度学习模型服务:定义、挑战和设计

如果我们放大预测器(组件C),我们可以看到模型服务逻辑与我们在图6.3中介绍的一般模型预测工作流程相同。预测器(模型服务服务)从模型仓库中加载模型文件,并运行模型以响应通过Web接口接收到的请求。

在图6.4中的设计通常适用于具有Web后端且只有一个模型的任何应用程序。这个设计中的关键组件是预测器;它是一个Web服务,通常作为一个Docker容器运行。我们可以快速实现这种方法,因为预测器容器可以很容易地从构建模型的训练容器转换而来。将训练容器转换为预测器容器的两个主要工作是Web预测API和训练神经网络中的评估模式。我们将在第7.1节中介绍一个具体的预测器容器示例。

直接模型嵌入方法

另一种构建单个模型应用程序的设计方法是将模型执行代码与应用程序的用户逻辑代码结合在一起。没有服务器后端,一切都在用户的计算机或手机上本地进行。以人脸交换应用为例,深度伪造模型文件位于应用程序的部署包中,当应用程序启动时,模型被加载到应用程序的进程空间中。图6.5说明了这个概念。

深度学习模型服务:定义、挑战和设计

模型服务不一定需要在单独的服务中运行。在图6.5中,我们可以看到模型服务代码(单个模型框)和数据转换代码可以与用户逻辑代码在同一个应用程序中运行。如今,许多深度学习框架提供了在非Python应用程序中运行模型的库。例如,TensorFlow提供了Java、C++和JavaScript的SDK来加载和执行模型。借助SDK的帮助,我们可以直接在Java/C++/JavaScript应用程序中训练和执行模型。

注意为什么要考虑直接模型嵌入?通过使用模型嵌入,我们可以直接将模型服务逻辑与应用程序逻辑集成,并在同一个进程空间中同时运行它们。与图6.4中的预测器服务方法相比,这提供了两个优势。首先,它减少了一个网络跳跃;没有向预测器发出Web请求,模型执行在本地进行。其次,它提高了服务的调试能力,因为我们可以在本地将应用程序作为一个整体运行。

为什么模型服务方法更受欢迎?

尽管直接模型嵌入方法看起来简单并减少了一个网络跳跃,但它仍然不是构建模型服务的常见选择。以下是四个原因:

  • 模型算法必须在不同的语言中重新实现。模型的算法和执行代码通常是用Python编写的。如果我们选择模型服务方法,将模型服务实现为一个Web服务(图6.4中的预测器),我们可以重用大部分训练代码,并快速构建。但是,如果我们选择将模型服务嵌入到非Python应用程序中,就必须在应用程序的语言中(如Java或C++)重新实现模型加载、模型执行和数据处理逻辑。这项工作并不简单,而且很少有开发人员具备重写训练算法的深度知识。
  • 所有权边界不清晰。当将模型嵌入到应用程序中时,业务逻辑代码可能与服务代码混合在一起。当代码库变得复杂时,很难在服务代码(由数据科学家拥有)和其他应用程序代码(由开发人员拥有)之间划定界限。当数据科学家和开发人员来自两个不同的团队,但在同一个代码仓库上工作时,交叉团队的代码审查和部署时间会比通常更长,因此交付速度会显著降低。
  • 客户设备可能出现性能问题。通常,应用程序在客户的移动设备、平板电脑或低端笔记本上运行。在这些设备上,从原始用户数据中捕获特征,然后预处理模型输入数据并运行模型预测可能会导致性能问题,如CPU使用率波动、应用程序变慢和高内存使用。
  • 内存泄漏可能很容易发生。例如,在Java中执行TensorFlow模型时,算法执行和输入/输出参数对象都是在本地空间中创建的。这些对象不会被Java的垃圾收集(Garbage Collection)自动回收,我们必须手动释放它们。很容易忽视回收模型所占用的本地资源,因为本地对象的内存分配不会在Java堆中进行跟踪,所以很难观察和测量其内存使用情况。因此,内存泄漏可能会发生,并且很难修复。

注意, Jemalloc(github.com/jemalloc/je…)是一种非常实用的工具,用于解决本地内存泄漏问题。您可以查看我的博文“修复Java应用程序中的内存问题”(mng.bz/lJ8o)了解更多细节…

多租户应用程序

我们将以聊天机器人应用程序作为示例,解释多租户使用案例。首先,让我们设定背景。租户是使用聊天机器人应用程序与其客户进行沟通的公司或组织(例如学校或零售店)。租户使用相同的软件/服务-聊天机器人应用程序,但具有各自隔离的帐户和数据。聊天用户是租户的客户,使用聊天机器人与租户进行业务交流。

按设计,聊天机器人应用程序依赖于意图分类模型,以从用户的对话中识别用户的意图,然后将用户的请求重定向到正确的租户服务部门。目前,该聊天机器人采用单一模型应用程序的方法,意味着对于每个用户和租户,都使用相同的意图分类模型。

现在,由于来自租户的客户反馈称单一意图分类模型的预测准确性较低,我们决定让租户使用我们的训练算法,使用他们自己的数据集构建自己的模型。这样,模型可以更好地适应每个租户的业务情况。对于模型服务,我们将允许租户使用自己的模型进行意图分类预测请求。当聊天机器人用户现在与聊天机器人应用程序交互时,应用程序将找到租户特定的模型来回答用户的问题。聊天机器人变为多租户应用程序。

在这个聊天机器人多租户使用案例中,尽管模型属于不同的租户并且使用不同的数据集进行训练,它们是相同类型的模型。因为这些模型是使用相同的算法进行训练的,它们的模型算法和预测函数都是相同的。我们可以扩展图6.4中的模型服务设计以支持多租户,通过添加一个模型缓存来实现。通过在内存中缓存模型图和其依赖的数据,我们可以在一个服务中执行多租户模型服务。图6.6说明了这个概念。

与图6.4中的模型服务设计相比,图6.6中的设计增加了一个模型缓存(组件A)和一个模型文件服务器(组件B)。因为我们希望在一个服务中支持多个模型,所以我们需要一个内存中的模型缓存来托管和执行不同的模型。模型文件服务器存储可以加载到预测服务的模型缓存中的模型文件。模型服务器也可以在预测服务实例之间共享。

要构建一个良好的模型缓存,我们需要考虑模型缓存管理和内存资源管理。对于模型缓存,我们需要为每个模型分配一个唯一的模型ID作为缓存键来识别缓存中的每个模型。例如,我们可以使用模型训练运行ID作为模型ID;这样做的好处是,对于缓存中的每个模型,我们可以追踪生成它的训练运行。另一种更灵活的构建模型ID的方式是将模型名称(自定义字符串)和模型版本结合起来。无论我们选择哪种模型ID样式,该ID必须是唯一的,并且必须在预测请求中提供。

深度学习模型服务:定义、挑战和设计

对于内存资源管理,由于每个服务器的内存和GPU资源有限,我们无法将所有所需的模型都加载到内存中。因此,我们需要构建模型切换逻辑来管理模型缓存。当资源容量达到限制时,例如,进程即将耗尽内存时,需要从模型缓存中淘汰一些模型,以释放一些资源用于新的模型预测请求。像LRU(最近最少使用)算法和模型分区到不同实例等方法可以帮助降低缓存未命中率(请求的模型不在缓存中),并使模型切换的影响减少。我们在第7.1节中构建的示例意图分类预测服务演示了模型缓存的概念,您可以在那里探索详细信息。

我们不建议将模型缓存设计扩展到多个模型类型。不同模型类型的输入/输出数据格式和数据处理逻辑(例如图像分类模型和意图分类模型)非常不同,因此很难在同一个模型缓存中托管和执行不同类型的模型。要做到这一点,我们需要为每种模型类型构建单独的网络接口以及单独的数据预处理和后处理代码。在这种情况下,您会发现为每种模型类型构建单独的预测服务更加容易,每个服务都有自己的网络接口和数据处理逻辑,并管理自己模型类型的模型缓存。例如,我们可以分别为这两种不同的模型类型构建图像分类预测服务和意图分类预测服务。

这种每种模型类型一个服务的方法在您只有少数几种模型类型时效果良好。但是,如果您有20多种模型类型,那么它无法扩展。构建和维护Web服务(例如设置CI/CD流水线、网络和部署)是昂贵的工作。此外,监控服务的工作也不容易;我们需要构建监控和报警机制,以确保服务运行24/7。如果按照这种设计为整个公司支持100+模型类型,考虑到入职和维护工作的成本。要在一个系统中扩展和提供大量不同的模型类型,我们需要采用模型服务器方法(第6.2.3节),我们将在下一节中进一步讨论。

在一个系统中支持多个应用程序

您已成功构建了多个模型服务服务来支持不同的应用程序,例如多租户聊天机器人、人脸交换、花卉识别和PDF文档扫描。现在,您还有两个任务:(1) 为使用语音识别模型的新应用程序构建模型服务支持,以及 (2) 减少所有应用程序的模型服务成本。 到目前为止,所有的模型服务实现都是使用模型服务方法构建的。根据前面在6.3.1和6.3.2节中的讨论,我们知道这种方法在拥有越来越多的模型类型时无法扩展。

当许多产品和应用程序都有模型服务的需求时,最好是构建一个集中的预测服务来满足所有的服务需求。我们将这种类型的预测服务称为预测平台。它采用了模型服务器方法 (第6.2.3节) 并在一个地方处理所有类型的模型服务。这是多个应用程序情况下最具成本效益的方法,因为模型的接入和维护成本仅限于一个系统,远低于每个应用程序一个预测服务的方法 (第6.2.2节)。

为了构建这样一个全能的模型服务系统,我们需要考虑许多要素,例如模型文件格式、模型库、模型训练框架、模型缓存、模型版本管理、模型流程执行、模型数据处理、模型管理以及适用于所有模型类型的统一预测 API。图6.7展示了预测平台的设计和工作流程。 图6.7中的预测平台设计比图6.6中的模型服务方法要复杂得多。这是因为我们需要结合多个组件和服务来支持任意的模型。让我们看看系统的每个组件,然后再看模型预测的工作流程。

统一的web API

为了支持任意模型,我们希望公共预测 API 是通用的。无论调用哪个模型,API 的规范,例如预测请求和响应的有效负载模式,应该足够通用,以满足模型算法的要求。其中一个这种统一 API 的示例是 KFServing 预测协议 (mng.bz/BlB2),它旨在标准化适用于任何模型和各种预测后端的预测协议。

深度学习模型服务:定义、挑战和设计

预测的 Web API 也应该简单,以便减少客户的接入和维护工作。预测 API 可以分为三个类别:模型预测请求 API、模型元数据获取 API 和模型部署 API。模型元数据获取 API 和部署 API 非常有用,因为它们与所服务的模型无关。我们需要这些方法来检查模型的元数据,例如模型版本和算法信息,并检查模型的部署状态。

资源组件

通常,每种类型的服务后端只能处理少数类型的模型。为了支持任意模型,我们需要有不同类型的服务后端,例如 TensorFlow 模型的 TensorFlow Serving 后端和 PyTorch 模型的 TorchServe 后端。当接收到模型预测请求时,系统需要知道哪个后端能够处理它。这就是路由组件的作用。

路由组件负责将预测请求路由到正确的后端推理服务器。对于给定的请求,路由组件首先获取模型的元数据;元数据包括模型算法名称和版本、模型版本以及训练框架。然后,通过将模型元数据与路由配置进行匹配,确定应该将预测请求路由到哪个推理后端。

图执行组件

图执行组件处理需要执行一系列模型预测的类型。例如,为了自动化抵押贷款批准流程,我们需要按照以下三个模型的顺序运行贷款批准预测请求:PDF扫描模型用于解析PDF贷款申请中的文本,命名实体识别模型用于识别关键词,贷款评分模型用于对贷款申请进行评分。为了支持这样的要求,我们可以定义一个有向无环图(DAG)来描述模型执行链,并构建一个图执行引擎以一次性执行。

推理服务器

推理(模型)服务器负责管理模型缓存和执行模型预测,从而进行实际的计算工作。它类似于图6.6中所示的预测服务,但更为复杂,因为它需要支持任意的模型算法。除了预测API,推理服务器还应该提供模型管理API,以便可以编程方式注册新模型和移除模型。

构建一个推理服务器比构建一个预测服务要复杂得多,因此很少有工程师愿意尝试。但幸运的是,有许多现成的黑盒开源解决方案可供使用,例如TensorFlow Serving、TorchServe和NVIDIA Triton Inference Server。在实践中,我们经常重用这些现有的开源推理服务器,并将它们集成到我们自己的路由组件和图执行组件中。在第7章中,我们将更详细地讨论这些开源模型服务器工具。

应用程序

在图6.7中,我们可以看到应用程序A、B和C共享同一模型服务后端。不同应用程序的模型服务发生在同一位置。与图6.6中的模型服务设计相比,预测平台更具可扩展性和成本效益,因为添加新的应用程序D几乎没有任何入门成本。

例如,如果我们要添加新的应用程序D-一个语音转文本脚本应用程序,我们只需要将语音脚本模型上传到模型文件服务器,然后让应用程序使用预测平台的统一预测Web API。对于支持新应用程序,预测平台方面无需进行任何代码更改。

模型预测工作流程

在解释了每个关键组件之后,让我们来看一个典型的模型预测工作流程(图6.7)。首先,我们将模型文件发布到模型文件服务器,并更新路由组件中的配置,以便路由组件知道将该类型的预测请求路由到哪个推理服务器。其次,应用程序通过预测系统的Web API发送预测请求,然后由路由组件将请求路由到正确的推理服务器。第三,推理服务器将从模型文件服务器加载模型,将请求数据转换为模型输入,运行模型算法,并使用后处理返回预测结果。

注意: 预测平台的设计并不总是最佳的模型服务方法!理论上,图6.7中的设计可以适用于任何模型,但它确实带来了一些额外的成本。它的设置、维护和调试要比模型服务方法复杂得多。这种设计对于6.3.1和6.3.2节介绍的场景来说过于复杂。由于每种设计都有其优点,我们建议根据实际用户场景选择模型服务方法,而不是坚持一个服务方法。

常见的预测服务需求

尽管我们强调设计预测服务应该从具体的使用情况出发,但不同的情况会导致不同的设计。在所有模型服务设计中存在三个共同的需求:

  1. 模型部署的安全性:无论我们选择什么样的模型发布策略和版本策略,我们必须有一种方法可以将模型回滚到先前的状态或版本。
  2. 延迟:网络请求的延迟是许多在线业务成功的关键因素。一旦我们构建了模型服务支持,下一步就是尽力减少平均预测响应时间。
  3. 监控和报警:模型服务是深度学习系统中最关键的服务;如果它停止工作,业务也会停止。请记住,实际的业务是实时运行在模型预测之上的。如果服务停止或服务延迟增加,客户会立即受到影响。预测服务应该是其他深度学习服务中监控和报警方面最完备的服务。

在本章中,我们回顾了模型服务的概念、定义和抽象的高级系统设计。希望您对模型服务有一个清晰的了解,并知道在设计模型服务系统时应考虑哪些因素。在下一章中,我们将演示两个示例预测服务,并讨论常用的预测开源工具。这些示例将展示本章中的设计概念如何应用于实际生活中。

总结

  • 一个模型可以由多个文件组成;它由三个元素构成:机器学习算法、模型执行器(包装器)和模型数据。

  • 在模型服务的上下文中,模型预测和模型推断具有相同的意义。

  • 直接嵌入模型、模型服务和模型服务器是三种常见的模型服务策略类型。

  • 模型服务方法涉及为每个模型、每个模型版本或每个模型类型构建一个预测服务。

  • 模型服务器方法包括构建仅一个预测服务,但可以运行使用不同算法和框架训练的模型,并可以运行每个模型的不同版本。

  • 在设计模型服务系统时,首先要了解的组件是使用案例,以便确定最合适的服务方法。成本效益是设计模型服务系统的主要目标;成本包括服务部署、维护、监控、基础设施和服务开发等方面。

  • 对于单一模型应用程序,我们推荐采用模型服务方法。

  • 对于多租户应用程序,我们推荐采用具有内存模型缓存的模型服务方法。

  • 对于支持具有不同模型类型的多个应用程序,模型服务器和预测平台是最合适的方法。它们包括统一的预测 API、路由组件、图执行组件和多个模型服务器后端。

本网站的内容主要来自互联网上的各种资源,仅供参考和信息分享之用,不代表本网站拥有相关版权或知识产权。如您认为内容侵犯您的权益,请联系我们,我们将尽快采取行动,包括删除或更正。
AI教程

ChatGPT注册攻略及使用体验

2023-12-18 10:59:14

AI教程

柔性Actor-Critic算法原理及应用

2023-12-18 11:09:14

个人中心
购物车
优惠劵
今日签到
有新私信 私信列表
搜索