《设计深度学习系统》第十章:生产之路(全书完)

269 阅读21分钟

本章涵盖以下内容:

  • 生产化深度学习模型之前的初步工作和任务
  • 使用深度学习系统生产化深度学习模型
  • 在生产环境中进行实验的模型部署策略

对于本书的结尾章节,我们认为回到一个高层次的视角,并连接前面章节的所有内容是有意义的。我们已经详细讨论了深度学习系统中的每个服务。在本章中,我们将讨论这些服务如何共同工作,以支持我们在第一章介绍的深度学习产品开发周期。如果你还记得的话,该周期将研究和数据科学的努力贯穿到将产品生产化并提供给客户使用的阶段。

作为提醒,图10.1是从第一章借用的,展示了产品开发周期。在本章中,我们的重点将放在过程末端发生的三个阶段上:深度学习研究、原型制作和生产化。这意味着我们将忽略实验、测试、训练和探索的循环,着重研究如何将研究阶段的最终产品转化为最终产品,使其准备好发布给公众。

截屏2023-07-09 17.01.17.png

定义:生产化是生产出一个有价值且可以被用户使用的产品的过程。常见的生产可用性定义是能够处理客户请求、承受一定程度的请求负载,并能够优雅地处理诸如格式错误的输入和请求过载等不良情况。

正如我们所说,本章重点关注从研究、通过原型制作到生产化的生产周期路径。让我们从图10.1中将这三个阶段单独提取出来,以便更详细地了解它们。我们在下图10.2中标注了这些阶段,并放大了它们,以揭示每个阶段内部的步骤,以及这三个阶段之间的联系。不要被这个图表的复杂性吓到!我们将在本章中逐步解释每个阶段和每个步骤。

截屏2023-07-09 17.04.07.png

让我们简要回顾一下这个图表,因为它将预览本章的内容。图10.2中的前两个阶段是研究和原型制作。这两个阶段都需要从模型训练和实验中快速迭代和反馈。这些阶段(步骤1-8)的主要交互点是一个笔记本环境。研究人员和数据科学家使用笔记本,在步骤2和6中调用数据集管理服务来跟踪训练数据集,并在步骤4和8中使用训练服务和超参数优化库/服务进行模型训练和实验。我们在第10.1节中介绍了这些阶段,并在训练数据形状和代码相对稳定并准备好生产化时结束。换句话说,团队已经得到了基本的最终版本,并准备进行最后的步骤,将其发布给公众。

在第10.2节中,我们将从前一节继续讲述模型的生产化过程,直到模型被提供给生产推断请求流量的阶段。

定义:推断请求是用户或应用程序针对训练过的模型生成推断的输入。以视觉识别为例,推断请求可以是一张猫的图片。使用训练过的视觉识别模型,或者推断,可以生成一个标签,例如“猫”。

本节对应图10.2中的第三个和最后一个阶段。在生产化中,我们的系统中几乎每个服务都将发挥作用。数据集管理服务管理训练数据;工作流管理服务启动和跟踪训练工作流;训练服务执行和管理模型训练作业;元数据和工件存储包含并跟踪代码工件、训练模型及其元数据;模型服务为推断请求流量提供训练好的模型。

从生产化过程中,我们进入部署阶段。在第10.3节中,我们将研究一些模型部署策略,支持在生产环境中更新模型到新版本。这些策略还支持在生产环境中进行实验。这里的主要重点将放在模型服务上,因为这是为所有推断请求提供服务的地方。

通过完整地了解从研究到生产的整个过程,我们希望您能够看到我们在前面章节中讨论的基本原则如何影响使用系统交付深度学习功能的不同参与方的工作。您从本章中获得的理解应该能够帮助您根据不同情况调整自己的设计。我们将以图像识别产品的开发为例,来说明所有步骤的实际应用。

准备生产化

在本节中,我们将看一下深度学习模型从诞生前到准备生产化的过程。在图10.3中,我们突出了深度学习研究和原型制作的阶段,这些阶段来自更大的深度学习开发周期(如图10.1所示)。我们将从深度学习研究步骤开始,这是模型训练算法诞生的地方。并不是每个组织都进行深度学习研究,有些组织使用现成的训练算法,所以如果不适用于您的情况,可以跳过此步骤。

截屏2023-07-09 17.08.08.png

在深度学习研究之后,我们进行原型制作。在这个阶段,我们假设算法已经准备好用于训练模型。数据探索和实验性模型训练的快速迭代过程是这一步骤的核心部分。这一步的目标是找到适当的训练数据形状,并开发一个稳定的代码库用于模型训练。

研究

通过研究,新的深度学习算法被发明,现有算法也得到改进。由于同行评审的研究需要可复现的结果,模型训练数据需要公开获取。许多公共数据集,例如ImageNet,供研究团队使用。

对于模型训练的原型制作,研究人员通常选择交互性和灵活性较高的笔记本环境,如JupyterLab。让我们来看看研究人员在模型训练原型制作过程中可能采取的一些示例步骤:

  1. 研究人员Alice正在改进一个视觉识别算法。在研究了她的理论之后,她准备开始原型制作。

  2. Alice在JupyterLab中创建一个新的笔记本。

  3. Alice希望使用ImageNet数据集进行训练和算法基准测试。她可以:

    • 编写代码将数据集下载到她的笔记本,并将其存储在数据集管理服务(第2章)中以便重复使用。
    • 发现数据集已经存储在数据集管理服务中,并编写代码直接使用它。
  4. Alice开始对现有的视觉识别算法进行改进,直到可以在笔记本中生成实验模型。

  5. Alice尝试更改一些超参数,训练和测试几个实验模型,并比较它们生成的指标。

  6. Alice可能进一步使用超参数优化技术(第5章)自动运行更多实验,以确认她确实对现有算法进行了改进。

  7. Alice发布她的研究结果,并将她的训练代码改进打包成一个库,供他人使用。

通过使用版本控制的数据集进行训练,Alice确保了所有实验模型训练运行的输入训练数据都是相同的。她还使用源代码管理系统(如Git)来跟踪她的代码,以便可以将所有实验模型追溯到代码的某个版本。

请注意,在这个阶段,模型训练通常在托管笔记本环境的计算节点上进行,因此有必要为这些节点分配足够的资源。如果训练数据存储在网络上,确保读取速度不会成为模型训练的瓶颈。

原型制作

原型制作是将研究与实际应用案例相结合的过程。它是寻找合适的训练数据、算法、超参数和推断支持的实践,以提供符合产品要求的正确深度学习功能。

在这个阶段,由于原型制作的快速迭代性质,笔记本环境仍然是数据科学家和工程师的首选。快速反馈是预期的。让我们来看一个可能的原型制作场景:

  1. 模型开发团队接收到改进安防摄像机产品的运动检测的产品需求。

  2. 基于需求,团队发现Alice的新视觉识别训练算法可能有助于改善运动检测。

  3. 团队创建一个新的笔记本,并开始探索与模型训练相关的数据,根据他们选择的算法集合:

    • 如果已有的数据恰好适用于解决的问题,团队可以使用现有的已收集数据进行模型训练。
    • 在某些情况下,团队可能需要收集新的数据进行训练。
  4. 在大多数情况下,这个阶段会应用迁移学习,团队选择一个或多个现有模型作为源模型。

  5. 团队使用收集的数据和源模型开发建模代码,并训练实验模型。

  6. 评估实验模型以查看是否产生了满意的结果。步骤3到6将重复,直到训练数据形状和代码变得稳定。

我们将步骤3到6称为探索循环。这个循环对应于图10.3中原型制作扩大部分中的迭代循环。在开始原型制作时,这个循环会快速迭代。在这个阶段的重点是缩小训练数据形状和代码的范围。

一旦训练数据形状和代码变得稳定,它们就准备好进行进一步的调优和优化。在这个阶段的目标是收敛到一个状态,使模型训练和推断代码准备好打包并部署到生产环境中。

主要要点

我们已经走过图10.1中参考的深度学习开发周期中的研究和原型制作阶段。尽管它们有不同的目的,但我们在它们与深度学习系统的工作方式中看到了相当多的重叠之处:

  • 笔记本环境是研究和预生产原型制作的常见选择,由于其高度的交互性和可扩展性。
  • 训练数据的访问应尽可能广泛和灵活(在合法和合规的限制下),这有助于加速数据探索过程。
  • 应为模型训练分配足够的计算资源,以确保回报时间短。
  • 至少使用数据集管理服务和源代码管理系统来跟踪实验模型的来源。此外,使用元数据存储来保存指标,并将其与训练数据集和代码关联起来,以完成完整的渊源追踪。

模型生产化

在深度学习模型被集成到最终产品之前,它们需要经历生产化的过程。对于这个术语,肯定有许多不同的解释,但从根本上来说:

  • 模型需要为生产推断请求提供服务,无论是来自最终产品还是最终用户。
  • 模型服务应满足预先定义的服务级别协议,例如在50毫秒内响应或99.999%的时间可用。
  • 与模型相关的生产问题应易于排查。

在本节中,我们将看一下深度学习模型是如何从一个相对动态的环境(如笔记本)过渡到一个生产环境,在这个环境中它们将面临各种恶劣条件。图10.4显示了相对于开发周期的生产化阶段。让我们回顾一下这个阶段的步骤。

截屏2023-07-09 17.15.12.png

代码组件化

如前一节所示,在原型制作阶段,数据准备、模型训练和推断代码通常存在于同一个笔记本中。为了将它们生产化为一个深度学习系统,我们需要将它们分开作为独立的组件。图10.5展示了将这些组件分开的一种方法,即代码组件化。

截屏2023-07-09 17.18.15.png

让我们将图中的过程付诸实践。在代码中进行分割的第一个地方是模型作为输出的地方。这应该会导致以下两个代码片段:

  • 输出模型的模型训练代码
  • 接受模型和推断请求作为输入并生成推断的模型推断代码

可选地,可以按照以下方式分割模型训练代码:

  • 数据转换代码,将原始数据作为输入,并输出可供模型训练代码使用的训练数据
  • 模型训练代码,接受训练数据并训练模型作为其输出

如果您有其他模型训练代码可以从相同类型的准备数据中受益,进行这种分离是一个不错的选择。如果数据准备步骤需要按照与模型训练不同的节奏执行,分离也是一个好主意。

代码打包

一旦代码组件被清晰地分离出来,它们就可以进行打包以便部署。为了能够在训练服务(第3章),模型服务(第6章)和工作流服务(第9章)上运行它们,我们首先需要确保它们遵循这些服务设定的约定。

模型训练代码应进行修改,从训练服务设置的环境变量指示的位置获取训练数据。其他组件也应遵循类似的约定。

模型推断代码应遵循您选择的模型服务策略的约定:

  • 如果您使用直接嵌入模型的方式,请与嵌入您模型的团队合作,确保您的推断代码可以正常工作。
  • 如果您计划使用模型服务来提供模型,确保您的推断代码提供了一个可以与模型服务进行通信的接口。
  • 如果您使用模型服务器,只要模型服务器可以正确提供模型,您可能就不需要模型推断代码。

我们将这些代码组件打包为Docker容器,以便它们可以被各自的主机服务启动、访问和跟踪。关于如何进行这样的打包,可以在附录A中找到示例。如果需要特殊的数据转换,我们可以将数据转换代码集成到数据管理服务中。

代码注册

在训练代码和推断代码能够被系统使用之前,它们的包必须被注册并存储到元数据和艺术品服务中。这为训练代码和推断代码之间提供了必要的关联。让我们来看一下它们之间的关系(如图10.6所示)。

截屏2023-07-09 17.23.00.png

一旦训练和推断代码被打包为容器(图中的训练容器和推断容器),它们可以使用一个共同的标识(如图10.6中的visual_recognition)在元数据和艺术品存储中进行注册。当系统服务接收到提供相同标识名称的请求时,这有助于系统服务找到并使用正确的代码容器。我们将在接下来的几节中继续介绍图中的内容。

训练工作流设置

即使您不经常训练模型,我们推荐建立一个训练工作流。主要原因是在生产中提供相同的模型训练流程的可重复性。这对于除您之外的其他人需要训练模型,并可以使用您设置的流程非常有帮助。在某些情况下,生产环境是隔离的,并且通过在生产环境中设置的工作流程进行训练可能是在那里生成模型的唯一方法。在图10.7中,我们放大了先前图中的模型训练部分,以便您可以看到细节。

截屏2023-07-09 17.23.18.png

参考图10.7,在设置了visual_recognition的训练工作流程后,可以触发训练到训练服务中。训练服务使用该标识查找元数据和艺术品存储中要执行的训练代码容器。一旦训练出模型,它将使用相同的标识名称将模型保存到元数据和艺术品存储中。

在这个阶段,通常还会使用超参数优化技术来找到模型训练过程中的最佳超参数。如果使用了超参数优化服务,则工作流将与超参数优化服务进行通信,而不是直接与训练服务进行通信。如果您需要回顾超参数优化服务的工作原理,请参考第5章。

模型推断

一旦模型在生产环境中训练和注册成功,下一步就是确保它能够处理进入系统的推断请求,并在一定的速率和延迟内生成推断结果。我们可以通过向模型服务发送推断请求来实现这一点。当模型服务接收到请求时,它会在请求中查找名为visual_recognition的标识,并在元数据和艺术品存储中查询匹配的模型推断容器和模型文件。然后,模型服务可以使用这些艺术品一起生成推断响应。您可以在图10.8中看到这个过程,它是图10.6中模型服务部分的放大版本。

截屏2023-07-09 17.25.32.png

如果您使用模型服务器,您可能需要在其前面添加一个薄层,以便它知道从哪里获取模型文件。一些模型服务器实现支持自定义模型管理器的实现,也可以用于对元数据和艺术品存储进行查询,以加载正确的模型。

产品集成

一旦从模型服务获得适当的推断响应,就是将模型服务客户端集成到将使用这些推断的产品中的时候了。这是生产化的最后一步,在将其推出给最终客户之前,我们应该确保检查一些事项。因为我们正在改进安防摄像机产品的运动检测功能,所以我们必须将模型服务客户端集成到安防摄像机视频处理后端中,以从新改进的模型中请求推断:

  • 确保推断响应可以被使用它的产品消耗。
  • 通过以接近生产流量的速率发送推断请求进行压力测试。
  • 使用错误格式的推断请求进行推断测试,以确保它们不会破坏模型推断代码或模型服务。

这只是一个非常基本的事项清单。您的组织可能会定义更多的生产就绪准则,您需要在集成之前满足这些准则。除了可以告诉我们模型是否正确提供推断请求的系统指标外,我们还应该建立业务指标,以告诉我们模型是否有助于业务用例的实现。

模型部署策略

在前面的部分中,我们经历了从原型制作到生产的示例路径。这个过程假设模型是第一次部署,没有现有版本的模型可以替换。一旦模型在生产环境中使用,除非有维护窗口允许,否则通常需要使用模型部署策略来确保不会中断生产推断请求流量。事实上,这些模型部署策略也可以用作在生产环境中进行实验的方式,通过使用我们在前面设置的业务指标。我们将看到三种策略:金丝雀、蓝绿部署和多臂老虎机。

金丝雀部署

金丝雀部署,类似于A/B测试,意味着在保留旧模型为大部分请求提供服务的同时,将新模型部署来为一小部分生产推断请求提供服务。图10.9展示了一个示例。这要求模型服务能够支持将一小部分推断请求流量分割和路由到新模型。

截屏2023-07-09 17.28.47.png

通过这种策略,部署新模型可能产生的任何不良影响都仅限于少部分终端用户。通过将所有推断请求流量重新路由到旧模型,回滚变得相对简单。

这种方法的一个缺点是您只能了解模型在少部分终端用户中的性能。将新模型释放以服务所有推断请求流量可能会产生与仅服务少量流量时观察到的效果不同的影响。

蓝绿部署

在我们的上下文中,蓝绿部署意味着部署一个新模型,将所有推断请求流量路由到新模型,并保持旧模型在线,直到我们确信新模型的性能符合预期。在所有三种策略中,它在实施上是最简单的,因为根本不需要流量分割。服务所需做的就是在内部指向新模型,以服务所有的推断请求。蓝绿部署的示例如图10.10所示。

截屏2023-07-09 17.30.21.png

这种策略不仅简单,而且可以让您全面了解模型在为所有终端用户提供服务时的表现。回滚也很简单,只需将模型服务指向旧模型即可。

这种方法的明显缺点是,如果新模型出现问题,将影响所有终端用户。当您基于新模型开发新的产品功能时,这种策略可能是有意义的。随着您随着时间的推移不断迭代训练更好的模型,您可能希望摆脱这种策略,因为终端用户已经对稳定的体验建立了期望。

多臂老虎机部署

多臂老虎机 (MAB) 是三者中最复杂的部署策略。 MAB 是指一种持续监控多个模型性能并随着时间的推移将越来越多的推理请求流量重定向到获胜模型的技术。这使用了模型服务最复杂的实现,因为它需要服务了解模型性能,这可能会很复杂,具体取决于模型性能指标的定义方式。 MAB 部署如图 10.11 所示。

截屏2023-07-09 17.32.11.png

不过,这种策略确实有一个优势,因为它可以在设定的时间范围内最大化表现最好的模型的收益,而使用金丝雀部署,如果新模型优于旧模型,您可能只能获得最小的收益。请注意,您应该确保模型服务报告流量分配如何随时间变化。这有助于与模型的性能相关联。

总结

  • 深度学习研究团队发明并改进了用于训练模型的深度学习算法。
  • 模型开发团队利用现有算法和可用数据来训练模型,帮助解决深度学习用例。
  • 研究和原型设计都需要代码开发、数据探索和可视化的高度交互性。笔记本环境是这些团队的热门选择。
  • 数据集管理服务可在研究和原型设计过程中使用,以帮助跟踪用于训练实验模型的训练数据。 一旦训练数据和代码足够稳定,生产化的第一步就是打包模型训练代码、模型推理代码和任何源模型。
  • 深度学习系统的所有服务都可以使用这些包来训练、跟踪和服务模型。
  • 一旦模型训练工作流程启动并运行并获得满意的推理响应,就可以开始与最终用户产品集成。 如果服务推理请求不能被中断,则需要模型部署策略。
  • 提供多种模型部署策略,并且它们可以兼作生产中的实验。