TensorFlow-和-AWS-Lambda-无服务器深度学习实用指南-全-

TensorFlow 和 AWS Lambda 无服务器深度学习实用指南(全)

原文:annas-archive.org/md5/bfe32637cd602c8dc2b1f8f37cfa30c0

译者:飞龙

协议:CC BY-NC-SA 4.0

前言

本书将帮助你使用自己训练的模型与 AWS Lambda 配合,实现一种简化的无服务器计算方法,无需花费大量时间和金钱。到本书结尾时,你将能够实现一个展示 AWS Lambda 在提供 TensorFlow 模型服务中应用的项目。

此外,我们还将介绍深度学习和 TensorFlow 框架。我们将探讨如何训练神经网络,但更重要的是,我们将讲解如何在应用中使用预训练的神经网络以及如何找到它们。之后,我们将深入了解如何使用无服务器方法部署深度学习应用程序。我们还将讨论它们的优点、缺点、可能的限制和最佳实践。

接下来,我们将构建多个应用程序,利用无服务器深度学习方法。我们将创建一个规划 API,了解 AWS API Gateway 服务,并探讨如何以方便的方式部署所有内容。在后续阶段,我们将创建一个深度学习管道和 AWS 简单查询服务。我们将探讨如何与 AWS Lambda 一起使用它,并展示如何部署该应用程序。

本书适合的读者

本课程将帮助数据科学家学习如何轻松部署模型,也适合那些希望了解如何将应用部署到云端的初学者。无需具备 TensorFlow 或 AWS 的先前知识。

本书涵盖的内容

第一章,从无服务器计算与 AWS Lambda 开始,介绍了我们计划要看的所有示例。我们还将描述无服务器概念,以及它如何改变当前的云基础设施环境。最后,我们将看到无服务器深度学习如何使我们能够比传统部署技术更容易实现项目,同时具有相同的可扩展性和低成本。

第二章,使用 AWS Lambda 函数开始部署,介绍了 AWS Lambda,并解释了如何创建 AWS 账户。我们将创建第一个 Lambda,并了解如何使用 Serverless Framework 轻松部署它。

第三章,部署 TensorFlow 模型,介绍了 TensorFlow 框架,并展示了几个如何训练和导出模型的示例。此外,我们将查看任何人都可以用于自己任务的预训练模型库。最后,我们将展示如何导入项目中所需的预训练模型。

第四章,在 AWS Lambda 上使用 TensorFlow,深入探讨了如何开始使用无服务器 TensorFlow。我们还将了解无服务器 TensorFlow 在成本、规模和速度方面与传统部署的小细节差异。我们还将查看如何使用标准的 AWS UI 开始,并了解如何使用 Serverless Framework 完成相同的工作。

第五章,创建深度学习 API,解释了如何制作深度学习 REST API。然后我们将介绍 AWS API Gateway 并学习如何使用两种方法制作应用程序:AWS UI 和 Serverless Framework。

第六章,创建深度学习管道,解释了如何制作深度学习管道应用程序。我们将介绍 AWS SQS,并说明如何使用两种方法制作应用程序:AWS UI 和 Serverless Framework。

第七章,创建深度学习工作流程,解释了如何制作复杂的深度学习算法应用程序。我们将介绍 AWS Step Functions,并说明如何使用两种方法制作应用程序:AWS UI 和 Serverless Framework。

要充分利用这本书

需要基本的 AWS Lambda 和 Python 知识才能充分利用这本书。

下载示例代码文件

您可以从您在 www.packt.com 的帐户下载本书的示例代码文件。如果您在其他地方购买了这本书,您可以访问 www.packt.com/support 并注册,直接将文件发送到您的邮箱。

您可以按照以下步骤下载代码文件:

  1. 登录或注册 www.packt.com

  2. 选择支持选项卡。

  3. 点击下载代码和勘误。

  4. 在搜索框中输入书名并按照屏幕上的说明操作。

一旦文件下载完成,请确保使用最新版本的解压或提取文件夹:

  • WinRAR/7-Zip 适用于 Windows

  • Zipeg/iZip/UnRarX 适用于 Mac

  • 7-Zip/PeaZip 适用于 Linux

本书的代码包也托管在 GitHub 上,网址为 github.com/PacktPublishing/Hands-On-Serverless-Deep-Learning-with-TensorFlow-and-AWS-Lambda。如果代码有更新,将在现有的 GitHub 仓库中更新。

我们还提供来自丰富书籍和视频目录的其他代码包,都可在 github.com/PacktPublishing/ 上查看!

下载彩色图片

我们还提供了一个 PDF 文件,包含本书中使用的带有彩色截图/图表的版本。您可以在此下载: www.packtpub.com/sites/default/files/downloads/9781838551605_ColorImages.pdf

使用的约定

本书中使用了多种文本约定。

CodeInText:表示文本中的代码单词、数据库表名、文件夹名称、文件名、文件扩展名、路径名、虚拟 URL、用户输入和 Twitter 账号。这里有一个例子:“在 serverless.yml 版本中,包含了函数的名称、可用资源和区域。”

一块代码设置如下:

model.fit(x_train, y_train, epochs=2)
print('Evaluation:')
print(model.evaluate(x_test, y_test))

任何命令行输入或输出的格式如下:

npm install -g Serverless
serverless --version

粗体:表示新术语、重要单词或屏幕上看到的单词。例如,菜单或对话框中的单词通常以这种方式显示。这里有一个例子:“接下来,进入用户页面并点击添加用户。”

警告或重要提示通常显示为这样的格式。

提示和技巧通常显示为这样的格式。

与我们联系

我们非常欢迎读者的反馈。

一般反馈:如果您对本书的任何方面有疑问,请在邮件主题中注明书名,并通过电子邮件与我们联系,地址是 customercare@packtpub.com

勘误表:尽管我们已尽力确保内容的准确性,但错误仍可能发生。如果您在本书中发现任何错误,我们将非常感激您向我们报告。请访问 www.packt.com/submit-errata,选择您的书籍,点击勘误提交表单链接,并填写相关细节。

盗版:如果您在互联网上发现我们作品的任何非法复制品,我们将非常感激您提供其地址或网站名称。请通过电子邮件联系我们,地址是 copyright@packt.com,并附上该材料的链接。

如果您有兴趣成为作者:如果您在某个领域拥有专长并且有意写作或为书籍做贡献,请访问 authors.packtpub.com

评价

请留下您的评价。阅读并使用本书后,您不妨在购买书籍的网站上留下评价。潜在读者可以查看您的公正意见,帮助他们做出购买决定,我们 Packt 也能了解您对我们的产品的看法,而我们的作者也可以看到您对他们书籍的反馈。谢谢!

欲了解更多关于 Packt 的信息,请访问 packt.com

第一章:从无服务器计算和 AWS Lambda 开始

本书将鼓励你使用自定义训练的模型与 AWS Lambda 进行配合,并使用简化的无服务器计算方法。稍后,你将实现一些示例项目,展示使用 AWS Lambda 为 TensorFlow 模型提供服务的方式。

在本章中,我们将讨论无服务器深度学习,你将探索为什么无服务器如此受欢迎,以及使用无服务器部署应用程序的优势。同时,你还将了解数据科学流程,以及无服务器如何提供一种简便快捷的方式来部署深度学习应用程序。你还将简要了解我们将在后续章节中制作的示例项目。

你还将学习 AWS 实现的工作原理,包括传统和无服务器的深度学习应用程序部署方式。

特别地,我们将涵盖以下主题:

  • 什么是无服务器计算?

  • 为什么选择无服务器深度学习?

  • AWS Lambda 函数

  • 示例项目

什么是无服务器计算?

无服务器计算是一种架构,其代码执行由云提供商管理,这意味着开发者在部署代码时无需担心管理、配置和维护服务器。

让我们讨论应用程序部署的可能方式:

  • 本地部署让你控制整个基础设施,包括硬件。换句话说,它意味着应用程序运行在我们的机器上,你可以物理访问。

  • 然后,你有基础设施即服务IaaS),这意味着你无法物理访问服务器,但你控制其中发生的所有事情。

  • 接下来,你有平台即服务PaaS),在这种模式下,你不能控制操作系统或运行时,但你可以控制我们的代码和容器。

  • 最后,你有功能即服务FaaS),这是一种无服务器模型,唯一能控制的就是代码本身。它可以大大促进我们在不同应用程序上的工作。

为什么选择无服务器深度学习?

让我们理解为什么无服务器基础设施在数据科学流程中部署深度学习模型极为有用。

一般的数据科学流程如下:

  • 商业理解:你需要理解业务需求,包括定义目标和可能的数据源。

  • 数据获取:你需要查看你打算使用的数据,探索它,尝试找到相关性和空白。

  • 建模:你从选择最有前景的特征开始,构建模型并进行训练。

  • 部署:你需要将模型投入生产并部署。

  • 客户接受度:你可以将结果提供给客户并接收反馈。

之前的要点通过以下图表呈现:

根据从客户那里收到的反馈,你可以更新模型并改变部署方式。部署和客户接受阶段具有迭代性质。这意味着你需要尽早从用户那里获得反馈。为此,我们的部署基础设施必须同时既简单又具备可扩展性,这可以通过无服务器基础设施来完成,从而用于部署深度学习模型。

你需要意识到,我们的深度学习基础设施必须能够与现有基础设施进行集成。

无服务器深度学习适用于哪些场景,哪些场景不适用?

无服务器深度学习部署具有很高的可扩展性、简单性,并且启动成本低。它的缺点是时间限制、CPU 限制和内存限制。

无服务器深度学习适用于哪些场景?

在接下来的部分中,你将从重申无服务器深度学习部署的优点开始:

  • 对于你的项目来说,它非常有用。如果你训练了模型并希望向世界展示,无服务器深度学习将让你在没有复杂部署和前期成本的情况下做到这一点。AWS 还提供每月免费使用。这意味着在 AWS Lambda 中的多个调用将完全免费。例如,在我们将在后续章节讨论的图像识别项目中,运行次数大约为 10 万次。

  • 无服务器深度学习非常适合那些希望尽早验证业务假设的早期创业公司。简单性和可扩展性使得小团队可以在没有 AWS 专业知识的情况下开始。AWS Lambda 让你能够轻松计算每个客户的成本,并了解每个用户的创业成本。

  • 无服务器深度学习在你已有现有基础设施并希望优化成本时非常方便。与集群架构相比,无服务器架构将更简单、更便宜,并且更易于维护。显著的是,它能降低成本,因为你不需要保留未使用的服务器。

  • 无服务器深度学习对于负载非常高的场景非常有用。例如,许多公司在遇到第一分钟有 100 万次请求,而下一分钟没有请求的情况下,难以维护系统。集群要么过大,要么需要一定时间才能扩展。而无服务器架构具有无与伦比的可扩展性,可以让系统在高负载下运行而不会崩溃。

无服务器深度学习不适用于哪些场景?

在以下情况下,深度学习将无法工作:

  • 如果你的系统的主要特点之一是提供实时响应,而且这是一个非常复杂的模型;例如,如果它是用户与系统之间交互的一部分,那么无服务器架构可能不足以满足你的需求。AWS Lambda 有冷启动延迟以及将模型卸载和加载到内存中的延迟。它确实运行得很快,但可能需要几秒钟的时间。速度高度依赖于模型的大小和复杂性,因此这是你需要事先进行测试的部分。

  • 如果你的模型使用大量数据,无服务器深度学习可能会失败。AWS Lambda 有一些限制,比如运行时为 3 GB 和硬盘为 0.5 GB,这意味着你要么需要优化代码的内存使用,要么使用集群。

  • 如果你的模型对 CPU 性能或核心数量有要求,那么它可能无法在 Lambda 上启动。没有明确的限制可以预测你的模型是否能够在 AWS Lambda 上启动,因此这需要进行测试。

  • 一个极为复杂的模型可能无法在无服务器基础设施上良好运行。所谓复杂的模型,是指超过 1 或 2 GB 的模型。它需要更长的时间从 S3 下载,且 Lambda 可能没有足够的内存来加载它。

上述用例向我们展示了无服务器学习的应用场景,它将帮助我们决定是否使用它。最后,在很多情况下,并没有一个明确的答案,继续在无服务器环境中测试你的模型是有意义的。

现在我们来讨论 Lambda 函数作为无服务器模型的情况。

Lambda 函数 – AWS 实现的 FaaS

在本节中,我们将讨论 AWS 实现的 FaaS 的工作原理。Lambda 函数是 AWS 实现的 FaaS。AWS 服务会保存 Lambda 配置,基本上包括代码、库和服务内的参数。一旦接收到触发信号,AWS 会从池中提取容器,并将配置放入容器中。然后,它会用事件触发的数据在容器内运行代码。一旦容器生成结果,服务会将其返回给响应。

以下图表展示了 Lambda 函数的工作原理:

Lambda 可以自动扩展,支持最多 10,000 个并发执行。此外,Lambda 定价是按使用量计费的,因此你只需为每次 Lambda 调用付费,当它不运行时,你无需付费。

Lambda 配置包括以下内容:

  • 代码:这就是你想要在函数中运行的内容。代码需要明确声明你希望服务运行的函数。

  • :这些库使我们能够运行更复杂的流程。你需要将它们与代码本身放在同一个包内。

  • 配置:这些是决定 Lambda 工作方式的各种参数。

主要参数如下:

  • 关系内存和超时

  • 运行时(例如,Python 或 Node)

  • 触发器,我们将在下一节中描述

  • IAM 角色,提供 Lambda 访问其他内部服务的权限

  • 环境参数,允许我们自定义代码的输入参数

Lambda 触发器

有许多 AWS 服务可以作为 AWS Lambda 的触发器,它们是:

  • DynamoDB:这使我们能够在每次数据库中新条目时启动 Lambda 函数

  • Amazon S3:这有助于 Lambda 函数启动存储桶中的文件

  • CloudWatch:这使我们能够根据时间表(例如,每分钟,每天,或每周四中午)运行 Lambda 函数

  • Lex:这通过查看常见的数据科学过程来开始

  • Kinesis、SQS 和 SNS:这些使我们能够在事件流中的每个对象上启动 Lambda 函数

有很多不同的触发器,这意味着你可以将 Lambda 绑定到许多不同的服务。

为什么在 AWS Lambda 上进行深度学习?

在这里,你将看到 AWS Lambda 的优势:

  • 在 AWS Lambda 上编码非常简单。你只需要代码包和库,而不需要 Docker 容器。它使你能够提前开始,并部署与本地运行相同的代码。因此,这对于早期阶段的项目来说非常合适。

  • AWS Lambda 具有极高的可扩展性,更重要的是,你不必管理可扩展性或为其编写单独的逻辑,因为你的数据科学应用可以轻松处理大量任务或与多个用户进行协作。

  • AWS Lambda 的定价非常合理。你只需为实际使用的部分付费,且价格非常实惠。例如,对于图像识别模型,成本为每 20,000 至 30,000 次运行 1 美元。

在下一节,你将了解使用 Lambda 的传统架构和无服务器架构的区别。

传统架构与使用 Lambda 的无服务器架构

让我们看一下传统架构和无服务器架构之间的区别。以下图示表示了通过传统架构的深度学习 API:

在上面的传统架构中,你不仅需要处理集群本身,还需要处理所有 API 请求的负载均衡。此外,你还需要管理带有代码和库的 Docker 容器,并找到使用容器注册表部署它的方法。

你需要对 AWS 有广泛的了解才能理解这个架构。虽然它不是特别困难,但对于初学者来说确实可能是个问题。你需要记住,AWS 的深度学习架构将有固定的成本。

让我们讨论一下上述应用程序的无服务器实现。以下图示表示了使用 Lambda 进行深度学习的架构:

在前面的图示中,你可以看到它看起来比传统架构简单得多。你无需管理节点的负载均衡扩展性或容器——你只需放入你的代码库,Lambda 会管理其他所有事项。而且,你可以使用它制作多个不同的原型,你只需为调用付费。这使得 Lambda 成为将深度学习模型提供给用户的完美方式。在接下来的章节中,你将简要了解你将在本书中开发的项目。

示例项目

在本节中,你将涵盖在本书过程中开发的项目。你将创建三个项目:

  • 深度学习 API

  • 深度学习批处理

  • 无服务器深度学习工作流

深度学习 API

深度学习 API 项目提供了很好的实践体验,因为你可以直接从浏览器看到结果。你将从用于图像识别的深度学习 API 开始。图像识别是深度学习在其中展示出令人难以置信的结果的任务之一,这些结果无法通过其他任何方法实现。你将使用一个现代的、公开可用的预训练 Inception 模型,它是版本独立的。这个项目还将向你展示如何轻松地将开源模型创建一个 API 接口。

深度学习批处理

在深度学习批处理项目中,你将深入了解许多公司如何运行深度学习应用程序。这个项目中,你将构建用于图像识别的深度学习批处理。它将向我们展示高 Lambda 可扩展性如何让我们同时处理成千上万的预测任务。

无服务器深度学习工作流

在无服务器深度学习工作流项目中,你将重点展示深度学习模型在无服务器架构上的模式。你将为图像识别制作一个无服务器深度学习工作流。该项目将向你展示如何使用 AWS Step Functions 进行现代化的部署技术。你还将学习如何在部署过程中进行 A/B 测试、错误处理以及多步骤过程。这个项目将帮助你理解无服务器部署的潜在应用,并教你如何将这些知识应用到个人项目或公司项目中。

总结

在本章中,你了解了无服务器函数、AWS 实现及其服务。你学习了 Lambda 函数,这是 AWS 实现的 FaaS。你还了解了 AWS 实现的 FaaS 的工作原理。之后,你理解了为什么无服务器基础设施在部署深度学习模型时极其有用,以及在部署过程中可能面临的挑战。你还比较了传统方式和无服务器方式在部署深度学习应用时的差异。你研究了无服务器深度学习的适用场景以及不适用场景。最后,你了解了本书中将要学习的各种示例项目。

在下一章中,你将学习如何使用 AWS Lambda 及其部署。

第二章:使用 AWS Lambda 函数开始部署

在本章中,我们将更深入了解 AWS Lambda 并学习它是如何工作的。我们还将讨论部署 Lambda 的不同方式以及在为 AWS Lambda 开发应用时需要考虑的事项。

我们将学习如何设置 AWS 账户以及访问管理。我们还将使用 AWS Lambda 创建一个 Hello World 函数。

我们将覆盖以下主题:

  • AWS Lambda 函数

  • 开始使用 AWS 账户

  • 无服务器框架简介

  • 部署 AWS Lambda 函数

技术要求

本章的技术要求如下:

AWS Lambda 函数

让我们来看看 AWS Lambda 的前提条件,如下所示:

import sys, os
import mylib
...
def handler(event, context):
  ...
  print("Hello world log")
  return result

它包括以下步骤:

  1. 导入你已在 AWS Lambda 上安装的库。这包括系统库和一些特定于 AWS 的库。你不必将这些库包含在你的包中。

  2. 导入外部库,无论是其他开发者和公司的库,还是你自己的库。你需要将它们包括在你的包中。

  3. 实现 handler 函数,它处理将请求的主变量作为输入事件和上下文的处理。event 是特定于触发器的信息,context 是有关 Lambda 的信息,用于处理请求。它包含函数的 ID 和参数。

  4. 处理请求。

  5. 返回 result,这将在同步执行时返回给触发器,或者在异步执行时将其保存到日志中。

你需要记住的是,除了触发器提供的上下文或状态外,你不能使用任何其他上下文或状态。而且,如果你在代码执行过程中打印了某些内容,它会被保存到函数的本地流中。

AWS Lambda 的优缺点及限制

AWS Lambda 有一些优缺点和限制,如下所述:

  • 优点:AWS Lambda 非常易于部署。我们无需了解 Docker 或其他容器框架来管理它。它只应包含库和代码。AWS Lambda 可以轻松连接到触发器,这意味着我们可以轻松地将其与其他基础设施集成,而且它非常具有可扩展性,这使得它在生产部署中非常有用。它的成本也相对较低。

  • 缺点:在多个 Lambda 本地调试时可能很困难。你必须重建整个环境和库,并能够在超时期间检查内存消耗。很难准确估计在 AWS Lambda 上承受高峰负载时的速度。AWS Lambda 是无状态的,这会极大影响你如何组织应用程序。这意味着阶段应该来自触发器。

  • 限制:在开发过程中,你需要考虑 RAM、磁盘、CPU 和超时的某些限制。

以下图表详细描述了优缺点和限制:

现在,我们已经对 AWS Lambda 的优缺点和限制有了一个大致了解,接下来让我们看看如何创建 AWS 账户的基础知识。

开始使用 AWS 账户

在这一部分,你将了解 AWS 免费套餐和 IAM。我们需要一个 AWS 账户来深入学习。

如果你没有 AWS 账户,可以在此注册:aws.amazon.com/account/

Lambda API 网关、简单队列服务和函数都是 AWS 免费套餐的一部分,因此对于少量的使用不会收费。

AWS 免费套餐

免费套餐允许你免费使用 AWS 服务。它涵盖了多个不同的 AWS 服务,例如:

  • AWS Lambda:这包括 100 万次调用,这使得 Lambda 非常适合托管你的宠物项目

  • AWS API Gateway:这包括 100 万个通过付费网关的请求,因此可以扩展至具有 AWS REST API 功能的项目

  • AWS SQS:包括 100 万个简单队列服务请求

  • AWS Step Functions:这包括 4,000 次步骤函数的状态转换,允许我们创建免费的无服务器工作流

身份与访问管理(IAM)

你可以为 AWS 用户创建两种类型的访问权限:

  • AWS 管理控制访问:这允许你使用 AWS 网络服务。用户需要有一个登录 ID 和密码,用户将在线使用这些信息。

  • 程序访问:这允许你使用 AWS 软件开发密钥。用户需要两个密钥:访问密钥 ID 和秘密访问密钥。

现在,让我们创建一个具有程序访问权限的用户。这将允许我们使用无服务器框架,管理 AWS Lambda 的部署和编排。

为了创建用户,我们将按照以下步骤操作:

  1. 首先,你需要进入 AWS 控制台并选择 IAM 服务,如下图所示:

  1. 接下来,转到用户页面并点击添加用户,如下所示:

  1. 现在,设置名称为 lambda,并勾选程序访问复选框:

  1. 接下来,您需要为用户设置权限,以便使用之前讨论过的 AWS 服务。最简单的方法是选择直接附加现有策略,然后选择AdministratorAccess策略,如下图所示:

  1. 最后,您需要确认所有的选择:

  2. 它将显示我们的访问密钥 ID 和密钥访问密钥。您可以从 Web 服务中复制它们或通过 CSV 文件保存它们。稍后在设置无服务器框架时,您将需要这些访问密钥,如图所示:

在下一节中,我们将创建一个 Hello World AWS Lambda 函数。

创建一个 Hello World AWS Lambda 函数

从 AWS 控制台有三种主要方法来创建一个 Hello World AWS Lambda:

  • 我们可以从头开始创建一个 Lambda。这是创建一个简单 Lambda 的最简单方法。

  • 我们可以使用现有的蓝图来创建 Lambda。AWS 有一个适用于任何基础 Lambda 的使用目录,您可以使用它从一个接近您想要创建的项目的 Lambda 开始。

  • 2018 年,AWS 添加了无服务器应用程序库,用户可以在其中提交他们的 Lambda 配置。这个库包含数百个不同的 Lambda 包,对于在 AWS Lambda 中创建 Hello World 非常有用。

使用 Lambda 函数

我们将通过以下几个要点来讨论如何使用 Lambda 函数:

  • 您可以使用 AWS 服务 Cloud 9 中的内联编辑器。如果您不想在本地安装任何内容,并希望将所有文件保存在云中,这将非常有用。缺点是,使用内联编辑器进行自动化部署可能非常具有挑战性,同时处理复杂的附加库和多个文件的大型项目也比较困难。

  • 您可以通过 Web 界面或命令行上传带有库和代码的 ZIP 文件。这是一个非常简单的过程,您可以轻松地将其自动化。此方法的主要缺点是包的大小有限制,最多只能是 50 MB。

  • 上传包的最佳且最流行的方式是通过 S3 桶。它对包没有 50 MB 的限制,尽管我们的 ZIP 库和代码仍然会有 250 MB 的限制。

AWS Lambda 代码

执行以下步骤以创建 Hello World 代码:

  1. 使用您的lambda IAM 用户登录。进入 AWS 控制台并选择 AWS Lambda 服务:

  1. 点击创建函数,如以下截图所示:

  1. 选择从头开始创建,如图所示:

  1. 我们需要添加一个名称、运行时和角色。然后,我们需要添加一个角色名称,helloLambda。对于策略模板,选择简单的微服务权限,并点击创建函数按钮,如下图所示:

  1. 最终,我们得到了 AWS Lambda 的界面。我们得到了连接的触发器、代码编辑器和设置:

  1. 你需要配置测试事件并启动你的第一个 Lambda 函数。对于我们的第一个 Lambda 函数,你只需创建一个空事件:

  1. 编辑代码并保存后,你会看到 Lambda 已经更新:

在接下来的章节中,我们将学习无服务器框架。

无服务器框架简介

在之前的章节中,我们了解了不同的 Lambda 函数部署方式。虽然 Lambda 包仅仅是包含库和代码的 ZIP 文件,但仍然有如下方式来部署它们。生产使用的部署需要具备以下特性:

  • 首先,无服务器框架应该有一个单一的配置文件,在该文件中我们可以设置所有的部署选项和参数。这将使我们在编写启动每个服务的长脚本时节省时间,并且它将使我们能够保存环境的版本。

  • 它应该能够创建并附加其他 AWS 服务,以便将它们添加到 Lambda 中。由于大多数使用场景涉及 Lambda 作为更大基础设施的一部分工作,因此将其他基础设施部分单独部署可能会是一个大问题。

  • 拥有一个方便的命令行界面非常有帮助,因为这不仅意味着你可以使用一个脚本部署所有内容,还可以设置自动部署。

无服务器框架的特性

无服务器框架具有许多有用的特性。它们如下:

  • 它是开源的,这意味着无服务器社区帮助构建和维护该框架。这使得该框架保持免费并保持最新。

  • 无服务器框架支持不同的公共云平台,如 AWS、Google 云函数和 Azure 函数。这意味着你不必学习上述服务的 UI 是如何工作的。你可以使用相同的通用 UI 在另一个服务上部署函数。

  • 无服务器框架具有生产级质量,许多公司使用它来部署无服务器基础设施。

  • 它具有插件系统,允许用户为框架创建自定义插件。这使得无服务器框架可以具备多种功能;例如,支持步骤函数。

无服务器框架的安装

为了安装无服务器框架,我们需要安装以下功能:

无服务器框架的完整安装过程可以在这里找到 serverless.com/framework/docs/providers/aws/guide/installation

安装无服务器框架非常简单。我们只需运行以下命令:

npm install -g serverless

我们可以通过运行以下命令来检查它是否正常工作:

serverless --version

这将返回已安装的无服务器框架版本。

使用无服务器框架部署 AWS Lambda 函数

我们将从无服务器部署过程的样子开始:

  • 我们有用于 Lambda 执行的代码和库。这些与您直接上传 ZIP 包时看到的代码和库相同。从这个角度来看,通过无服务器框架开始部署现有的 Lambda 非常简单。

  • 我们有一个配置文件,它基本上包含了有关 Lambda 部署方式的所有信息。

配置文件

Lambda 配置文件包含与前面讨论过的相同参数(例如,名称、运行时、内存和超时)。有三个主要区别。

您不仅是在设置触发器,还在设置这些触发器所依赖的服务。您可以设置特定的角色和访问权限。有些访问权限会自动设置,但有些需要您手动配置。最后,您可以设置额外的插件,这些插件将在部署时使用。我们将在部署步骤函数时更详细地了解它们。

部署过程

本节介绍了部署过程,这将根据我们的配置文件生成自定义的云形成文件。云形成是 AWS 提供的一项服务,允许我们自动部署多个服务。这个功能对于处理部署过程非常方便,但它的标记语法可能一开始比较难以理解。这就是为什么我们使用服务器配置文件,因为它更具可读性。接下来,服务框架会将库和代码打包成一个单独的包并上传,然后利用之前生成的文件运行 AWS 云形成服务进行部署。

现在,让我们继续使用 serverless 框架进行 Lambda 的实际部署,查看可用的文件。

有两个文件:index.pyserverless.yml。我们来看一下 index.py。以下代码将打印输入事件并返回 Hello World 消息,如下所示:

def handler(event,context):
    print('Log event',event)
    return 'Hello world'

以下代码片段显示了 serverless.yml 文件:

service: helloworld

frameworkVersion: ">=1.2.0 <2.0.0"

provider:
  name: aws
  region: us-east-1
  runtime: python3.6
  memorySize: 128
  timeout: 10

functions:
  main:
    handler: index.handler

serverless.yml 版本中,有函数的名称、可用资源和区域。helloworld 是我们部署的服务名称。main 是函数的名称,index.handlerindex.py 文件中的函数名称和文件处理器的名称。

一个服务可能有不同的功能,这就是为什么它们被分开的原因。在部署之前,我们可以先在本地运行 Lambda。这是 serverless 框架的一个好功能,但由于操作系统的差异,它可能不适用于复杂的库。我们可以看到,我们打印了一个空的日志并接收到了 Hello World 消息作为输出:

在部署 Lambda 之前,你需要使用以下命令将你的 AWS 账户链接到 serverless:

serverless config credentials --provider aws --key "Your access key" --secret "Your secret access key"

你将使用 serverless 框架部署 Lambda。同时,即使你只有一个简单的程序,serverless 框架部署服务时也可能需要一些时间:

现在,你可以运行 Lambda 代码并查看输出:

如你所见,它和我们之前收到的相同。这里有两个非常有用的标志,在使用 Lambda 时非常有帮助。第一个标志帮助我们在 Lambda 内部发送自定义事件,从而模拟来自自定义服务的触发事件,而日志则可以让我们看到当前执行的日志。这个日志标志将允许我们查看日志,而数据标志则允许我们发送自定义消息。

总结

在这一章中,我们了解了 AWS Lambda 函数,并开始了 AWS 账户的使用。我们还学习了如何创建一个 Hello World 的 AWS Lambda 函数,并介绍了 serverless 框架以及 AWS Lambda 函数的部署。

在下一章,我们将开始部署 TensorFlow 模型,在那里我们将深入了解 TensorFlow 模型及其部署方法。

第三章:部署 TensorFlow 模型

在本章中,我们将讨论 TensorFlow 框架。首先,我们将描述构建算法的各种方法如何不同。我们还将介绍深度学习及如何训练神经网络,但更重要的是,你将学习如何在应用中使用预训练的神经网络,以及如何找到它们。

我们将涵盖以下主题:

  • 构建算法的方法

  • 为什么是神经网络?

  • 预训练 TensorFlow 模型的代码库

  • 图像标题的示例

技术要求

构建算法的方法

构建算法的各种方法是:

  • 首先,有确定性算法,它们非常透明和可预测,但对于复杂任务而言,构建一个能够在所有情况下都有效的自定义算法可能非常困难。

  • 接下来是机器学习技术,在这种方法中,我们根据从数据中获得的特征来训练模型。我们不需要大量的数据来可靠地训练模型,但我们需要为训练验证和测试创建一个单独的过程。

  • 最后是深度学习方法,在这种方法中,我们训练自己的神经网络。其主要优点是我们可以使用原始数据,而不需要预定义的特征。缺点是我们需要大量的数据和计算资源来进行训练。

机器学习方法与经典方法有很大的不同。经典方法使用规则和数据作为输入,答案作为输出。而在机器学习方法中,我们使用数据和答案作为输入,输出的是规则,如下所示:

让我们看看为什么神经网络在近年来变得如此流行。

为什么是神经网络?

神经网络在近年来变得流行的原因如下:

  • 与过去的价格相比,计算资源现在变得便宜得多。随着公共云的引入,使用这些资源进行大规模运作变得异常简单且经济实惠。

  • 机器学习方法需要大量数据,而且现在有大量的公共和私人数据可以用于训练。

  • 先进的算法使得可以构建和训练更复杂的神经网络。

让我们讨论一下为什么我们实际上不需要训练神经网络也能成功使用它们。

预训练的网络

虽然训练神经网络可能需要大量的计算能力和数据,但部署神经网络可以通过简单的 CPU 来完成。这样,我们可以说,部署一个深度学习模型几乎和在代码中使用外部库一样简单。其次,有一个庞大的社区,很多人和公司将他们预训练的神经网络开源,这意味着你可以自由使用它们。

使用预训练神经网络有两个场景非常方便:

  • 第一种情况是当你的任务已经解决时。例如,如果你想进行图像描述并进行X分类,你可以使用已经存在的神经网络。

  • 第二种情况是当你的任务与已做的任务差别不大,但又有所不同时。然后,你可以使用预训练模型生成特征,稍后可以结合确定性方法或简单的机器学习模型使用这些特征。

大多数预训练模型使用 TensorFlow,因此它目前是深度学习中最流行的框架。它拥有一个庞大的社区,很多人分享他们训练的模型。大多数在生产环境中使用神经网络的公司都在使用 TensorFlow 框架。因此,我们将在下一部分通过一个示例学习如何使用 TensorFlow 进行预训练模型的应用。

简单的 TensorFlow 示例

展示深度学习强大能力的一个典型案例是MNIST修改版美国国家标准与技术研究所数据集)数据集。它由黑白图像和手写数字组成,如下图所示:

每张图像都根据图像上写的数字进行标注。在这种情况下,任务是根据图像预测标签。使用确定性方法实现这种任务非常困难;正如你在前面的图像中看到的,写同一个数字有很多不同的方式。因此,你不能使用单一模板进行预测。

MNIST 的训练

在本节中,我们将讨论 MNIST 的模型训练:

  1. 首先,我们开始导入tensorflow库。在这个示例中,我们将使用 Keras 深度学习框架,它使得设置神经网络的层变得简单。简单来说,Keras 是 TensorFlow 之上的一个封装,因此一切仍然是基于 TensorFlow 的。

  2. 接下来,我们需要加载数据并以二进制格式呈现它,因为原始图像的像素值为 0 和 255。我们还将把数据集分为训练集和测试集。这将允许我们衡量神经网络的性能。机器学习方法的一个好习惯是,在训练数据集上训练模型,并在测试数据集上衡量最终得分。这可以确保模型在训练后不会看到它将被评估的数据点。接下来我们将看到具体的解释:

import tensorflow as tf

mnist = tf.keras.datasets.mnist

(x_train, y_train),(x_test, y_test) = mnist.load_data()
x_train, x_test = x_train / 255.0, x_test / 255.0
  1. 现在,我们需要为我们的神经网络设置各个层。基本上,每一层由若干个神经元和一个激活函数组成。在这个例子中,第一层试图从原始数据中提取更多有用的数据。第二层则试图利用这些数据来为图像是否为 10 个数字中的一个分配概率。

  2. 作为模型的一部分,您需要选择三个参数来进行训练过程:

    • 首先是loss函数,神经网络将使用它来优化性能。训练过程基本上就是通过减少loss函数的值,并试图为神经网络找到最优的权重,使得loss函数的值最小。

    • 接下来是optimizer,它处理神经网络如何向最优解迭代,以及每次迭代后如何更新权重。

    • 最后,metrics允许我们在数据集上衡量神经网络的性能。例如,accuracy帮助我们理解数据集中哪些部分被正确分类。这个度量不会直接参与训练过程,主要帮助我们理解网络性能是否有所提升。我们可以通过以下代码来理解前面的解释:

model = tf.keras.models.Sequential([
  tf.keras.layers.Flatten(),
  tf.keras.layers.Dense(512, activation=tf.nn.relu),
  tf.keras.layers.Dense(10, activation=tf.nn.softmax)
])
model.compile(optimizer='adam',
              loss='sparse_categorical_crossentropy',
              metrics=['accuracy'])
  1. 一切设置好后,我们只需要在训练数据集上进行训练。这可能需要几分钟,具体取决于您计算机的配置。之后,我们可以评估模型在测试集上的表现。我们的模型将达到大约 97%的准确率/测试集,这非常令人印象深刻,正如演示所示,即使是一个简单的神经网络,也能通过如下代码实现这一点:
model.fit(x_train, y_train, epochs=2)
print('Evaluation:')
print(model.evaluate(x_test, y_test))
  1. 最后,一旦神经网络被训练好,我们可以保存它,以便以后使用。如您所见,这是一个非常简单的过程。模型文件将包含模型架构、层的组成、层的权重和训练配置,以及优化器的状态,这些都可以帮助我们在已经训练的模型上继续训练:
model.save('MNISTmodel.h5')
modelImported = tf.keras.models.load_model('MNISTmodel.h5')
print('Evaluation by imported model:')
print(modelImported.evaluate(x_test, y_test))

让我们讨论一下可用的文件。这里只有一个 Python 文件,就是我们将要运行的testMNIST.py文件。在这个文件中,我们可以看到我们讨论过的部分,包括数据转换、模型安装、模型训练、模型评估、模型导出和模型导入。

现在,让我们在命令行中运行testMNIST.py文件来查看结果。通过运行代码,我们可以看到训练过程,它是以“epoch”为单位进行的。这种神经网络不需要 GPU 进行训练,即使在 CPU 上也可以取得非常好的结果:

python testMNIST.py

正如您在下方的截图中所看到的,我们只用了两个 epoch 就达到了 97%的准确率,并成功导出了并导入了模型。我们可以看到导出的重新训练的模型,现在可以在不同的代码中使用:

在下一部分,我们将讨论预训练 TensorFlow 模型的代码库。

预训练的 TensorFlow 模型仓库

预训练模型在导入和导出方面非常有能力。简而言之,部署声明包括导入训练好的模型并将输入数据转化为神经网络能够接受的格式。在部署过程中,有一些事情需要牢记:

  • 模型可能非常大,例如,可能达到数百兆字节,这使得部署变得更加困难。

  • 我们需要保持模型的版本并跟踪其性能。如果你自己训练模型,可能需要根据输入数据的变化或发现更好的架构来更新模型。

  • 一些模型需要额外的文件,将预测的数字或值转换为有意义的信息。

TensorFlow 仓库

TensorFlow 有五个主要的仓库,包含多个精选的模型。它们已经有些成熟,并且非常容易与 TensorFlow 框架一起使用。

如需了解更多关于使用 TensorFlow 训练的最受欢迎模型的信息,请访问此网站:github.com/tensorflow/models

各个仓库的不同示例如下:

  • 图像到文本模型,可以将图像上的内容进行描述

  • 图像标题生成,它对图像进行分类

  • Deep speech,它可以识别语音

  • 文本摘要,它可以将文章内容进行总结

  • Vid2depth,它基于视频流生成深度图

TensorFlow Hub

有一个专门为神经网络设计的 TensorFlow Hub 托管平台。TensorFlow Hub 拥有许多优秀的模型,这些模型可以免费使用,并且主要由 Google 训练。它们质量很好,属于最先进的技术水平。TensorFlow Hub 的优势是,在添加模型之前会对其进行检查,而劣势则是它的提交门槛较高。

不同模型的 TensorFlow Hub 可通过以下链接查看:tfhub.dev/

GitHub

GitHub 被认为是最大的开源代码仓库。那里发布了无数的模型,但由于没有入门过滤机制,你在生产环境中使用这些模型时需要更加小心。GitHub 的优点是入门门槛低,缺点是可能很难找到相关模型,并且用户需要在部署之前检查模型的工作原理。

在接下来的部分中,我们通过一个示例来学习图像标题生成。

图像标题生成示例

图像标注是一个任务,我们需要识别图像中的物体。虽然听起来很简单,但它一直被认为是计算机视觉中最困难的问题之一,因为为每种物体类型制作一个单独的检测器几乎是不可能的。测试图像标注算法的主要方法是将其应用于 ImageNet 数据集。ImageNet 数据集包含 1400 万张图像和超过 20,000 个标签。它于 2010 年推出,每年都会有不同模型的竞赛,近年来由于复杂神经网络的引入,准确率显著提高。

有许多不同的模型和架构能够成功地与 ImageNet 一起工作。我们将看到,随着时间的推移,错误率显著下降。下图展示了 ImageNet 数据集中获胜模型的错误率变化。

我们现在来讨论 Inception v3,它将在稍后的代码示例中使用。

Inception v3

Inception v3 是由 Google 提出的,并且达到了 3.46% 的错误率。你会发现 Inception v3 显著更复杂。它也需要更多的资源来训练这个模型,但这里的好处是我们不需要训练它就可以使用它。

我们将看看使用 Inception v3 时我们需要什么。模型由 classify_image_graph_def.pb 文件中存在的层和权重值组成。

我们还拥有一份标签列表,模型可以在 imagenet_2012_challenge_label_map_proto.pbtxt 文件中预测这些标签,并且有一个文档允许将神经网络的结果映射到 imagenet_synset_to_human_label_map.txt 文件中的标签。

这是一个熊猫图像的例子。首先,我们接收得分的 ID。最高的得分意味着模型对图像具有该标签的高信心。将 ID 映射到标签名称后,我们可以看到模型正确地检测到了熊猫。以下截图解释了这一点:

Inception v3 的 TensorFlow 代码

现在,让我们看看任何 Inception v3 模型的代码是怎样的:

  1. 首先,我们需要设置一个 TensorFlow 会话。会话是一个环境,在其中张量会被评估。

  2. 我们需要通过从文件中加载神经网络来读取并设置它。

  3. 接下来,我们需要以神经网络能够读取的格式请求图像。

  4. 我们需要运行一个强大的模型并接收一系列行预测,然后将这些预测转化为实际的标签值,如下代码所示:

SESSION = tf.InteractiveSession()
softmax_tensor = tf.get_default_graph().get_tensor_by_name('softmax:0')

predictions = SESSION.run(softmax_tensor,{'DecodeJpeg/contents:0': image_data})

node_loolup.id_to_string(predictions)

运行代码

让我们看看可用的文件,inputimage.pngtestinception.py,我们即将运行这些文件。在这个例子中,我们将使用熊猫图像(inputimage.png)。

  1. 如以下代码所示,存在 NodeLookup 类,它将帮助我们将模型的响应转换为标签名称:
class NodeLookup(object):
    """Converts integer node ID's to human readable labels."""
  1. 以下代码展示了我们如何读取图像:
image = 'inputimage.png'
image_data = tf.gfile.FastGFile(image, 'rb').read()
  1. 接下来,这是导入预训练模型的代码:
with tf.gfile.FastGFile('classify_image_graph_def.pb', 'rb') as f:
  graph_def = tf.GraphDef()
  graph_def.ParseFromString(f.read())
  tf.import_graph_def(graph_def, name='')
  1. 在这里,我们更换了模型:
SESSION = tf.InteractiveSession()
softmax_tensor = tf.get_default_graph().get_tensor_by_name('softmax:0')

predictions = SESSION.run(softmax_tensor,{'DecodeJpeg/contents:0': image_data})
  1. 最后,我们翻译模型的结果:
predictions = np.squeeze(predictions)
node_lookup = NodeLookup(label_lookup_path='imagenet_2012_challenge_label_map_proto.pbtxt',
  uid_lookup_path='imagenet_synset_to_human_label_map.txt')

top_k = predictions.argsort()[-5:][::-1]
strResult = '%s (score = %.5f)' % (node_lookup.id_to_string(top_k[0]), predictions[top_k[0]])
print()
for node_id in top_k:
    human_string = node_lookup.id_to_string(node_id)
    score = predictions[node_id]
    print('%s - %s (score = %.5f)' % (node_id, human_string, score))
  1. 现在,我们可以运行代码并查看响应。从以下输出中可以看出,模型成功检测到了图片中的熊猫。由于不涉及训练,代码运行非常快。你可以在不同的图片上尝试此代码,体验一下该模型的潜力:

总结

在这一章中,我们研究了构建算法的不同方法。我们讨论了如何训练 TensorFlow 模型以及预训练 TensorFlow 模型的存储库。我们还了解了如何使用 Inception v3 TensorFlow 示例进行图像描述。

在下一章中,我们将学习如何使用 TensorFlow AWS Lambda,在那里我们将进一步了解如何在 AWS Lambda 上使用 TensorFlow 模型。

第四章:在 AWS Lambda 上使用 TensorFlow

在本章中,我们将学习如何在 AWS 上部署 TensorFlow 的架构,并通过预先存在的包和无服务器框架在 AWS Lambda 上部署 TensorFlow。我们还将探讨在 AWS Lambda 上部署各种 Python 框架时的常见问题,并涵盖所有解决这些问题的方案。

我们将涵盖以下主题:

  • 使用 AWS Lambda 部署 TensorFlow 的架构

  • 在 AWS Lambda 上部署 Python 框架的常见问题

  • 使用预先存在的包在 AWS Lambda 上部署 TensorFlow

  • 使用无服务器框架部署 TensorFlow

技术要求

使用 AWS Lambda 部署 TensorFlow 的架构

在本节中,我们将学习如何使用 AWS Lambda 部署 TensorFlow 的架构。部署的一个关键问题是,应该将重新训练的模型存放在哪里,以便在 AWS Lambda 中使用。

有以下三种可能的选项:

  • 将模型与代码和库一起保存在部署包中

  • 将模型保存在 S3 存储桶中,并在执行时加载到 AWS Lambda 中

  • 将模型保存在 FTP 或 HTTP 服务器上,并在执行时加载到 AWS Lambda 中

部署包中的模型

这个选项意味着模型位于部署包中。代码将从本地文件系统中导入它。这个选项有自己的优缺点。

优点

模型在部署包中的优势如下:

  • 由于没有加载模型的开销,我们的部署将有一个非常好的启动速度

  • 我们将从一个单一的包开始

  • 我们的部署不需要任何外部服务器或 AWS 服务

缺点

模型在部署包中的缺点如下:

  • 包大小有相当大的限制,这限制了我们模型的可能大小

  • 如果需要管理模型的不同版本,可能很难将它们全部保存在一个包中,或者处理不同版本的包

S3 存储桶中的模型

这个选项意味着我们必须将模型保存在 S3 存储桶中,并在 AWS Lambda 执行期间卸载它。此选项在包大小方面非常有限。

优点

模型在 S3 存储桶中的优势如下:

  • 初看之下,使用会限制为 500 MB,这是 AWS Lambda 上 TMP 文件夹的最大大小,但实际上可以通过绕过此限制直接将模型下载到内存中

  • 管理多个模型会变得更容易,因为你可以使用 AWS Lambda 环境变量为每个你想要使用的模型提供与 S3 存储桶的设备链接。

缺点

存放在 S3 存储桶上的模型的缺点如下:

  • 我们的启动速度会比之前的案例慢,因为 Lambda 需要先下载模型。

  • 需要注意的是,尽管这只在冷启动时发生,但在热启动时,模型已经在内存中。

  • 你需要将所有模型上传到 S3 存储桶,作为部署的一部分,并在代码中添加管理不同模型的逻辑。

存放在 HTTP/FTP 服务器上的模型

这个选项主要适用于你希望限制 AWS 服务使用、内存或与 AWS 之外的服务进行集成的情况。在部署过程中,AWS Lambda 会从 HTTP 或 FTP 服务器下载模型。

优点

模型存放在 HTTP/FTP 服务器上的优点如下:

  • 你可以使用多个公开可用的服务与模型进行交互。

  • 你无需更新 S3 存储桶中的模型或包内的模型。

缺点

存放在 HTTP/FTP 服务器上的模型的缺点如下:

  • 这可能比前一个案例还要慢,这是该模型的一个缺点。

  • 由于较慢的时间,你需要确保服务器在你的地点是可用的。

在 AWS Lambda 上部署 Python 框架时的一般问题

在这一节中,我们将了解 AWS Lambda 的主要限制,也就是包的大小。Lambda 部署包的当前限制是 50 MB。该包应包括库和代码。我们需要适配的两个主要库如下:

  • TensorFlow

  • NumPy

这些库用于矩阵计算。如你所知,单独的这些库非常大,并且在 AWS Lambda 上无法正常运行。正如你在前一节部署中看到的,当我们通过 S3 部署时,我们没有这个限制,只需要面对解压包大小的 250 MB 限制。在这种情况下,为了使其正常工作,我们需要减小包的大小。

解决在 AWS Lambda 上部署 Python 框架的问题

有多种方式可以减少包的大小。以下是针对这些问题的解决方案:

  • 我们可以压缩共享库,通常这样能实现最佳的大小减少。

  • 我们可以删除 .pyc 文件,因为它们不会影响库的工作。

  • 接下来,我们可以从库中删除测试和可视化文件夹,因为它们在生产环境中没有用处。

  • 接下来,我们可以删除 AWS Lambda 上已经存在的库。

  • 最后,我们可以检查并删除执行过程中未使用的库,例如 wheel 或 PIP 库。

现在,在以下代码中,有一部分是查找并压缩所有共享库。然后,我们查找并删除所有 .pyc 文件。

以下截图展示了前面解释的命令:

接下来,我们需要删除在执行过程中不会使用到的库,例如.pipwheel。最后,我们还可以删除 TensorFlow 库中的一些文件夹。

以下截图展示了前述说明中的不同命令:

准备 AWS Lambda 的整个包过程可以通过 Docker 完成。虽然在我们将要创建的项目中你不需要使用它,但了解如何准备这类包是很有帮助的。

要安装 Docker,你只需要在命令行中运行三个命令:

  1. 你需要获取最新的 Amazon Linux 镜像,我们将在该镜像上运行脚本。

  2. 你需要启动一个 Docker 容器,并将管理输出文件夹放在容器内。

  3. 你可以在容器内运行脚本,它将为你组装包。以下截图展示了安装 Docker 的所有命令:

使用现有的包在 AWS Lambda 上部署 TensorFlow

在本节中,我们将学习如何使用现有的包在 AWS Lambda 上部署 TensorFlow。在项目文件中,我们有模型文件,这些文件也被称为模型本身,以及能够通过标签翻译模型响应的文件。在Inception文件夹和 Lambda 包中,后者也称为lambdapack文件夹中的代码和库。

要运行代码,我们需要执行以下步骤:

  • 我们将创建 S3 桶,存放模型并上传模型本身

  • 接着,我们将修改代码以适应特定的桶,并添加已创建的桶名称

  • 最后,我们可以将其打包并上传,以添加到 AWS Lambda

现在,我们将使用 AWS 控制台创建 S3 桶并将文件上传到其中。我们将打开代码并添加刚创建的桶。然后,让我们打包它并上传到 AWS Lambda。

我们需要按照以下步骤进行:

  1. 我们需要前往 S3 服务并点击创建桶(Create bucket):

  1. 现在,我们可以选择桶名称:

  1. 一旦我们设置好桶(bucket),就可以将文件上传到其中。你只需要点击上传(Upload),然后选择文件。在这里,我们只需上传包含库的包,它将开始上传过程,以及包本身。我们还需要上传位于Inception文件夹中的模型文件:

  1. 你可以看到,现在我们的 S3 桶中已经有一个包:

  1. 现在,我们必须为我们的 AWS Lambda 创建角色,可以通过 IAM 服务来完成:

  1. 我们需要选择 Lambda 并点击右下角的“下一步:权限”(Next: Permissions):

  1. 为了简化操作,选择管理员访问并点击下一步:标签,位于屏幕的右下角。这将允许我们的 Lambda 访问所有服务。通常在生产环境中,角色的访问权限会限制为仅访问特定服务。我们将在使用无服务器框架时讨论这个问题:

  1. 创建角色名称:lambdaAdminRole,这将在 Lambda 中创建该角色:

  1. 创建 Lambda 函数,进入 Lambda 函数页面并创建该函数。在此处,输入名称testensorflolambda,运行环境选择 Python 3.6。对于角色,选择选择一个现有角色,在现有角色中选择lambdaAdminRole,然后点击右下角的创建函数:

10. 创建函数后,我们需要将 Handler 修改为index.handler

  1. 在同一页面,向下滚动,在基础设置标签页中,按照以下截图添加足够的资源:

  1. 传递包含我们包(S3 存储桶)URL 的链接,并点击右上角的保存:

  1. 你可以看到函数已经创建。为了测试该函数,点击右上角的测试按钮:

  1. 在测试完函数后,它将成功生成以下结果:

使用无服务器框架部署 TensorFlow

首先,我们将查看项目文件。我们在Inception文件夹中有模型文件,在Lambdapack文件夹中有 Lambda 代码和配置文件Serverless.yml

部署流程将与上一节相同。主要的不同之处在于,我们将通过无服务器 CML 文件提供对存储桶的访问权限,而不是提供 AWS Lambda 管理员角色。我们只需要添加bucketname,并按照如下所示运行访问属性:

我们需要创建一个 S3 存储桶,将文件上传到其中,然后部署 AWS Lambda。我们将创建一个 S3 存储桶,并通过命令行上传文件:aws s3 sync.s3://<bucket>/

创建存储桶

我们首先需要创建一个存储桶,然后将模型文件上传到存储桶,运行无服务器框架,并启动 AWS Lambda。

Index.py

让我们来看一下可用的文件。我们将查看index.py文件,如下所示:

import boto3
import numpy as np
import tensorflow as tf
import os.path
import re
from urllib.request import urlretrieve
import json
SESSION = None
strBucket = 'serverlessdeeplearning'
def handler(event, context):
 global strBucket
 if not os.path.exists('/tmp/imagenet/'):
 os.makedirs('/tmp/imagenet/')
strFile = '/tmp/imagenet/inputimage.jpg'

主要的不同之处在于我们在handler函数内部运行代码,并且需要从 S3 存储桶下载模型文件和图像文件:

if not os.path.exists('/tmp/imagenet/'):
 os.makedirs('/tmp/imagenet/')
strFile = '/tmp/imagenet/inputimage.jpg'
downloadFromS3(strBucket,'imagenet/inputimage.jpg',strFile)
global SESSION
 if SESSION is None:
downloadFromS3(strBucket,'imagenet/imagenet_2012_challenge_label_map_proto.pbtxt','/tmp/imagenet/imagenet_2012_challenge_label_map_proto.pbtxt')
downloadFromS3(strBucket,'imagenet/imagenet_synset_to_human_label_map.txt','/tmp/imagenet/imagenet_synset_to_human_label_map.txt')
 image = os.path.join('/tmp/imagenet/', 'inputimage.jpg')
 strResult = run_inference_on_image(image)
return strResult
def run_inference_on_image(image):

此外,我们还可以利用 AWS Lambda 的一个优势。我们可以将模型文件保存为全局变量。基本上,我们可以将会话定义为全局变量。通过这些,如果我们在上一个 Lambda 执行完毕后立即启动 Lambda,所有模型文件将保存在 RAM 内存中:

global SESSION
 if SESSION is None:
 downloadFromS3(strBucket,'imagenet/imagenet_2012_challenge_label_map_proto.pbtxt','/tmp/imagenet/imagenet_2012_challenge_label_map_proto.pbtxt')
 downloadFromS3(strBucket,'imagenet/imagenet_synset_to_human_label_map.txt','/tmp/imagenet/imagenet_synset_to_human_label_map.txt')
 image = os.path.join('/tmp/imagenet/', 'inputimage.jpg')
 strResult = run_inference_on_image(image)
return strResult
def run_inference_on_image(image):
 image_data = tf.gfile.FastGFile(image, 'rb').read()
 global SESSION
 if SESSION is None:
 SESSION = tf.InteractiveSession()
 create_graph()

Serverless.yml

Serverless.yml文件中,我们需要定义对 S3 桶的访问权限,因为我们将在那里存储模型。除此之外,它将与之前提到的其他 Lambda 的无服务器 CML 文件完全相同:

service: deeplearninglambda
frameworkVersion: ">=1.2.0 <2.0.0"
provider:
  name: aws
  region: us-east-1
  runtime: python3.6
  memorySize: 1536
  timeout: 60
iamRoleStatements:
 - Effect: "Allow"
 Action:
 - "s3:ListBucket"
 Resource:
 - arn:aws:s3:::serverlessdeeplearning
 - Effect: "Allow"
 Action:
 - "s3:GetObject"
 Resource:
 - arn:aws:s3:::serverlessdeeplearning/*
functions:
 main:
 handler: index.handler

此外,我们还需要inputimage.jpg图像来进行 inception 模型的处理。

让我们看看需要上传到 S3 桶的文件:

有两个非常方便的命令,一个允许我们创建一个桶,另一个允许我们轻松地将文件上传到桶中:

  • aws s3api create-bucket --bucket serverlessdeeplearning

  • aws s3 sync . s3://serverlessdeeplearning/imagenet

由于我们已经在此桶中有模型文件,因此现在不需要再保存它,但您可以使用此命令将文件上传到您的桶中。接下来,我们可以返回到包含我们函数的文件夹并运行serverless deploy命令。

现在,我们将使用以下命令调用函数:

serverless invoke --function main

正如您所看到的,它成功识别了图像。此外,如果我们再次调用该函数,它将运行得更快:

总结

在本章中,我们了解了使用 AWS Lambda 部署 TensorFlow 的架构,其中涵盖了使用 AWS Lambda 部署 TensorFlow 的各种选项,以及每个选项的优缺点。我们还讨论了在 AWS Lambda 中部署 Python 框架的一般问题及其解决方案。最后,我们使用现有的包和无服务器框架在 AWS Lambda 上部署了 TensorFlow。

在下一章中,我们将使用 AWS Lambda 创建深度学习 API。

第五章:创建深度学习 API

在上一章中,我们学习了如何在 AWS Lambda 上使用 TensorFlow。本章简要介绍了 RESTful API 和 AWS API 网关。我们将学习如何使用无服务器框架创建 API 网关。

在本章中,我们将涵盖以下主题:

  • API 服务

  • AWS API 网关

  • 创建深度学习 API 项目

技术要求

本章的技术要求如下:

RESTful API

RESTful API 近年来变得极为流行,随着宏服务的普及,它成为了应用程序内部不同服务之间沟通的通用方式——例如,我们可以在一个应用程序中,使用 RESTful API 服务来连接不同的编程语言和不同的托管平台。

RESTful API 是一种允许不同应用程序之间进行通信的接口,它可以服务于许多用途。RESTful API 使你可以轻松地集成不同的服务。它还允许你在应用程序的前端和后端之间建立简单的连接,并且允许其他开发者使用你的服务。在此背景下,深度学习 API 使你能够轻松地将深度学习模型集成到你的应用中,或者为其他开发者提供一种使用你模型的方式。现在让我们更详细地了解 API 网关服务。

AWS API 网关

API 网关是一个双重服务,它允许你创建、发布、监控和保护 API。我们不仅可以将 API 网关连接到业务 Lambda,还可以连接到 AWS EC2 实例、弹性集群ECS),甚至是 弹性 BeanstalkEBS)。它采用按需付费的系统,使其成为一个非常方便的起始服务。让我们来看看 API 网关的具体功能。

功能

以下是 API 网关的一些功能:

  • 易于扩展:API 服务会自动处理扩展问题,这意味着我们不需要担心它是否适合处理峰值负载,也不必担心是否会过度配置资源。

  • 流量管理:API 网关有一种控制流量的方式。流量管理的主要用例是节流,特别是当我们希望对后端负载进行更均匀的分配时。对于 AWS Lambda 来说,这不是一个问题,因为它几乎可以无限扩展。

  • 授权:这允许你控制用户对 API 的访问。这意味着我们可以将 API 保持私密,或者将其商业化。这个功能对你的应用程序至关重要。

  • 监控:此功能使我们能够获取用户级别的使用统计信息。如果我们希望根据用户的使用情况限制他们,或者需要排除故障 API,这将非常重要。

  • 缓存:这可以通过缓存部分响应来减少发送到后端的请求数量。如果您的应用程序需要处理大量重复请求,那么此功能可以显著减少后端的使用量。

  • 版本控制:这使您可以管理 API 的多个版本,这对于应用程序的生产非常重要。

现在,让我们来看一下 API 的定价。

定价

API Gateway 的主要优点之一是按需付费功能。该服务的定价为每百万个请求 3.5 美元,数据传输费用为每 1 GB 大约 0.09 美元。根据选择的服务,可能会产生其他可选费用。因此,我们需要确保它有助于降低后端成本。我们看到的 API Gateway 的费用对于我们的项目来说是非常实惠的。对于初学者来说,AWS API Gateway 是免费套餐的一部分,每月可免费获得 100 万个请求。请注意,免费套餐仅适用于新用户。

创建 API Gateway

现在我们了解了 API Gateway 的费用和功能后,我们将通过 AWS 控制台创建 API Gateway。但在开始之前,我们需要创建并定位 AWS Lambda(在第四章,在 AWS Lambda 上使用 TensorFlow中创建),然后我们将学习如何创建 AWS API Gateway 和 AWS Lambda 之间的连接。

创建 AWS Lambda 实例

我们将通过 AWS 控制台创建 AWS Lambda 实例并连接到 Gateway。让我们从创建 AWS Lambda 实例开始,并选择在上一章中创建的管理角色,如下图所示:

让我们测试该功能,并检查它是否已通过屏幕右上方的测试选项创建,如下图所示:

现在,让我们通过单击左侧“添加触发器”下的 API Gateway 选项来添加 API Gateway 触发器。在“配置触发器”选项卡下,选择“创建新的 API”并选择 Open API 端点。然后,在“附加设置”中,只需检查 API 名称并单击“添加”以创建 API 并保存。这将为您提供如下图所示的页面,其中包含一个 API 链接,可在浏览器中进行测试:

如您所见,它产生的结果与演示代码相似,如下图所示:

现在我们已经准备好了 AWS Lambda 和 API Gateway,我们将使用无服务器框架创建连接。

使用无服务器框架创建 API Gateway

在创建 API 之前,让我们看看我们的项目文件:主 Python 文件(index.py)和无服务器配置文件(serverless.yml)。让我们查看如下所示的 Python 文件:

import json
def handler(event, context):
print('Log event', event)
return{
'status code': 200;
'body': json.dump('Hello world API!')
}

从前面的代码块中,你可以看到这个文件将返回 JSON 响应,而不是字符串给 API 请求。为此,我们需要将 status code 更改为 200,并将 body 更改为 JSON 格式的 transform

在服务器配置文件中,我们将添加一个 events 并添加一个 API 端点名称:

functions:
  main:
    handler: index.handler
    events:
      - http: GET hello

部署无服务器框架

现在让我们使用以下命令来部署服务:

serverless deploy

部署成功完成后,它将返回 API Gateway 的 URL。现在使用 curl 命令和 URL 测试我们在命令行中得到的 URL:

我们也可以在浏览器中运行该 URL 并测试部署,找到期望的输出。

创建第一个 API 项目

现在让我们从创建深度学习 API 项目的示例开始。在开始项目之前,先来看一下我们的文件:主 Python 文件和服务配置文件,以及一些库文件和 Inception 模型。

在这个项目中,我们将添加一个 events 部分以及端点名称。在 Python 文件中,我们将对请求返回一个 JSON 响应。此外,我们将使 Lambda 接受请求中的图片链接,并将其应用到一个模块中。然后,我们将部署服务器,并在命令行和浏览器中测试文件,就像在前一节中检查的那样。

当前的配置文件是前一节修改内容的结合,并且非常相似。我们将要进行更改的另一个部分是 Python 文件,在其中我们添加了读取 URL 参数。如你所见,如果没有 URL,我们使用之前获取的图片。但如果我们有 URL 路径,我们可以从该 URL 下载图片。

现在让我们使用 serverless deploy 命令部署服务,该命令会提供 API Gateway 的 URL。让我们使用 curl 命令和浏览器测试这个 URL,您将看到与前一节中相同的响应:

我们还可以通过下载图片来测试部署。为了测试这一点,我们只需要将图片的 URL 作为参数添加到 API Gateway URL 中。

总结

在这一章中,我们学习了 API Gateway 服务和 RESTful API。我们看到 AWS Gateway 如何为我们的应用提供高性价比。然后,我们了解了如何使用 AWS 控制台创建 AWS API Gateway 和 AWS Lambda。我们还通过无服务器框架创建了 AWS Lambda 和 AWS API Gateway 之间的连接。最后,我们使用 API Gateway 创建了深度学习 API 项目。

在下一章,我们将通过连接和明显的 Lambda 小组件来创建交叉管道,小费很有意思,我们将在这里学习如何构建深度学习管道。

第六章:创建深度学习管道

在上一章中,我们研究了使用 AWS 控制台创建 API 网关服务以及无服务器框架。本章我们将学习如何使用 AWS 控制台以及无服务器框架创建 SQS 连接。

本章将覆盖以下主题:

  • 消息队列

  • 介绍 AWS 简单查询服务

  • 使用 AWS 控制台和无服务器框架创建 AWS SQS

  • 示例项目——深度学习管道

技术要求

本章的技术要求如下:

消息队列

消息队列是不同服务之间互动的重要附加方式。虽然 RESTful API 有超时限制,但消息队列没有这种缺点。因此,它有助于处理长时间运行的过程或延迟消息。另外,它允许后端负载更均匀。它对于与 AWS Lambda 一起工作并非关键功能,因为 Lambda 可以轻松扩展,但在处理集群时非常有用。最后,消息队列支持重试逻辑,这意味着失败的任务可以被多次重新发送。现在让我们更深入地了解 AWS SQS。

AWS SQS 介绍

基本上,这是一个 AWS 服务,允许发送、接收和存储消息。它可以连接到任何处理后端。它采用按需付费系统,这使其成为一个非常方便的起点。

AWS API 网关特性

AWS API 的不同特性如下:

  • 它具有极高的可扩展性,你无需管理队列中的其他扩展。

  • 该服务处理来自读者的队列访问,因此你无需实现此功能。

  • SQS 拥有可自定义的重试机制,增加了避免错误的概率,从而提高了整体速度。

  • SQS 提供非常简单的 API,你可以在几乎任何编程语言中使用它。

  • 最后,它提供加密功能,这对于提高服务的安全性非常有用。

AWS SQS 定价

SQS 的主要优势之一是按用户付费系统,非常简单。定价为每 100 万次请求 50 美分,每月前 100 万次请求免费。这使它非常适合早期项目。

使用 AWS 控制台创建 AWS SQS 连接

在本节中,我们将首先创建一个 AWS Lambda,然后创建简单查询服务,最后将 SQS 连接到 AWS Lambda。

创建 AWS Lambda 实例

创建 AWS Lambda 实例的步骤如下:

  1. 首先,在“名称”下添加名称,选择运行时为 Python 3.6,将角色设置为“选择现有角色”,然后从现有角色中选择lambda1,点击“创建函数”,如图所示:

  1. Lambda 函数创建成功,如下截图所示:

  1. 接下来,切换到 SQS 并通过选择“创建新队列”来创建一个 SQS 队列:

  1. 在创建名为 testLambda 的队列后,我们得到如下截图中高亮显示的 SQS ARN:

5. 在左侧的 Designer 标签页中,选择 SQS 作为触发器:

  1. 我们将通过选择“队列操作”下拉菜单中的“发送消息”来向队列发送一些消息:

  1. 如你所见,我们只有一条可用消息,意味着所有消息都已经被 Lambda 消费,如下截图所示:

8. 点击“监控”后,我们会看到如下详细概览:

  1. 我们还可以通过点击 CloudWatch 中的“查看日志”来查看日志详情,如前述截图所示。每次开始和结束意味着每条消息的调用。

下一部分讲解如何使用无服务器框架创建一个 AWS SQS 连接到 AWS Lambda。

使用无服务器框架创建 AWS SQS 连接

要创建 SQS 连接,我们有主 Python 文件和无服务器配置文件。配置文件会稍微复杂一些,我们需要在资源部分定义 SQS,将其作为 Lambda 的事件源,然后允许 Lambda 从 SQS 读取数据。

Python 文件

对于 Python 文件的主要区别是,我们将不再返回一个字符串,而是写入另一个 SQS 查询,如下所示:

代码

在开始编写代码之前,我们首先需要部署无服务器框架,然后通过命令行界面检查它是否能够运行。我们将使用index.py文件和serverless.yml配置文件来运行代码。

serverless.yml

serverless.yml文件中,我们可以看到我们在之前章节中讨论的所有部分,特别是定义访问查询的角色部分,我们将在其中读取消息,并且 Lambda 将写入此查询。以下代码展示了解释:

Effect: "Allow"
Action:
    "sqs:ReceiveMessage"
    "sqs:DeleteMessage"
    "sqs:GetQueueAttributes"
Resource:
    arn:aws:sqs:#{AWS::Region}:#{AWS::AccountId}:ReadSQS

我们还需要定义其中一个查询将作为事件源,正如下图所示:

events:
    sqs:
      arn:
        Fn::GetAtt:
          ReadSQS
          Arn

最后,我们定义查询,这些查询可以在资源部分执行,如代码所示:

resources:
  Resources: 
    WriteSQS: 
      Type: AWS::SQS::Queue
      Properties:
        QueueName: "WriteSQS"
    ReadSQS: 
     Type: AWS::SQS::Queue
     Properties:
        QueueName: "ReadSQS"

此外,我们还需要使用插件serverless-pseudo-parameters,我们将安装它:

plugins:
  - serverless-pseudo-parameters

我们需要从deployment包中删除带有前述插件的包,如下所示:

package:
  exclude:
    - node_modules/**

下一步是使用此插件访问我们使用的区域 ID 和账户 ID,如下所示:

Resource:
  - arn:aws:sqs:#{AWS::Region}:#{AWS::AccountId}:ReadSQS
Effect: "Allow"
Action:
  - "sqs:SendMessage"
  - "sqs:GetQueueUrl"
Resource:
  - arn:aws:sqs:#{AWS::Region}:#{AWS::AccountId}:WriteSQS

你可以在没有这个插件的情况下访问账户 ID 和区域 ID,或者手动查找它们。

index.py

index.py文件非常简单。我们只是读取传入的消息,然后将其写入 SQS。以下是index.py的代码:

import boto3

def handler(event,context):
    for message in event['Records']:
        client = boto3.client('sqs')
        sqsAddress = client.get_queue_url(QueueName='WriteSQS')
        response = client.send_message(QueueUrl=sqsAddress['QueueUrl'],
                                        MessageBody=message['body'])
    return

我们将看到前面的index.pyserverless.yml文件在命令行中的输出:

首先,我们需要安装插件serverless-pseudo-parameters

npm install serverless-pseudo-parameters

输出如下:

接下来,我们将使用以下命令部署 Lambda:

serverless deploy

如你所见,插件已将区域替换为实际的基础区域和账户,如下图所示:

要通过队列发送消息,首先我们需要使用以下命令查找队列的 URL:

aws sqs get-queue-url --queue-name ReadSQS

有了队列 URL,我们就可以发送消息。我们看到命令成功执行:

现在我们可以从 SQS 队列中读取相同的消息。基本上,在这里我们可以检查 Lambda 是否已接收到我们发送的消息Hello world1,并将其发送到 SQL 写入。我们看到 Lambda 成功运行,并且可以在以下截图中看到结果消息Hello world1

示例项目 – 深度学习管道

在项目文件中,我们有主要的 Python 文件、无服务器配置文件、库文件和一个启动模块。配置文件将与我们在前一章中使用的配置文件相同。我们将查看 Python 文件。我们 Python 文件的主要区别在于,我们将不再返回字符串,而是将消息发送到另一个 SQS 查询。此外,我们将使 Lambda 接受消息中的图片链接,然后应用模块进行结构化。部署将与前一节中的类似。

我们将跳过模型的部署,因为我们之前已经讲解过了。

代码

首先,我们需要部署无服务器框架,然后可以使用命令行界面检查它是否运行。我们有index.py文件和serverless.yml配置文件。我们还为 TensorFlow 提供了库,并为无服务器框架预安装了插件。

配置文件 - serverless.yml

我们可以看到当前的配置文件来自前面的部分。

我们有一个存储模型的存储桶,如下所示的代码片段:

Effect: "Allow"
Action:
  - "s3:ListBucket"
Resource:
  - arn:aws:s3:::serverlessdeeplearning
Effect: "Allow"
Action:
  - "s3:GetObject"
Resource:
  - arn:aws:s3:::serverlessdeeplearning/*

有一个 Lambda 的事件源和资源,如下所示的代码片段:

- sqs:
    arn:
      Fn::GetAtt:
        - DLReadSQS
        - Arn

index.py

index.py文件中,脚本与前一节中的一样。添加了一个额外的部分,即从消息中读取 URL 并将结果写入另一个队列。以下是index.py的代码片段:

import boto3
import numpy as np
import tensorflow as tf
import os.path
import re
from urllib.request import urlretrieve
import json
SESSION = None
strBucket = 'serverlessdeeplearning'
def handler(event, context):
    global strBucket
    global SESSION
    if not os.path.exists('/tmp/imagenet/'):
       os.makedirs('/tmp/imagenet/')
       ...

以下截图展示了我们如何检索图像并在其上运行模型,因此,我们将模型的结果写入另一个队列,如下所示:

if ('Records' in event):
    for message in event['Records']:
        urlretrieve(message['body'].strip('\''), strFile)
        vecResult = run_inference_on_image(strFile)
        client = boto3.client('sqs')
        sqsAddress = client.get_queue_url(QueueName='DLWriteSQS')
        response = client.send_message(QueueUrl=sqsAddress['QueueUrl'],
                                       MessageBody=vecResult[0])
 else:
        downloadFromS3(strBucket,'imagenet/inputimage.png',strFile)
        strResult = run_inference_on_image(strFile)

现在让我们按照如下方式部署服务:

我们将通过命令行界面将带有 URL 的消息发送到第一个队列:

我们可以从另一个队列中读取发送的消息,如下所示:

总结

在本章中,我们介绍了 AWS SQS,包括其功能以及定价。我们还使用 AWS 控制台和无服务器框架创建了 AWS SQS 连接。

我们学习了serverless.yml配置文件和index.py文件的部署。本章以一个示例项目结束,该项目是一个深度学习管道。

在下一章中,我们将学习如何通过连接 AWS Lambda 实例和 AWS 函数创建跨越的工作流,并在其中学习如何构建深度学习工作流。

第七章:创建深度学习工作流

在本章中,你将学习 AWS Step Functions 服务,并通过使用 AWS 控制台连接到 AWS Lambda 来创建 AWS Step Functions。你还将学习如何使用 Serverless 框架创建 AWS Step Functions 连接,最后,你将查看一个深度学习工作流的示例项目。

我们将涵盖以下主题:

  • AWS Step Functions 服务介绍

  • 使用 AWS 控制台创建连接到 AWS Lambda 的 AWS Step Functions 连接

  • 使用 Serverless 框架创建 AWS Step Functions 连接

  • 深度学习工作流

技术要求

本章的技术要求如下:

AWS Step Functions 服务介绍

本节我们将介绍 AWS Step Functions 服务,包括其功能以及使用该服务的定价信息。

处理工作流

处理工作流是不同服务之间交互的额外方法。如果你想在深度学习中构建一个多步骤的过程,它可能意味着加载数据、预处理数据然后运行模型。虽然你可以在每个后端节点之间放置查询,但监控单个任务的处理将变得非常困难。这就是工作流非常方便的地方。基本上,工作流服务在需要时负责调用每个节点,并处理处理作业的中间状态。它让你能够高层次地查看每个任务的状态,并跟踪任务失败和超时。最后,它允许你在工作流中非常灵活地使用组件。

AWS Step Functions

AWS Step Functions 是一个 AWS 服务,允许你将工作流管理为一个状态机。它可以连接到任何处理后端,并与 AWS Lambda 进行原生集成。它采用按需计费系统,非常便捷。

AWS Step Functions 功能

现在我们来看看 Step Functions 的具体功能:

  • Step Functions 极具可扩展性,你无需管理扫描或工作流。

  • Step Functions 提供了出色的可视化 UI,便于监控处理作业。

  • 状态管理允许你添加复杂的逻辑,例如根据前一个节点的结果选择下一个节点,并且它还支持并行运行多个节点。

  • 一些功能提供了方便的重试任务逻辑,使你能够确保任务的处理。

  • 内置的错误处理功能允许你处理各种情况。例如,当你遇到某些异常时,你需要一种方式来为错误处理添加逻辑,例如在数据库中将任务标记为失败。

  • 调度允许你运行延迟处理任务,非常方便当你需要等待另一个过程完成时。

AWS Step Functions 定价

Step Functions 的主要优势之一是按需付费系统。非常简单,每 10,000 次请求收费 25 美分,其中每月前 4,000 次请求是免费的。这使其非常适合早期项目。

Step Functions 与 SQS 的对比

如果我们深入分析 Step Functions 与 SQS 在功能和可能的使用场景上的区别,可以说 SQS 最适合处理简短、简单、低优先级的任务,这些任务的数量可能非常庞大(每天可能有数百万个任务)。而 Step Functions 则最适合处理那些需要多步骤、耗时较长的复杂过程,并且我们希望保证每个任务的交付(每天可能有数千个任务)。在接下来的部分中,你将学习如何使用 AWS 控制台创建 AWS Step Functions 与 AWS Lambda 的连接。

使用 AWS 控制台创建 AWS Step Functions 与 AWS Lambda 的连接

在本节中,我们将使用 AWS 控制台创建 Step Functions。创建 Step Function 有两个主要步骤:

  1. 创建 AWS Lambda 实例

  2. 创建将使用 Lambda 实例的 Step Function

创建 AWS Lambda 实例

现在我们将使用 AWS 控制台创建一个 AWS Lambda 实例:

  1. 导航到 Lambda 来创建 Lambda 实例。

  2. 现在输入名称为testLambdaStepFunction,运行时选择 Python 3.6,角色选择“选择现有角色”,现有角色选择lamdaAdminRole。然后点击“创建功能”,位于屏幕的右下角:

  1. Lambda 实例已成功创建:

创建 Step Function

创建 Step Function 时,我们需要执行以下步骤:

  1. 进入 Step Functions 服务并点击“创建状态机”:

  1. 在“定义状态机”标签中,输入名称为testLambda:

  1. 现在我们需要将Type定义为TaskResource。对于资源,你需要使用你 Lambda 的 ARN 地址,可以在标签的右上角找到。你可以将其复制并粘贴到状态机定义部分,如下图所示:

  1. 现在我们将创建一个 IAM 角色,这一步是自动完成的。输入名称为StepFunctionTestRole,然后点击“创建功能”。在你的状态机获得执行权限之前,这将花费一分钟时间:

  1. 现在,在我们创建了 Step Function 后,我们可以测试并发送一条简单的消息。为此,请点击“开始执行”:

  1. 我们可以在这里看到执行图:

  1. 对于每次执行,你可以看到整个步进函数的输入和输出:

  1. 我们可以看到每个节点的输入和输出(这可以在“步进详情”标签中查看)。如果有错误,我们将在“异常”标签中看到它。此外,如果你向下滚动,还可以看到执行的时间线:

  1. 我们还可以通过点击“步进详情”标签下的“资源”标签中的链接来检查日志。这将带你到以下页面:

因此,我们可以看到步进函数是一个非常方便的服务,用于管理 Lambda 执行。

使用无服务器框架为 AWS Lambda 实例创建 AWS 步进函数

在本节中,我们将使用无服务器框架创建步进函数。首先,让我们看看我们的项目文件:一个 Python 文件和无服务器配置文件。在配置文件中,我们将添加一些插件,并描述步进函数,这是一个复杂的内容。

所以,让我们通过开始实时代码来探索无服务器配置文件中的步进函数:

  1. 部署无服务器框架。

  2. 使用 CLI,检查无服务器框架的部署状态。

  3. 现在,通过 AWS 控制台检查步进函数结果。

步进函数

让我们通过执行ls命令来检查我们拥有的文件列表。如你所见,我们有index.py文件和serverless.yml配置文件服务文档。我们还为无服务器框架安装了插件。

让我们看看配置文件及其两个主要部分:

  1. 首先,我们将添加几个函数,这些函数将在步进函数的不同状态下使用:
function:
    branch:
        handler: index.handlerBranch
    map:
        handler: index.handlerMap
    reduce:
        handler: index.handlerReduce
  1. 接下来,我们将添加一些插件,这是与步进函数一起工作的必要条件:
plugins:    - serverless-step-functions
    - serverless-pseudo-parameters
  1. 现在让我们看一下index.py文件,在那里你可以看到到目前为止讨论的所有部分:
def handlerMap(event,context):
    return event

def handlerReduce(event,context):
    return event

def handlerBranch(event,context):
    return 'Hello world'

无服务器部署

现在,让我们通过执行以下命令来部署我们的服务:

serverless deploy

上述命令将部署你的服务,如下图所示:

作为部署的一部分,它将提供 API 网关的 URL,如下图所示:

现在让我们在命令行中测试这个 URL:

curl https://dns1519ilj.execute-api.us-east-1.amazonaws.com/dev/startFunction

你可以在浏览器中检查结果。在以下截图中,你可以看到我们的步进函数:

在以下截图中,我们可以看到最新的执行成功完成:

你可以检查每个节点的输入和输出。如果有任何错误,可以在“异常”部分检查。

两个分支都返回了 hello world,步进节点将结果合并并将其作为步进函数的结果返回:

这里,让我们检查一下执行的时间线。你还可以看到这些分支几乎是同时启动的。

在下一节中,我们将查看深度学习工作流项目的一个示例。

示例项目 – 深度学习工作流

首先,让我们看看以下的项目文件。我们有主 Python 文件、服务集成文件,以及一些库和 Inception 模型。在配置文件中,我们将添加一些插件并描述步骤函数,这是一个复杂的内容。

与我们的 Python 文件的主要区别在于,我们将有三个函数。其中一个将把一组 URL 链接映射成不同的对象。另一个将在链接上运行模型。最后一个将把结果合并。部署结构与上一节中的类似。由于我们在上一章已经覆盖过模型部署到 S3 的部分,这里就跳过。

创建模型

这里,我们需要部署无服务器框架,然后使用 CLI 检查痕迹:

  1. 让我们来看看配置文件。你可以看到我们需要定义的所有主要部分和角色,以便访问模型:
provider:
  name: aws
  region: us-east-1
  runtime: python3.6
  memorySize: 1536
  timeout: 30
  iamRoleStatements:
    - Effect: "Allow"
       Action:
         - "s3:ListBucket"
       Resource:
         - arn:aws:s3:::serverlessdeeplearning
    - Effect: "Allow"
       Action:
         - "s3:GetObject"
       Resource:
         - arn:aws:s3:::serverlessdeeplearning/*
  1. 这里是我们将在步骤函数的不同状态下使用的函数:
functions:
  main:
    handler: index.handler
  map:
    handler: index.map
  reduce:
    handler: index.reduce
  1. map 将启用将传入的事件映射到不同的 Lambda,range 将使得每个链接可以并行地单独处理,而 reduce 则有助于将它们合并成一个响应。我们有状态机定义,它与之前讨论的非常相似:
stepFunctions:
  stateMachines:
    DeepLearningWorkflow:
      events:
        - http:
            path: gofunction
            method: POST
      name: DeepLearningWorkflow
      definition:
        StartAt: StartStepF
        States:
          StartStepF:
            Type: Task
            Resource: arn:aws:lambda:#{AWS::Region}:#{AWS::AccountId}:function:${self:service}-${opt:stage}-map
            Next: Parallel
          Parallel:
            Type: Parallel
            Next: EndStepF
            Branches:
              - StartAt: Branch1
                States:
                  Branch1:
                    Type: Task
                    Resource: arn:aws:lambda:#{AWS::Region}:#{AWS::AccountId}:function:${self:service}-${opt:stage}-main
                    InputPath: '$.branch1.url'
                    ResultPath: '$.res'
                    End: True
              - StartAt: Branch2
                States:
                  Branch2:
                    Type: Task
                    Resource: arn:aws:lambda:#{AWS::Region}:#{AWS::AccountId}:function:${self:service}-${opt:stage}-main
                    InputPath: '$.branch2.url'
                    ResultPath: '$.res'
                    End: True
              - StartAt: Branch3
                States:
                  Branch3:
                    Type: Task
                    Resource: arn:aws:lambda:#{AWS::Region}:#{AWS::AccountId}:function:${self:service}-${opt:stage}-main
                    InputPath: '$.branch3.url'
                    ResultPath: '$.res'
                    End: True
          EndStepF:
            Type: Task
            Resource: arn:aws:lambda:#{AWS::Region}:#{AWS::AccountId}:function:${self:service}-${opt:stage}-reduce
            End: true
  1. 这里是我们所需的插件,以便使函数正常工作:
plugins:
  - serverless-step-functions
  - serverless-pseudo-parameters
  1. 我们的索引文件与上一节的主要区别是,我们添加了 MapReduce 逻辑。这将使得每个 URL 可以单独处理:
def map(event, context):
    dictMap = {}
    dictMap['branch1'] = {'url':event[0]}
    dictMap['branch2'] = {'url':event[1]}
    dictMap['branch3'] = {'url':event[2]}
    return dictMap

def reduce(event, context):
    vecRes = []
    for res in event:
        vecRes.append(res['res'])
    return vecRes

对于这个例子,我们将使用三个 URL,分别对应来自免费图片网站的狗、熊猫和红熊猫图像。

  1. 现在我们的模型已经准备好,接下来使用以下命令部署服务:
serverless deploy
  1. 你将会得到一个 API 的 URL 用于测试。

  2. 让我们测试一下这个 URL。我们将需要使用 curl 命令,它与之前的用法略有不同。

  3. 首先,我们将使用 POST 请求而不是 GET 请求,并且会提供一个包含链接的列表作为请求的一部分。正如你所看到的,它成功返回了。这次执行表明它成功地将命令发送到了步骤函数:

  1. 现在让我们在浏览器中查看图表。我们可以看到它已经完成了执行:

  1. 我们可以看到每个分支都收到了一个独立的 URL,并且我们可以看到最终的节点成功地将不同分支的结果合并为一个,并且成功识别了这些图像:

此外,我们可以查看执行的时间线,看到几乎所有分支几乎同时开始。

这意味着并行化真正使我们能够更快地处理链接列表。

总结

在本章中,我们学习了 AWS Step Functions 服务,包括其功能和定价。我们还了解了如何通过 AWS 控制台将 AWS Step Functions 连接到 AWS Lambda。我们还看到了如何使用无服务器框架创建步骤函数,并且甚至创建了一个深度学习工作流。

posted @ 2025-07-08 21:22  绝不原创的飞龙  阅读(20)  评论(0)    收藏  举报