【Designing ML Systems】第 7 章 :模型部署和预测服务

本章探讨了机器学习模型部署的常见误解,包括批量预测与在线预测的区别,以及云和边缘计算的权衡。模型压缩技术如低秩分解、知识蒸馏、修剪和量化被讨论,以减少推理延迟和提高效率。重点还放在了模型优化和编译器的角色,特别是如何使用ML来优化ML模型的编译过程,以及WebAssembly在浏览器中运行模型的潜力。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

 🔎大家好,我是Sonhhxg_柒,希望你看完之后,能对你有所帮助,不足请指正!共同学习交流🔎

📝个人主页-Sonhhxg_柒的博客_CSDN博客 📃

🎁欢迎各位→点赞👍 + 收藏⭐️ + 留言📝​

📣系列专栏 - 机器学习【ML】 自然语言处理【NLP】  深度学习【DL】

 🖍foreword

✔说明⇢本人讲解主要包括Python、机器学习(ML)、深度学习(DL)、自然语言处理(NLP)等内容。

如果你对这个系列感兴趣的话,可以关注订阅哟👋

文章目录

机器学习部署神话

误区 1:一次只部署一个或两个 ML 模型

误区 2:如果我们什么都不做,模型性能保持不变

误区 3:你不需要更新你的模型

误区 4:大多数 ML 工程师不需要担心规模

批量预测与在线预测

术语混淆

流媒体功能与在线功能

从批量预测到在线预测

统一 Batch Pipeline 和 Streaming Pipeline

模型压缩

低秩分解

知识蒸馏

修剪

量化

云和边缘的机器学习

编译和优化边缘设备的模型

模型优化

使用 ML 优化 ML 模型

浏览器中的机器学习

概括


在第4章到第6章中,我们讨论了开发 ML 模型的注意事项,从创建训练数据、提取特征和开发模型到制定指标来评估该模型。这些考虑构成了模型的逻辑——关于如何从原始数据进入 ML 模型的说明,如图 7-1所示。开发此逻辑需要 ML 知识和主题专业知识。在许多公司中,这是由 ML 或数据科学团队完成的过程。

图 7-1。构成 ML 模型逻辑的不同方面

在本章中,我们将讨论迭代过程中的另一部分:部署模型。“部署”是一个宽松的术语,通常意味着让您的模型运行且可访问。在模型开发过程中,您的模型通常在开发环境中运行。1要部署,您的模型必须离开开发环境。您的模型可以部署到暂存环境进行测试,也可以部署到最终用户使用的生产环境。在本章中,我们专注于将模型部署到生产环境。

在我们继续前进之前,我想强调生产是一个频谱。对于某些团队来说,生产意味着在笔记本中生成漂亮的图表以展示给业务团队。对于其他团队来说,生产意味着每天为数百万用户保持模型正常运行。如果你的工作是在第一个场景中,你的生产环境和开发环境类似,本章对你的相关性较小。如果您的工作更接近第二种情况,请继续阅读。

我曾经在互联网上某处读到:如果忽略所有困难部分,部署很容易。如果你想为你的朋友部署一个模型来玩,你所要做的就是使用 Flask 或 FastAPI 将你的预测函数包装在一个 POST 请求端点中,将这个预测函数需要运行的依赖项放在一个容器中,2和将您的模型及其关联容器推送到 AWS 或 GCP 等云服务以公开端点:

# Example of how to use FastAPI to turn your predict function 
# into a POST endpoint
@app.route('/predict', methods=['POST'])
def predict():
    X = request.get_json()['X']
    y = MODEL.predict(X).tolist()
    return json.dumps({'y': y}), 200

您可以将此暴露端点用于下游应用程序:例如,当应用程序接收到用户的预测请求时,该请求将发送到暴露端点,后者返回预测。如果您熟悉必要的工具,您可以在一个小时内完成功能部署。我的学生在经过 10 周的课程后,都能够将 ML 应用程序部署为他们的最终项目,尽管之前很少有人有部署经验。3

困难的部分包括使您的模型以毫秒的延迟和 99% 的正常运行时间提供给数百万用户,设置基础架构以便在发生时可以立即通知合适的人出现问题,找出问题所在,并无缝部署更新以修复问题。

在许多公司中,部署模型的责任落在开发这些模型的同一个人手中。在许多其他公司中,一旦准备好部署模型,就会将其导出并交给另一个团队进行部署。但是,这种职责分离可能会导致高开销团队之间的沟通,并减慢更新模型的速度。如果出现问题,它也会使调试变得困难。我们将在第 11 章讨论更多关于团队结构的内容。

笔记

导出模型意味着将此模型转换为其他应用程序可以使用的格式。有些人打电话这个过程“序列化”。4您可以导出模型的两个部分:模型定义和模型的参数值。模型定义定义了模型的结构,例如它有多少隐藏层以及每层中有多少单元。参数值提供这些单位和层的值。通常,这两个部分一起导出。

在 TensorFlow 2 中,您可以使用tf.keras.Model.save()将模型导出为 TensorFlow 的 SavedModel 格式。在 PyTorch 中,您可以使用torch.onnx.export()将模型导出为 ONNX 格式。

无论您的工作是否涉及部署 ML 模型,了解模型的使用方式都可以让您了解它们的约束并帮助您根据它们的目的定制它们。

在本章中,我们将从一些关于 ML 部署的常见神话开始,这些神话是我经常从尚未部署 ML 模型的人那里听到的。然后,我们将讨论模型生成并向用户提供预测的两种主要方式:在线预测和批量预测。生成预测的过程称为推理

我们将继续讨论应该在哪里进行生成预测的计算:在设备(也称为边缘)和云上。模型如何服务和计算预测会影响其设计方式、所需的基础设施以及用户遇到的行为。

如果您来自学术背景,本章讨论的某些主题可能超出您的舒适范围。如果出现不熟悉的术语,请花点时间查一下。如果某个部分变得太密集,请随意跳过它。本章是模块化的,因此跳过一节不应影响您对另一节的理解。

机器学习部署神话

第 1 章所述,部署 ML 模型可能与部署传统软件程序大不相同。这种差异可能会导致以前从未部署过模型的人害怕这个过程或低估它需要多少时间和精力。在本节中,我们将揭开关于部署过程的一些常见误解,希望它们能让您在开始该过程时保持良好的心态。本部分对几乎没有部署经验的人最有帮助。

误区 1:一次只部署一个或两个 ML 模型

在做学术项目时,我建议选择一个小问题来关注,这通常会导致模型单一。与我交谈过的许多具有学术背景的人也倾向于在单一模型的背景下考虑 ML 生产。随后,他们心目中的基础设施不适用于实际应用,因为它只能支持一两个模型。

实际上,公司有很多很多的机器学习模型。一个应用程序可能有许多不同的特性,并且每个特性都可能需要自己的模型。考虑像优步这样的拼车应用。它需要一个模型来预测以下每个元素:乘车需求、司机可用性、预计到达时间、动态定价、欺诈性交易、客户流失等等。此外,如果这个应用程序在 20 个国家/地区运行,那么在您拥有能够泛化不同用户资料、文化和语言的模型之前,每个国家/地区都需要自己的模型集。因此,对于 20 个国家和每个国家/地区的 10 个模型,您已经拥有 200 个模型。图 7-2显示了 Netflix 使用机器学习的各种任务。

图 7-2。Netflix 利用机器学习的不同任务。资料来源:Ville Tuulos 5

事实上,优步有数千种模型在生产中。6在任何特定时刻,谷歌都有成千上万以数千亿个参数同时训练的模型。7 Booking.com 拥有 150 多个模型。8 Algorithmia 2021 年的一项研究表明,在拥有超过 25,000 名员工的组织中,41% 的组织拥有 100 多个生产模型。9

误区 2:如果我们什么都不做,模型性能保持不变

软件不会像美酒一样陈年。它变老了不良。即使似乎没有任何变化,软件程序也会随着时间的推移而退化的现象被称为“软件腐烂”或“位腐烂”。

机器学习系统也不能幸免。最重要的是,当您的模型在生产中遇到的数据分布与其训练时的数据分布不同时,机器学习系统会遭受所谓的数据分布变化。10因此,ML 模型往往在训练后立即表现最佳,并随着时间的推移而退化。

误区 3:你不需要更新你的模型

人们往往会问我:“我应该多久更新一次模型?” 这是一个错误的问题。正确的问题应该是:“我可以多久更新一次我的模型?”

由于模型的性能下降随着时间的推移,我们希望尽快更新它。这是 ML 的一个领域,我们应该从现有的 DevOps 最佳实践中学习。早在 2015 年,人们就已经在不断推出系统更新。Etsy 每天部署 50 次,Netflix 每天部署数千次,AWS 每 11.7 秒部署一次。11

虽然许多公司仍然每月只更新一次模型,甚至每季度更新一次,但微博更新部分 ML 模型的迭代周期为 10 分钟。12我在阿里巴巴和字节跳动(TikTok 背后的公司)等公司听到过类似的数字。

用 Google 前任工程师和 Slack 数据工程总监 Josh Wills 的话来说,“我们一直在努力以尽可能快的速度将新模型投入生产。” 13

我们将在第 9 章讨论更多关于重新训练模型的频率。

误区 4:大多数 ML 工程师不需要担心规模

“规模”的含义因应用而异应用程序,但示例包括每秒服务数百个查询或每月数百万用户的系统。

您可能会争辩说,如果是这样,只有少数公司需要担心它。只有一个谷歌,一个Facebook,一个亚马逊。确实如此,但少数大公司雇用了大部分软件工程人员。根据 2019 年 Stack Overflow 开发者调查,超过一半的受访者为至少 100 名员工的公司工作(见图 7-3)。这不是一个完美的相关性,但一个拥有 100 名员工的公司很有可能为合理数量的用户提供服务。

图 7-3。软件工程师工作的公司规模分布。资料来源:改编自 Stack Overflow 14的图片

我找不到针对 ML 特定角色的调查,所以我在Twitter 上询问并发现了类似的结果。这意味着,如果您正在行业中寻找与 ML 相关的工作,您可能会为一家拥有至少 100 名员工的公司工作,其 ML 应用程序可能需要可扩展。从统计学上讲,ML 工程师应该关心规模。

批量预测与在线预测

您必须做出的一项基本决定将影响您的最终用户和在您的系统上工作的开发人员是它如何生成预测并将其提供给最终用户:在线或批量。由于行业缺乏标准化实践,围绕批处理和在线预测的术语仍然相当混乱。我将尽我所能解释本节中每个术语的细微差别。如果您发现此处提到的任何术语过于混乱,请暂时忽略它们。如果您忘记了其他所有内容,我希望您能记住三种主要的预测模式:

  • 批量预测,仅使用批量特征。

  • 仅使用批量特征(例如,预先计算的嵌入)的在线预测。

  • 同时使用批处理功能和流式处理功能的在线预测。这也称为流式预测。

在线预测是在对这些预测的请求到达后立即生成并返回预测。例如,您在谷歌翻译中输入一个英文句子并立即获取其法语翻译。在线预测是也称为按需预测。传统上,在进行在线预测时,请求通过 RESTful API 发送到预测服务(例如,HTTP 请求——请参阅“通过服务传递数据”)。当通过 HTTP 请求发送预测请求时,在线预测也称为同步预测:预测是与请求同步生成的。

批量预测是在周期性或触发时生成预测。预测存储在某处,例如 SQL 表或内存数据库中,并根据需要进行检索。例如,Netflix 可能每四个小时为其所有用户生成电影推荐,并在用户登录 Netflix 时提取并显示预先计算的推荐。批量预测也称为异步预测:预测是与请求异步生成的。

术语混淆

“在线预测”和“批量预测”这两个术语可能会造成混淆。两者都可以一次预测多个样本(批量)或一个样本。为了避免这种混乱,人们有时更喜欢术语“同步预测”和“异步预测”。但是,这种区别也不完美,因为当在线预测利用实时传输向您的模型发送预测请求时,请求和预测在技术上是异步的。

图 7-4显示了批量预测的简化架构,图 7-5显示了仅使用批量特征的在线预测的简化版本。接下来,我们将讨论仅使用批处理功能的含义。

图 7-4。批量预测的简化架构

图 7-5。仅使用批量特征的在线预测简化架构

 正如第 3 章所讨论的,从历史数据计算的特征,例如数据库和数据仓库中的数据,是批量特征。从流数据(实时传输中的数据)计算的特征是流特征。在批量预测中,仅使用批量特征。然而,在在线预测中,可以同时使用批处理功能和流功能。例如,用户在 DoorDash 下订单后,他们可能需要以下功能来估计交货时间:

批处理功能

这家餐厅过去的平均准备时间

流媒体功能

过去 10 分钟内,他们还有多少其他订单,以及有多少送货人可用

流媒体功能与在线功能

我听说过可以互换使用的术语“流媒体功能”和“在线功能”。它们实际上是不同的。在线的特征更通用,因为它们指的是用于在线预测的任何特征,包括存储在内存中的批量特征。

用于在线预测的一种非常常见的批处理功能类型,尤其是基于会话的推荐,是项目嵌入。项目嵌入通常是批量预先计算的,并在需要在线预测时提取。在这种情况下,嵌入可以被认为是在线特征,而不是流特征。

流特征专门指从流数据计算的特征。

图 7-6显示了使用流式特征和批处理特征的在线预测的简化架构。一些公司将这种预测称为“流式预测”,以区别于不使用流式功能的在线预测。

图 7-6。一种简化的在线预测架构,同时使用批量特征和流特征

 但是,在线预测和批量预测不必相互排斥。一种混合解决方案是您预先计算流行查询的预测,然后为不太流行的查询在线生成预测。表 7-1总结了在线预测和批量预测要考虑的关键点。

表 7-1。批量预测和在线预测之间的一些关键区别
批量预测(异步)在线预测(同步)
频率定期,例如每四个小时一旦请求到来
对...有用当您不需要即时结果时处理累积的数据(例如推荐系统)一旦生成数据样本就需要预测(例如欺诈检测)
针对高吞吐量低延迟

在许多应用程序中,在线预测和批量预测同时用于不同的用例。例如,DoorDash 和 UberEats 等食品订购应用程序使用批量预测来生成餐厅推荐——因为有很多餐馆,在线生成这些推荐需要很长时间。但是,一旦您点击餐厅,就会使用在线预测生成食物推荐。

许多人认为,在线预测在成本和性能方面的效率都低于批量预测,因为您可能无法将输入批量化并利用矢量化或其他优化技术。这不一定是真的,正如我们已经在“批处理与流处理”一节中讨论的那样。

此外,通过在线预测,您不必为未访问您网站的用户生成预测。想象一下,您运行一个应用程序,其中每天只有 2% 的用户登录——例如,在 2020 年,Grubhub 有 3100 万用户和 622,000 个每日订单。15如果您生成预测对于每天的每个用户,用于生成 98% 预测的计算都将被浪费。

从批量预测到在线预测

对于具有学术背景的人来说,更自然的预测方式可能是在线。你给你的模型一个输入,它会立即生成一个预测接收该输入。这可能是大多数人在制作原型时与模型交互的方式。大多数公司在首次部署模型时也可能更容易做到这一点。您导出模型,将导出的模型上传到 Amazon SageMaker 或 Google App Engine,然后取回公开的终端节点。16现在,如果您向该端点发送包含输入的请求,它将发回在该输入上生成的预测。

在线预测的一个问题是您的模型可能需要很长时间才能生成预测。如果您提前计算预测并将它们存储在数据库中,并在请求到达时获取它们,而不是在预测到达时立即生成预测,该怎么办?这正是批量预测所做的。使用这种方法,您可以一次生成多个输入的预测,利用分布式技术有效地处理大量样本。

因为预测是预先计算的,所以您不必担心模型生成预测需要多长时间。出于这个原因,批量预测也可以被视为减少更复杂模型的推理延迟的技巧——检索预测所需的时间通常少于生成预测所需的时间。

当您想要生成大量预测并且不需要立即获得结果时,批量预测非常有用。您不必使用所有生成的预测。例如,您可以为所有客户预测他们购买新产品的可能性,并覆盖前 10%。

但是,批量预测的问题在于它会使您的模型对用户的更改偏好的响应速度较慢。即使在 Netflix 等技术更先进的公司中也可以看到这种限制。假设您最近一直在看很多恐怖电影,所以当您第一次登录 Netflix 时,恐怖电影会主导推荐。但是你今天心情很好,所以你搜索“喜剧”并开始浏览喜剧类别。Netflix 应该在他们的推荐列表中学习并向您展示更多喜剧,对吗?在编写本书时,它无法更新列表,直到生成下一批推荐,但我毫不怀疑这个限制将在不久的将来得到解决。

批量预测的另一个问题是,您需要提前知道生成预测的请求。在为用户推荐电影的情况下,您提前知道要为多少用户生成推荐。17但是,如果您有不可预知的查询——如果您有一个从英语翻译成法语的系统,可能无法预测要翻译的每一个可能的英语文本——您需要使用在线预测来在请求到达时生成预测。

在 Netflix 示例中,批量预测会导致轻微的不便(与用户参与度和留存率密切相关),而不是灾难性的失败。在许多应用中,批量预测会导致灾难性故障或根本不起作用。在线预测至关重要的示例包括高频交易、自动驾驶汽车、语音助手、使用面部或指纹解锁手机、老年人护理跌倒检测和欺诈检测。能够检测到三个小时前发生的欺诈交易仍然比根本没有检测到要好,但是能够实时检测到它可以防止欺诈交易通过。

当在线预测不够便宜或不够快时,批量预测是一种解决方法。如果您可以根据需要以完全相同的成本和相同的速度生成每个预测,为什么要提前生成一百万个预测并担心存储和检索它们?

随着硬件变得更加定制化和强大,并且正在开发更好的技术以实现更快、更便宜的在线预测,在线预测可能会成为默认设置。

近年来,公司进行了大量投资,从批量预测转向在线预测。为了克服在线预测的延迟挑战,需要两个组件:

  • 一个(近乎)实时的管道,可以处理传入的数据,提取流特征(如果需要),将它们输入到模型中,并近乎实时地返回预测。具有实时传输和流计算引擎的流管道可以帮助解决这个问题。

  • 一种可以以最终用户可接受的速度生成预测的模型。对于大多数消费者应用程序来说,这意味着毫秒。

我们已经在第 3 章讨论过流处理。出色地下一节继续讨论流流水线与批处理流水线的统一。然后我们将在“模型优化”部分讨论如何加速推理。

统一 Batch Pipeline 和 Streaming Pipeline

批量预测很大程度上是遗留系统的产物。在过去的十年中,大数据处理一直由像 MapReduce 和 Spark 这样的批处理系统,它们使我们能够非常有效地定期处理大量数据。当公司开始使用 ML 时,他们利用现有的批处理系统进行预测。当这些公司想要使用流媒体功能进行在线预测时,他们需要建立一个单独的流媒体管道。让我们通过一个例子来使这更具体。

想象一下,您想要构建一个模型来预测 Google 地图等应用程序的到达时间。随着用户旅行的进行,预测会不断更新。您可能想要使用的一个特征是过去五分钟内您路径上所有汽车的平均速度。对于培训,您可以使用上个月的数据。要从您的训练数据中提取此特征,您可能希望将所有数据放入一个数据框中,以便同时为多个训练样本计算此特征。在推理期间,将在滑动窗口上不断计算此特征。这意味着在训练中,这个特征是批量计算的,而在推理过程中,这个特征是在流式过程中计算的。

拥有两个不同的管道来处理您的数据是 ML 生产中出现错误的常见原因。错误的一个原因是当一个管道中的更改未正确复制到另一个管道时,导致两个管道提取两组不同的特征。如果两个管道由两个不同的团队维护,这尤其常见,例如 ML 团队维护批处理管道进行训练,而部署团队维护流管道进行推理,如图 7-7所示。

图 7-7。有两个不同的训练和推理管道是生产中 ML 错误的常见来源

图 7-8显示了用于进行在线预测的 ML 系统的数据管道的更详细但也更复杂的特征。标有研究的盒装元素是人们在学术环境中经常接触到的内容。

图 7-8。用于进行在线预测的 ML 系统的数据管道

 构建基础设施以统一流处理和批处理已成为近年来 ML 社区的热门话题。包括 Uber 和微博在内的公司已经进行了重大的基础设施改造,通过使用 Apache Flink 等流处理器来统一他们的批处理和流处理管道。18一些公司使用特色商店来确保训练期间使用的批特征与预测中使用的流特征之间的一致性。我们将在第 10 章讨论特征存储。

模型压缩

我们已经讨论过流式管道,它允许 ML 系统从传入数据中提取流式特征,并将它们(近)实时地输入到 ML 模型中。但是,对于在线预测而言,拥有近乎(实时)的管道是不够的。在下一节中,我们将讨论 ML 模型的快速推理技术。

如果您要部署的模型需要很长时间才能生成预测,有三种主要方法可以减少其推理延迟:使其推理速度更快、模型更小或使其部署的硬件运行得更快。

使模型更小的过程称为模型压缩,而使其推理速度更快的过程称为推理优化。最初,模型压缩是使模型适合边缘设备。但是,使模型更小通常会使它们运行得更快。

我们将在“模型优化”部分讨论推理优化,我们将在“云端和边缘机器学习”部分讨论专门为更快运行 ML 模型而开发的硬件后端的前景。在这里,我们将讨论模型压缩。

关于模型压缩的研究论文数量正在增长。现成的公用事业正在激增。截至 2022 年 4 月,Awesome Open Source 有一份“168 大模型压缩开源项目”名单,而且这个名单还在不断增加。虽然有许多新技术正在开发中,但您可能最常遇到的四种技术是低秩优化、知识蒸馏、修剪和量化。有兴趣全面回顾的读者可能想查看 Cheng 等人的“深度神经网络模型压缩和加速调查”,该论文于 2020 年更新。19

低秩分解

低秩分解背后的关键思想是用低维张量替换高维张量。20一种低秩分解紧凑型卷积滤波器,其中过度参数化(具有太多参数)的卷积滤波器被紧凑块替换,以减少参数数量并提高速度。

例如,通过使用多种策略,包括将 3×3 卷积替换为 1×1 卷积,SqueezeNets 在 ImageNet 上实现了 AlexNet 级别的精度,而参数减少了 50 倍。21

类似地,MobileNets 将大小为K × K × C的标准卷积分解为深度卷积(K × K × 1)和逐点卷积(1 × 1 × C),其中K是内核大小,C是通道数. 这意味着每个新卷积只使用2 + C而不是C参数。如果K = 3,这意味着参数数量减少了 8 到 9 倍(见图 7-9)。22

图 7-9。MobileNets 中的紧凑型卷积滤波器。(a) 中的标准卷积滤波器被 (b) 中的深度卷积和 (c) 中的点卷积代替,以构建深度可分离滤波器。资料来源:改编自 Howard等人的图片。

与标准模型相比,此方法已用于开发具有显着加速的较小模型。然而,它往往特定于某些类型的模型(例如,紧凑卷积滤波器特定于卷积神经网络)并且需要大量架构知识来设计,因此它还没有广泛适用于许多用例。

知识蒸馏

知识蒸馏是一种方法,其中训练一个小模型(学生)来模仿一个更大的模型或集合模特(老师)。您将部署较小的模型。尽管学生经常在经过预培训的老师之后接受培训,但两者也可能同时接受培训。23生产中使用的蒸馏网络的一个例子是 DistilBERT,它将 BERT 模型的大小减少了 40%,同时保留了 97% 的语言理解能力,速度提高了 60%。24

这种方法的优点是无论教师和学生网络之间的架构差异如何,它都可以工作。例如,您可以将随机森林作为学生,将变压器作为教师。这种方法的缺点是它高度依赖于教师网络的可用性。如果您使用预训练模型作为教师模型,则训练学生网络将需要更少的数据并且可能会更快。但是,如果您没有可用的教师,则必须在训练学生网络之前先训练教师网络,而训练教师网络将需要更多的数据并且需要更多的时间来训练。这种方法对应用程序和模型架构也很敏感,因此在生产中没有广泛使用。

修剪

修剪最初是一种方法用于决策树,您可以在其中删除对分类不重要且冗余的树部分。25随着神经网络得到更广泛的采用,人们开始意识到神经网络是过度参数化的,并开始寻找方法来减少额外参数带来的工作量。

修剪,在神经网络的上下文中,有两个含义。一种是移除神经网络的整个节点,这意味着改变其架构并减少其参数数量。更常见的含义是找到对预测最无用的参数并将其设置为 0。在这种情况下,剪枝不会减少参数的总数,只会减少非零参数的数量。神经网络的架构保持不变。这有助于减小模型的大小,因为修剪使神经网络更加稀疏,而稀疏架构往往比密集结构需要更少的存储空间。实验表明,剪枝技术可以将训练网络的非零参数数量减少 90% 以上,26第 11 章中,我们将讨论剪枝如何将偏差引入模型。

虽然人们普遍认为修剪是有效的,但27关于修剪的实际价值已经有很多讨论。刘等人。认为修剪的主要价值不在于继承的“重要权重”,而在于修剪后的架构本身。28在某些情况下,修剪可用作架构搜索范式,并且应该从头开始将修剪后的架构重新训练为密集模型。然而,朱等人。表明修剪后的大型稀疏模型优于重新训练的密集模型。29

量化

量化是最普遍和最常用的模型压缩方法。这很简单,并且可以概括任务和架构。

量化通过以下方式减小模型的大小使用更少的位来表示其参数。默认情况下,大多数软件包使用 32 位来表示浮点数(单精度浮点)。如果一个模型有 100M 个参数并且每个参数需要 32 位来存储,那么它将占用 400 MB。如果我们使用 16 位来表示一个数字,我们将减少一半的内存占用。使用 16 位表示浮点数称为半精度。

除了使用浮点数之外,您还可以拥有一个完全采用整数的模型;每个整数只需要 8 位来表示。这种方法也称为“定点”。在极端情况下,一些人尝试了每个权重的 1 位表示(二进制权重神经网络),例如 BinaryConnect 和 XNOR-Net。30 XNOR-Net 论文的作者剥离了 Xnor.ai,这是一家专注于模型压缩的初创公司。2020 年初,它被苹果以 2 亿美元的价格收购。31

量化不仅减少了内存占用,还提高了计算速度。首先,它允许我们增加批量大小。其次,较低的精度会加快计算速度,从而进一步减少训练时间和推理延迟。考虑两个数字的相加。如果我们逐位执行加法,每次加法需要x纳秒,对于 32 位数字将需要 32 x纳秒,但对于 16 位数字只需 16 x纳秒。

量化有缺点。减少表示数字的位数意味着您可以表示较小范围的值。对于该范围之外的值,您必须将它们四舍五入和/或将它们缩放到范围内。舍入数字会导致舍入误差,而小的舍入误差会导致较大的性能变化。您还冒着将数字舍入/缩放为下溢/溢出并将其呈现为 0 的风险。在低级别实现有效的舍入和缩放并非易事,但幸运的是,主要框架已内置此功能。

量化可以在训练期间发生(量化感知训练),32模型在较低精度下训练,也可以在训练后发生,模型在单精度浮点中训练,然后进行量化以进行推理。在训练期间使用量化意味着您可以为每个参数使用更少的内存,这允许您在相同的硬件上训练更大的模型。

最近,在大多数现代训练硬件的支持下,低精度训练变得越来越流行。NVIDIA 推出了 Tensor Core,这是一种支持混合精度训练的处理单元。33 个谷歌 TPU(张量处理单元)还支持使用 Bfloat16(16 位大脑浮点格式)进行训练,该公司称之为“云 TPU 高性能的秘诀”。34定点训练还没有那么流行,但已经取得了很多可喜的成果。35

定点推理已成为标准在行业中。一些边缘设备仅支持定点推理。最流行的设备机器学习推理框架——谷歌的 TensorFlow Lite、Facebook 的 PyTorch Mobile、英伟达的TensorRT——只需几行代码即可免费提供训练后量化。

案例分析

为了更好地了解如何在生产中优化模型,请考虑 Roblox 的一个引人入胜的案例研究,了解他们如何扩展 BERT 以服务于 CPU 上每天超过 10 亿个请求。36对于他们的许多 NLP 服务,他们需要以低于 20 毫秒的延迟每秒处理超过 25,000 次推理,如图 7-10所示。他们从具有固定形状输入的大型 BERT 模型开始,然后用 DistilBERT 替换 BERT,用动态形状输入替换固定形状输入,最后对其进行量化。

图 7-10。通过各种模型压缩方法改善延迟。资料来源:改编自 Le 和 Kaehler 的图片

 他们获得的最大性能提升来自量化。将 32 位浮点数转换为 8 位整数可将延迟降低 7 倍,将吞吐量提高 8 倍。

这里的结果似乎很有希望改善延迟;但是,它们应该与一粒盐一起服用因为没有提到每次性能改进后输出质量的变化。

云和边缘的机器学习

您需要考虑的另一个决定是模型的计算将发生在哪里:在云端还是在边缘。在云上意味着大量的计算是在云上完成的,要么公共云或私有云。在边缘意味着大量计算是在消费设备上完成的,例如浏览器、手机、笔记本电脑、智能手表、汽车、安全摄像头、机器人、嵌入式设备、FPGA(现场可编程门阵列)和 ASIC(专用集成电路)——也称为边缘设备。

最简单的方法是将模型打包并通过 AWS 或 GCP 等托管云服务进行部署,这就是许多公司在开始使用 ML 时部署的数量。云服务已经完成了一项令人难以置信的工作,使公司能够轻松地将 ML 模型投入生产。

但是,云部署有很多缺点。首先是成本。ML 模型可能是计算密集型的,而且计算成本很高。早在 2018 年,Pinterest、Infor 和 Intuit 等大公司就已经在每年花费数亿美元购买云账单。37对于中小型公司来说,这个数字可能在每年 5 万美元到 200 万美元之间。38处理云服务的错误可能导致初创公司破产。39

随着云计算费用的攀升,越来越多的公司正在寻找将计算推向边缘设备的方法。在边缘完成的计算越多,对云的需求就越少,他们为服务器支付的费用就越少。

除了有助于控制成本外,还有许多特性使边缘计算具有吸引力。首先是它允许您的应用程序在云计算无法运行的地方运行。当您的模型位于公共云上时,它们依靠稳定的互联网连接将数据发送到云端并返回。边缘计算允许您的模型在没有互联网连接或连接不可靠的情况下工作,例如在农村地区或发展中国家。我曾与几家有严格禁止互联网政策的公司和组织合作过,这意味着我们要出售的任何应用程序都不得依赖互联网连接。

其次,当您的模型已经在消费者的设备上时,您可以减少对网络延迟的担忧。要求通过网络传输数据(将数据发送到云上的模型以进行预测,然后将预测发送回用户)可能会使某些用例变得不可能。在许多情况下,网络延迟是比推理延迟更大的瓶颈。例如,您可能能够将 ResNet-50 的推理延迟从 30 毫秒减少到 20 毫秒,但网络延迟可能会长达几秒钟,具体取决于您所在的位置以及您尝试使用的服务。

在处理敏感的用户数据时,将模型置于边缘也很有吸引力。云上的 ML 意味着您的系统可能必须通过网络发送用户数据,使其容易被拦截。云计算通常还意味着将许多用户的数据存储在同一个地方,这意味着数据泄露会影响到许多人。“近 80% 的公司在过去 18 个月内经历过云数据泄露,” Security杂志称。40

边缘计算使合规变得更容易GDPR 等关于如何传输或存储用户数据的法规。虽然边缘计算可能会减少隐私问题,但它并不能完全消除它们。在某些情况下,边缘计算可能使攻击者更容易窃取用户数据,例如他们可以随身携带设备。

要将计算转移到边缘,边缘设备必须足够强大以处理计算,有足够的内存来存储 ML 模型并将它们加载到内存中,以及有足够的电池或连接到能源来为应用程序供电一段合理的时间。如果您的手机能够运行 BERT,那么在手机上运行全尺寸的 BERT 是一种非常快速的耗尽电池电量的方法。

由于边缘计算相对于云计算具有许多优势,因此公司正在竞相开发针对不同 ML 用例优化的边缘设备。包括谷歌、苹果和特斯拉在内的老牌公司都宣布了他们制造自己芯片的计划。与此同时,机器学习硬件初创公司已经筹集了数十亿美元来开发更好的人工智能芯片。41预计到 2025 年,全球有源边缘设备的数量将超过 300 亿台。42

有了这么多新的硬件产品来运行 ML 模型,一个问题出现了:我们如何让我们的模型有效地在任意硬件上运行?在下一节中,我们将讨论如何编译和优化模型以在特定硬件后端运行它。在此过程中,我们将介绍您在处理边缘模型时可能遇到的重要概念,包括中间表示 (IR) 和编译器。

编译和优化边缘设备的模型

对于使用特定框架(例如 TensorFlow 或 PyTorch)构建以在硬件后端运行的模型,框架必须得到硬件供应商的支持。例如,尽管 TPU 在 2018 年 2 月公开发布,但直到 2020 年 9 月,TPU 才支持 PyTorch。在此之前,如果您想使用 TPU,则必须使用 TPU 支持的框架。

为硬件后端的框架提供支持是耗时且工程密集型的。从 ML 工作负载映射到硬件后端需要了解并利用该硬件的设计,并且不同的硬件后端具有不同的内存布局和计算原语,如图 7-11所示。

图 7-11。CPU、GPU 和 TPU 的不同计算原语和内存布局。资料来源:改编自 Chen 等人的图片。43

例如,CPU 的计算原语曾经是数字(标量),GPU 的计算原语曾经是一维向量,而 TPU 的计算原语是二维向量(张量)。44与二维向量相比,使用一维向量执行卷积算子会有很大不同。同样,您需要考虑不同的 L1、L2 和 L3 布局和缓冲区大小以有效地使用它们。

由于这一挑战,框架开发人员倾向于只专注于为少数服务器级硬件提供支持,而硬件供应商倾向于为少数框架提供自己的内核库。将 ML 模型部署到新硬件需要大量的手动工作。

与其为每个新的硬件后端定位新的编译器和库,不如创建一个中间人来桥接框架和平台呢?框架开发人员将不再需要支持每种类型的硬件;他们只需要将他们的框架代码翻译成这个中间人。然后,硬件供应商可以支持一个中间人而不是多个框架。

这种“中间人”被称为中间表示(IR)。IR 是编译器工作方式的核心。从模型的原始代码中,编译器生成一系列高级和低级 IR,然后生成硬件后端的本机代码,以便它可以在该硬件后端上运行,如图 7-12所示。

图 7-12。原始模型代码与可在给定硬件后端运行的机器代码之间的一系列高级和低级 IR

 这个过程也称为降低,因为您将高级框架代码“降低”为低级硬件原生代码。它没有翻译,因为它们之间没有一对一的映射。

高级 IR 通常是您的 ML 模型的计算图。计算图是描述计算执行顺序的图。感兴趣的读者可以阅读PyTorchTensorFlow中的计算图。

模型优化

在您“降低”代码以将模型运行到您选择的硬件中之后,您可能会遇到性能问题。生成的机器代码可能能够在硬件后端上运行,但它可能无法有效地做到这一点。生成的代码可能没有利用数据局部性和硬件缓存,或者它可能没有利用可以加速代码的向量或并行操作等高级功能。

典型的 ML 工作流程由许多框架和库组成。例如,您可以使用 pandas/dask/ray 从数据中提取特征。您可以使用 NumPy 执行矢量化。您可以使用 Hugging Face 的 Transformers 等预训练模型来生成特征,然后使用由 sklearn、TensorFlow 或 LightGBM 等各种框架构建的模型集合进行预测。

尽管这些框架中的个别功能可能会被优化,但跨框架几乎没有优化。在这些函数之间移动数据以进行计算的幼稚方式可能会导致整个工作流程的速度下降一个数量级。斯坦福 DAWN 实验室的研究人员进行的一项研究发现,与手动优化的代码相比,使用 NumPy、pandas 和 TensorFlow 的典型 ML 工作负载在一个线程中的运行速度要慢 23 倍。45

在许多公司中,通常发生的情况是数据科学家和 ML 工程师开发的模型似乎在开发中运行良好。然而,当部署这些模型时,它们变得太慢了,因此他们的公司聘请了优化工程师来优化他们的模型,以适应模型运行的硬件。Mythic 优化工程师的职位描述示例如下:

这一愿景在 AI 工程团队中得到体现,我们的专业知识用于开发针对我们的硬件进行优化的 AI 算法和模型,并为 Mythic 的硬件和编译器团队提供指导。

AI 工程团队通过以下方式显着影响 Mythic:

  • 开发量化和鲁棒性 AI 再训练工具
  • 为我们的编译器研究利用神经网络适应性的新功能
  • 开发针对我们的硬件产品进行优化的新神经网络
  • 与内部和外部客户对接以满足他们的发展需求

优化工程师很难找到,而且雇佣成本很高,因为他们需要同时具备 ML 和硬件架构方面的专业知识。优化编译器(也优化您的代码的编译器)是一种替代解决方案,因为它们可以自动化优化模型的过程。在将 ML 模型代码降低为机器代码的过程中,编译器可以查看您的 ML 模型的计算图以及它所包含的运算符——卷积、循环、交叉熵——并找到一种加速它的方法。

有两种方法可以优化您的 ML 模型:本地和全局。本地是当您优化模型的一个或一组运算符时。全局是当您端到端优化整个计算图时。

众所周知,有一些标准的局部优化技术可以加速您的模型,其中大多数使事情并行运行或减少芯片上的内存访问。以下是四种常用技术:

矢量化

给定一个循环或嵌套循环,与其一次执行一项,不如同时执行内存中连续的多个元素,以减少数据 I/O 引起的延迟。

并行化

给定一个输入数组(或n维数组),将其划分为不同的、独立的工作块,并分别对每个块进行操作。

循环平铺46

更改数据访问顺序循环利用硬件的内存布局和缓存。这种优化取决于硬件。CPU 上的良好访问模式不是 GPU 上的良好访问模式。

算子融合

融合多个运算符合二为一,以避免多余的内存访问。例如,对同一个数组的两个操作需要对该数组进行两次循环。在融合的情况下,它只是一个循环。图 7-13显示了一个算子融合的例子。

图 7-13。算子融合的一个例子。资料来源:改编自 Matthias Boehm 的图片47

 为了获得更大的加速,您需要利用计算图的更高级别结构。例如,具有计算图的卷积神经网络可以垂直或水平融合,以减少内存访问并加快模型速度,如图 7-14所示。

图 7-14。卷积神经网络计算图的垂直和水平融合。来源:改编自 TensorRT 团队48的图片

使用 ML 优化 ML 模型

正如上一节所暗示的那样卷积神经网络的垂直和水平融合,有许多可能的方法来执行给定的计算图。例如,给定三个运算符 A、B 和 C,您可以将 A 与 B 融合,将 B 与 C 融合,或者将 A、B 和 C 融合在一起。

传统上,框架和硬件供应商聘请优化工程师,他们根据他们的经验提出关于如何最好地执行模型计算图的启发式方法。例如,NVIDIA 可能有一个工程师或一个工程师团队专门专注于如何让 ResNet-50 在他们的 DGX A100 服务器上运行得非常快。49

手工设计的启发式算法有几个缺点。首先,它们不是最优的。不能保证工程师提出的启发式方法是最好的解决方案。其次,它们是非自适应的。在新框架或新硬件架构上重复该过程需要付出巨大的努力。

由于模型优化依赖于其计算图所包含的算子,这一点变得复杂。优化卷积神经网络不同于优化循环神经网络,也不同于优化变压器。NVIDIA 和 Google 等硬件供应商专注于为其硬件优化 ResNet-50 和 BERT 等流行模型。但是,如果您作为 ML 研究人员想出一个新的模型架构呢?在硬件供应商采用和优化之前,您可能需要自己对其进行优化,以证明它的速度很快。

如果您没有好的启发式方法,一种可能的解决方案可能是尝试所有可能的方法来执行计算图,记录它们需要运行的时间,然后选择最好的方法。然而,鉴于可能路径的组合数量,探索它们将是棘手的。幸运的是,近似解决棘手问题是 ML 擅长的。如果我们使用 ML 来缩小搜索空间,这样我们就不必探索那么多路径,并预测一条路径需要多长时间,这样我们就不必等待整个计算图完成执行,该怎么办?

估计通过计算图的路径运行需要多长时间是很困难的,因为它需要对该图做出很多假设。专注于图表的一小部分要容易得多。

如果您在 GPU 上使用 PyTorch,您可能已经看过torch.backends.cudnn.benchmark=True. 当它设置为 True 时,将启用cuDNN 自动调谐。cuDNN 自动调谐搜索一组预先确定的选项以执行卷积算子,然后选择最快的方式。尽管 cuDNN 自动调整很有效,但它只适用于卷积算子。一个更通用的解决方案是autoTVM,它是开源编译器堆栈 TVM 的一部分。autoTVM 使用子图而不仅仅是一个运算符,因此它使用的搜索空间要复杂得多。autoTVM 的工作方式相当复杂,但简单来说:

  1. 它首先将您的计算图分解为子图。

  2. 它预测每个子图有多大。

  3. 它分配时间来为每个子图搜索最佳路径。

  4. 它缝合了将每个子图一起运行以执行整个图的最佳方法。

autoTVM 测量运行每条路径所需的实际时间,从而为它提供地面实况数据来训练成本模型以预测未来路径需要多长时间。这种方法的优点在于,因为模型是使用运行时生成的数据进行训练的,所以它可以适应它运行的任何类型的硬件。缺点是成本模型开始改进需要更多时间。图 7-15显示了 autoTVM 在 NVIDIA TITAN X 上的模型 ResNet-50 与 cuDNN 相比的性能提升。

虽然 ML 驱动的编译器的结果令人印象深刻,但它们有一个问题:它们可能很慢。您遍历所有可能的路径并找到最优化的路径。对于复杂的 ML 模型,此过程可能需要数小时甚至数天。但是,这是一次性操作,您的优化搜索结果可以被缓存并用于优化现有模型并为未来的调整会话提供起点。您为一个硬件后端优化一次模型,然后在相同硬件类型的多台设备上运行它。当您准备好模型时,这种优化是理想的用于生产和目标硬件运行推理。

图 7-15。autoTVM 在 NVIDIA TITAN X 上的 ResNet-50 上通过 cuDNN 实现了加速。autoTVM 需要大约 70 次试验才能胜过 cuDNN。资料来源:陈等人。50

浏览器中的机器学习

我们一直在讨论编译器如何帮助我们在特定硬件上生成机器本机代码运行模型后端。但是,可以通过在浏览器中运行代码来生成可以在任何硬件后端上运行的代码。如果您可以在浏览器中运行模型,则可以在任何支持浏览器的设备上运行模型:MacBook、Chromebook、iPhone、Android 手机等。您无需关心这些设备使用什么芯片。如果 Apple 决定从 Intel 芯片切换到 ARM 芯片,那不是你的问题。

说到浏览器,很多人都会想到 JavaScript。有一些工具可以帮助您将模型编译为 JavaScript,例如TensorFlow.jsSynapticBrain.js。然而,JavaScript 速度很慢,并且它作为一种编程语言的能力对于从数据中提取特征等复杂逻辑来说是有限的。

更有前途方法是 WebAssembly (WASM)。WASM 是一个开放标准,允许您在浏览器中运行可执行程序。在 scikit-learn、PyTorch、TensorFlow 或您使用的任何框架中构建模型后,您可以将模型编译为 WASM,而不是编译模型以在特定硬件上运行。你会得到一个可执行文件,你可以用它来使用 JavaScript。

WASM 是我在过去几年中看到的最令人兴奋的技术趋势之一。它高性能、易于使用,并且拥有一个像野火一样发展的生态系统。51截至 2021 年 9 月,全球 93% 的设备都支持它。52

WASM 的主要缺点是因为 WASM 在浏览器中运行,所以速度很慢。尽管 WASM 已经快得多了与 JavaScript 相比,与在设备(例如 iOS 或 Android 应用程序)上本地运行代码相比,它仍然很慢。Jangda 等人的一项研究。显示编译为 WASM 的应用程序运行速度比原生应用程序平均慢 45%(在 Firefox 上)到 55%(在 Chrome 上)。53

概括

恭喜,您可能已经完成了本书中技术含量最高的章节之一!这一章是技术性的,因为部署 ML 模型是一项工程挑战,而不是 ML 挑战。

我们讨论了部署模型的不同方法,比较了在线预测与批量预测,以及边缘机器学习与云端机器学习。每种方式都有自己的挑战。在线预测让你的模型更能响应用户不断变化的偏好,但你不得不担心推理延迟。当您的模型需要很长时间才能生成预测时,批量预测是一种解决方法,但它会降低您的模型的灵活性。

同样,在云上进行推理很容易设置,但由于网络延迟和云成本,它变得不切实际。在边缘进行推理需要拥有具有足够计算能力、内存和电池的边缘设备。

然而,我相信这些挑战中的大部分是由于机器学习模型运行所依赖的硬件的限制。随着硬件变得更加强大并针对 ML 进行了优化,我相信 ML 系统将过渡到在设备上进行在线预测,如图 7-16 所示

图 7-16。随着硬件变得更加强大,机器学习模型将转向在线和边缘

我曾经认为一个 ML 项目是在模型部署后完成的,我希望我在本章中已经明确了我的严重错误。将模型从开发环境转移到生产环境会产生一系列全新的问题。首先是如何在生产中保留该模型。在下一章中,我们将讨论我们的模型如何在生产中失败,以及如何持续监控模型以检测问题并尽快解决它们。

评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Sonhhxg_柒

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值