《设计深度学习系统》第一章:深度学习系统简介

950 阅读44分钟

本章内容包括:

 定义深度学习系统

 产品开发周期以及深度学习系统如何支持它

 基本深度学习系统及其组成部分的概述

 构建深度学习系统和开发模型之间的区别

本章将为您提供一个深度学习系统的大局观思维模型。我们将回顾一些定义,并提供一个参考的系统架构设计以及架构的完整示例实现。我们希望这个思维模型能够帮助您理解后续章节的内容,这些章节会详细介绍每个系统组件如何融入整体框架。

在开始本章之前,我们将讨论深度学习系统之外更广阔的层面:我们称之为深度学习开发周期。这个周期概述了基于深度学习的产品上市所涉及的各种角色和阶段。模型和平台并不是独立存在的;它们会影响并受到产品管理、市场调研、生产和其他阶段的影响。我们相信,当工程师们了解这个周期以及每个团队的职责和所需时,他们能够设计出更好的系统。

在第1.2节中,我们将以一个典型系统的示例架构开始讨论深度学习系统设计,这个示例架构可以用来设计您自己的深度学习系统。本节中描述的组件将在各自的章节中进行更详细的探讨。最后,我们将强调开发模型和开发深度学习系统之间的区别。这个区别通常是一个令人困惑的问题,所以我们希望能够立即澄清这个问题。

在阅读完这个引言章节之后,您将对深度学习领域有一个扎实的理解。您也将能够开始创建自己的深度学习系统设计,并理解现有设计以及如何使用和扩展它们,这样您就不必从头开始构建一切。随着您继续阅读本书,您将看到如何将所有内容连接起来,并作为一个深度学习系统一起工作。

既然我们对术语都有了共识,那么让我们开始吧!

深度学习开发周期

正如我们所说,深度学习系统是深度学习项目开发中必不可少的基础设施,能够提高开发效率。因此,在我们深入探讨深度学习系统的结构之前,审视一下深度学习系统所支持的开发范式是很明智的。我们将这个范式称为深度学习开发周期。

或许您会想,在一本技术书中,为什么我们要强调像产品开发这样非技术性的事情呢?事实上,大多数深度学习工作的最终目标是将产品或服务推向市场。然而,许多工程师并不熟悉产品开发的其他阶段,就像许多产品开发人员不了解工程或建模一样。通过我们在构建深度学习系统方面的经验,我们了解到,在公司中说服多个角色采用一个系统,很大程度上取决于该系统是否能够真正解决他们的特定问题。我们相信,概述深度学习开发周期中的各个阶段和角色有助于明确、解决、沟通并最终解决每个人的痛点。

理解这个周期还可以解决其他一些问题。在过去的十年里,许多新的深度学习软件包被开发出来,用于解决不同的领域。其中一些处理模型训练和服务,而另一些处理模型性能跟踪和实验。每当数据科学家和工程师需要解决特定应用或用例时,他们会将这些工具组合在一起;这被称为MLOps(机器学习运营)。随着这些应用的数量增加,每次从头开始组合这些工具来开发新应用变得重复且耗时。与此同时,随着这些应用的重要性增加,对其质量的期望也在增长。这两个问题都要求以一致的方式快速可靠地开发和交付深度学习功能。这种一致的方法始于所有人都在同一个深度学习开发范式或周期下工作。

深度学习系统如何融入深度学习周期呢?一个构建良好的深度学习系统将支持产品开发周期,并使得执行这个周期变得简单、快速和可靠。理想情况下,数据科学家可以将深度学习系统作为基础设施来完成整个深度学习周期,而不需要了解底层复杂系统的所有工程细节因为每个产品和组织都是独特的,对于系统构建者来说,了解各种角色的独特需求是构建成功系统的关键。我们所说的“成功”是指能够帮助利益相关者有效合作,快速交付深度学习功能的系统。在本书中,当我们讨论深度学习系统的设计原则并研究每个组件的工作方式时,您对利益相关者需求的理解将有助于您将这些知识适应为您自己的系统设计。在讨论技术细节时,我们将指出在系统设计过程中需要注意哪些类型的利益相关者。深度学习开发周期将作为指导框架,帮助我们考虑深度学习系统每个组件的设计需求。

让我们从一个图示开始。图1.1展示了一个典型的周期是如何逐步进行机器学习(特别是深度学习)开发的。正如您所看到的,跨职能合作几乎发生在每个步骤上。接下来的两节中,我们将讨论此图中涉及的每个阶段和角色。

截屏2023-07-06 17.14.52.png

深度学习产品开发周期中的阶段

深度学习产品开发周期通常从商业机会开始,并由产品计划和管理推动。之后,周期通常经历四个阶段:数据探索、原型开发、投产(交付至生产)和应用集成。让我们逐个看看这些阶段。然后我们将一起查看所涉及的所有角色(在图1.1中用人物图标表示)。

注意:每个小节标题后面的括号中的数字对应图1.1中相同的数字。

产品启动(1)

首先,业务利益相关者(产品负责人或项目经理)分析业务并确定可能的业务机会或可用机器学习解决的问题。

数据探索(2)

当数据科学家对业务需求有明确的理解后,他们开始与数据工程师合作,收集尽可能多的数据,进行标注,并构建深度学习数据集。数据收集可以包括搜索公开可用数据和探索内部数据源。可能还需要进行数据清洗。数据标注可以外包或内部完成。

与后续阶段相比,数据探索的早期阶段是非结构化的,通常是以随意的方式进行的。它可能是一个Python脚本或shell脚本,甚至是手动复制数据。数据科学家通常使用基于Web的数据分析应用程序,例如Jupyter Notebook(开源;jupyter.org)、Amazon(jupyter.xn--org%29amazon-fh3i/)、 SageMaker Data Wrangler(aws.amazon.com/sagemaker/d…)和Databricks(www.databricks.com),来分析数据。此时并不需要构建正式的数据收集流程。 数据探索不仅重要,而且对于深度学习项目的成功至关重要。可用的相关数据越多,构建有效和高效的深度学习模型的可能性就越高。

研究和原型开发(3、4)

原型开发的目标是找到最可行的算法/方法来解决产品负责人提出的业务需求,并利用在前一阶段构建的数据集与AI研究人员一起提出和评估不同的训练算法。在这个阶段,数据科学家通常会尝试多个想法,并构建概念验证(POC)模型来评估它们。

尽管通常会考虑新发布的算法,但其中大部分不会被采用。评估算法时,不仅考虑算法的准确性,还必须考虑计算资源需求、数据量和算法实现成本。通常最实际的方法是获胜者。

请注意,在图1.1中,开发周期中有一个内部循环(循环A):产品启动>数据探索>深度学习研究>原型开发>模型>产品启动。循环的目的是通过构建一个概念验证(POC)模型,在早期阶段获取产品反馈。我们可能会多次运行这个循环,直到所有利益相关者(数据科学家、产品负责人)就用于解决业务需求的算法和数据达成一致。

我们从多次经验中得出的重要教训是,在开始昂贵的投产过程之前,必须与产品团队或客户(甚至更好)验证解决方案,即使在后期阶段重新工作也是昂贵且令人沮丧的过程。

投产(也称为MLOps)(5)

投产,也称为“交付至生产”,是使产品具备投产条件,准备供用户使用的过程。投产条件通常定义为能够提供客户请求、承受一定水平的请求负载,并能够优雅地处理异常情况,例如异常输入和请求超载。投产条件还包括后期工作,例如持续的模型指标监控和评估、反馈收集和模型重新训练。

投产是开发周期中工程密集型的部分,因为我们将把原型实验转化为严肃的生产过程。投产的一份非详尽清单可能包括:

  • 构建数据管道,重复地从不同的数据源获取数据,并保持数据集的版本和更新。
  • 构建数据预处理的数据管道,如数据增强或丰富,并与外部标注工具集成。
  • 重构和容器化原型代码,以生成具备生产质量的模型训练代码。
  • 通过版本控制和跟踪输入和输出,使训练和服务代码的结果可复现。例如,我们可以使训练代码报告训练元数据(训练日期和时间、持续时间、超参数)和模型元数据(性能指标、使用的数据和代码),以确保每次模型训练运行的全面可追溯性。
  • 建立持续集成(Jenkins、GitLab CI)和持续部署流程,自动化代码构建、验证和部署。
  • 构建连续的模型训练和评估管道,使模型训练能够自动消耗最新的数据集,并以可重复、可审计和可靠的方式生成模型。
  • 构建模型部署管道,自动发布通过质量检查的模型,以便模型服务组件可以访问它们;根据业务需求可以进行异步或实时的模型预测。模型服务组件托管模型并通过Web API提供访问。
  • 构建连续监控管道,定期评估数据集、模型和模型服务的性能,以检测数据分布的潜在特征漂移(数据分布变化)或模型性能下降(概念漂移),并向开发人员发出警报或重新训练模型。

以上是投产阶段的一些工作任务,这是开发周期中最需要工程方面的部分。将原型实验转化为严肃的生产流程。

如今,投产步骤有一个新的流行术语,即MLOps(机器学习运营),这是一个模糊的术语,其定义对于研究人员和专业人士来说是模糊的。我们将MLOps解释为在模型开发(实验)和生产环境运营之间架起桥梁,以便促进机器学习项目的投产。一个例子可能是简化将机器学习模型引入生产环境的流程,然后监控和维护它们。

MLOps是一种根植于将DevOps原则应用于软件开发的范式。它整合了机器学习、软件工程(尤其是运维)和数据工程这三个学科。请参见图1.2,从MLOps的角度来看深度学习。

截屏2023-07-06 17.22.34.png

由于本书是关于构建支持ML操作的机器学习系统,我们不会详细介绍图1.2中所示的实践方法。但是,正如您所看到的,支持在生产环境中开发机器学习模型的工程工作是巨大的。与数据科学家在之前的数据探索和模型原型开发阶段所做的工作相比,工具(软件)、工程标准和流程发生了巨大变化,变得更加复杂。

现在,回到开发周期,您可能会注意到在图1.1中有另一个内部循环(循环B),从投产(方框5)和模型到产品启动(方框1)。这是在将模型推理与AI应用程序集成之前与产品团队进行的第二次验证。

我们的第二次验证(循环B)比较了原型和生产环境中的模型和数据。我们希望确保模型的性能和可扩展性(例如,模型服务能力)与业务需求相匹配。

注意:以下两篇论文是推荐的;如果您想了解更多关于MLOps的信息,它们是很好的起点:“Operationalizing Machine Learning: An Interview Study”(arXiv:2209.09125)和“Machine Learning Operations (MLOps): Overview, Definition, and Architecture”(arXiv:2205.02302)

应用集成(6)

产品开发周期的最后一步是将模型预测集成到AI应用程序中。通常的模式是将模型托管在深度学习系统的模型服务中(将在第1.2.2节中讨论),并通过互联网发送模型预测请求来将业务应用逻辑与模型集成起来。

作为一个示例用户场景,一个聊天机器人用户通过键入或语音提问与聊天机器人用户界面进行交互。当聊天机器人应用程序接收到来自客户的输入时,它调用远程模型服务运行模型预测,然后根据模型预测结果采取行动或向客户作出响应。

除了将模型服务与应用逻辑集成之外,这个阶段还涉及评估对产品重要的指标,例如点击率和流失率。良好的ML特定指标(良好的精确度-召回率曲线)并不总能保证满足业务需求。因此,业务利益相关者通常在这个阶段进行客户访谈和产品指标评估。

开发周期中的角色

现在您已经对典型开发周期中的每个步骤有了清晰的了解,让我们来看看在这个周期中合作的关键角色。每个角色的定义、职位标题和职责可能因组织而异。因此,请确保澄清在您的组织中谁负责什么,并相应调整您的系统设计。

业务利益相关者(产品负责人)

许多组织将利益相关者角色分配给多个职位,例如产品经理、工程经理和高级开发人员。业务利益相关者定义产品的业务目标,并负责沟通和执行产品开发周期。以下是他们的职责:

  • 从深度学习研究中获取灵感,讨论将深度学习功能应用于产品,并推动驱动模型开发的产品需求
  • 拥有产品!与客户沟通,确保工程解决方案满足业务需求并提供结果
  • 协调不同角色和团队之间的跨职能合作
  • 运行项目开发执行;在整个开发周期中提供指导或反馈,以确保深度学习功能为产品的客户提供真正的价值
  • 评估产品指标(如用户流失率和功能使用情况),而不是模型指标(精确度或准确度),并推动模型开发、投产或产品集成的改进

研究人员

机器学习研究人员研究和开发新颖的神经网络架构。他们还开发提高模型准确性和训练效率的技术。这些架构和技术可在模型开发过程中使用。

注意:机器学习研究人员角色通常与谷歌、微软和Salesforce等大型技术公司相关联。在许多其他公司中,数据科学家担任相同的角色。

数据科学家

数据科学家可能会穿上研究者的帽子,但大部分时间,他们将业务问题转化为机器学习问题,并使用机器学习方法进行实现。数据科学家的动力来自产品的需求,并将研究技术应用于生产数据,而不是标准基准数据集。除了研究模型算法之外,数据科学家的职责还包括:

  • 将不同研究中的多个深度学习神经网络架构和/或技术结合起来解决问题。有时他们除了纯粹的深度学习外还会应用其他机器学习技术。
  • 探索可用数据,确定哪些数据是有用的,并决定在供训练之前如何预处理数据。
  • 原型设计不同的方法(编写实验性代码)来解决业务问题。
  • 将模型原型设计代码转换为具有工作流自动化的生产代码。
  • 遵循工程流程,使用深度学习系统将模型投入到生产中。
  • 根据模型开发的需要进行任何额外数据的迭代。
  • 在生产环境中持续监控和评估数据和模型的性能。
  • 解决与模型相关的问题,如模型退化。

数据工程师

数据工程师帮助收集数据并建立连续数据摄取和处理的数据管道,包括数据转换、增强和标注。

MLOps工程师/ML工程师

MLOps工程师在多个领域扮演多种角色,包括数据工程师、DevOps(运维)工程师、数据科学家和平台工程师。除了设置和操作机器学习基础设施(包括系统和硬件),他们还管理自动化流程,用于创建数据集、训练和部署模型。MLOps工程师还监控ML基础设施和用户活动,如训练和服务。

正如您所看到的,MLOps很难,因为它要求人们掌握跨软件开发、运维、维护和机器学习开发的一套实践方法。MLOps工程师的目标是确保机器学习模型的创建、部署、监控和维护高效可靠。

深度学习系统/平台工程师

深度学习系统工程师构建和维护机器学习基础设施的主要组成部分,即本书的主要关注点,以支持数据科学家、数据工程师、MLOps工程师和AI应用。机器学习系统的组件包括数据仓库、计算平台、工作流编排服务、模型元数据和工件存储、模型训练服务、模型服务服务等等。

应用工程师

应用工程师构建面向客户的应用程序(前端和后端),以满足给定的业务需求。应用程序逻辑将根据给定的客户请求的模型预测做出决策或采取行动。

注意:随着机器学习系统(基础设施)的发展,深度学习开发周期中涉及的角色将越来越少。最终,数据科学家将能够独立完成整个周期的工作。

深度学习周期演示

通过给出一个例子,我们可以更具体地演示深度学习开发周期中的角色和过程。假设您被指派构建一个能够自动回答关于公司产品线的问题的客户支持系统。以下步骤将指导您完成将该产品推向市场的过程:

  1. 产品要求是构建一个客户支持应用程序,提供一个菜单,让客户可以浏览以找到常见问题的答案。随着问题的增多,菜单变得越来越大,有多层导航。分析显示,许多客户在导航系统中感到困惑,并在试图找到答案时放弃导航菜单。
  2. 拥有该产品的产品经理(PM)致力于提高用户保留率和体验(快速找到答案)。在与客户进行一些研究后,PM发现大多数客户希望在没有复杂菜单系统的情况下获得答案,最好能够以自然语言提问的方式简单地获取答案。
  3. PM与机器学习研究人员联系,寻找潜在解决方案。结果发现,深度学习可能有所帮助。专家认为该技术已经成熟到可以应用于这个案例,并提出了一些基于深度学习模型的方法。
  4. PM撰写产品规格说明,指明应用程序应一次接收一个客户的问题,从问题中识别意图,并与相关答案匹配。
  5. 数据科学家收到产品要求并开始原型设计满足需求的深度学习模型。首先进行数据探索,收集可用的训练数据,并与研究人员商讨算法选择。然后数据科学家开始构建原型代码以生成实验模型。最终,他们得到一些数据集、几种训练算法和几个模型。经过仔细评估,从各种实验中选择了一个自然语言处理模型。
  6. 然后,PM组建了一个由平台工程师、MLOps工程师和数据工程师组成的团队,与数据科学家一起将在步骤5中创建的原型代码引入到生产环境中。这项工作包括构建连续的数据处理管道、连续的模型训练、部署和评估管道,以及设置模型服务功能。PM还规定了每秒预测数和所需的延迟。
  7. 一旦完成生产设置,应用程序工程师将客户支持服务的后端与模型服务(在步骤6中构建)集成,因此当用户输入问题时,该服务将根据模型预测返回答案。PM还定义了产品指标,如平均寻找答案的时间,以评估最终结果并用于推动下一轮改进。

扩展项目开发

正如您在1.1.2节中所看到的,我们需要填补七种不同的角色来完成一个深度学习项目。这些角色之间的跨职能合作几乎在每一步都发生。例如,数据工程师、平台开发人员和数据科学家共同努力将项目推向生产。任何参与过需要许多利益相关者的项目的人都知道,为了推动这样的项目,需要多少沟通和协调工作。

这些挑战使得深度学习开发难以扩展,因为我们要么没有资源来填补所有所需的角色,要么由于沟通成本和减速而无法满足产品的时间表。为了减少大量的运营工作、沟通和跨团队协调成本,公司正在投资于机器学习基础设施,并减少构建机器学习项目所需的人员数量和知识范围。深度学习基础设施堆栈的目标不仅是自动化模型构建和数据处理,还要使技术角色合并,使数据科学家能够在项目中独立完成所有这些功能。

深度学习系统的关键成功指标是观察模型生产化过程的流程是否顺畅。借助良好的基础设施,数据科学家无需突然成为专业的DevOps或数据工程师,就应能够以可扩展的方式实施模型、建立数据管道,并独立部署和监控生产中的模型。

通过使用高效的深度学习系统,数据科学家将能够以最小的附加开销完成开发周期,减少所需的沟通并减少等待他人的时间浪费,并专注于最重要的数据科学任务,如理解数据和尝试算法。实现深度学习项目开发的可扩展性是深度学习系统的真正价值主张。

深度学习系统设计概述

在考虑了第1.1节的背景之后,让我们深入研究本书的重点:深度学习系统本身。设计一个系统——任何系统——都是在一组特定约束条件下实现目标的艺术,而这对于深度学习系统也同样适用。例如,假设您有几个需要同时提供服务的深度学习模型,但是您的预算不允许您运行具有足够内存来同时存储所有模型的计算机。您可能需要设计一个缓存机制,将模型在内存和磁盘之间进行交换。然而,交换会增加推理延迟。这个解决方案是否可行将取决于延迟要求。如果您的模型大小和预算允许,另一个可能性是为每个模型运行多台较小的计算机。

或者,以另一个例子为例,想象一下您的公司的产品必须符合某些认证标准。它可能规定了数据访问策略,对于想要访问公司产品收集的数据的任何人来说,这可能会带来重大限制。您可能需要设计一个框架,以便以符合规定的方式允许数据访问,以便研究人员、数据科学家和数据工程师可以在您的深度学习系统中解决问题并开发需要这种数据访问的新模型。

正如您所见,有许多可以调整的参数。要满足尽可能多的要求,这肯定是一个迭代的过程。但为了缩短迭代过程,最好从一个尽可能接近最终状态的设计开始。

在本节中,我们首先提出了一个只包含基本组件的深度学习系统设计,然后解释了每个组件和用户工作流的责任。根据我们设计和定制深度学习系统的经验,一些关键组件在不同的设计中是共通的。我们认为它们可以作为您设计的合理起点。我们称之为参考系统架构。

您可以将此参考架构复制到您的设计项目中,仔细查看您的目标和约束条件列表,并开始确定每个组件中可以根据您的需求调整的参数。由于这不是一种权威的架构,您还应该评估是否真的需要所有组件,并根据需要添加或删除组件。

参考系统架构

图1.3展示了参考深度学习系统的高级概述。深度学习系统由两个主要部分组成。第一个部分是系统的应用程序编程接口(API;框A),位于图中间位置。第二个部分是深度学习系统的组件集合,由位于图下半部分、用虚线框线划定的大框内的所有矩形框表示。每个矩形框代表一个系统组件:

 API(框A)

 数据集管理器(框B)

 模型训练器(框C)

 模型服务(框D)

 元数据和工件存储(框E)

 工作流编排(框F)

 交互式数据科学环境(框G)

在本书中,我们假设这些系统组件是微服务。

截屏2023-07-06 17.39.36.png

定义:微服务没有单一的定义。在这里,我们将使用该术语来指代使用HTTP或gRPC协议通过网络进行通信的进程。

这个假设意味着我们可以合理地期望这些组件能够安全地支持多个具有不同角色的用户,并且可以通过网络或互联网轻松访问。(然而,本书不会涵盖有关如何设计或构建微服务的所有工程方面的内容。我们的讨论重点将放在与深度学习系统相关的具体问题上。)

注意:您可能会想知道是否需要自己设计、构建和托管所有深度学习系统的组件。事实上,有一些开源(Kubeflow)和托管(Amazon SageMaker)的替代方案可供选择。我们希望在您学习了每个组件的基本原理、它们如何融入整体架构以及不同角色如何使用它们之后,您能够为自己的用例做出最佳决策。

关键组件

现在让我们逐个介绍被视为基本深度学习系统的关键组件,如图1.3所示。根据您的要求,您可能希望添加其他组件或进一步简化它们。

应用程序编程接口(API)

我们的深度学习系统的入口点(图1.3中的方框A)是一个可以通过网络访问的API。我们选择了API,因为该系统不仅需要支持由研究人员、数据科学家、数据工程师等使用的图形用户界面,还需要支持应用程序和可能来自合作伙伴组织的其他系统,例如合作伙伴组织的数据仓库。

数据集管理器

深度学习基于数据。毫无疑问,数据管理组件是深度学习系统的核心组成部分。每个学习系统都是一个“垃圾进,垃圾出”的系统,因此确保学习的数据质量至关重要。一个良好的数据管理组件应提供解决此问题的解决方案。它使得收集、组织、描述和存储数据成为可能,从而使数据可以被探索、标记和用于模型训练。

模型训练器

模型训练器(也称为模型训练服务;方框C)提供基础计算资源,如CPU、RAM和GPU,以及作业管理逻辑,用于运行模型训练代码并生成模型文件。在图1.3中,我们可以看到工作流编排服务(方框F)告诉模型训练器执行模型训练代码。训练器从数据集管理器(方框B)获取输入的训练数据并生成一个模型。然后,它将带有训练指标和元数据的模型上传到元数据和工件存储(方框E)。

模型服务

模型可以在各种环境中使用,例如用于实时预测的在线推理或用于批量预测的离线推理,这就是模型服务的作用——当系统托管模型、接收输入的预测请求、运行模型预测并将预测结果返回给用户时。有一些关键问题需要回答:

  • 您的推理请求是来自网络还是来自需要本地提供服务的传感器?
  • 什么是可接受的延迟?推理请求是即席的还是流式的?有多少个模型正在提供服务?是每个模型单独处理某种推理请求,还是多个模型一起处理?
  • 模型的大小如何?您需要预算多少内存容量?需要支持哪些模型架构?是否需要GPU?您需要多少计算资源来生成推理结果?是否还有其他支持推理的组件,例如嵌入、归一化、聚合等?

元数据和工件存储

想象一下,您作为一个单人团队正在开发一个简单的深度学习应用程序,只需处理少量数据集并训练和部署一种类型的模型。您可能可以跟踪数据集、训练代码、模型、推理代码以及彼此之间的关系。这些关系对于模型的开发和故障排除至关重要,因为您需要能够追溯特定观察结果的原因。

现在想象一下,添加更多的应用程序、更多的人员和更多类型的模型。这些关系的数量将呈指数级增长。在一个旨在支持多种类型的用户在多个数据集、代码和模型的各个阶段工作的深度学习系统中,需要一个组件来跟踪这些关系的网络。深度学习系统中的元数据和工件存储就是做这个的。工件包括训练模型和生成推理等代码,以及任何生成的数据,例如训练模型、推理和指标。元数据是描述工件或工件之间关系的任何数据。以下是一些具体的例子:

  • 训练代码的作者和版本
  • 训练模型的输入训练数据集的引用和训练环境
  • 训练模型的训练指标,例如训练日期和时间、持续时间和训练作业的所有者
  • 模型特定的指标,例如模型版本、模型训练中使用的数据和代码的血统以及性能指标
  • 生成某个推理结果的模型、请求和推理代码
  • 工作流历史,跟踪模型训练和数据处理管道的每个步骤

这些只是基线元数据和工件存储有助于跟踪的一些例子。您应根据团队或组织的需求对组件进行定制。

工作流编排

工作流编排(图1.3中的方框F)在许多系统中都是普遍存在的,它帮助根据编程条件自动启动计算任务。在机器学习系统的上下文中,工作流编排是深度学习系统中所有自动化的驱动力。它允许人们定义工作流程或管道(有向无环图)来将各个任务以特定的执行顺序连接在一起。工作流编排组件编排这些工作流程的任务执行。一些典型的例子包括:

  • 每当构建新数据集时启动模型训练
  • 监控上游数据源,增加新数据,转换其格式,通知外部标注者,并将新数据合并到现有数据集中
  • 如果通过某些条件,则将训练好的模型部署到模型服务器上...

在第8章中,我们将深入探讨一个基线的元数据和工件存储。这个存储通常是深度学习系统用户界面的核心组件。

以上是基本深度学习系统中的关键组件。当然,根据具体需求,您可以根据自己的情况进行调整和定制。

关键用户场景

为了更好地理解深度学习系统在开发周期中的应用(图1.1),我们准备了一些示例场景,展示了它们的使用方式。让我们从图1.4中展示的编程消费者开始。将数据推送到系统的数据收集器通常会通过API最终到达数据管理服务,该服务收集和组织原始数据用于模型训练。

截屏2023-07-06 17.47.15.png

深度学习应用通常会访问模型推断服务,从训练好的模型中获取推断结果,用于提供给最终用户使用的深度学习功能。图1.5展示了这种交互的顺序。脚本,甚至完整的管理服务,也可以作为编程消费者。由于它们是可选的,为了简洁起见,我们在图中省略了它们。

截屏2023-07-06 17.49.04.png

在人类用户和API之间通常还存在一个额外的层级 - 用户界面。界面可以是基于Web或基于命令行的。一些高级用户甚至可以跳过此界面直接使用API。让我们逐个遍历每个用户角色。

图1.6展示了研究人员使用系统的典型情景。研究人员可以查找可用数据来尝试他们的新建模技术。他们访问用户界面,进入数据探索和可视化部分,该部分从数据管理服务中获取数据。可能需要进行大量的手动数据处理,将其转换为可以被新的训练技术使用的形式。一旦研究人员确定了一种技术,他们可以将其打包为库,供他人使用。

截屏2023-07-06 17.50.06.png

数据科学家和工程师可以通过首先查看可用数据来处理使用案例,类似于前面段落中研究人员最初的做法。这将由数据管理服务来支持。他们提出假设并将数据处理和训练技术组合成代码。这些步骤可以组合成一个工作流,使用工作流管理服务来进行管理。

当工作流管理服务运行工作流时,它会与数据管理服务和模型训练服务进行通信,执行实际任务并跟踪进度。每个服务和训练代码都将超参数、代码版本、模型训练指标和测试结果存储到元数据和工件存储中。

通过用户界面,数据科学家和工程师可以比较实验运行结果,并推断出训练模型的最佳方式。图1.7展示了上述情景。

截屏2023-07-06 17.51.17.png

产品经理也可以通过用户界面查看和查询整个系统中的各种指标。这些指标数据可以由元数据和工件存储提供。

根据您自己的设计进行推导

现在我们已经讨论了参考系统架构的各个方面,让我们讨论一些自定义您自己版本的准则。

收集目标和需求

设计任何成功系统的第一步是拥有一组清晰的目标和需求。这些目标和需求最好来自于系统的用户,可以直接或间接地通过产品管理团队或工程管理团队获取。这个目标和需求的简要列表将帮助您形成系统的外观愿景。而这个愿景则应该是指导您在系统的设计和开发阶段的准则。

注意有时工程师会被要求开发一个支持一个或多个现有深度学习应用的系统。在这种情况下,您可以从这些应用程序中识别出共同的需求,并思考如何设计您的系统以快速为这些应用程序带来创新。

为了收集系统的目标和需求,您需要识别出系统的不同类型的用户和利益相关者,即人物角色。这是一个通用的概念,可以应用于大多数系统设计问题。毕竟,正是用户将帮助您阐明系统的目标和需求。

我们建议如果您不确定一个好的起点,可以从使用案例或应用程序需求开始。以下是一些您可以向用户提问的示例问题:

  • 对于数据工程师和产品经理:系统是否允许应用程序收集训练数据?系统是否需要处理流式输入数据?收集了多少数据?
  • 对于数据科学家和工程师:我们如何处理和标记数据?系统是否需要为外部供应商提供标注工具?我们如何评估模型?我们如何处理测试数据集?是否需要交互式笔记本用户界面来进行数据科学工作?
  • 对于研究人员和数据科学家:训练模型需要多大量的数据?模型训练的平均时间是多久?对于研究和数据科学,需要多少计算和数据容量?系统应该支持哪些实验?需要收集什么样的元数据和指标来评估不同的实验?
  • 对于产品经理和软件工程师:模型推断是在远程服务器上还是在客户端上进行?是实时模型推断还是离线批处理预测?是否有延迟要求?
  • 对于产品经理:我们在组织中试图解决什么问题?我们的商业模式是什么?我们将如何衡量我们的实施效果?
  • 对于安全团队:系统需要多高级别的安全性?数据访问是完全开放还是严格限制/隔离的?是否有审计要求?系统是否需要遵守特定的合规性或认证(例如,通用数据保护条例、系统和组织控制2等)?

自定义参考架构

一旦设计要求和范围明确,我们就可以开始根据具体需求自定义参考架构(图1.3)。首先,我们可以决定是否需要添加或删除任何组件。例如,如果需求纯粹是管理远程服务器群中的模型训练,那么我们可以删除工作流管理组件。如果数据科学家希望有效地评估模型在生产数据上的性能,他们还可以添加实验管理组件。该组件允许数据科学家使用系统中已存在的全量数据进行训练和验证,并针对以前未见过的数据进行在线A/B测试。

第二步是根据具体需求设计和实现每个关键组件套件。根据需求,您可以排除数据流式处理API,增加分布式训练支持(如果训练速度是一个问题)。您可以从头开始构建每个关键组件,也可以使用开源软件。在本书的其余部分,我们涵盖了每个关键组件的这两种选择,以确保您知道该怎么做。

提示:保持系统设计简单和用户友好。创建如此庞大的深度学习系统的目的是提高深度学习开发的效率,请在设计时记住这一点。我们希望使数据科学家能够在不必了解底层系统内部工作原理的情况下构建高质量的模型。

在Kubernetes之上构建组件

我们介绍了一系列作为服务实现的关键组件。由于服务数量众多,您可能希望使用一种复杂的基础架构级别系统来管理它们,例如Kubernetes。

Kubernetes是一个开源系统,用于自动化部署、扩展和管理容器化应用程序,这些应用程序在隔离的运行时环境中运行,例如Docker容器。我们已经看到了一些构建在Kubernetes之上的深度学习系统。有些人学习如何使用Kubernetes,却不知道为何要用它来运行深度学习服务,因此我们希望解释背后的思想。如果您对Kubernetes已经很熟悉,请随意跳过本节。

注意,Kubernetes是一个复杂的平台,需要一本书的篇幅来教授,所以我们只讨论它在深度学习系统中的优点。如果您想学习Kubernetes,我们强烈推荐您阅读Marko Luksa的《Kubernetes in Action》(Manning, 2018)。

管理计算资源的挑战

在远程服务器上执行一个Docker容器似乎是一项简单的任务,但在30个不同的服务器上运行200个容器则是另一回事。存在许多挑战,比如监控所有远程服务器以确定在哪个服务器上运行容器,需要将容器故障转移到健康的服务器,当容器卡住时重新启动容器,跟踪每个容器运行并在其完成时收到通知等等。为了解决这些挑战,我们必须自己监控硬件、操作系统进程和网络。这不仅在技术上具有挑战性,而且工作量巨大。

Kubernetes的帮助

Kubernetes是一个开源的容器编排平台,用于调度和自动化部署、管理和扩展容器化应用程序。一旦您设置了一个Kubernetes集群,您的服务器组的运维(部署、修补、更新)和资源管理变得可管理。以下是一个部署示例:您可以告诉Kubernetes运行一个具有16 GB内存和1个GPU的Docker镜像,Kubernetes将为您分配资源来运行此Docker镜像。

这对软件开发人员来说是巨大的好处,因为并不是每个人都有丰富的硬件和部署经验。通过Kubernetes,我们只需要声明集群的最终状态,Kubernetes将根据我们的目标来执行实际工作。

除了容器部署的好处之外,Kubernetes的其他一些关键功能对于管理训练容器至关重要:

  • 自动扩展功能:Kubernetes根据工作负载自动调整集群中节点的数量。这意味着如果突然有大量用户请求,Kubernetes会自动添加容量,这被称为弹性计算管理。
  • 自愈能力:当Pod失败或节点故障时,Kubernetes会重新启动、替换或重新调度Pod。它还会终止不响应用户定义的健康检查的Pod。
  • 资源利用和隔离:Kubernetes负责计算资源的利用率,确保每个服务器得到充分利用。在内部,Kubernetes在Pod中启动应用程序容器。每个Pod都是一个带有计算资源保证的隔离环境,它运行一个功能单元。在Kubernetes中,多个Pod可以在一个节点(服务器)上,只要它们的组合资源需求(CPU、内存、磁盘)不超过节点的限制,因此可以轻松地共享服务器给不同的功能单元,并确保隔离性。
  • 命名空间:Kubernetes支持将物理集群划分为不同的虚拟集群,称为命名空间。您可以为每个命名空间定义资源配额,通过将它们分配给不同的命名空间,可以将资源隔离给不同的团队。

但与此同时,这些好处也需要付出代价-它们也会消耗资源。当您运行一个Kubernetes Pod时,Pod本身会占用一定数量的系统资源(CPU、内存)。这些资源是在运行Pod内的容器所需资源之上消耗的。在许多情况下,Kubernetes的开销似乎是合理的;例如,在Lally Singh和Ashwin Venkatesan于2021年2月发表的文章《How We Minimized the Overhead of Kubernetes in Our Job System》(mng.bz/DZBV)中的实验中,每个Pod的CPU开销约为每秒10毫秒。

注意:我们建议您查看附录B,了解现有的深度学习系统与本章介绍的概念之间的关系。在该附录中,我们将参考架构与Amazon SageMaker、Google Vertex AI、Microsoft Azure Machine Learning和Kubeflow进行比较。

构建深度学习系统与开发模型的区别

在我们开始之前,还有一项重要的准备工作:我们认为有必要强调构建深度学习系统和开发深度学习模型之间的区别。在本书中,我们将解决问题的深度学习模型开发定义为以下过程:

  • 探索可用数据及其如何转换用于训练
  • 确定用于解决问题的有效训练算法
  • 训练模型并开发推理代码以针对未见数据进行测试

请记住,深度学习系统不仅应支持模型开发所需的所有任务,还应支持其他角色执行的任务,并使这些角色之间的协作无缝进行。在构建深度学习系统时,您并不是在开发深度学习模型;而是在构建一个支持深度学习模型开发的系统,使该过程更加高效和可扩展。

我们发现已有大量关于构建模型的资料,但关于设计和构建支持这些模型的平台或系统的资料相对较少。这也是我们撰写本书的原因。

总结

以下是一些摘要:

  • 典型的机器学习项目开发经历以下循环:产品启动、数据探索、模型原型制作、生产化和生产集成。
  • 深度学习项目开发涉及七种不同角色:产品经理、研究员、数据科学家、数据工程师、MLOps工程师、机器学习系统工程师和应用程序工程师。
  • 深度学习系统应该简化深度学习开发周期中的复杂性。
  • 借助深度学习系统的帮助,数据科学家无需突然成为专业的DevOps或数据工程师,就能够以可扩展的方式实现模型、设置数据流水线,并独立地部署和监控生产中的模型。
  • 高效的深度学习系统应该使数据科学家能够专注于有趣和重要的数据科学任务。
  • 类似于图1.3中所示的高级参考架构可以帮助您快速启动新的设计。首先,制作自己的副本,然后收集目标和要求。最后,根据需要添加、修改或删除组件及其关系。
  • 基本的深度学习系统包括以下关键组件:数据集管理器、模型训练器、模型服务、元数据和艺术品存储、工作流编排和数据科学环境。
  • 数据管理组件帮助收集、组织、描述和存储数据,作为用于训练输入的数据集。它还支持数据探索活动并跟踪数据集之间的血统关系。第2章将详细讨论数据管理。
  • 模型训练组件负责处理多个训练请求,并在给定的有限计算资源集合下高效运行它们。第3章和第4章将回顾模型训练组件。
  • 模型服务组件处理传入的推理请求,使用模型生成推理结果并将其返回给请求者。它将在第6章和第7章进行介绍。
  • 元数据和艺术品存储组件记录元数据并存储来自系统的艺术品。系统产生的任何数据都可以视为艺术品。其中大部分将是模型,其具有将存储在同一组件中的元数据。这提供了完整的血统信息,以支持实验和故障排除。我们将在第8章讨论该组件。
  • 工作流管理组件存储将数据处理和模型训练中的不同步骤链接在一起的工作流定义。它负责触发周期性的工作流运行,并跟踪每个运行步骤在其他组件上的执行进度,例如,在模型训练服务上执行的模型训练步骤。在第9章中,我们将详细介绍该组件。
  • 深度学习系统应该支持深度学习开发周期,并使多个角色之间的协作变得简单。
  • 构建一个深度学习系统与开发深度学习模型不同。系统是支持深度学习模型开发的基础架构。