训练 Amazon SageMaker 目标检测模型并在 AWS IoT Greengrass 上运
在AWS上训练Amazon SageMaker物体检测模型并运行于AWS IoT Greengrass
主要要点
在这篇文章中,我们将探讨如何使用Amazon SageMaker和AWS IoT Greengrass,将自定义物体检测模型构建并部署到边缘设备。本文为系列文章的第三部分,您将学习如何在边缘设备上运行推理。
本文的重点包括:
设置环境并安装AWS IoT Greengrass核心创建AWS IoT Greengrass组以管理物体检测模型编写AWS IoT Greengrass Lambda函数以执行推理测试Lambda函数以验证模型的输出清理AWS资源这篇文章是关于如何在AWS上将自定义物体检测模型部署到边缘的第三篇文章。在前面两部分中,我们介绍了如何准备训练数据和训练自定义物体检测模型。本文将讨论如何将模型的输出文件在AWS IoT Greengrass上的边缘设备上执行推理。
以下是您正在构建架构的概览:
在AWS帐户中按照步骤操作
您可以在自己的AWS帐户和边缘设备上按照以下步骤操作。第1部分和第2部分不是这一部分的前提条件。您可以使用您自己训练的自定义模型,或者使用我们提供的示例模型根据CDLA Permissive许可进行使用。
设置环境和在边缘设备上安装AWS IoT Greengrass核心
在开始安装AWS IoT Greengrass核心之前,请确保检查硬体和作业系统要求。在此文章中,我们使用了一个Ubuntu 1804的Amazon EC2实例。虽然这不是一个真正的边缘设备,但我们发现使用EC2实例作为AWS IoT用例的测试和开发环境是非常有帮助的。
设备设置
对于有GPU支持的设备,请确保安装相应的GPU驱动程序,例如CUDA。如果您的设备仅有CPU,仍然可以进行推理,但性能会较慢。
同时,请确保在边缘设备上安装MXNet和OpenCV,这些是运行模型推理代码所必需的。具体指导请参见这里。
接著,按照设置环境并安装AWS IoT Greengrass软件中的步骤配置设备以及安装AWS IoT Greengrass核心软件。
或者,您可以通过启动这个AWS CloudFormation堆栈来启动一个测试EC2实例,完成上述设置:
创建AWS IoT Greengrass组
现在,您可以在AWS云中创建一个AWS IoT Greengrass组。有几种不同的方法可以做到这一点并配置AWS Lambda函数以在边缘运行您的模型:
使用 Greengo,这是一个开源项目,用于在配置文件中定义AWS IoT Greengrass资源并通过命令行管理部署:本文将详细介绍这个选项。使用 AWS IoT Greengrass控制台:请参见AWS IoT上的配置AWS IoT Greengrass的步骤。使用 AWS CloudFormation 有关示例设置,请参见使用AWS CloudFormation自动化AWS IoT Greengrass设置 。在本篇文章中,我们将使用Greengo设置此物体检测模型。我们团队在快速原型和开发环境中特别偏好使用Greengo项目来管理AWS IoT Greengrass的部署。我们建议在管理生产环境时使用AWS CloudFormation。
在macOS或Linux计算机上,使用git clone下载我们提供的示例代码。下面的命令未在Windows上测试过。
在greengrass/文件夹中,您会看到一个名为greengoyaml的文件,其中定义了AWS IoT Greengrass组的配置和Lambda函数。文件的上部分定义了AWS IoT Greengrass组的名称和AWS IoT Greengrass核心:
yamlGroup name GGObjectDetectionCores name GGObjectDetectionCore keypath /certs configpath /config SyncShadow True
为了在AWS IoT中初始化AWS IoT Greengrass组资源,请在找到greengoyaml的文件夹中运行以下命令:
bashpip install greengogreengo create
这将在AWS中创建所有AWS IoT Greengrass组的工件,并将证书和configjson放置在/certs/和/config/中。
同时,它还会在gg/ggstatejson中生成一个状态文件,该文件在部署期间引用所有正确的资源:
gg ggstatejson certs GGObjectDetectionCorekey GGObjectDetectionCorepem GGObjectDetectionCorepub config configjson
使用scp将certs和config资料夹复制到边缘设备或测试EC2实例,然后将它们复制到设备的/greengrass/certs/和/greengrass/config/目录中:
bashsudo cp certs/ /greengrass/certs/sudo cp config/ /greengrass/config/
在您的设备上,还需下载与Greengo生成的证书兼容的根CA证书,并放置到/greengrass/certs/文件夹中:
bashcd /greengrass/certs/sudo wget O rootcapem https//wwwsymanteccom/content/en/us/enterprise/verisign/roots/VeriSignClass203PublicPrimaryCertificationAuthorityG5pem
启动AWS IoT Greengrass核心
现在,您准备好在边缘设备上启动AWS IoT Greengrass核心守护进程了。
bash sudo /greengrass/ggc/core/greengrassd startSetting up greengrass daemonValidating hardlink/softlink protectionWaiting for up to 1m10s for Daemon to startGreengrass successfully started with PID 4722
初始AWS IoT Greengrass组部署
当AWS IoT Greengrass守护进程运行时,请回到您从GitHub下载的代码库,然后进入greengrass/文件夹即greengoyaml所在的位置,运行以下命令:
bashgreengo deploy
这将把您在greengoyaml中定义的配置部署到边缘设备上的AWS IoT Greengrass核心。到目前为止,您尚未在Greengo配置中定义任何Lambda函数,因此此部署仅初始化AWS IoT Greengrass核心。您在下一步中将添加一个Lambda函数到AWS IoT Greengrass的设置中。

MXNet推理代码
在上篇文章的结尾,您在Jupyter Notebook上使用了以下推理代码。在runmodel/文件夹中,检查您如何将这段代码放入单个Python类MLModel中,位于modelloaderpy:
pythonclass MLModel(object) 加载预训练模型,该模型在执行greengrass核心时可以在/ml/od中找到 或在本地测试时则可以从其他路径找到。 def init(self parampath labelnames=[] inputshapes=[(data (1 3 DEFAULTINPUTSHAPE DEFAULTINPUTSHAPE))]) # 使用可用的第一个GPU设备进行推理。如果GPU不可用,则使用CPU context = getctx()[0] # 从默认的epoch 0加载网络参数 logginginfo(Load network parameters from default epoch 0 with prefix {}format(parampath)) sym argparams auxparams = mxmodelloadcheckpoint(parampath 0)
# 加载网络到MXNet模组并绑定相应的参数 logginginfo(Loading network into mxnet module and binding corresponding parameters {}format(argparams)) selfmod = mxmodModule(symbol=sym labelnames=labelnames context=context) selfmodbind(fortraining=False datashapes=inputshapes) selfmodsetparams(argparams auxparams)接收一张图片,重新塑形并通过加载的MXNet图进行推理,返回softmax的最高标签def predictfromfile(self filepath reshape=(DEFAULTINPUTSHAPE DEFAULTINPUTSHAPE)) # RGB转BGR格式ImageNet网络使用的格式 img = cv2cvtColor(cv2imread(filepath) cv2COLORBGR2RGB) if img is None return [] # 调整图像大小以适应网络输入 img = cv2resize(img reshape) img = npswapaxes(img 0 2) img = npswapaxes(img 1 2) img = img[npnewaxis ] selfmodforward(Batch([mxndarray(img)])) prob = selfmodgetoutputs()[0]asnumpy() prob = npsqueeze(prob) # 获取最高结果,转换为Python列表并返回 results = [prob[0]tolist()] return results直接在设备上测试推理代码可选
虽然这是可选的,但在边缘设备上快速测试通常有助于验证其它依赖项MXNet等是否正确设置。
我们写了单元测试testmodelloaderpy来测试前述的MLModel类。请查看这个GitHub存储库中的代码。
要运行单元测试,将代码和机器学习ML模型工件下载到边缘设备并启动单元测试:
bashgit clone https//githubcom/awssamples/amazonsagemakerawsgreengrasscustomobjectdetectionmodelgitcd amazonsagemakerawsgreengrasscustomobjectdetectionmodel/greengrass/runmodel/resources/ml/odwget https//greengrassobjectdetectionblogs3amazonawscom/deployablemodel/deploymodelalgo10000paramscd //python m unittest testtestmodelloaderTestModelLoader
飞速加速器官网flycn单元测试通过后,您现在可以查看这段代码如何在AWS IoT Greengrass Lambda函数中使用。
在AWS IoT Greengrass核心中创建推理管道
现在您已经启动了AWS IoT Greengrass并在边缘设备上测试了推理代码,您已准备好将其整合:创建一个AWS IoT Greengrass Lambda函数,在AWS IoT Greengrass核心中运行推理代码。
要测试AWS IoT Greengrass Lambda函数进行推理,请创建以下管道:
一个包含物体检测推理代码的Lambda函数在AWS IoT Greengrass核心中运行,名为BlogInfer。AWS IoT主题blog/infer/input提供输入给BlogInfer Lambda函数,指定要进行推理的边缘设备上的图像文件的位置。IoT主题blog/infer/output将BlogInfer Lambda函数的预测输出发布到云中的AWS IoT消息代理。为AWS IoT Greengrass Lambda函数选择生命周期配置
有两种AWS IoT Greengrass Lambda函数类型:按需或长期存活的。进行机器学习推理时,必须运行长期存活的函数,因为加载机器学习模型到内存中通常可能需要300毫秒或更长时间。
在长期存活的AWS IoT Greengrass Lambda函数中运行机器学习推理代码,仅需承担一次初始化延迟。当AWS IoT Greengrass核心启动时,为长期运行的Lambda函数创建的单一容器将保持运行。每次调用Lambda函数时都将重用同一容器,并使用已经加载到内存中的相同机器学习模型。
创建Lambda函数代码
要将前述推理代码转换为Lambda函数,您需要创建一个mainpy作为Lambda函数的入口。由于这是长期存活的函数,在lambdahandler外部初始化MLModel对象。lambdahandler函数内的代码每次新输入可用时都会被调用。
pythonimport greengrasssdkfrom modelloader import MLModelimport loggingimport osimport timeimport json
MLMODELBASEPATH = /ml/od/MLMODELPREFIX = deploymodelalgo1
创建Greengrass核心sdk客户端
client = greengrasssdkclient(iotdata)model = None
在启动时加载模型
def initialize(parampath=ospathjoin(MLMODELBASEPATH MLMODELPREFIX)) global model model = MLModel(parampath)
def lambdahandler(event context) 每当调用此函数时被调用。 if filepath not in event logginginfo(filepath is not in input event nothing to do returning) return None
filepath = event[filepath]logginginfo(predicting on image at filepath {}format(filepath))start = int(round(timetime() 1000))prediction = modelpredictfromfile(filepath)end = int(round(timetime() 1000))logginginfo(Prediction {} for file {} in {}format(pred