窝牛号

Amazon Ads 使用 PyTorch 和 AWS Inferentia 扩展广告处理模型

亚马逊广告通过在亚马逊商店内外展示的广告(包括网站、应用程序和超过 15 个国家/地区的流媒体电视内容)帮助公司建立品牌并与购物者建立联系。各种规模的企业和品牌,包括注册卖家、供应商、图书供应商、Kindle Direct Publishing (KDP) 作者、应用程序开发人员和代理机构都可以上传自己的广告创意,其中可以包括图像、视频、音频,当然,在亚马逊上销售的产品。

为了促进准确、安全和愉快的购物体验,这些广告必须符合内容指南。例如,广告不能闪烁,产品必须在适当的环境中进行展示,图像和文字应该适合普通观众。为了帮助确保广告符合所需的政策和标准,我们需要开发可扩展的机制和工具。

作为一种解决方案,Amazon使用机器学习 (ML) 模型来展示可能需要修改的广告。随着深度神经网络在过去十年中蓬勃发展,我们的数据科学团队开始探索更通用的深度学习 (DL) 方法,这些方法能够以最少的人工干预处理文本、图像、音频或视频。为此,我们使用 Pytorch 构建了计算机视觉 (CV) 和自然语言处理 (NLP) 模型,可以自动标记可能不合规的广告。PyTorch 直观、灵活且用户友好,让我们无缝过渡到使用 DL 模型。在基于 AWS Inferentia 的 Amazon EC2 Inf1 实例而不是基于 GPU 实例上部署这些新模型,对于相同的工作负载,我们的推理延迟降低了 30%,推理成本降低了 71%。

过渡到深度学习

我们的机器学习系统将经典模型与词嵌入配对以评估广告文本。但是我们的需求不断变化,随着提交量的不断扩大,我们需要一种足够灵活的方法来随着我们的业务扩展。此外,我们的模型必须快速并在几毫秒内投放广告,以提供最佳的客户体验。

在过去的十年里,深度学习在许多领域变得非常流行,包括自然语言、视觉和音频。因为深度神经网络通过许多层来引导数据集——逐步提取更高级别的特征——它们可以比经典的 ML 模型做出更细微的推断。例如,DL 模型不仅可以简单地检测被禁止的语言,还可以拒绝虚假声明的广告。

此外,深度学习技术是可转移的——为一项任务训练的模型可以适应执行相关任务。例如,可以优化预训练的神经网络以检测图像中的对象,然后进行微调以识别不允许在广告中显示的特定对象。

深度神经网络可以自动执行两个经典 ML 最耗时的步骤:特征工程和数据标记。与需要探索性数据分析和手工设计特征的传统监督学习方法不同,深度神经网络直接从数据中学习相关特征。DL 模型还可以分析非结构化数据,例如文本和图像,而无需 ML 中所需的预处理。深度神经网络可以有效扩展更多数据,并且在涉及大型数据集的应用程序中表现特别好。

我们选择 PyTorch 来开发我们的模型,因为它帮助我们最大限度地提高了系统的性能。借助 PyTorch,我们可以更好地为客户服务,同时利用 Python 最直观的概念。PyTorch 中的编程是面向对象的:它将处理函数与它们修改的数据组合在一起。因此,我们的代码库是模块化的,我们可以在不同的应用程序中重用代码片段。此外,PyTorch 的 Eager 模式允许循环和控制结构,因此模型中的操作更复杂。Eager 模式可以很容易地对我们的模型进行原型设计和迭代,并且我们可以使用各种数据结构。这种灵活性有助于我们快速更新模型以满足不断变化的业务需求。

“在此之前,我们尝试了其他“Pythonic”框架,但 PyTorch 显然是我们的赢家。” 应用科学家 Yashal Kanungo 说。“使用 PyTorch 很容易,因为这种结构感觉是 Python 编程的原生结构,而数据科学家对此非常熟悉”。

模型训练

今天,我们完全可以使用 PyTorch 重新构建我们的文本模型。为了节省时间和金钱,我们经常通过微调预训练的 NLP 模型来跳过训练的早期阶段以进行语言分析。如果我们需要一个新模型来评估图像或视频,我们首先浏览 PyTorch 的torchvision库,该库为图像和视频分类、对象检测、实例分割和姿势估计提供了预训练选项。对于专门的任务,我们从头开始构建自定义模型。PyTorch 非常适合这一点,因为 Eager 模式和用户友好的前端可以轻松地尝试不同的架构。

在开始训练之前,我们会优化模型的超参数、定义网络架构的变量(例如隐藏层的数量)和训练机制(例如学习率和批量大小)。选择适当的超参数值至关重要,因为它们将塑造模型的训练行为。在这一步中,我们依赖AWS 的 ML 平台SageMaker 中的贝叶斯搜索功能。贝叶斯搜索将超参数调整视为回归问题:它提出可能产生最佳结果的超参数组合并运行训练作业来测试这些值。每次试验后,回归算法会确定下一组要测试的超参数值,并且性能会逐步提高。

我们使用 SageMaker Notebooks 对我们的模型进行原型设计和迭代。Eager 模式让我们通过为每个训练批次构建一个新的计算图来快速原型模型;操作的顺序可以在迭代之间改变,以适应不同的数据结构或与中间结果相结合。这使我们可以在训练期间调整网络,而无需从头开始。这些动态图对于基于可变序列长度的递归计算特别有价值,例如使用 NLP 分析的广告中的单词、句子和段落。

当我们最终确定模型架构后,我们会在SageMaker上部署训练作业。PyTorch 通过同时运行大量训练作业帮助我们更快地开发大型模型。PyTorch 的分布式数据并行(DDP) 模块在 SageMaker 内地多台互连机器上复制单个模型,并且所有进程在数据集自己独特的部分上同时向前运行。在反向传播过程中,模块对所有过程的梯度进行平均,因此每个局部模型都使用相同的参数值进行更新。

模型部署管道

当我们在生产中部署模型时,我们希望确保在不影响预测准确性的情况下降低推理成本。PyTorch 的多项功能和 AWS 服务帮助我们应对了这一挑战。

动态图的灵活性丰富了训练,但在部署中,我们希望最大限度地提高性能和可移植性。在 PyTorch 中开发 NLP 模型的一个优势是开箱即用,它们可以通过TorchScript追踪到静态操作序列,TorchScript是专门用于 ML 应用程序的 Python 子集。Torchscript 将 PyTorch 模型转换为更高效、生产友好的中间表示 (IR) 图,并且易于编译。我们通过模型运行样本输入,TorchScript 记录前向传递期间执行的操作。生成的 IR 图可以在高性能环境中运行,包括 C++ 和其他多线程无 Python 上下文,并且算子融合等优化可以加快运行时间。

神经元 SDK 和 AWS Inferentia 驱动的计算

我们将模型部署在由 AWS Inferentia 提供支持的Amazon EC2 Inf1 实例上,这是 Amazon 的第一个 ML 芯片,旨在加速深度学习推理工作负载。与基于 Amazon EC2 GPU 的实例相比,Inferentia 已证明可将推理成本降低多达 70%。我们使用AWS Neuron SDK(一组与 Inferentia 一起使用的软件工具)来编译和优化我们的模型,以便在 EC2 Inf1 实例上进行部署。

下面的代码片段展示了如何使用 Neuron 编译 Hugging Face BERT 模型。与 torch.jit.trace() 一样,neuron.trace() 在前向传递期间记录模型对示例输入的操作,以构建静态 IR 图。

import torch from transformers import BertModel, BertTokenizer import torch.neuron tokenizer = BertTokenizer.from_pretrained(&34;) model = BertModel.from_pretrained(&34;, returned_dict=False) inputs = tokenizer (&34;, return_tensor=&34;) neuron_model = torch.neuron.trace(model, example_inputs = (inputs[&39;], inputs[&39;]), verbose = 1) output = neuron_model(*(inputs[&39;], inputs[&39;]))

在底层,Neuron 通过将模型自动转换为更小的数据类型来优化模型的性能。默认情况下,大多数应用程序以32 位单精度浮点 (FP32) 数字格式表示神经网络值。将模型自动转换为 16 位格式——半精度浮点 (FP16) 或大脑浮点 (BF16)——减少了模型的内存占用和执行时间。在我们的案例中,我们决定使用 FP16 来优化性能,同时保持高精度。

在某些情况下,自动转换为较小的数据类型可能会引发模型预测的细微差异。为了确保模型的准确性不受影响,Neuron 比较了 FP16 和 FP32 模型的性能指标和预测。当自动转换降低模型的准确性时,我们可以告诉神经元编译器仅将权重和某些数据输入转换为 FP16,将其余中间结果保留在 FP32 中。此外,我们经常对训练数据进行几次迭代,以重新校准我们的自动铸造模型。这个过程比原来的训练要少得多。

部署

为了分析多媒体广告,我们运行了一组 DL 模型。上传到亚马逊的所有广告都通过专门的模型运行,这些模型评估它们包括的每种类型的内容:图像、视频和音频、标题、文本、背景,甚至语法、语法和可能不恰当的语言。我们从这些模型收到的信号表明广告是否符合我们的标准。

部署和监控多个模型非常复杂,因此我们依赖TorchServe,SageMaker 的默认 PyTorch 模型服务库。TorchServe 由 Facebook 的 PyTorch 团队和 AWS 联合开发,旨在简化从原型设计到生产的过渡,帮助我们大规模部署经过训练的 PyTorch 模型,而无需编写自定义代码。它为推理、管理、度量和解释提供了一组安全的 REST API。TorchServe 具有多模型服务、模型版本控制、集成支持和自动批处理等功能,非常适合支持我们巨大的工作量。您可以在这篇博文中阅读更多关于在 SageMaker 上部署 Pytorch 模型并集成原生 TorchServe 的信息。

在某些用例中,我们利用 PyTorch 的面向对象编程范式将多个 DL 模型包装到一个父对象(PyTorch nn.Module)中,并将它们作为一个整体服务。在其他情况下,我们使用 TorchServe 在单独的 SageMaker 终端节点上为单独的模型提供服务,这些终端节点在 AWS Inf1 实例上运行。

自定义处理程序

TorchServe 允许我们将模型初始化、预处理、推理和后处理代码嵌入到服务器上的单个 Python 脚本 handler.py 中。该脚本(处理程序)预处理来自广告的未标记数据,通过我们的模型运行该数据,并将结果推断传递给下游系统。TorchServe 提供了几个默认处理程序,用于加载权重和架构并准备模型以在特定设备上运行。我们可以将所有额外的必需工件(例如词汇文件或标签映射)与模型捆绑在一个存档文件中。

当我们需要部署具有复杂初始化过程或源自第三方库的模型时,我们会在 TorchServe 中设计自定义处理程序。这些让我们可以使用任何所需的过程从任何库加载任何模型。以下代码段显示了一个简单的处理程序,它可以在任何 SageMaker 托管端点实例上为 Hugging Face BERT 模型提供服务。

import torch import torch.neuron from ts.torch_handler.base_handler import BaseHandler import transformers from transformers import AutoModelForSequenceClassification,AutoTokenizer class MyModelHandler(BaseHandler): def initialize(self, context): self.manifest = ctx.manifest properties = ctx.system_properties model_dir = properties.get(&34;) serialized_File = self.manifest[&34;][&34;] model_pt_path = os.path.join(model_dir, serialized_file) self.tokenizer = AutoTokenizer.from_pretrained( model_dir, do_lower_case=True ) self.model = AutoModelForSequenceClassification.from_pretrained( model_dir ) def preprocess(self, data): input_text = data.get(&34;) if input_text is None: input_text = data.get(&34;) inputs = self.tokenizer.encode_plus(input_text, max_length=int(max_length), pad_to_max_length=True, add_special_tokens=True, return_tensors=&39;) return inputs def inference(self,inputs): predictions = self.model(**inputs) return predictions def postprocess(self, output): return output

硬件加速器针对并行性进行了优化,批处理(在一个步骤中为模型提供多个输入)有助于使所有可用容量饱和,通常会导致更高的吞吐量。然而,过高的批量大小会增加延迟,而吞吐量的提高却很小。尝试不同的批量大小有助于我们确定模型和硬件加速器的最佳位置。我们进行实验以确定模型大小、有效负载大小和请求流量模式的最佳批量大小。

Neuron 编译器现在支持可变批量大小。以前,跟踪模型硬编码了预定义的批量大小,因此我们必须填充数据,这会浪费计算、降低吞吐量并加剧延迟。Inferentia 经过优化,可最大限度地提高小批量的吞吐量,通过减轻系统负载来减少延迟。

并行性

多核上的模型并行性还提高了吞吐量和延迟,这对于我们繁重的工作负载至关重要。每个 Inferentia 芯片包含四个 NeuronCore,它们既可以同时运行单独的模型,也可以形成流水线来传输单个模型。在我们的用例中,数据并行配置以最低的成本提供最高的吞吐量,因为它扩展了并发处理请求。

数据并行:

模型并行:

监控生产中推理的准确性至关重要。最初做出良好预测的模型最终会在部署中退化,因为它们暴露于更广泛的数据。这种现象称为模型漂移,通常发生在输入数据分布或预测目标发生变化时。

我们使用SageMaker 模型监视器来跟踪训练和生产数据之间的奇偶性。当生产中的预测开始偏离训练和验证结果时,模型监视器会通知我们。多亏了这个早期警告,我们可以在我们的广告商受到影响之前恢复准确性——必要时通过重新训练模型。为了实时跟踪性能,Model Monitor 还会向我们发送有关预测质量的指标,例如准确度、F 分数和预测类别的分布。

为了确定我们的应用程序是否需要扩展,TorchServe 会定期记录 CPU、内存和磁盘的资源利用率指标;它还记录收到的请求数量与服务数量。对于自定义指标,TorchServe 提供了一个Metrics API。

我们在 PyTorch 中开发并部署在 Inferentia 上的 DL 模型加快了我们的广告分析速度,同时降低了成本。从我们在 DL 中的第一次探索开始,在 PyTorch 中编程感觉很自然。其用户友好的功能有助于顺利完成从我们早期实验到部署多模式集成的过程。PyTorch 让我们能够快速原型化和构建模型,这对于我们的广告服务的发展和扩展至关重要。为了获得额外的好处,PyTorch 可以与 Inferentia 和我们的 AWS ML 堆栈无缝协作。我们期待使用 PyTorch 构建更多用例,以便我们可以继续为客户提供准确、实时的结果。

本站所发布的文字与图片素材为非商业目的改编或整理,版权归原作者所有,如侵权或涉及违法,请联系我们删除

窝牛号 wwww.93ysy.com   沪ICP备2021036305号-1