亚马逊AWS官方博客

Amazon Sagemaker 与 NVIDIA Jetson 平台结合打造智能边缘

随着物联网和AI芯片的发展,未来将会有越来越多的数据在边缘侧处理。很多业务场景已经对边缘智能提出了明确的需求,比如自动驾驶的汽车每天会产生5TB的数据,而智能工厂每天产生的数据高达1PB,其中包含视频和传感器的数据。如果不能借助边缘智能技术而依靠Internet网络把数据传输至云端处理,会造成网络延迟和拥塞,影响推理结果的实时性,造成生产事故甚至于安全事故。所以本篇将介绍使用Amazon SageMaker和Nvidia Jetson使用云+端结合的方式打造一个边缘推理的方案,整体方案架构如下:

 

在正式了解Amazon Sagemaker与NVIDIA Jetson平台之前,我们先了解一下什么是目标检测和YOLO。

 

目标检测与 YOLO(You Only Look Once)

目标检测是计算机视觉中的一个重要分支,但由于在边缘设备或移动端中部署神经网络模型需要很大的算力或GPU处理能力。近年来由于边缘AI芯片的算力增强,再加上边缘智能有着更广泛的应用场景,围绕机器学习模型在边缘设备上的高效应用等研究课题逐步火热。

目前在目标检测领域的深度学习方法主要分为两类:一类是 two stage的目标检测算法;另外一类是 one stage的目标检测算法。

前者是先由算法生成一系列作为样本的候选框,再通过卷积神经网络进行样本分类;后者one stage则不用产生候选框,直接将目标边框定位的问题转化为回归问题处理。正是由于两种方法的差异,在性能表现上也有不同,前者在检测准确率和定位精度上占优,而后者在算法推理速度上占优。最近很多AI公司都在做是否戴口罩的识别,实际上也是基于这两类方法。精度与速度往往在目标检测中是零和博弈,我们通过实践将两者平衡,以获得最大收益。

YOLO v3是目标检测经典模型YOLO的第三代版本,因其目标识别的速度很快,被业内称为边缘的目标检测之光,它由目标检测领域的经典论文YOLO(You Only Look Once)的两位作者——华盛顿大学的Joseph Redmon和Ali Farhadi创作。2018年9月,YOLO v3正式发布,下图是从 Focal Loss 论文中可以看出YOLOv3 的运行速度明显快于其他性能相似的检测方法。而Yolo V3 Tiny,是为满足嵌入式应用的场景而发布,现已成为很流行的目标检测算法,目前在主流AI芯片公司的产品中均有应用。在工业场景中做缺陷检测或在大众消费领域中的新零售、智能驾驶等均得到广泛的推广。关于YOLO的具体介绍和说明请参考:https://pjreddie.com/darknet/yolo/

 

为什么选用Tiny Yolo v3 ?

  • Tiny Yolo v3是Yolo v3的简化版本,Tiny Yolo v3的优点主要是,网络简单,计算量较小,可以在移动端或设备端运行。缺点是精度也比较低(候选框和分类精度都比较低)
  • 一般的深度学习网络架构对于很多边缘和移动场景而言太重,所以边缘侧需要一种更轻量级、推理速度更快的、更简单的网络模型。Tiny Yolo v3非常合适,它可以实现实时检测。
  • 下图是NVIDIA官网提供的,通过 TensorRT的加速后,每个ML frameworks例如TensorFlow, PyTorch, Caffe/Caffe2, Keras, MXNet等都获得了很好的加速效果。

TensorRT所支持的Object Detection的模型(Model)中基于Darknet的Tiny YOLO V3 是表现很好的。如下图:


所以我们下一步就通过训练Tiny YOLO V3模型,来实现边缘智能。

但训练模型不只是敲代码这么简单,因为大部分做机器学习或数据分析的公司,差不多一半的精力在数据准备上,另外一大部分精力用在了机器学习的训练环境部署、框架安装、调优、排错。举例来说,我使用Darknet53来训练自己的Yolo模型,但是我们大部分时间都耗费在GPU驱动、CUDA安装、cuDNN匹配、OpenCV、Python,VisualStudio引入各种库函数或安装框架上(版本一致)。每一个步骤都是强耦合,一步错,步步错。为了避免您重蹈覆辙,接下来我们介绍如何用Amazon Sagemaker来帮助我们化繁为简,减少不必要的环境部署时间来提升效率。

 

Amazon SageMaker

Amazon SageMaker 是一项完全托管的服务,可以帮助开发人员和数据科学家快速构建、训练和部署机器学习 (ML) 模型。SageMaker 完全消除了机器学习过程中每个步骤的繁重工作,让开发高质量模型变得更加轻松。传统的 ML 开发是一个复杂、昂贵、迭代的过程,而且没有任何集成工具可用于整个机器学习工作流程,这让它难上加难。我们需要将工具和工作流程拼接在一起,这既耗时又容易出错。SageMaker 在单个工具集中提供了用于机器学习的所有组件,让这一难题迎刃而解,因此模型将可以通过更少的工作量和更低的成本更快地投入生产。

 

 

这里我们把创建Amazon Sagemaker Notebook实例的步骤省略,直接使用创建好的Amazon SageMaker Notebooks去进行开发。它与本地使用jupyter notebook一样,不同的是我们可以直接调用AWS的底层计算资源, 比如P3实例,它可支持高达 8 个 NVIDIA® V100 Tensor Core GPU,并可为机器学习应用提供高达 100Gbps 的网络吞吐量。而且我们可以轻松启用或关闭可用资源,SageMaker 还支持一键共享笔记本。所有代码依赖项都是自动捕获,因此你可以轻松与他人协作。他们将获得保存在同一位置的完全相同的笔记本。现在我们可以直接将Yolo-tiny的源代码导入到SageMaker Notebooks中,进行模型开发。源代码参考链接https://github.com/AlexeyAB/darknet。做训练最重要的是数据集,需要注意darknet的数据集的标注格式是txt,我们要按照PASCAL VOC的目录结构去做图像标注,通过脚本将xml格式转换为txt格式的标签,结构与注释如下:

VOCdevkit

-VOC2018

├─ImageSets    # 存放数据集列表文件,比如Main下的train.txt或test.txt等

├─Annotations  # 存放数据集中图片文件

├─JPEGImages   # 存放图片标签,xml 格式

└─voc2yolo3.py # 用来生成数据集列表文件

 

了解目录结构的意义在于,我们可以对应到使用Sagemaker时所对应数据源为S3的目录结构。

 

我们要为darknet工程创建开发环境和依赖,幸运的是

Amazon SageMaker NoteBook实例附带多个已安装的环境。这些环境包含 Jupyter 内核和 Python 程序包,包括:scikit、Pandas、NumPy、TensorFlow 和 MXNet。也可以安装自己的包含所选程序包和内核的环境。通常会使用 conda install 或 pip install 来完成此操作。 而基于Darknet的YOLO好处是依赖少,执行效率高,如果不显示图片连opencv都可以省略。我们要对标注好的数据进行训练,当然需要有一台GPU算力强大的服务器支撑,下图是通过Amazon SageMaker NoteBook直接调用AWS的底层计算资源的实例,如下图,我们调用p3.2xlarge的GPU实例来进行模型训练(train_instance_type=‘ml.p3.2xlarge’)。

 

 

训练结束后我们会得到一个模型文件weight,下一步就是如何将模型文件部署到边缘智能的开发板NVIDIA Jetson Nano,并且通过NVIDIA的TensorRT和DeepStream来进行推理加速。

下面这一部分主要完成的就是设备端的工作,主要的步骤是:

1.Jetson Nano环境部署

2.将Sagemaker训练的模型部署到Jetson Nano上

3.测试

其实整个实验过程还是比较久的,由于篇幅原因我们不会扩展开每一个步骤的实现方法,这里先抛个最终实现的效果图。这个就是通过云端的Sagemaker服务做训练然后通过NVIDIA的TensorRT和DeepStream实现实时的目标检测。

Jetson的环境部署

这里会使用到NIVIDA的硬件与平台相关的组件主要有:

1.Jetson Nano

2.Jetson Nano  Developer Kit SD Card image

3.JetPack SDK

4.NVIDIA TensorRT

5.DeepStream

6.Run Sample Code

由于博客篇幅原因,我们先概况了解一下,具体可以参考后面的链接。

1.Jetson Nano

首先就是我们需要一个边缘智能的开发板NVIDIA Jetson Nano,虽然是入门级,但是足以应对大部分要求算力不高的场景。Jetson Nano介绍参考: https://developer.nvidia.com/embedded/jetson-nano-developer-kit

2.Jetson Nano  Developer Kit SD Card image

因为Jetson Nano的系统是内核是tegra-ubuntu 4.9.140-tegra  aarch64架构,所以NVIDIA给了我们一个microSD card的镜像来烧录到板子上,但由于推理框架、库、软件、驱动等等都要遵循其架构。就导致了如果没有一个好的工具,构建一个边缘推理的环境极其复杂。所以就有了JetPack和SDK Manager。镜像烧录参考: https://developer.nvidia.com/embedded/learn/get-started-jetson-nano-devkit#write

3.JetPack SDK

NIVIDA JetPack  可以实现在Jetson平台上快速构建机器学习环境,JetPack包括系统镜像、TensorRT、CUDA、各种库和API、开发工具、和示例代码。我们可以利用SDK Manager来安装Jetson的软件环境,SDK Manager要需要安装到一台Ubuntu Host主机上,然后由它来打包和推送环境到Jetson Nano上。

在使用SDK Manager部署环境之前,我们要确认完成以下工作:

  • Jetson Nano必须先通过MicroSD卡成功启动进入Ubuntu界面
  • 采用Micro USB链接Nano到Ubuntu Host(这里需要注意的是Host主机如果使用虚拟机,一定要添加USB控制器,如果你启用USB2.0就链接HOST主机的时候使用2.0,同理3.0也是一样)
  • Nano连接网线到外网,且与Ubuntu Host机器在一局域网内(Host主机如果使用虚拟机,请使用桥接模式。)

然后部署安装,部署时间取决于你Host主机的配置和网络情况,烧录过程中会弹出Jetson nano的root认证。具体步骤参考: https://docs.nvidia.com/sdk-manager/install-with-sdkm-jetson/index.html#install-with-sdkm-jetson

4.NVIDIA TensorRT

NVIDIA TensorRT 是NVIDIA推出的深度学习推理的框架,也可以理解为一个优化器。它能够以更低延迟、高吞吐率来部署推理模型到嵌入式平台。 这个框架可以将 Caffe,TensorFlow的网络模型解析,然后与tensorRT中对应的层进行一一映射,把其他框架的模型统一全部 转换到tensorRT中,然后在tensorRT中可以针对NVIDIA自家的GPU实施优化策略,并进行部署加速。TensorRT已经能够支持 TensorFlow、Caffe、Mxnet、Pytorch、Darknet等深度学习框架,这里我们用到的正是基于Darknet的Yolo。 TensorRT可以直接解析他们的网络模型;对于caffe2,pytorch,mxnet等框架则是首先要将模型转为 ONNX 的通用深度学习模型,然后对ONNX模型做解析。而Tensorflow和MATLAB已经将TensorRT集成到框架中去了。具体参考: https://developer.nvidia.com/tensorrt

5.DeepStream

NVIDIA DeepStream SDK 提供了完整的流分析工具包,可用于基于AI的视频和图像分析。实时分析来自摄像头或传感器或物联网网关的数据。底层基于GStreamer实现低延迟和高吞吐量。还可以将消息代理如Kafka和MQTT将边缘集成到云中。在NVIDIA平台上的设备上可以加速H.264和H.265视频解码 ,来构建端到端AI驱动的应用程序比如:零售分析,停车管理,物流管理,光学检查和缺陷检测等。具体参考: https://developer.nvidia.com/deepstream-sdk

Jetson Nano 可实时处理多达 8 个高清全运动视频流,可作为用于网络录像机 (NVR)、智能摄像机和 IoT 网关的低功耗边缘智能视频分析平台进行部署。NVIDIA 的 DeepStream SDK 使用 ZeroCopy 和 TensorRT 优化端到端推断管道,以实现边缘和本地服务器的终极性能。下图就是我跑的示例代码,显示Jetson Nano在8个1080p流上执行物体检测,同时基于ResNet的模型以全分辨率运行,吞吐量为500MP/s,解码率为 500 MP/s (H.264/H.265)和视频编码率(250 MP/s)H.264/H.265.具体请参考链接:https://devblogs.nvidia.com/jetson-nano-ai-computing/

6.Run Sample Code

这一点很重要,我们要先把示例代码跑通。

当我们通过SDK Manager 将DeepStream 成功烧录系统后,在路径在opt:/opt/nvidia/deepstream/deepstream-4.0/samples/configs/deepstream-app/ 运行nano.txt 的Demo code,如果运行成功,那么Jetson Nano平台的推理环境就部署成功了。步骤5就是我们通过DeepStream的Demo code运行成功的截图。

 

将Sagemaker训练好的模型部署到Jetson Nano上

首先找到在Sagemaker上定义好的output_path,将S3上的模型文件导出到Jetson Nano上。解压后的模型文件比如yolov3-tiny-xxx.weights。

这个时候把模型导入到Jetson Nano上是不能直接运行的。即使直接运行也没有通过TensorRT和DeepStream做优化和加速,Jetson Nano上如果不使用TensorRT加速,则会大大降低yolo的推理速度,例如yolo v3<1fps,yolov3 tiny<8fps,所以需要以下三步操作:

1.跑通 deepstream_reference_apps的yolov3-tiny应用

2.交叉编译

3.参数修改

1.跑通 deepstream_reference_apps的yolov3-tiny应用

在正式部署自己的model之前,我们还是要先测试Yiny YOLO v3使用DeepStream做目标检测的示例应用能否跑通:NVIDIA的技术网站中提供 了darknet的Tiny YOLO v3 for TensorRT和DeepStream。主要是操作步骤是:配置环境,下载trt-yolo-app的代码,修改参数,安装依赖等,最后执行Tiny YOLO推理:

具体参考:https://devtalk.nvidia.com/default/topic/1050377/jetson-nano/deep-learning-inference-benchmarking-instructions/

$ cd ~/deepstream_reference_apps/yolo

$ sudo trt-yolo-app --flagfile=config/yolov3-tiny.txt

2.交叉编译

交叉编译的原因是,Jetson Nano的系统是基于aarch64架构,而我们是在amd64架构上训练,所以可以将darknet-master(自己训练的Yolov3-tiny)的代码加上Sagemaker上训练的模型weights,导入到Jetson Nano上,先执行make clean 然后再make编译成aarch64架构的darknet工程。

3.参数修改

我们将工程放在与示例工程一致的路径上:/deepstream_sdk_v4.0.1_jetson\sources\objectDetector_Yolo,这么做的目的是因为sources\objectDetector_Yolo文件夹中有很多deepstream、GStreamer、trt(TensorRT)网络等配置文件。除此之外还涉及到deepstream对trt的调用。我们简单的对其中objectDetector_Yolo和deepstream-app目录下的几个文件做一个分析:

(1) sources\objectDetector_Yolo:

deepstream_app_config_yoloV3_tiny.txt     ##deepstream配置文件

config_infer_primary_yoloV3_tiny.txt        ##GStreamer等的配置文件

nvdsinfer_yolo_engine.cpp   ##根据网络类型创建引擎

nvdsparsebbox_Yolo.cpp    ##yolo目标检测结果的输出

yoloPlugins.cpp  ##模型搭建的一些组件以及相应的实现

trt_utils.cpp    ##建立tensorRT网络

yolo.cpp      ##创建引擎、创建网络等的具体实现

(2) sources\apps\sample_apps\deepstream-app:

deepstream_app.c     ##deepstream的操作如调用TensorRT等。

deepstream_app_config_parser.c     ##配置文件的解析灯。

deepstream_app_main.c   ##create_pipeline和图像显示灯。

打开nvdsinfer_custom_impl_Yolo/nvdsparsebbox_Yolo.cpp. 并修改参数NUM_CLASSES_YOLO ,这里我自定义的weights是识别人和自行车。所以classes=2。

static const int NUM_CLASSES_YOLO = 2;

用自己新的model文件替换示例项目中model文件的参数,NvDsInferParseCustomYoloV3Tiny( ),比如:

extern "C" bool NvDsInferParseCustomYoloV3( std::vector const& outputLayersInfo, NvDsInferNetworkInfo const& networkInfo, NvDsInferParseDetectionParams const& detectionParams, std::vector& objectList) {. . . ## 9 clusters from COCO dataset 
const std::vector kANCHORS = {10.0, 13.0, 16.0, 30.0, 33.0, 23.0, 30.0, 61.0, 62.0, 45.0, 59.0, 119.0, 116.0, 90.0, 156.0, 198.0, 373.0, 326.0}; 
## Specifies which of the 9 anchors above to use 
static const std::vector> kMASKS = { {6, 7, 8}, {3, 4, 5}, {0, 1, 2}}; }

static bool NvDsInferParseYoloV3()
{
 ## Bounding box overlap Threshold
 const float kNMS_THRESH = 0.5f;
 const float kPROB_THRESH = 0.7f;
 ## Predicted boxes 
 const uint kNUM_BBOXES = 3; 
}

具体步骤请参考:https://docs.nvidia.com/metropolis/deepstream/Custom_YOLO_Model_in_the_DeepStream_YOLO_App.pdf

(3) 测试

测试我们的程序:

deepstream-app -c <config> --gst-debug=<debug #>

总结

边缘智能随着低功耗和低成本的AI芯片普及,越来越多的企业关注智联网这个领域。边缘智能正在促成人工智能(AI)与物联网(IoT)的融合,AI与IoT相辅相成:如果没有AI,IoT只是收集数据的sensor,如果没有IoT,AI也不会应用到边缘。AIoT项目确实比其他单纯的一个软件或硬件的研发更加复杂,它是多学科或技术栈的融合。比如,数据的采集、分析、展现需要大数据相关的技术,边缘逻辑的推理、判断需要应用机器学习的模型,对数据加工后又要与大数据结合去ETL。云端的逻辑编写、OTA升级、安全设计、设备管理也要与终端集成。另外,如果是视频流交互还涉及到编解码、流媒体等技术。

正是因为它的复杂性,我们在云端训练,在边缘推理,既利用云计算提供的服务和接口来快速原型和开发,又利用NVIDIA提供的Jetson平台,在边缘侧加速推理,提高边缘侧算力的利用率。

 

参考链接

https://pjreddie.com/darknet/yolo/

https://devblogs.nvidia.com/jetson-nano-ai-computing/

https://developer.nvidia.com/embedded/jetson-nano-developer-kit

https://docs.nvidia.com/metropolis/deepstream/dev-guide/index.html

https://docs.nvidia.com/metropolis/deepstream/Custom_YOLO_Model_in_the_DeepStream_YOLO_App.pdf

https://docs.nvidia.com/sdk-manager/install-with-sdkm-jetson/index.html

https://docs.nvidia.com/jetson/jetpack/install-jetpack/index.html#package-management-tool

https://docs.nvidia.com/metropolis/deepstream/dev-guide/

 

本篇作者

李强

AWS解决方案架构师,负责基于AWS的云计算方案架构的咨询和设计,同时致力于AWS云服务在国内的应用和推广,在物联网和微软的技术栈有着广泛的设计和实践经验。在加入AWS之前,曾在东芝中国负责系统开发和运维工作,在微软中国负责中小企业的技术咨询和方案设计工作。