深度学习系统设计(三)(3)https://developer.aliyun.com/article/1517033
附录 A:一个“你好世界”深度学习系统
本书是关于教授构建适合自己情况的深度学习系统的设计原则。但你可能会想知道一个深度学习系统看起来是什么样子。或者人们在实践中如何、为什么以及何时使用这样一个系统。这些都是现阶段很好的问题。
我们相信学习新思想、技能和方法的最佳方法是通过实践——通过获取一些示例并看看你能做些什么。为了帮助你,我们建立了一个迷你深度学习系统和一个代码实验室供你使用。在这个“你好世界”深度学习系统中玩耍应该有助于你建立理解本书介绍的概念和原则的知识库。为了使这个示例系统易于理解,我们侧重于深度学习系统的关键组件,如数据集管理(DM)和模型训练与服务。整个迷你系统可以通过一个 bash 脚本轻松设置在你的本地系统上,并且它的组件在后面的章节中会详细讨论。
在这个附录中,我们将首先参观我们的示例系统,然后进行实验室练习,让你体验深度学习系统中最常见的用户活动,包括数据集摄入、模型训练和模型服务。虽然我们的示例系统非常简化,但它涵盖了深度学习系统的所有基础知识。通过阅读这个附录,你不仅会获得一个关于基本深度学习系统是如何组织和运作的实践理解,而且还会对本书其余部分讨论的示例服务有一个全面的了解。
A.1 介绍“你好世界”深度学习系统
从用户的角度来理解软件系统的最快方法。因此,在这个介绍部分,我们首先将看看深度学习系统的用户:人物角色及其责任。然后,我们将深入探讨系统设计、主要组件和用户工作流程。
A.1.1 人物角色
为了将复杂性降到最低,我们的示例迷你深度学习系统只有四个人物角色,或角色:数据工程师、数据科学家/研究员、系统开发人员和深度学习应用程序开发人员。我们选择了这四个角色,因为它们是保持深度学习系统运行所需的最少人员。在这个“你好世界”系统中,每个角色的角色定义和工作描述在以下各节中列出。
注意 这里描述的角色责任是过于简化的,因为我们想集中在深度学习系统的最基本工作流程上。关于深度学习系统中涉及的人物角色和职责的更详细定义,请参阅第 1.1 节。
A.1.2 数据工程师
数据工程师负责收集、处理和存储用于深度学习训练的原始数据。在这个小系统中,我们有一个 DM 服务用于存储用于模型训练的数据集。数据工程师将使用此服务上传原始训练数据。在我们的实验中,我们准备了一些意图分类数据集,供您体验此过程。
A.1.3 数据科学家/研究人员。
数据科学家或研究人员开发具有满足业务要求的模型训练算法和模型。它们是深度学习系统中模型训练基础设施的“客户”。
我们的示例系统包含一个训练服务,用于运行模型训练代码。在实验中,我们为你预先构建了一个意图分类训练代码,以体验模型训练执行。
A.1.4 系统开发人员。
系统开发人员构建整个深度学习系统并维护它,以确保所有的机器学习活动都正常运行。他们的活动包括数据集上传、模型训练和模型服务。
A.1.5 深度学习应用开发人员。
深度学习应用开发人员利用深度学习模型构建商业产品,如聊天机器人、自动驾驶软件和人脸识别移动应用程序。这些应用程序是任何深度学习系统的最重要的客户,因为它们为系统产生的模型创造业务影响(收入)。在我们的实验中,你将有机会想象自己是聊天机器人的客户,通过运行脚本向预测服务发送请求并分类你的消息。
A.1.6 样例系统概述。
我们的小型深度学习系统由四个服务和一个存储系统组成:
- 数据服务 — 用于存储和获取数据集。
- 模型训练服务 - 用于运行模型训练代码。
- 元数据存储服务 — 用于存储模型元数据,如模型名称、模型版本和模型算法。
- 预测服务 — 设计用于执行模型以处理客户的预测请求。
- MinIO 存储 — 旨在在您的本地计算机上运行,作为与 Amazon S3 类似的对象存储。
几乎所有这些服务在本书中都有自己的章节,因此我们将能够更详细地研究它们。现在,我们只想提供你需要理解后面的用户场景和实验的高级概述。图 A.1 说明了样例系统(四个服务和存储系统)的主要组成部分及其相互依赖关系。
图 A.1 所示是样例深度学习系统的设计概述。
除了四个服务和存储(用矩形框表示),你会注意到这些框之间有很多有向箭头。这些箭头显示了样例系统内部服务的相互依赖关系。以下是这些依赖关系的解释:
- DM 服务将数据集保存到 MinIO 存储中。
- 模型训练服务查询 DM 以准备训练数据集并获取训练数据。
- 模型训练服务从 MinIO 下载训练数据。
- 模型训练服务将模型文件保存到 MinIO。
- 模型训练服务将模型元数据保存到元数据存储服务中。
- 预测服务查询元数据存储以确定使用哪个模型。
- 预测服务从 MinIO 下载模型文件以提供预测请求。
A.1.7 用户工作流程
现在,我们已经介绍了人物角色和主要服务,让我们来看看用户工作流程。图 A.2 展示了每个角色的用户工作流程。
图 A.2 中的系统实现了 DM、训练、服务和系统维护四种不同的工作流程。
图 A.2 显示了每个角色使用迷你深度学习系统来执行自己的任务,利用图 A.1 中介绍的服务。让我们回顾一下每个工作流程:
- 场景 A ——数据工程师调用 DM 服务上传原始数据; DM 将数据摄取并保存到 MinIO 存储中的训练数据集格式中。
- 场景 B ——数据科学家首先编写训练代码,然后提交训练请求给训练服务。训练服务执行训练代码并生成模型。然后,它将模型元数据保存到元数据存储中,并将模型文件保存到 MinIO 存储中。
- 场景 C ——应用程序开发人员构建应用程序,调用预测服务来使用在场景 B 中训练的模型。
- 场景 D ——系统开发人员构建和维护此系统。
A.2 实验演示
现在是你开始学习的时候了。在这个实验练习中,你将在本地计算机上参与到 A.1.3 节中提到的用户场景中。为了使这个练习更生动,我们介绍了一些角色,这样你不仅会知道如何使用深度学习系统,还会了解谁负责处理每个不同的工作。虚构的角色包括伊万(一名数据科学家)、风(一名数据工程师)、唐(一名系统开发人员)和约翰娜(一名应用程序开发人员)。
A.2.1 演示步骤
在这个演示场景中,我们将有唐、风、伊万和约翰娜四个人一起合作,训练一个意图分类模型,并使用该模型对任意文本消息进行分类。这个场景模拟了一个典型模型开发工作流程的四个基本步骤:系统设置、数据集构建、模型训练和模型服务。
为了使实验易于运行,我们将所有微服务进行了 Docker 化,并构建了 shell 脚本来自动化实验设置和演示场景。通过按照我们 GitHub 仓库中 README 文件(github.com/orca3/MiniAutoML#lab
)中的说明,运行四个 shell 脚本,你可以完成实验。
注意:你可以在 github.com/orca3/MiniAutoML/tree/main/scripts
的 scripts 文件夹中找到实验演示脚本。该文件夹包含了整本书的演示脚本。以 lab- 开头的文件用于此演示,例如 lab-001-start-all.sh
(地址:mng.bz/zmv1
)可在本地系统上设置。对于未来的更新和成功执行实验脚本,请始终参考 GitHub 仓库中的说明。
第一步是系统设置。运行 scripts/lab-001-start-all.sh
(mng.bz/zmv1
)。
唐(系统开发者)通过运行 scripts/lab-001-start-all.sh
脚本启动迷你深度学习系统。该脚本将下载演示服务的预构建 Docker 镜像并执行它们。
当脚本执行完毕后,迷你深度学习系统已经启动并运行。你可以使用以下命令列出所有本地正在运行的 Docker 容器,以验证所有服务都在运行:
$ docker ps --format="table {{.Names}}\t{{.Image}}"
提供了用于运行实验的 Docker 容器,见下式。
附录 A.1 确认所有系统组件都在运行
NAMES IMAGE training-service orca3/services:latest prediction-service orca3/services:latest intent-classification-torch-predictor pytorch/torchserve:0.5.2-cpu intent-classification-predictor orca3/intent-classification-predictor metadata-store orca3/services:latest data-management orca3/services:latest minio minio/minio
唐确认所有微服务都在运行后,系统已准备好供使用。他通知伊凡和冯开始他们的工作。
注意:如果你阅读过 lab-001-start-all.sh
脚本,你会发现系统中大多数服务(除了预测器)—例如数据管理和模型训练—都被打包到一个 Docker 镜像中(orca3/services
)。这不是一个推荐的生产用例模式,但由于使用的磁盘空间较少且执行简单,它适用于我们的演示需求。
第二步是构建训练数据集。运行 scripts/lab-002-upload-data.sh
(mng.bz/0yqJ
)。
冯(数据工程师)首先从互联网上下载原始数据,并进行一些训练的修改(参见 scripts/prepare_data.py
,地址:mng.bz/KlKX
)。然后,冯将处理后的数据上传到 DM 服务。数据集上传完成后,DM 服务会返回一个唯一的数据集 ID,以供将来参考。
我们已经将冯的工作自动化在 scripts/lab-002-upload-data.sh
脚本中。执行完此脚本后,将创建一个数据集。你可以在终端中看到 DM 服务打印出一个 JSON 对象。此 JSON 对象表示数据集的元数据,请参考以下示例。
附录 A.2 DM 服务中的样本数据集元数据
# DM returns dataset metadata for a newly created dataset { "dataset_id": "1", ❶ "name": "tweet_emotion", ❷ "dataset_type": "TEXT_INTENT", ❸ "last_updated_at": "2022-03-25T01:32:37.493612Z", "commits": [ ❹ { ❹ "dataset_id": "1", ❹ "commit_id": "1", ❹ "created_at": "2022-03-25T01:32:38.919357Z", ❹ "commit_message": "Initial commit", ❹ "path": "dataset/1/commit/1", ❹ "statistics": { ❹ "numExamples": "2963", ❹ "numLabels": "3" ❹ } ❹ } ❹ ] ❹ }
❶ 数据集标识符
❷ 数据集名称
❸ 数据集类型
❹ 数据集审核历史记录
数据集元数据在第二章中有详细讨论。现在,我们可以忽略元数据 JSON 对象的大部分属性,只关注dataset_id
属性。数据集 ID是数据集的唯一标识符;你需要在第 3 步将此 ID 传递给训练服务以进行模型训练。一旦数据集准备好,Feng 就会通知 Ivan 使用dataset_id="1"
开始模型训练。
*步骤 3 是模型训练。*运行scripts/lab-003-first-training.sh
(mng.bz/vnra
)。
Ivan(数据科学家)首先构建意图分类训练代码(training-code/text-classification
位于github.com/orca3/MiniAutoML/tree/main/training-code/text-classification
)并将其打包成 Docker 镜像(mng.bz/WA5g
)。接下来,Ivan 向模型训练服务提交训练请求以创建模型训练作业。在训练请求中,他指定了在训练中使用的数据集(数据集 ID)和训练算法(Docker 镜像名称)。
注意 在本实验中,我们使用了硬编码的数据集 ID "1"
。要测试其他数据集,请随意将任何其他数据集 ID 设置为训练请求中。
一旦训练服务接收到训练请求,它将启动一个 Docker 容器来运行 Ivan 提供的意图分类训练代码。在我们的演示中,Docker 镜像是orca3/intent-classification
(mng.bz/WA5g
)。请运行实验脚本(scripts/lab-003-first-training.sh
位于mng.bz/916j
)来启动模型训练作业,该脚本设置了依赖项和参数。
列表 A.3 向训练服务提交训练作业
# send gRPC request to kick off a model training in training service. function start_training() { grpcurl -plaintext \ -d "{ \"metadata\": { \"algorithm\":\"intent-classification\", ❶ \"dataset_id\":\"1\", ❷ \"name\":\"test1\", \"train_data_version_hash\":$2, ❸ \"output_model_name\":\"twitter-model\", ❹ \"parameters\": { ❹ \"LR\":\"4\", ❹ \"EPOCHS\":\"15\", ❹ \"BATCH_SIZE\":\"64\", ❹ \"FC_SIZE\":\"128\" ❹ } ❹ } }" \ localhost:"6003" training.TrainingService/Train }
❶ 训练 Docker 镜像名称
❷ 要训练的数据集的 ID
❸ 数据集版本
❹ 训练超参数
一旦训练作业开始,训练服务将持续监视训练执行状态并返回作业 ID 以便跟踪。有了作业 ID,Ivan 可以通过查询训练服务的GetTrainingStatus
API 和元数据存储服务的GetRunStatus
API 获取最新的训练作业状态和训练元数据。查看示例查询请求如下。
列表 A.4 查询模型训练作业状态和模型元数据
# query training job status from training service grpcurl -plaintext \ -d "{\"job_id\": \"1\"}" \ ❶ localhost:"6003" training.TrainingService/GetTrainingStatus # query model training metrics from metadata store. grpcurl -plaintext \ -d "{\"run_id\": \"1\"}" \ ❶ localhost:"6002" metadata_store.MetadataStoreService/GetRunStatus
❶ 模型 ID,也是训练作业 ID
训练服务可以实时返回训练执行状态;查看示例响应如下:
job 1 is currently in "launch" status, check back in 5 seconds job 1 is currently in "running" status, check back in 5 seconds job 1 is currently in "succeed" status ❶
❶ 训练完成
由于训练 Docker 容器在训练执行期间向元数据存储报告实时指标,如训练准确性,因此元数据存储服务可以返回实时训练指标。查看来自元数据存储服务的示例模型训练指标如下:
{ "run_info": { "start_time": "2022-03-25T14:25:44.395619", "end_time": "2022-03-25T14:25:48.261595", "success": true, ❶ "message": "test accuracy 0.520", ❷ "run_id": "1", ❸ "run_name": "training job 1", "tracing": { "dataset_id": "1", ❹ "version_hash": "hashAg==", ❹ "code_version": "231c0d2" }, "epochs": { ❺ "0-10": { ❺ "start_time": "2022-03-25T14:25:46.880859", ❺ "end_time": "2022-03-25T14:25:47.054872", ❺ "run_id": "1", ❺ "epoch_id": "0-10", ❺ "metrics": { ❺ "accuracy": "0.4925373134328358" ❺ } ❺ }, ❺ .. .. .. } }
❶ 训练状态
❷ 训练容器的最后一条消息
❸ 训练作业 ID,以及模型 ID
❹ 数据集标识符
❺ 每个时期的训练度量
训练完成后,Ivan 通知 Johanna 模型已经准备好使用。在我们的实验室中,他将模型 ID(作业 ID = "1"
)传递给 Johanna,以便她知道要使用哪个模型。
请注意,代码清单 A.3 和 A.4 中描述的所有 API 请求都在 scripts/lab-003-first-training.sh
中自动执行;您可以一次性执行它们。在第三章和第四章中,我们会详细讨论训练服务的工作原理。
步骤 4 是模型服务。 运行 scripts/lab-004-model-serving.sh
(mng.bz/815K
)。
Johanna(应用程序开发人员)正在构建一个聊天机器人,所以她想要使用新训练的意图分类模型来对客户的问题进行分类。当 Ivan 告诉 Johanna 模型已经准备好使用时,Johanna 向预测服务发送一个预测请求来测试新训练的模型。
在预测请求中,Johanna 指定了模型 ID(runId
)和文档,其中文档是正在被分类的文本消息。样本预测服务将自动加载预测请求中请求的模型。您可以在以下清单中看到一个样本 gRPC 预测请求。
清单 A.5 一个样本模型预测 gRPC 请求
grpcurl -plaintext \ -d "{ \"runId\": \"1\", ❶ \"document\": \"You can have a certain arrogance, and I think that's fine, but what you should never lose is the respect for the others.\" ❷ }" \ localhost:6001 prediction.PredictionService/Predict
❶ 模型 ID,以及训练作业 ID
❷ 请求体(文本)
在终端中执行查询(代码清单 A.5)或 scripts/lab-004-model-serving.sh
后,您将会看到以下来自模型服务的输出:对于给定文本,意图分类模型预测出的类别(标签)。
{ "response": "{\"result\": \"joy\"}" ❶ }
❶ 预测的类别是“快乐”。
如果在完成实验过程中遇到任何问题,请查看我们 GitHub 仓库 README 文件的实验部分(github.com/orca3/MiniAutoML#lab
)中的最新说明。如果示例系统被修改,我们会尽量保持这些说明的更新。
A.2.2 一个自己完成的练习
现在我们已经向您展示了一个完成的模型开发周期,现在是作业时间。想象一下,在成功发布聊天机器人之后,Johanna 的聊天机器人服务需要支持一个新类别,乐观。这个新需求意味着当前的意图分类模型需要重新训练以识别乐观类型的文本消息。
Feng 和 Ivan 需要共同合作建立一个新的意图分类模型。Feng 需要收集更多带有“乐观”标签的训练数据并将其添加到当前数据集中。虽然 Ivan 不需要更改训练代码,但他确实需要使用更新的数据集触发训练服务中的训练作业来构建一个新模型。
通过按照第 A.2.1 节中的示例查询和脚本,您应该能够完成 Feng 和 Ivan 的任务。如果您想要检查您的结果或者在完成这些任务时需要帮助,您可以在 scripts/lab-005-second-training.sh
文件中找到我们的解决方案。我们鼓励您在检查我们的解决方案之前尝试或者玩弄这个问题。
附录 B:现有解决方案调查
从零开始实施深度学习系统是一项庞大的工作。在某些情况下,特殊需求可能需要额外的努力来从头开始构建深度学习系统。在其他情况下,鉴于有限的资源和时间,使用现有组件,甚至整个系统,并将其定制为符合自己需求可能是有意义的。
本附录的目的是审查几个由不同云供应商和开源社区实施的深度学习系统。这些操作范围从无服务器部署到自定义服务容器部署。通过将它们与我们的参考架构进行比较,并突出它们的相似之处和不同之处,你将了解到哪些操作可以用来设计自己的项目。
如果你想看到我们将要涵盖的每个解决方案的快速摘要比较,请随意跳转到 B.5 节。另外,为了方便起见,在第 1.2.1 节介绍的参考架构在图 B.1 中重新发布。
图 B.1 典型深度学习系统概述,包括支持深度学习开发周期的基本组件。这个参考架构可以作为一个起点,并进一步定制。
B.1 亚马逊 SageMaker
亚马逊 SageMaker 是其人工智能产品系列的总称,可以一起使用形成完整的深度学习系统。在本节中,我们将回顾产品套件,并查看它们与我们的关键组件的比较。正如本节开头所提到的,我们进行这些比较是为了让你了解哪种产品能最好地帮助构建你自己的系统。
B.1.1 数据集管理
亚马逊 SageMaker 没有提供数据集管理组件,该组件提供统一的接口来帮助管理数据准备与深度学习系统不同类型用户的复杂交互。然而,亚马逊提供了一系列数据存储、转换和查询解决方案,可以用来构建数据管理组件。
可以构建一个数据管理组件,用于收集 Amazon S3 的原始数据,这是一款对象存储产品。元数据标记可以由 AWS Glue 数据目录支持,该目录可以由 AWS Glue ETL 用于进一步处理成可用于训练的数据集。阅读第二章后,你应该能够确定如何使用这些亚马逊产品构建自己的数据管理组件。
B.1.2 模型训练
Amazon SageMaker 支持内置算法和提供外部自定义代码进行深度学习模型训练。它还支持用于训练运行的容器。它公开了一个 API,可以通过调用来启动按需训练作业。这与驱动深度学习系统培训组件的计算后端非常相似,本书也对此进行了介绍。要实现训练组件的资源管理部分,您可以使用 Amazon 提供的现有工具,例如为不同的 AWS 身份和访问管理(IAM)用户或角色分配资源限制和策略。如果您的组织需要额外的控制或复杂性,或者已经有身份提供者实现,您可能需要花费更多的时间构建自定义解决方案。阅读第三章和第四章后,您应该能够弄清楚如何使用现有的 Amazon 工具来构建自己的训练组件。
B.1.3 模型服务
在其最基本的形式下,Amazon SageMaker 能够支持将训练后的模型部署为可以通过互联网访问的 Web 服务。为了扩展多个模型的部署而无需将它们部署到单独的端点,SageMaker 提供了一个多模型端点,同时也配备了可配置的模型缓存行为。如果这些工具符合您的需求,它们会很有用。截至本文撰写时,SageMaker 支持多容器端点和串行推理流水线,这与本书中描述的服务架构和 DAG 支持类似。第六章和第七章回顾了模型服务原则,以便您了解现有工具和在遇到现有工具的限制时如何构建自己的工具。
B.1.4 元数据和工件存储
作为以受过训练的模型为中心的组件,云供应商推出了专门的产品是不足为奇的。SageMaker 模型注册表提供了许多元数据和深度学习系统工件存储的关键概念相对应的功能。例如,可以使用模型注册表跟踪模型的训练度量和模型版本等元数据。然而,它并不提供同一组件中的工件存储解决方案。您可以轻松地在模型注册表和其他 Amazon 存储产品之上构建接口,以提供这个组件的工件存储方面。
在工件之间跟踪的另一种重要元数据类型是它们的谱系信息。SageMaker 提供了 ML 谱系跟踪作为一个独立的功能,它会自动跟踪这些信息。
在第八章中,我们将讨论构建元数据和工件存储的关键问题。阅读本章后,您将了解这个组件背后的设计原则以及现有的产品如何帮助您快速构建自己的组件。
B.1.5 工作流编排
- 在亚马逊 SageMaker 上,您可以使用 Model Building Pipelines 产品来管理工作流程或管道(这是 SageMaker 的术语)。使用此产品,您可以按照预定义的顺序以任意方式执行一组操作,例如数据准备步骤、训练步骤和模型验证步骤,作为一个单元。为了允许多种类型的用户共同解决同一个问题,SageMaker 还提供了一个 Project 产品,帮助组织工作流程、代码版本、血统信息以及每种用户类型的不同访问权限之间的关系。
- 在第九章中,我们将介绍如何使用工作流管理器启用不同的训练模式。阅读本章后,您将了解到在深度学习系统中设计和实用工作流管理器的原因,以及其在企业环境中的作用。
- B.1.6 实验
- 亚马逊 SageMaker 提供了一个名为 Experiments 的功能,它使用相关的跟踪信息和指标标记实验运行。事实上,这种跟踪信息也是一种元数据,对于需要评估不同数据输入、训练算法和超参数组合性能的深度学习系统用户来说,这种元数据是很重要的。
- B.2 Google Vertex AI
- Google Vertex AI 是 Google AI 平台提供的一项功能与其 AutoML 产品相结合的产品,提供了一系列可用作深度学习系统的工具和服务。在本节中,我们将回顾其提供的功能,并将其与本书介绍的关键组件进行比较。
- B.2.1 数据集管理
- Google Vertex AI 提供了一个简单的 API 来管理数据集,尽管您必须首先将对象数据上传到 Google Cloud Storage,然后通过 Vertex AI API 上传引用 Google Cloud Storage 中对象数据的元数据和注释文件。数据集 API 在提供给开发人员时提供了统一的体验,尽管不同类型的数据集(图像、文本、视频等)之间的 API 类似。然而,该 API 并未提供版本信息和其他血统跟踪信息。在第二章中,我们探讨了核心数据管理原则。阅读本章后,您将能够比较现有解决方案,并针对自己的需求扩展它们或从头开始构建。
- B.2.2 模型训练
Google Vertex AI 支持使用 Docker 容器进行训练。它为那些不需要进一步定制的用户提供预构建的训练容器,并支持为那些需要比预构建版本提供的内容更多的用户提供自定义构建的训练容器。其训练服务公开了一个接口,允许在单个节点或多个节点上启动训练运行以进行分布式训练。在运行分布式训练时,Vertex AI 提供额外的支持,以加速训练过程。在第三章和第四章中,我们探讨了这些功能及其背后的原理。阅读完这些章节后,您将能够确定可以使用哪些现有产品,如何在需要更多功能时扩展它们,以及如何根据具体需求从头开始构建它们。
B.2.3 模型服务
Google Vertex AI 支持向经过训练的模型提供在线推断请求服务,可以使用预构建推断容器或自定义推断容器。训练过的模型与容器分离,并且必须使用计算资源部署,以形成可以提供在线推断请求服务的端点。Vertex AI 支持将一个模型部署到多个端点,并支持将多个模型部署到单个端点。与支持各种模型类型的其他解决方案不同,在 Vertex AI 中,将多个模型部署到单个端点主要用于使用分流流量模式来执行新模型版本的金丝雀发布。在 Vertex AI 中,如果您训练了一个 Vertex AI 视频模型,则无法使其提供在线推断请求服务。
在第六章和第七章中,我们学习了模型服务背后的基本原理。完成这些章节后,您将对模型服务有很好的理解,并能够决定现有解决方案是否满足您的需求。您将能够构建自己的解决方案,并了解如何高效且规模化地运行模型服务器。
B.2.4 元数据和工件存储
Vertex ML Metadata 是谷歌的元数据存储解决方案,可用于深度学习系统中。它使用图来描述诸如数据集、训练运行和训练模型等工件之间的关系。图中的每个节点和边都可以用一系列键值对标记,以描述任何元数据。当正确使用时,这可以为深度学习系统中的所有内容提供全面的血统信息。
工件不直接存储在 Vertex ML Metadata 中。工件存储在 Google Cloud Storage 中。Vertex ML Metadata 使用 URI 引用指向这些工件。
在第八章中,我们将探讨一种类似的方法,即构建元数据和工件存储,通过单一统一的界面可以管理两者。阅读完本章后,您将能够了解如何利用和扩展现有解决方案以满足您的需求。
B.2.5 工作流编排
使用 Google,您可以使用 Vertex Pipelines 来管理和操作您的深度学习工作流程。您可以将数据准备和训练操作表示为管道中的步骤。在 Vertex Pipelines 中,步骤被组织为有向无环图中的节点。管道的每个步骤由一个容器实现。管道的运行实际上是对容器执行的编排。
在第九章中,我们将介绍如何使用工作流管理器来启用不同的训练模式。阅读该章后,您将了解到在深度学习系统中设计工作流管理器的原因和效用以及它在企业环境中的作用。
实验
Google Vertex AI Experiments 提供了统一的用户界面来创建、跟踪和管理实验。Vertex AI SDK 提供了用于模型训练代码的自动记录支持,以记录超参数、指标和数据衍生关系。与 Vertex ML Metadata 结合使用时,您可以获得所有模型训练实验运行的完整概述。
微软 Azure 机器学习
不同于微软经典的 ML Studio 方案,该方案专注于机器学习的图形用户界面方法,Azure 机器学习是一套新的工具和服务,还支持使用代码和已建立的开源框架进行广泛定制。在本节中,我们将比较它们的功能与本书中描述的关键组件。完成本节后,您将对可直接使用的内容、可扩展的内容以及需要从头开始构建以满足您需求的内容有所了解。
数据集管理
在 Azure 机器学习中,数据集是第一类对象,是数据处理和训练任务的输入和输出。数据集被定义为与数据集的原始数据相关联的元数据集合。数据集通过 URI 引用指向底层数据存储的原始数据。一旦数据集被创建,它就变成了不可变的。然而,底层数据并没有同样的保证,您需要自己管理其不可变性。
一旦数据集被定义,数据处理和训练代码可以通过统一的客户端 API 访问它们。数据可以被下载以供本地访问,也可以被挂载为网络存储以供直接访问。阅读第二章后,您将能够识别出这种范例与本书中描述的范例之间的相似之处。您将学习如何直接使用这个现有产品以及如何根据自己的需求进行扩展。
模型训练
Azure Machine Learning 提供预构建的带有 Python 分发的容器,并允许用户定义符合特定要求的自定义基础镜像。在我们撰写本文时,仅支持使用 Python 定义自定义的训练代码。要启动一个训练过程,您需要指定运行时容器和符合特定约定的训练代码的引用。如果您需要其他设置,则需要构建自己的训练服务。第 3 和第四章将向您展示训练服务的关键原则和一个示例,作为自己训练服务的起点。
B.3.3 模型服务
在 Azure Machine Learning v2 上,可以创建端点来提供在线推断请求。端点可以配置为加载某个模型并使用 Python 脚本产生推断结果,或者配置为使用完全自定义的容器镜像(如 TensorFlow Serving)产生推断结果。Azure Machine Learning 还与 NVIDIA Triton Inference Server 集成,当 GPU 用于产生推断结果时,可以提供额外的性能提升。
如果您需要将多个模型部署到一个端点或在边缘设备上管理模型和推断产量,则需要构建自己的服务。在第 6 和第七章中,我们深入讨论了模型服务。完成这些章节后,您将能够构建自己的模型服务器,以便支持现有提供的功能无法支持的其他功能。
B.3.4 元数据和工件存储
在 Azure Machine Learning 中,元数据可以以标签的形式附加到许多对象上,例如模型、训练运行等等。虽然不是一个独立的产品,但模型注册功能支持在注册模型时添加额外的元数据。在注册期间,接口同时接收元数据和模型文件(工件),相比其他需要先将模型注册到其云存储中的解决方案,需要少一步操作。
我们撰写本文时,一个称为注册表的预览功能可用于将与 ML 相关的元数据集中存储到一个位置。但是,如果您想要跟踪不同工件之间的传承关系,可能需要构建自己的解决方案。
阅读第八章后,您将深入了解元数据和工件存储。您将学习其基础知识,并能够快速构建自己的存储。
B.3.5 工作流编排
Azure Machine Learning 提供了一个称为 ML pipelines 的功能,允许您将数据、训练和其他任务定义为步骤。这些步骤可以通过编程方式组合成管道,并可以根据时间表或触发器定期执行,或仅可手动启动。管道定义时,可以编程配置计算资源、执行环境和访问权限。
在第九章中,我们将回顾如何使用工作流管理器启用不同的训练模式。阅读完本章后,你将理解深度学习系统中工作流管理器的设计理念和实用性,以及它在企业环境中的作用。
B.3.6 实验
Azure 机器学习提供了一个用于定义和跟踪实验的功能。在实验的一部分进行模型训练时,可以从训练代码中记录指标,并通过 Web 界面可视化。它还支持任意标记和实验运行之间的父子关系,以进行层次化组织和查找。
B.4 Kubeflow
Kubeflow 是一个开源工具套件,为构建深度学习系统提供了许多有用的组件,而不会被锁定到特定的云供应商。在本节中,我们列出了本书介绍的关键组件,并将它们与 Kubeflow 提供的类似组件进行了比较。
B.4.1 数据集管理
Kubeflow 的愿景是不重复造轮子,因此不会有数据管理组件也不足为奇,因为其他开源解决方案已经存在。在第二章中,我们审查了一些开源数据管理解决方案,并探讨了它们如何进一步扩展以实现该章节描述的关键原则。
B.4.2 模型训练
Kubeflow 是一个基于 Kubernetes 的工具套件,具有复杂的资源调度器支持。不像云供应商提供预构建的模型训练容器,你必须构建自己的容器并管理它们的启动。在第三章和第四章中,我们讨论了训练服务的原则以及它如何帮助抽象出资源分配和调度中的复杂性。我们将介绍一个参考训练服务,你将学会如何根据自己的需求构建一个。
B.4.3 模型服务
截至目前,Kubeflow 提供了一个名为 KServe 的组件,可用于将训练好的模型部署为推断服务,通过网络提供推断请求。它是一个接口,位于现有的服务框架之上,如 TensorFlow Serving、PyTorch TorchServe 和 NVIDIA Triton 推断服务器。使用 KServe 的主要好处在于额外抽象了操作复杂性,如自动缩放、健康检查和自动恢复。由于它是一个开源解决方案,可以在同一个端点上托管一个或多个模型。在第六章和第七章中,我们将介绍模型服务原理,以便你理解设计流行服务接口的原因以及如何自定义它们以适应自己的需求。
B.4.4 元数据和工件存储
从 Kubeflow 版本 1.3 开始,元数据和工件成为 Kubeflow Pipelines 的一个组成部分。Kubeflow Pipelines 由一组管道组件图组成。在每个组件之间,参数和工件可以传递。类似于本书中的描述,工件封装了深度学习系统的任何类型的数据,例如模型本身、训练指标和数据分布指标等。元数据是描述管道组件和工件的任何数据。有了这些构造,你可以推断出输入训练数据集、训练模型、实验结果和服务推理之间的衍生关系。
在第八章中,我们讨论了构建元数据和工件存储的关键问题。阅读完本章后,你将理解该组件背后的设计原则以及现有产品如何帮助你快速构建自己的存储。
B.4.5 工作流编排
此前的章节中也有描述,Kubeflow Pipelines 可以用于帮助管理深度学习数据准备和训练工作流程。元数据和版本控制已集成到管道中,并且可以使用 Kubernetes 的本机用户和访问权限来限制访问。
在第九章中,我们将回顾工作流程管理器如何实现不同的训练模式。阅读完本章后,你将理解深度学习系统中工作流程管理器设计和实用性背后的原理。
B.4.6 实验
Kubeflow Pipelines 提供了实验结构,其中多个训练运行可以组织成一个逻辑组,在其中为每个实验运行提供了额外的可视化工具以显示差异。这非常适用于离线实验。如果需要进行在线实验,则需要自行解决方案。
B.5 旁边对比
我们认为,提供一个按照我们先前涵盖的组件分组的所有解决方案的摘要概述表格将会很方便。我们希望表格 B.1 能够让你更轻松地选择合适的解决方案。
表格 B.1 旁边对比
亚马逊 SageMaker | 谷歌 Vertex AI | 微软 Azure 机器学习 | Kubeflow | |
比较数据集管理解决方案 | AWS 组件,如 S3、Glue 数据目录和 Glue ETL,可用于构建数据集管理组件。 | 用于管理数据集的 API 已经准备就绪。数据内容上传和元数据标记是分开的操作。 | 数据集是一级对象,一旦创建就不可变。提供了统一的客户端 API 用于训练作业访问训练数据集。 | 不提供数据集管理解决方案。其他开源替代方案随时可用。 |
比较模型训练解决方案 | 支持内置算法、外部提供的自定义代码和用于训练的自定义容器。提供一个 API 用于按需启动训练作业。 | 提供可以直接使用的预构建训练容器。支持自定义训练容器。提供支持在多个节点上启动训练容器的 API。 | 提供具有 Python 的预构建训练容器,可进行定制。训练容器必须符合某种约定。 | 具有对 Kubernetes 调度能力的本地访问。不提供预构建的训练容器。 |
比较模型服务解决方案 | 模型可以部署为 Web 端点。可以将多个模型部署到同一端点以实现更好的利用,但使用 GPU 时存在一些限制。可配置的模型缓存行为。 | 模型和推断容器是分离的。它们必须一起部署以形成用于服务的 Web 端点。支持自定义推断容器。主要用于金丝雀测试新版本模型的单个端点上使用多个模型。不支持视频模型。 | 可以部署端点以通过 Web 提供模型服务。端点配置为使用特定模型,使用自定义 Python 脚本生成推断。支持 NVIDIA Triton 推理服务器集成。 | KServe 是 Kubeflow 的组件,用于提供模型服务。它在流行的服务框架(如 TensorFlow Serving、PyTorch TorchServe 和 NVIDIA Triton 推理服务器)之上提供了一个无服务器推断抽象。 |
比较元数据和工件存储解决方案 | SageMaker 模型注册表提供了一个中心化的元数据存储解决方案。工件单独存储在亚马逊的对象存储中。 | Vertex ML 元数据提供了一个中心化的元数据存储解决方案。元数据以能描述复杂关系的图形形式存储。工件存储在谷歌的对象存储中。 | 一个称为注册表的预览功能可用于集中管理 ML 元数据。元数据存在于不同对象(训练运行、模型等)的标签中,并且对象可以是工件。可以使用这些对象标签推断出血统信息。 | 没有中心化的元数据或工件存储库。元数据和工件是 Kubeflow Pipelines 的组成部分。管道中的每个阶段都可以用元数据注释,并且可以跟踪生成的工件。可以从 Pipelines API 检索到的信息中推断出血统信息。 |
比较工作流编排解决方案 | 模型构建流水线可用于构建和管理深度学习工作流。 | Vertex ML Metadata 提供了一个集中的元数据存储解决方案。元数据存储为可以描述复杂关系的图形。工件存储在谷歌的对象存储中。 | 一个名为注册表的预览功能可用于集中化 ML 元数据。元数据存在于不同对象的标签中(训练运行、模型等),对象可以是工件。可以使用这些对象标签推断出谱系信息。 | 没有元数据或工件的中央存储库。元数据和工件是 Kubeflow 流水线的组成部分。管道中的每个阶段都可以用元数据注释,并产生可以被跟踪的工件。可以从可以从流水线 API 中检索的详细信息中推断出谱系信息。 |
比较实验解决方案 | 实验功能提供了对训练运行的分组和跟踪。 | 为 Vertex AI 实验提供跟踪和可视化实验设置和运行结果的功能。 | 提供了定义和跟踪实验的功能。实验可以关联为父子关系。Web 接口支持可视化。 | 提供了一个实验构造,用于逻辑分组 Kubeflow 流水线,这些流水线属于同一个实验组。提供了可视化工具,用于突出显示同一实验中每个流水线运行之间的差异。 |
附录 C:创建使用 Kubeflow Katib 的 HPO 服务
我们将向您介绍一个开源的超参数优化(HPO)服务——Kubeflow Katib,它满足了我们在第五章讨论的几乎所有 HPO 要求。我们强烈建议您在构建自己的 HPO 服务之前考虑采用 Katib。除了向您展示如何使用 Katib 外,我们还将介绍其系统设计和代码库,以使您对这个开源服务感到舒适。
作为 Kubeflow 家族的一员,Katib 是一个云原生、可扩展且可投入生产的超参数优化系统。此外,Katib 不关心机器学习框架或编程语言。此外,Katib 是用 Go 编写的,采用 Kubernetes 本地方法,可以在 Kubernetes 集群中独立运行。除了支持具有早期停止支持的超参数优化外,Katib 还支持神经架构搜索(NAS)。
Katib 有许多优点,包括其支持多租户和分布式训练的能力、其云原生性以及其可扩展性,所有这些都使其与其他系统有所区别。无论您是在云中还是在本地服务器上使用 Kubernetes 管理服务器集群,Katib 都是最佳选择。在本章中,我们将以以下五个步骤介绍 Katib:Katib 概述、如何使用 Katib、Katib 系统设计和代码阅读、加速 HPO 执行以及向 Katib 添加自定义 HPO 算法。
C.1 Katib 概览
Katib 以黑盒方式管理 HPO 实验和计算资源,因此 Katib 用户只需要提供训练代码并定义 HPO 执行计划,然后 Katib 就会处理其余事务。图 C.1 显示了 Katib 的系统概述。
图 C.1 Katib 系统概述。Katib 组件作为 Kubernetes 本地服务运行,并且 Katib 支持三种类型的用户界面:UI、API 和 SDK。
在图 C.1 中,我们看到 Katib 为用户的方便性提供了三种类型的用户界面:一个 Web UI,一个 Python SDK,以及一组 API。用户可以通过网页、Jupyter 笔记本、Kubernetes 命令和 HTTP 请求来运行 HPO。
从用户的角度来看,Katib 是一个远程系统。要运行 HPO,用户需要向 Katib 提交一个实验请求,然后 Katib 为他们执行 HPO 实验。要构建实验请求,用户需要做两件事:首先,将训练代码制作成 Docker 镜像,并将要优化的超参数暴露为外部变量;其次,创建一个实验对象,定义 HPO 实验的规范,如 HPO 算法、试验预算或超参数及其值搜索空间。一旦实验对象在 Katib 中创建完成,Katib 将分配计算资源以启动 HPO 执行。
Katib 在 Kubernetes 集群内部运行。Katib 服务本身并不消耗大量内存或磁盘空间;它启动 Kubernetes pod 来运行模型训练作业(HPO 试验)以测试不同的超参数建议。Katib 可以在不同的命名空间为不同的用户运行训练作业,以创建资源隔离。
C.2 使用 Katib 入门
在本节中,我们将看一下如何操作 Katib。首先,我们在本地安装 Katib,然后解释术语,最后,我们向您展示一个 Katib 的端到端使用案例。
为什么在设计书中谈论 Katib 操作和安装呢?
理想情况下,我们不希望在设计书中包含软件的安装和用户指南,因为这些信息在书出版后可能会过时,并且我们可以在官方网站上找到实时的文档。以下是我们违反规则的两个原因。
首先,因为我们建议您使用 Katib 而不是构建您自己的服务,我们有责任向您展示完整的用户体验,既从 Katib 用户(数据科学家)的角度,又从 Katib 运营者(工程师)的角度。其次,为了理解 Katib 的设计并学习如何阅读其代码库,最好先解释其术语和典型用户工作流程。一旦你理解了 Katib 的工作原理,阅读其代码就会更容易。
C.2.1 第一步:安装
如果您安装了 Kubeflow 系统 (mng.bz/WAp4
),那么 Katib 已包含在内。但如果您只对 HPO 感兴趣,您可以单独安装 Katib。Katib 正在积极发展和得到良好维护,所以请查看其官方安装文档 “Getting Started with Katib: Installing Katib” (mng.bz/81YZ
),获取最新的安装提示。
C.2.2 第二步:理解 Katib 术语
对于 Katib 用户来说,实验、建议和试验是需要熟悉的三个最重要的实体/概念。定义如下。
实验
一个实验是单一的优化运行;它是一个端到端的 HPO 过程。一个实验配置包含以下主要组件:用于训练代码的 Docker 镜像,一个我们要优化的客观指标(也称为目标值),需要调整的超参数,以及一个值搜索空间和 HPO 算法。
建议
一个建议是一个由 HPO 算法提出的一组超参数值。Katib 创建一个试验作业来评估建议的值集。
试验
试验是实验的一次迭代。一次试验会接受一个建议,执行一个训练过程(一个试验作业)以产生一个模型,并评估模型的性能。
每个实验都运行一个试验循环。实验会持续调度新的试验,直到达到客观目标或者配置的最大试验数。您可以在 Katib 官方文档 “Introduction to Katib” (mng.bz/ElBo
) 中看到更多的 Katib 概念解释。
深度学习系统设计(三)(5)https://developer.aliyun.com/article/1517038