Category: SageMaker


Amazon SageMaker – 加快机器学习进程

机器学习是许多初创公司和企业的关键技术。尽管经历了数十年的投入和改进,开发、训练和维护机器学习模型的过程仍然繁琐且欠缺通用性。将机器学习技术集成到应用程序中的过程往往需要一个专家团队进行为期数月的调整和修补,而且设置还不一致。企业和开发人员需要一个端到端、开发到生产的机器学习管道。

Amazon SageMaker 简介

Amazon SageMaker 是一种完全托管的端到端机器学习服务,数据科研人员、开发人员和机器学习专家可以快速、大规模地构建、训练和托管机器学习模型。这极大地推进了您所有的机器学习工作,让您能够将机器学习技术迅速融入生产应用程序。

Amazon SageMaker 包含三个主要组件:

  • 编写:零设置托管式 Jupyter 笔记本 IDE,可进行数据探索、清理和预处理。您可以在一般实例类型或 GPU 驱动实例上运行上述功能。
  • 模型训练:分布式模型构建、训练和验证服务。您可以使用内置的通用监督式和非监督式学习算法和框架,也可以借助 Docker 容器创建自己的训练。训练可以扩展到数十个实例以支持更快的模型构建。从 S3 读取训练数据,并将模型构件存放到 S3。模型构件是数据相关的模型参数,而不是允许您从模型进行推理的代码。这种问题隔离策略简化了将经过 Amazon SageMaker 培训的模型部署到物联网设备等其他平台的过程。
  • 模型托管:一种模型托管服务,可通过 HTTPS 终端节点调用模型获取实时推理。这些终端节点能够扩展以支持流量,允许您同时对多个模型进行 A/B 测试。同样,您可以使用内置软件开发工具包构建这些终端节点,也可以利用 Docker 镜像提供自定义配置。

这些组件中的每一个都可以独立使用,这使得使用 Amazon SageMaker 填补现有管道中的空白变得极其简单。也就是说,在端到端管道中使用此服务时,您可以获得一些非常强大的功能。

使用 SageMaker

我打算构建、训练和部署一个基于 Apache MXNet 的图像分类器。我将使用 Gluon 语言、CIFAR-10 数据集和 ResNet V2 模型架构。

使用 Jupyter 笔记本编写


创建笔记本实例时,它会启动一个 ML 计算实例,其中包含深度学习应用中常见的 Anaconda 包和库、一个 5 GB ML 存储卷和几个演示各种算法的示例笔记本。我可以选择配置 VPC 支持来在我的 VPC 中创建一个 ENI,以方便、安全地访问我的资源。

待实例完成预配置后,我就可以打开笔记本开始编写代码了!

模型训练

对于任何类型的 Amazon SageMaker 常见框架训练,您都可以实现类似下面的简单训练接口。为简洁起见,这里省略了实际的模型训练代码:

def train(
    channel_input_dirs, hyperparameters, output_data_dir,
    model_dir, num_gpus, hosts, current_host):
    pass

def save(model):
    pass

我打算在 Amazon SageMaker 基础设施上的 4 个 ml.p2.xlarge 实例上创建一个分布式训练作业。我已经下载了本地所需的全部数据。

import sagemaker
from sagemaker.mxnet import MXNet
m = MXNet("cifar10.py", role=role, 
          train_instance_count=4, train_instance_type="ml.p2.xlarge",
          hyperparameters={'batch_size': 128, 'epochs': 50, 
                           'learning_rate': 0.1, 'momentum': 0.9})

现在,我们构建好了模型训练作业,可以通过下面的调用为其提供数据: m.fit("s3://randall-likes-sagemaker/data/gluon-cifar10")

导航到作业控制台,可以看到系统正在运行此作业!

托管和实时推理

现在,我的模型已完成训练,可以开始生成预测了!我使用跟以前相同的代码创建和启动一个终端节点。


predictor = m.deploy(initial_instance_count=1, instance_type='ml.c4.xlarge')

调用终端节点的操作十分简单,直接运行: predictor.predict(img_input)!

这就是一个代码不足 100 行的端到端机器学习管道。

下面我们再演练一个示例,了解一下如何只使用 Amazon SageMaker 的模型托管组件。

使用自定义 Docker 容器

Amazon SageMaker 为 Docker 容器定义了一个简单的规范,让您能够轻松编写自定义训练算法或自定义推理容器。

我有一个基于此处所述架构的现有模型,我打算托管此模型进行实时推理。

我创建了一个简单的 Dockerfile 和 flask 应用程序来提供推理。

由于加载模型和生成预测的代码因实际应用而异,此处省略了这些代码。从本质上说,我构建了一个方法来从输入 URL 下载图像,然后将此图像数据传递给 MXNet 模型进行预测。

from flask import Flask, request, jsonify
import predict
app = Flask(__name__)

@app.route('/ping')
def ping():
    return ("", 200)

@app.route('/invocations', methods=["POST"])
def invoke():
    data = request.get_json(force=True)
    return jsonify(predict.download_and_predict(data['url']))

if __name__ == '__main__':
    app.run(port=8080)
FROM mxnet/python:latest
WORKDIR /app
COPY *.py /app/
COPY models /app/models
RUN pip install -U numpy flask scikit-image
ENTRYPOINT ["python", "app.py"]
EXPOSE 8080

我将这个图像推送到 ECR,然后导航到 Amazon SageMaker 中的模型控制台来创建一个新模型。

创建新模型后,我还预配置了一个终端节点。

现在我可以从 AWS Lambda 或任何其他应用程序调用此终端节点了!我设置了一个 Twitter 账户来展示这个模型。您可以通过 Twitter 向 @WhereML 推送一张图片,看看它能否猜出位置!


import boto3
import json
sagemaker = boto3.client('sagemaker-runtime')
data = {'url': 'https://pbs.twimg.com/media/DPwe4kMUMAAWCd_.jpg'}
result = sagemaker.invoke_endpoint(
    EndpointName='predict',
	Body=json.dumps(data)
)

定价

作为 AWS 免费套餐的一部分,您可以免费开始使用 Amazon SageMaker。在前两个月,您每月可以免费使用:250 小时的 t2.medium 笔记本用量、50 小时的 m4.xlarge 用量和 125 小时的 m4.xlarge 用量。超出免费套餐部分的定价因地区而异,但基于以下要素计费:实例用量 (秒)、存储 (GB) 和传入/传出服务的数据量 (GB)。

Jeff 告诉我,在今年的 re:Invent 大会举办之前,不要撰写“太过重磅”的文章。显然,我没把持住。在 re:Invent 2017 发布的众多美妙产品中,Amazon SageMaker 是我最喜欢的服务。我已经迫不及待想要知道我们的客户能够利用这个令人兴奋的工具套件完成哪些“壮举”了。

Randall

AWS DeepLens 扩展:自建项目

AWS DeepLens 提供了极好的机会来学习新技术,例如深度学习和物联网 (IoT),以及构建可以解决实际问题的创新系统。该设备和服务附带有一组预定义的项目,使得从头开始运行非常简单。它设计作为开放平台,使得新手和有经验的开发人员都能构建 (和分享) 新的激动人心的项目。

在本博客文章中,您将逐步完成构建自己项目的过程,包括以下步骤:

  • 训练深度学习模型 (使用 Amazon SageMaker)
  • 优化经过训练的模型以在 AWS DeepLens 边缘设备上运行
  • 开发 AWS Lambda 函数以加载模型并用于在视频流上运行推理
  • 使用 AWS Greengrass 将 AWS Lambda 函数部署到 AWS DeepLens 设备
  • 将边缘 AWS Lambda 函数传递到云中,用于发送命令和接收推理输出
  • 营利

训练深度学习模型 (使用 Amazon SageMaker)

Amazon SageMaker 是面向繁重的数据科学的另一项新服务。它汲取了 Amazon 数据科学家在 Amazon.com 众多业务领域的多年经验,从建议引擎到 Alexa、Amazon Go、Amazon Robotics 乃至其他无穷的基于机器学习的系统。

虽然本篇博客帖子所涵盖的内容极为有趣,不过设计和构建良好机器学习模型的完整过程远不止这些。实际上,通过将深度学习模型部署到 DeepLens 设备,然后传输回来并从输出中获益,一旦通过这个流程实现生产,您就会发现自己会有越来越多的时间构建模型,来解决真实世界的新问题。

对于机器学习新手以及数据科学专家而言,当您在 Amazon SageMaker 中启动 Notebook 实例时,Jupyter Notebook 中提供的一组 Notebook 是一个很好的起点。例如,这里有一个 Notebook,展示了两个流程,一个是转换学习,另一个是使用 Amazon SageMaker 开发工具包构建、训练和部署经过调整的深度学习模型工作流,用于推理终端节点托管。

在本篇博客帖子中,您的重点是将模型项目保存到 Amazon S3 中以启用流程中的后续步骤。

以下示例模型使用 SageMaker 中的训练作业进行训练,包括输出目录以及在其训练中使用的超级参数:

超级参数可帮助您了解如何使用模型。例如,根据 image_shape (3,224,224),我们知道您可以处理彩色图像 (3=RGB 通道),并且需要将其大小调整为 224*224 像素。它还有助于在未来的训练作业中获得更准确的模型,例如,对训练数据 (epochs>2) 运行更多次数,更改 learning_rate 以及添加更多 num_training_samples。

优化经过训练的模型以在 AWS DeepLens 边缘设备上运行

对 DeepLens 设备模型进行硬件优化的步骤是它在任何实际深度学习系统中的重要示例。在之前的步骤中,您拥有几乎无限的云资源用于模型训练,但是,当您希望使用模型进行推理时,面临着一系列的业务约束,主要与业务规模有关。在云中,您可以轻松获得基于 GPU 的大量实例,并可以在很多小时数的训练中运行多个实验。但是,当您要将模型部署到边缘设备时,您需要考虑芯片集 (CPU/GPU)、内存、网络带宽和稳定性等各种设备规格。您的 DeepLens 设备可能会足够强大,能够在高帧率的高分辨率视频流上运行多个模型,不过多数情况下您需要在较低规格的设备上运行。因此,Intel 开发了库,获取 MXNet 模型的构件,并根据 DeepLens 设备中的 Intel 芯片板进行优化。从前一步骤导入模型之后,当您通过 DeepLens 控制台部署模型时,此库自动执行。

完成训练模型后,在将模型导入到 DeepLens 时,您可以指向训练作业 ID。(请注意,Sagemaker 和 DeepLens 需要位于同一个 AWS 区域中才能导入。)

开发 AWS Lambda 函数以加载模型并用于在视频流上运行推理

运行在 IoT 设备 (在我们的案例中是 AWS DeepLens 摄像机) 上的 AWS Greengrass 核心能够运行部署到其中的 AWS Lambda Python 函数。在未来的帖子中,我们将探讨创建 Greengrass 组和核心以及准备和注册设备的步骤,您可以查看 Greengrass 文档中的入门指南。AWS DeepLens 可以自动完成其中的大部分步骤。我们可以侧重于开发 Lambda 函数以部署到所注册和配置的设备。

对于每个 Lambda 函数,请遵循以下步骤:

  • 加载模型
  • 捕获帧
  • 在帧上运行模型推理
  • 解析推理的结果
  • 将结果发布到 MQTT 主题

下面的一些示例是关于这些步骤中的每个步骤。

加载模型

AWS DeepLens 设备预安装了帮助程序库 awscam。利用这个库,您很容易就可以集中注意力于 Lambda 函数逻辑。它包装了大部分常用步骤,例如加载模型。如您在以下示例中所见,您需要提供模型 XML 文件的路径以及模型 (GPU/CPU) 的上下文,然后库会自动执行模型的加载和绑定:

import awscam
modelPath = "/opt/awscam/artifacts/mxnet_deploy_CaltechTransfer_224_FP16_FUSED.xml"
# 将模型加载到 GPU (对 CPU 使用 {"GPU": 0})
mcfg = {"GPU": 1}
model = awscam.Model(modelPath, mcfg)

请注意,此步骤应该在内部推导函数之外定义 (例如,下面的 greengrass_infer_image_run)。此步骤应仅运行一次,因为将模型从磁盘加载到内存再到 GPU 需要几秒钟。

捕获帧

可使用 OpenCV (cv2) 在深度学习模型之前 (调整大小) 和之后 (绘制框和标签) 来处理图像。由于各个模型在不同的输入规范上训练,因此第一步都需要将捕获的帧大小调整为合适的尺寸:

import cv2
input_width = 224
input_height = 224
ret, frame = awscam.getLastFrame()
# 调整帧大小以适应模型输入要求
frameResize = cv2.resize(frame, (input_width, input_height))

在帧上运行模型推理

帮助程序库 awscampredict 命令包装到简单 doInference 函数中,使得 Lambda 函数的这一部分非常简明:

# 在调整大小后的帧上运行模型推理
inferOutput = model.doInference(frameResize)

解析推理的结果

帮助程序库支持几个经典的计算机视觉问题:“classification”用于对象分类,即提供标签;“ssd”(“single-shot-multibox-detector”) 用于对象检测和本地化,为对象提供标签和边界框;以及“segmentation”,用于将图像细分为区域,并提供像素级别的输出 (例如,用于风格转换)。以下示例针对常见的“ssd”类型模型:

modelType = "ssd"
parsed_results = model.parseResult(modelType, inferOutput)['ssd']

将结果发布到 MQTT 主题

最后一部分是发送模型的输出。此逻辑取决于模型的类型以及您尝试解决的问题类型。其中一个简单输出是图像的标签,例如“狗/猫”或者“热狗/非热狗”,如以下示例所示。其他类型的输出还包括从人脸检测模型剪裁图像中的脸部并发送以进行面部识别,视频流中对象的边界框,或图像/视频的神经风格转换。从设备发送输出的最简单方法是通过 MQTT 使用 Greengrass 客户端,如以下代码所示。此通道可以支持文本消息,不过也支持经过文本编码之后的图像 (例如,带有边界框和标签)。

# 创建 greengrass 核心开发工具包客户端
client = greengrasssdk.client('iot-data')
iotTopic = 'iot-data'
for obj in parsed_results:
    if obj['prob'] > max_threshold:
        label = '{{"label":"{}", "prob":{:.2f}%'.format(outMap[obj['label']], obj['prob']*100 )
        client.publish(topic=iotTopic, payload = label)

使用 AWS Greengrass 将 AWS Lambda 函数部署到 DeepLens 设备

Greengrass 以两种主要模式运行 Lambda 函数:固定和按需。针对 AWS DeepLens 模型,推荐方法是使用固定选项作为 Lambda 函数的开始。这花的时间会很长,特别是在深度学习模型很大时 (数百 MB,甚至若干 GB)。您可以通过几种模式来控制触发推理的频率和时间:

  • 最高帧率 – 以无限循环方式运行函数,帧与帧之间没有“休眠”。根据模型推理、预处理和后处理的速度,您可以得到 10-30 FPS 的帧率。
  • 特定帧率 – 以无限循环方式运行函数,帧与帧之间具有预定义的“休眠”。一些任务 (例如人脸检测) 可以按照每秒 1-5 帧的速度运行,并提供检测某一区域中所有脸部时的必需功能。您可以使用 Timer 来控制函数推理的速率:
    from threading import Timer
    def greengrass_infer_image_run():
        # 读取图像
        # 预处理
        # 对图像运行模型推理
        # 解析结果
        # 输出结果
        
        # 异步调用此函数,在 1/2 秒后重新运行
        Timer(0.5, greengrass_infer_image_run).start()
  • 按需 – 每当您希望触发时运行函数,可以手动触发,也可以从其他事件触发。即使您在以固定方式运行函数,也可以使用事件处理程序来按需触发。以下示例演示了如何在每个事件上触发推理,不过您还可以使用事件处理程序,通过解析事件参数来进一步控制函数 (例如,切换模型或模型模式)。
    def greengrass_infer_image_run():
        # 读取图像
        # 预处理
        # 对图像运行模型推理
        # 解析结果
        # 输出结果
        
    def lambda_handler(event, context):
        client.publish(topic=iotTopic, payload="About to call image inference function")
        greengrass_infer_image_run()
    return

为您的 Lambda 函数获取 Greengrass 骨架有一种简单方法,这就是在 AWS Lambda 控制台中使用 Greengrass 蓝图之一,最好是 greengrassHelloWorld,因为在其程序包中已经包括了 Greengrass 客户端库。使用此蓝图创建 Lambda 函数并使用您的代码替换函数的 Python 代码,然后发布新创建的 Lambda 函数。现在您可以将它添加到项目,然后通过 AWS DeepLens 控制台将其部署到设备。

将本地 Lambda 函数传递到云中,用于发送命令和接收推理输出

如前文所述,Lambda 函数可以使用 IoT 主题通过 MQTT 协议写出其输出。内置项目使用的默认输出主题为:

iotTopic = '$aws/things/{}/infer'.format(os.environ['AWS_IOT_THING_NAME'])

您可以在 AWS DeepLens 控制台或 AWS IoT 控制台中找到此内容。在 Lambda 函数中,您可以选择使用相同的格式,也可以使用任何其他主题名称,例如前面示例中的 iotTopic = ‘iot-data’。

在前文中还可以看到,您能够使用 lambda_handler 以按需模式触发 Lambda 函数。为了实现这一点,您需要使用 IoT 控制台,在 IoT 云与 Lambda 函数之间设置订阅。例如,此处是对 Lambda 函数的入站和出站订阅 (ImageInferenceTest 版本 19):

在本例中,边缘 Lambda 函数侦听到主题“trigger-image-inference”,并在每次有事件发布到此主题时触发推理。使用第二个订阅可以查看边缘 Lambda 函数的输出消息,并在云端对其做出反应。例如,您可以使用 AWS IoT 规则引擎筛选特定消息 (例如“face detected”),然后将其发送到其他云端 Lambda 函数、Amazon Elasticsearch Service、Amazon Kinesis 等。请不要忘记部署 (在“Actions”下) 订阅以同样在 DeepLens 设备上启用订阅。

我们还建议您为设备的 Greengrass 组启用 Amazon CloudWatch Logs,以允许您查看 Lambda 函数的日志和 Greengrass 核心信息 (或调试) 日志。您可在 Greengrass 组控制台页的“Settings”部分下找到该设置。

结论

在本篇博客帖子中,您了解了如何扩展在 AWS DeepLens 中提供的开放项目环境。在以后的博客中,您将看到以这个流程为基础的更详细、更具体的示例,它们使用相同的结构和构建块。此处的图形展示了各种步骤,您可在扩展现有项目时 (采用更好的模型或不同 Lambda 函数) 或者从头开始创建全新项目时使用这些步骤。

如果您有任何疑问,请在评论中留言。


补充阅读

了解如何扩展 AWS DeepLens 以使用 AWS Lambda 发送 SMS 通知


作者简介

Guy Ernest 是 Amazon AI 的首席解决方案架构师。他有一个令人非常兴奋的机会来帮助塑造和践行策略,以构建思想共享并广泛使用适用于 AI、机器学习和深度学习使用案例的 Amazon 云计算平台。在空闲时间,他喜欢与妻子和家人呆在一起,收集一些令人尴尬的故事,然后在谈论 Amazon 和 AI 的未来时进行分享。