训练亚马逊 SageMaker 对象检测模型并在 亚马逊云科技 IoT 上运行它 Greengrass — 第 3 部分,共 3 部分:部署到边缘

作者: 王 安琪 |

亚马逊云科技 解决方案架构研发 和创新团队的高级工程师 Angela W ang 和 Tanner McRae 的帖子

这篇文章是关于如何使用亚马逊 SageMaker 和 亚马逊云科技 IoT Greengrass 在边缘构建和部署自定义对象检测模型的系列文章中的第三篇。在本系列的前两部分中,我们引导您 使用 Amazon SageMaker 的内置 SSD 算法 准备 训练数据 和训练自定义对象检测模型 。您还将模型输出文件转换为可部署格式。在这篇文章中,我们获取输出文件并向您展示如何使用 亚马逊云科技 IoT Greengrass 在边缘设备上运行推断。

以下提醒您正在建造的整体架构:

architecture diagram of the blog

按照您的 亚马逊云科技 账户中的步骤操作

欢迎您在自己的 亚马逊云科技 账户和边缘设备上关注即将采取的步骤。第 1 部分和第 2 部分不是学习本节的先决条件。您可以使用自己训练过的自定义模型,也可以使用我们提供的示例模型(在 CDLA 许可 协议下)。

在边缘设备上设置环境和 亚马逊云科技 IoT Greengrass Core

在开始在边缘设备上安装 亚马逊云科技 IoT Greengrass 核心之前,请务必 检查 硬件和操作系统要求。 在这篇文章中,我们使用了带有 Ubuntu 18.04 AMI 的亚马逊 EC2 实例。尽管它不是真正的边缘设备,但我们经常发现使用 EC2 实例作为 亚马逊云科技 IoT 用例的测试和开发环境很有帮助。

设备设置

对于支持 GPU 的设备,请确保安装了 GPU 驱动程序,例如 CU DA。如果你的设备只有 CPU,你仍然可以运行推理,但性能会变慢。

此外,请务必在边缘设备上安装运行模型推理代码所必需的 MXNet 和 OpenCV。有关指导,请参阅 此处 的文档 。

接下来,配置您的设备,按照 设置环境中的 步骤安装 亚马逊云科技 IoT Greengrass 核心软件并安装 亚马逊云科技 IoT Greengrass 软件。

或者,启动以下 亚马逊云科技 CloudFormation 堆栈,启动一个测试版 EC2 实例,完成前面的设置:

button to launch predefinied cloudformation stack

创建 亚马逊云科技 IoT Greengrass 群组

现在,您可以在 亚马逊云科技 云中创建 亚马逊云科技 IoT Greengrass 群组了。有几种不同的方法可以做到这一点,并配置 亚马逊云科技 Lambda 函数以在边缘运行您的模型:

  • 使用 Greengo ,这是一个开源项目,用于在配置文件中定义 亚马逊云科技 IoT Greengrass 资源并通过命令行管理部署:这是本文中详细介绍的选项。
  • 使用 亚马逊云科技 IoT G reengrass 控制台:有关步骤,请参阅在 亚马逊云科技 I oT 上配置 亚马逊云科技 IoT Greeng rass。
  • 使用 亚马逊云科技 CloudFormation :有关示例设置,请参阅使用 亚马逊云科技 CloudFormation 自动设置 亚马逊云科技 IoT Greengrass

在这篇文章中,我们将引导你使用Greengo设置这个物体检测模型。我们的团队更喜欢使用 Greengo 项目来管理 亚马逊云科技 IoT Greengrass 部署,特别适合在快速原型设计和开发环境中使用。我们建议使用 亚马逊云科技 CloudFormation 来管理生产环境。

在 macOS 或 Linux 计算机上,使用 git clon e 下载我们提供的 示例代码 (如果您尚未这样做)。此处显示的命令尚未在 Windows 上经过测试。

greengrass/ 文件夹中,你会看到一个 greengrass 文件,该 文件定义了 A WS IoT Greengrass 群组的配置和 Lambd a 函数。该文件的顶部定义了 亚马逊云科技 IoT Greengrass 组和 亚马逊云科技 IoT Greengrass 核心的名称:

Group:
  name: GG_Object_Detection
Cores:
  - name: GG_Object_Detection_Core
    key_path: ./certs
    config_path: ./config
    SyncShadow: True

要在 AWS IoT 中初始设置 AWS IoT Greengrass 组资源,请在找到 greengo.yaml 的文件夹中运行以下命令。

pip install greengo
greengo create

这会在 AWS 中创建所有 AWS IoT Greengrass 群组构件,并将 AWS IoT Greengrass Core 的 证书和 c onfig. json 放入其中。 /certs /和。 /配置/

它还会在 .gg/gg_state.json 中生成一个状态 文件, 该文件在部署期间引用了所有正确的资源:

├── .gg
│   └── gg_state.json
├── certs
│   ├── GG_Object_Detection_Core.key
│   ├── GG_Object_Detection_Core.pem
│   └── GG_Object_Detection_Core.pub
├── config
│   └── config.json

使用 scp 将证书和配置文件夹复制到边缘设备(或测试 EC2 实例),然后将其复制到设备上的 /greengrass/c erts/ 和 /greengrass/ config/ 目录中。

sudo cp certs/* /greengrass/certs/
sudo cp config/* /greengrass/config/

在您的设备上,还可以将与 Greengo 生成的证书兼容的根 CA 证书下载到 /greengrass / certs/ 文件夹:

cd /greengrass/certs/
sudo wget -O root.ca.pem https://www.symantec.com/content/en/us/enterprise/verisign/roots/VeriSign-Class%203-Public-Primary-Certification-Authority-G5.pem

启动 亚马逊云科技 IoT Greengrass 核心

现在,您可以准备在边缘设备上启动 亚马逊云科技 IoT Greengrass 核心守护程序。

$ sudo /greengrass/ggc/core/greengrassd start
Setting up greengrass daemon
Validating hardlink/softlink protection
Waiting for up to 1m10s for Daemon to start
...
Greengrass successfully started with PID: 4722

亚马逊云科技 IoT Greengrass 群组的初始部署

当 亚马逊云科技 IoT Greengrass 守护程序启动并运行时,返回到您在笔记本电脑或工作站上从 GitHub 下载代码存储库的位置。然后,转到 greengrass/ 文件夹(green go.yaml 所在的位置)并运行以下命令:

greengo deploy

这会将你在 greengo.yaml 中定义的配置部署到边缘设备上的 亚马逊云科技 IoT Greengrass 内核。到目前为止,您尚未在 Greengo 配置中定义任何 Lambda 函数,因此此部署只是初始化了 亚马逊云科技 IoT Greengrass 内核。在下一步中进行快速健全性测试后,您可以将 Lambda 函数添加到 亚马逊云科技 IoT Greengrass 设置中。

MXNet 推理码

在上一篇文章的结尾,你在 Jupyter 笔记本上使用了以下推理代码。 run_model/ 文件夹中,查看如何将其放入 model_loader.py 中的单个 Python 类 mlM odel 中:

class MLModel(object):
    """
    Loads the pre-trained model, which can be found in /ml/od when running on greengrass core or
    from a different path for testing locally.
    """
    def __init__(self, param_path, label_names=[], input_shapes=[('data', (1, 3, DEFAULT_INPUT_SHAPE, DEFAULT_INPUT_SHAPE))]):
        # use the first GPU device available for inference. If GPU not available, CPU is used
        context = get_ctx()[0]
        # Load the network parameters from default epoch 0
        logging.info('Load network parameters from default epoch 0 with prefix: {}'.format(param_path))
        sym, arg_params, aux_params = mx.model.load_checkpoint(param_path, 0)

        # Load the network into an MXNet module and bind the corresponding parameters
        logging.info('Loading network into mxnet module and binding corresponding parameters: {}'.format(arg_params))
        self.mod = mx.mod.Module(symbol=sym, label_names=label_names, context=context)
        self.mod.bind(for_training=False, data_shapes=input_shapes)
        self.mod.set_params(arg_params, aux_params)

    """
    Takes in an image, reshapes it, and runs it through the loaded MXNet graph for inference returning the top label from the softmax
    """
    def predict_from_file(self, filepath, reshape=(DEFAULT_INPUT_SHAPE, DEFAULT_INPUT_SHAPE)):
        # Switch RGB to BGR format (which ImageNet networks take)
        img = cv2.cvtColor(cv2.imread(filepath), cv2.COLOR_BGR2RGB)
        if img is None:
            return []

        # Resize image to fit network input
        img = cv2.resize(img, reshape)
        img = np.swapaxes(img, 0, 2)
        img = np.swapaxes(img, 1, 2)
        img = img[np.newaxis, :]

        self.mod.forward(Batch([mx.nd.array(img)]))
        prob = self.mod.get_outputs()[0].asnumpy()
        prob = np.squeeze(prob)

        # Grab top result, convert to python list of lists and return
        results = [prob[0].tolist()]
        return results

直接在设备上测试推理代码(可选)

尽管是可选的,但在边缘设备上进行快速测试以验证其他依赖关系(MXNet 和其他依赖关系)是否已正确设置总是很有用的。

我们已经编写了一个单元测试 test_model_loader.py ,用于测试前面的 mlModel 类。查看此 GitHub 存储库中的代码。

要运行单元测试,请将代码和机器学习 (ML) 模型工件下载到边缘设备并开始单元测试:

git clone https://github.com/aws-samples/amazon-sagemaker-aws-greengrass-custom-object-detection-model.git
cd amazon-sagemaker-aws-greengrass-custom-object-detection-model/greengrass/run_model/resources/ml/od
wget https://greengrass-object-detection-blog.s3.amazonaws.com/deployable-model/deploy_model_algo_1-0000.params
cd ../../..
python -m unittest test.test_model_loader.TestModelLoader

单元测试通过后,您现在可以查看如何在 亚马逊云科技 IoT Greengrass Lambda 函数中使用此代码。

在 亚马逊云科技 IoT Greengrass 核心中创建您的推理管道

现在你已经启动了 亚马逊云科技 IoT Greengrass 并在边缘设备上测试了推理代码,你已经准备好将其全部组合起来:创建一个 亚马逊云科技 IoT Greengrass Lambda 函数,在 亚马逊云科技 IoT Greengrass 内核中运行推理代码。

要测试用于推理的 亚马逊云科技 IoT Greengrass Lambda 函数,请创建以下管道:

architecture diagram of greengrass core inference

  • 包含对象检测推理代码的 Lambda 函数正在 亚马逊云科技 IoT Greengrass 核心 BlogInfer 中运行。
  • 亚马逊云科技 IoT 主题 博客/推断/输入为 BlogIn fer Lambda 函数 提供输入,用于输入图像文件在边缘设备上的位置,以便进行推断。
  • 物联网主题 博客/推断/输出将 BlogIn fer Lambda 函数的预测输出 发布到云中的 亚马逊云科技 Io T 消息代理。

为 亚马逊云科技 IoT Greengrass Lambda 函数选择生命周期配置

亚马逊云科技 IoT Greengrass Lambda 函数有两种类型:按需函数或长寿命函数 。 要进行 ML 推断,您必须在长寿命函数中运行模型,因为将 ML 模型加载到内存中通常需要 300 ms 或更长时间。

在运行时间长的 亚马逊云科技 IoT Greengrass Lambda 函数中运行机器学习推理代码只允许您产生一次初始化延迟。当 亚马逊云科技 IoT Greengrass 核心启动时,将为长时间运行的 Lambda 函数创建一个容器并保持运行状态。每次调用 Lambda 函数都会重复使用同一个容器,并使用已加载到内存中的相同机器学习模型。

创建 Lambda 函数代码

为了将前面的推理代码转换为 Lambda 函数,您创建了一个 main.py 作为 Lambda 函数的入口点。因为这是一个长期存在的函数,所以在 lambda_handler 之外初始化 mlModel 对象。每当有新的输入可供您的函数处理时,就会调用 lambda_handler 函数中的代码。

import greengrasssdk
from model_loader import MLModel
import logging
import os
import time
import json

ML_MODEL_BASE_PATH = '/ml/od/'
ML_MODEL_PREFIX = 'deploy_model_algo_1'

# Creating a Greengrass Core sdk client
client = greengrasssdk.client('iot-data')
model = None

# Load the model at startup
def initialize(param_path=os.path.join(ML_MODEL_BASE_PATH, ML_MODEL_PREFIX)):
    global model
    model = MLModel(param_path)

def lambda_handler(event, context):
    """
    Gets called each time the function gets invoked.
    """
    if 'filepath' not in event:
        logging.info('filepath is not in input event. nothing to do. returning.')
        return None

    filepath = event['filepath']
    logging.info('predicting on image at filepath: {}'.format(filepath))
    start = int(round(time.time() * 1000))
    prediction = model.predict_from_file(filepath)
    end = int(round(time.time() * 1000))

    logging.info('Prediction: {} for file: {} in: {}'.format(prediction, filepath, end - start))

    response = {
        'prediction': prediction,
        'timestamp': time.time(),
        'filepath': filepath
    }
    client.publish(topic='blog/infer/output', payload=json.dumps(response))
    return response

# If this path exists, then this code is running on the greengrass core and has the ML resources to initialize.
if os.path.exists(ML_MODEL_BASE_PATH):
    initialize()
else:
    logging.info('{} does not exist and you cannot initialize this Lambda function.'.format(ML_MODEL_BASE_PATH))

使用 Greengo 在 亚马逊云科技 IoT Greengrass 中配置机器学习资源

如果您按照该步骤在边缘设备上运行单元测试,则必须手动将 ML 模型参数文件复制到边缘设备。这不是管理机器学习模型工件部署的可扩展方式。

如果您定期重新训练机器学习模型并继续部署机器学习模型的更新版本会怎样?如果你有多台边缘设备都应该采用新的 ML 模型会怎样? 为了简化向边缘部署新的机器学习模型工件的流程,亚马逊云科技 IoT Greengrass 支持机器学习资源的 管理。

当您在 亚马逊云科技 IoT Greengrass 中定义机器学习资源时,您可以将资源添加到 亚马逊云科技 IoT Greengrass 群组中。您可以定义群组中的 Lambda 函数如何访问它们。作为 亚马逊云科技 IoT Greengrass 组部署的一部分,亚马逊云科技 IoT Greengrass 从 Amazon S3 下载机器学习项目并将其提取到 Lambda 运行命名空间内的目录中。

然后,您的 亚马逊云科技 IoT Greengrass Lambda 函数可以使用本地部署的模型进行推断。当您的机器学习模型项目有新版本需要部署时,您必须重新部署 亚马逊云科技 IoT Greengrass 组。亚马逊云科技 IoT Greengrass 服务会自动检查源文件是否已更改,并且仅在有更新时才下载新版本。

要在您的 AWS IoT Greengrass 群组中定义机器学习资源,请在 greengo.yaml 文件中取消此部分的注释。 (要使用自己的模型,请将 S3Uri 替换为自己的值。)

Resources:
  - Name: MyObjectDetectionModel
    Id: MyObjectDetectionModel
    S3MachineLearningModelResourceData:
      DestinationPath: /ml/od/     
      S3Uri: s3://greengrass-object-detection-blog/deployable-model/deploy_model.tar.gz

使用以下命令部署配置更改:

greengo update && greengo deploy

在 亚马逊云科技 IoT Greengrass 控制台中,你现在应该会看到一个机器学习资源已创建。以下屏幕截图显示模型的状态为 “ 无关联 ”。这是意料之中的,因为您尚未将其附加到 Lambda 函数。

greengrass console screenshot showing unaffiliated ml resource

要对机器学习资源部署进行故障排除,记住 亚马逊云科技 IoT Greengrass 具有容器化架构会很有帮助。它在部署 ML 模型工件等资源时使用文件系统叠加层。

在前面的示例中,尽管您将机器学习模型工件配置为提取到 /ml/od/,但 AWS IoT Greengrass 实际上还是将其下载到类似 /ggc/deployment/mlmodel// 这样的文件上。 对于您声明使用此构件的 亚马逊云科技 IoT Greengrass 本地 Lambda 函数,由于文件系统重叠,提取的文件似乎 存储 在 /ml/od/ 中。

使用 Greengo 配置 Lambda 函数

要配置您的 Lambda 函数并允许其访问先前定义的机器学习资源,请取消注释您 的 greengo.yaml 文件:

Lambdas:
  - name: BlogInfer
    handler: main.lambda_handler
    package: ./run_model/src
    alias: dev
    greengrassConfig:
      MemorySize: 900000 # Kb
      Timeout: 10 # seconds
      Pinned: True # True for long-lived functions
      Environment:
        AccessSysfs: True
        ResourceAccessPolicies:
          - ResourceId: MyObjectDetectionModel
            Permission: 'rw'

您没有为 Lambda 函数指定语言运行时间。这是因为,目前,Greengo 项目仅支持运行 python2.7 的 Lambda 函数。

另外,如果你的边缘设备尚未 安装 greengrassd k,你可以将 greengrass dk 安装 到。 /run_model/src/ 目录并将其包含在 Lambda 部署包中:

cd run_model/src/
pip install greengrasssdk -t .

使用支持 GPU 的设备

如果您使用的是仅限 CPU 的设备,则可以跳到下一节。

如果您使用带有 GPU 的边缘设备或实例,则必须使用 亚马逊云科技 IoT Greengrass 的 本地资源功能 启用 Lambda 函数才能访问 GPU 设备。

要在 greengo.yaml 中定义设备资源 ,请取消对资源下方的 部分的注释:

  - Name: Nvidia0
    Id: Nvidia0
    LocalDeviceResourceData:
      SourcePath: /dev/nvidia0
      GroupOwnerSetting:
        AutoAddGroupOwner: True
  - Name: Nvidiactl
    Id: Nvidiactl
    LocalDeviceResourceData:
      SourcePath: /dev/nvidiactl
      GroupOwnerSetting:
        AutoAddGroupOwner: True
  - Name: NvidiaUVM
    Id: NvidiaUVM
    LocalDeviceResourceData:
      SourcePath: /dev/nvidia-uvm
      GroupOwnerSetting:
        AutoAddGroupOwner: True
  - Name: NvidiaUVMTools
    Id: NvidiaUVMTools
    LocalDeviceResourceData:
      SourcePath: /dev/nvidia-uvm-tools
      GroupOwnerSetting:
        AutoAddGroupOwner: True

要使推断 Lambda 函数能够访问设备资源,请取消注释 Lambda 函数的 resourceAccessPolicies 中的以下部分。

         - ResourceId: Nvidia0
           Permission: 'rw'
         - ResourceId: Nvidiactl
           Permission: 'rw'
         - ResourceId: NvidiaUVM
           Permission: 'rw'
         - ResourceId: NvidiaUVMTools
           Permission: 'rw'

使用 Greengo 配置主题订阅

最后,要测试调用 Lambda 推理函数并接收其输出,请为推理 Lambda 函数的输入和输出创建订阅。在你的 greengo .yaml 文件中取消此部分的注释:

Subscriptions:
# Test Subscriptions from the cloud
- Source: cloud
  Subject: blog/infer/input
  Target: Lambda::BlogInfer
- Source: Lambda::BlogInfer
  Subject: blog/infer/output
  Target: cloud

要将这些配置部署到 亚马逊云科技 IoT Greengrass,请运行以下命令。

greengo update && greengo deploy

部署完成后,您还可以在 亚马逊云科技 IoT Greengrass 控制台中查看订阅配置:

screenshot of greengrass console showing subscriptions

而且,如果您查看已部署的 Lambda 函数,则可以看到 ML 资源现在与之相关联:

screenshot of greengrass console showing affliated ML resource

测试 亚马逊云科技 IoT Greengrass Lambda 函数

现在,您可以测试调用 Lambda 函数。确保将图像( 示例 )下载到边缘设备,以便可以使用它来测试推断。

在 亚马逊云科技 IoT Greengrass 控制台中 , 选择测试, 然后订阅博客/推断/输出主题。 然后,发布一条消息 blog/推断/输入 , 指定要在边缘设备上进行推理的图像路径:

screenshot of IOT console testing inference on lambda

你应该已经得到了边界框的预测结果。

将其用于实时视频推断

到目前为止,该实现创建了一个 Lambda 函数,该函数可以对边缘设备上的图像文件进行推断。要让它对视频源执行实时推断,你可以扩展架构。添加另一个使用寿命长的 Lambda 函数,它可以从摄像机捕获视频、从视频中提取帧(类似于我们在 第 1 部分 中所做的事情 ),并将图像的引用传递给 ML 推理函数:

greengrass architecture diagram for real-time video inference

资源清理

请记住,您需要为在 亚马逊云科技 上运行的资源付费,因此,如果您一直关注这些资源,请记住清理这些资源:

  • 通过运行 greengo remove 来删除 AWS IoT Greengrass 群组。
  • 关闭亚马逊 SageMaker 笔记本电脑实例。
  • 如果您使用测试 EC2 实例来运行 亚马逊云科技 IoT Greengrass,请删除 亚马逊云科技 CloudFormation 堆栈。
  • 清理使用的 S3 存储桶。

结论

在本系列文章中,我们介绍了将目标检测模型从头到尾训练和部署到边缘的过程。我们从捕获训练数据开始,并分享了选择训练数据和获取高质量标签的最佳实践。然后,我们讨论了使用 Amazon SageMaker 内置对象检测模型来训练您的定制模型并将输出转换为可部署格式的技巧。最后,我们介绍了边缘设备的设置以及使用 亚马逊云科技 IoT Greengrass 来简化边缘代码部署并将预测输出发送到云端。

我们认为,在边缘运行物体检测模型以改善制造、供应链和零售流程的潜力巨大。我们很高兴看到你利用机器学习和物联网的强大组合构建了什么。

你可以 在这个 GitHub 存储库 中找到我们介绍的所有代码 。

这个由三部分组成的系列中的其他帖子:

  • 第 1 部分:准备训练数据
  • 第 2 部分:训练自定义物体检测模型

*前述特定亚马逊云科技生成式人工智能相关的服务仅在亚马逊云科技海外区域可用,亚马逊云科技中国仅为帮助您发展海外业务和/或了解行业前沿技术选择推荐该服务。