本文是 OpenVINO™ 工具套件与百度飞桨 PaddlePaddle 模型转换 / 部署系列的第三部 – 目标检测模型。前面两篇文章分别谈到了用DeeplabV3和 BiSeNetV2的语义分割模型来做路面分割。本篇文章将关注展示如何将百度飞桨 PaddleDetection下的 YOLOv3 MobileNet 多目标检测模型转换为 OpenVINO™工具套件的 IR 模型,并且部署到 CPU 上。
为了使本文拥有更广的受众面,文章的目标部署平台选择了CPU。关于如何部署到边缘设备例如 Intel Movidius MyraidX VPU 上,请参考第一篇文章:<< 使用 OpenVINO™ 工具套件转换 \ 部署百度飞桨 PaddleSeg BiSeNetV2 语义分割模型到Intel Movidius MyriadX VPU>>。
目标检测的主要任务就是从一张图或者视频流的图像中检测图像内某个或者某几个类别对象实例的任务[1]。用更通俗易懂的话来解释就是 在图像中识别出有多少个物体,每个物体是什么类别的,并且对于每个识别出来的物体给出相应的定位。
理解了什么是目标检测之后我们就可以看出此类功能的重要性以及应用场景之广,大到可以在武器制导中做特定目标的自动跟踪,小到可以用来统计商店里客流量等等。
本篇文章的主要目的是展示如何把您已有的模型 ( 这里我们采用百度飞桨 PaddleDetection 下面的模型 ) 一步一步的部署到CPU 上,同时本文也展示了一种思路:如何在浩瀚的 Internet网络找到正确的信息,少走弯路。
面对当下众多流行的 AI 框架,比如 PaddlePaddle,PyTorch,Tensorflow 等等,每个框架都有自己特殊的神经网络结构和文件类型,每个框架内的设计也尽不一样,如此训练出来的模型则千差万别,这对软件开发和重用造成了一定的麻烦。
是否可以有一种工具可以使我们,不管选用什么 AI 框架来构建专属于自己的神经网络时,在最后部署到生产环境中的环节,都可以拥有统一的接口,可重用的代码呢 ?
答案是肯定的,OpenVINO™ 工具套件就是这样的一款工具。有了它的帮助,AI 工程师可以在模型构建,训练阶段,选择自己熟悉的任何 AI 框架来搭建起符合要求的个性化神经网络,而在后期使用 OpenVINO™ 工具套件快速构建起专属的解决方案,提供统一的接口,并在 Intel® 的硬件上优化性能。
正如前面提到的,这篇文章的着重点在于一步一步演示怎样导出已经训练好的模型,并且展示怎样转换 Paddle 模型到ONNX 格式,最后再转到 OpenVINO™ 工具套件 IR 模型,直至部署到 CPU 上为止。在每一步我都会提供相应的官方网址,一步一步的把读者推向正确的官网文档,减少走弯路。
再来讲一下这篇文章不讲什么。这篇文章不讲解怎样安装Python,Anaconda,OpenVINO™ 工具套件这样的基础需求框架。以上几个产品的官方网站教程都做的非常详细,而且会实时更新,相信对于每个不同的技术,阅读相对应的官方文档可以省去很多麻烦,少走弯路。这篇文章更多的精力会用在讲解模型之间的转换,部署,以及排错。
OpenVINO™ 工具套件 ( 以下简称 OV) 是 Intel 发布的一个综合性工具包,它是用于快速开发解决各种任务的应用程序和解决方案。它包括视觉,自动语音识别,自然语言处理,推荐系统等。该工具包基于最新一代人工神经网络,包括卷积神经网络 (CNN)、Recurrent Network 和基于注意力的网络,可跨英特尔® 硬件扩展计算机视觉和非视觉工作负载,从而最大限度地提高性能。
百度飞桨(以下简称Paddle)是百度旗下一个致力于让AI深度学习技术的创新与应用更加简单的工具集。其中包括PaddleDetection,PaddleCV,PaddleSeg,PaddleClas 等工具帮助您快速的搭建起 AI 应用程序,快速落地 AI 模型项目。对于有过 Tensorflow,PyTorch 经验的朋友来说,Paddle的角色和前面二者是一样的,都是高度集成的 AI 框架。目前Paddle 有很活跃的开发者社区,有利于快速找到自己需要的答案和帮助。
本文面向的读者是具有一定编程能力和经验的开发人员,AI 模型开发员,熟悉 Python 语言,并使用 Anaconda,已有训练好的模型,期待能部署到边缘设备上来投入实际生产中。对于0 基础的读者也是一个很好的机会通过一篇文章一并了解以上的几个技术以及怎样综合使用这些技术,让它们成为您得心应手的工具来帮助您最快的实现 AI 部署。
Anaconda,Python (创 建 Anaconda 虚 拟 环 境 的 时 候 会 自带 ), OpenVINO™ 工 具 套 件,Paddle,PaddleDetection,PaddleX (可选 ),Paddle2Onnx,Mamba (可选 )。
在介绍完以上内容后,我们可以正式动工啦。由于本文用到的YOLOv3 Mobile 的目标检测模型是来自于 PaddleDetection的 Model Zoo,所以需要先安装 PaddleDetection 的基础库 PaddlePaddle,然后再安装 PaddleDetection。
在安装 Paddle 组件之前,请确保您已经安装好了 Anaconda 。
第一步:创建一个 conda 虚拟环境:conda create -n “paddle” python=3.8.8 ipython创建好环境后 别忘了激活环境:conda activate paddle
第二步:安装 GPU 或者 CPU 版本的 PaddlePaddle:至于是选择 GPU 还是 CPU 版本的 Paddle,主要是根据您的硬件配置。如果您有 NVIDIA 最近几年的显卡例如:RTX 3080,RTX 2070,RTX 1060 等,那么请选择安装 GPU 版本。查看CUDA 对 GPU 支持的具体信息,请阅读 NVIDIA 官网的GPU Compute Capability。
首先安装 NVIDIA 的 cudnnconda install cudnn安装的时候也可以把 conda 换成Mamba,从而得到更快的下载速度。
这里快速介绍一下 Mamba。它是 Conda 的 C++ 实现。相比于Conda,它提供多线程下载,这也就意味着它可以比 Conda更好的利用网络资源,下载的更快,同时它也能更快的解析依赖项。估计用 Conda 多的朋友应该会遇到过,Conda 有时候查找依赖项非常慢 很耽误时间。Mamba 是您的好朋友,以下教程种再看到 conda 的命令,大家都可以自动替换成 Mamba来提高速度,让您的效率飞起来 ~!
安装PaddlePaddle的时候,Paddle的官网是您的好朋友,(任何时候安装任何东西,找到官网一般就能获取最新的指南 ),我以 Ubuntu 20.04 的系统为例 ( 如果您用其他的系统,那么请选择相应的选项 )。图 3:安装PaddlePaddle具体命令如下 :conda install paddlepaddle-gpu2.1.2 cudatoolkit=11.2 -c https://mirrors.tuna.tsinghua.edu.cn/anaconda/cloud/Paddle/ -c conda-forge安装完底层框架之后,是时候安装 PaddleDetection 啦。同理, 安装的时候您的好朋友是它的Github 仓库。 git clone https://github.com/PaddlePaddle/PaddleDetection.git当 PaddleDetection 的代码库下载完之后,就是激动人心的拿来即用步骤。下一步我们将会导出 PaddleDetection Model Zoo 里训练好的 Yolo V3 模型 ~!
具体命令如下 :conda install paddlepaddle-gpu2.1.2 cudatoolkit=11.2 -c https://mirrors.tuna.tsinghua.edu.cn/anaconda/cloud/Paddle/ -c conda-forge
安装完底层框架之后,是时候安装 PaddleDetection 啦。同理, 安装的时候您的好朋友是它的Github 仓库。 git clone https://github.com/PaddlePaddle/PaddleDetection.git
当 PaddleDetection 的代码库下载完之后,就是激动人心的拿来即用步骤。下一步我们将会导出 PaddleDetection Model Zoo 里训练好的 Yolo V3 模型 ~!
模型的转换分为 4 个步骤 :
本文将会以 PaddleDetection 的 Yolo 模型为例来演示。Yolo: You Only Look Once,它最显著的特性就是惊人的速度和不错的准确度。自从推出以来 已经历经多次更新,技术日益完善。本文中使用的就是 YOLOv3。从下图可以看出 YOLOv3 的惊人表现。
注意,请先创建一个名为:inference_model的文件夹,记得把参数文件的路径也改成您存放参数文件的相应路径。
导出后的模型将会保存在 inference_model/YOLOv3_mobilenet_v3_large_270e_voc 这个文件夹下面。
如果想知道更多参数,您的好朋友还是 PaddleDetection 的官方Github Repository:模型导出。
来看一下YOLOv3_mobilenet_v3_large_270e_voc.yml配置文件的内容 :
BASE[
‘…/datasets/voc.yml’,
‘…/runtime.yml’,
‘base/optimizer_270e.yml’,
‘base/YOLOv3_mobilenet_v3_large.yml’,
‘base/YOLOv3_reader.yml’,
]
napshot_epoch: 5
weights: output/YOLOv3_mobilenet_v3_large_270e_voc/model_final# set collate_batch to false because ground-truth info is needed
#on voc dataset and should not collate data in batch when batch size
#is larger than 1.
EvalReader:
collate_batch: false
LearningRate:
base_lr: 0.001
schedulers:
-!PiecewiseDecay
gamma: 0.1
milestones:
-216
-243
-!LinearWarmup
start_factor: 0.
steps: 1000
不难看出,这个配置文件是参照了 5 个模板,我们可以在 BASE 里面看到这些模板。那么我们就只需要指定任何与 5个参照的模板不一样的地方。这样做的好处显而易见,最大化的重用代码,丙炔用最少的代码和改动完成个性化的设置。
模型导出后第一道转换现在开始了。Paddle 提供了转换工具 Paddle2onnx。但是由于 OpenVINO™ 工具套件目前在推理过程中,要求模型的各计算节点 shape 固定,而目标检测模型的后处理NMS 节点中,最终出来的目标数量是不确定的,即 shape 不固定,所以我们必须做一些小处理。如果按照之前的步骤直接安装 Paddle2Onnx 工具来转换那么之后在转换成OpenVINO™ 工具套件IR格式的时候会出问题,如果想知道具体原因,可以点击超链接来查看。
比起之前的直接用 Paddle2Onnx 命令行工具,我们这次要直接使用 Paddle2Onnx 的源代码。
#如果事先已安装 paddle2onnx,需先卸载或者创建一个新的 conda 环境。
#pip uninstall paddle2onnx
git clone https://github.com/PaddlePaddle/Paddle2ONNX.gitcd Paddle2ONNXgit checkout release/0.9python setup.py install
在 Paddle2ONNX 项目的根目录下建一个 convertYOLOv3.py
from build.lib import paddle2onnx# import paddle2onnximport paddle
model_prefix = "/Models/Paddle/Detection/YOLOv3_mobilenet_v3_large_270e_voc_origin/model"model = paddle.jit.load(model_prefix)
input_shape_dict = {
“image”: [1,3,608,608],
“scale_factor”: [1, 2],
“im_shape”: [1,2]
}
onnx_model = paddle2onnx.run_convert(model, input_shape_dict=input_shape_dict,opset_version=11)
with open("./YOLOv3.onnx", “wb”) as f:f.write(onnx_model.SerializeToString())
在运行上面一段代码的时候请确认您的模型的input size。 可以通过Netron 来查看模型的各项参数,具体做法就是用Netron把刚才生成的model.pdmodel 文件打开 然后查看Model Properties。
运行这段代码可得到ONNX相应的模型。您将会看到一个 YOLOv3.onnx 的文件在当前文件夹下面生成。
铺垫了很久,终于来到了这一步。
先来快速介绍一下 OpenVINO™ 工具套件的 IR 模型。IR 的全称叫做 Intermediate Representation。IR 格式的模型是由 2个文件组成的,它们分别是 .xml 和 .bin。
来到这一步之前请确保您的 OpenVINO™ 工具套件已经安装成功。怎样安装OpenVINO™ 工具套件呢? 您的好朋友又出现了: OpenVINO™ 工具套件官网安装教程,这里是OpenVINO™ 工具套件官方下载地址。
OpenVINO™ 工具套件的安装包里 3 种安装选项分别是:
对于新手,推荐用 GUI 安装,清清楚楚,明明白白。
4.3.1 设置外部软件依赖
安装成功后,得把Install External Software Dependencies这个部分的要求也跟完。
4.3.2 激活OpenVINO™ 工具套件环境变量
小提示:接下来要使用 OV 就要设置好它的环境变量。官方教程要求把环境变量加载到您的 .bashrc 文件里,这样每次打开任何命令行接口都可以自动加载 OV 的环境变量。但是我在实际使用过程中发现了一个问题,安装完 OV 后,我的一部分程序开始报错,出现了一个和 Gstreamer 相关的错误信息。经过研究发现原来 OV 的环境变量会和 Anaconda 的虚拟环境冲突,导致 GStreamer 出现问题。
其实解决方法也很简单。我们一般只会在模型转换的时候用到OV,那么就不要把 OV 的环境变量设置到 .bashrc 文件里面, 只需要在使用 OV 之前,在命令行里激活 OV 的环境变量就行。激活环境变量的方法如下 :
source /opt/intel/openvino_2021/bin/setupvars.sh记住/opt/intel/openvino_2021/bin 是默认的OV安装路径,如果您改变了路径,请记得也随之改变这里的路径。
4.3.3 配置模型优化器Model Optimizer(MO)
MO 是一个基于 Python 的命令行工具,可以用来从其他流行的人工智能框架例如 Caffe,ONNX,TensorFlow 等 导入训练好的模型。没有用 MO 优化过的模型是不能用在 OV 上做推理的。
在这一步可以只为您需要的环境比如 ONNX,者 Tensorflow等做配置,但也可以一下配置好可以适用于各种人工智能框架的环境。我在这里选择了后者,毕竟路慢慢其修远 现在用ONNX 之后也有可能用到任何其他网络。
4.3.4 转ONNX模型到IR模式
配置好 MO 之后 CD 到 MO 设置的文件夹里面 :cd /opt/intel/openvino_2021/deployment_tools/model_optimizer
记得激活一下 OpenVINO™ 工具套件的环境变量 :source /opt/intel/openvino_2021/bin/setupvars.sh
之后我们就可以开始期待已久的 OpenVINO™ 工具套件 IR 模型转换 ( 请把下面文件的路径替换成您相应的路径 )。
$ python mo_onnx.py --input_model /Paddle2ONNX/YOLOv3.onnx --output_dir /Intel/Models/Paddle/Detection/YOLOv3_mobilenet_v3_large_270e_voc/OpenVINO/
Model Optimizer arguments:Common parameters:- Path to the Input Model: /media/winstonfan/Workspace/Learning/Github/Paddle2ONNX/YOLOv3.onnx- Path for generated IR: /media/winstonfan/Workspace/Work/Intel/Models/Paddle/Detection/YOLOv3_mobilenet_v3_large_270e_voc_origin/OpenVINO/- IR output name: YOLOv3- Log level: ERROR- Batch: Not specified, inherited from the model- Input layers: Not specified,inherited from the model- Output layers: Not specified,inherited from the model- Input shapes: Not specified,inherited from the model- Mean values: Not specified- Scale values: Not specified- Scale factor: Not specified- Precision of IR: FP32- Enable fusing: True- Enable grouped convolutions fusing: True- Move mean values to preprocess section: None- Reverse input channels: False
ONNX specific parameters:- Inference Engine found in: /opt/intel/openvino_2021/python/python3.8/openvinoInference Engine version: 2021.4.0-3839-cd81789d294-releases/2021/4Model Optimizer version: 2021.4.0-3839-cd81789d294-releases/2021/4[ SUCCESS ] Generated IR version 10 model.[ SUCCESS ] XML file: /media/winstonfan/Workspace/Work/Intel/Models/Paddle/Detection/YOLOv3_mobilenet_v3_large_270e_voc_origin/OpenVINO/YOLOv3.xml[ SUCCESS ] BIN file: /media/winstonfan/Workspace/Work/Intel/Models/Paddle/Detection/YOLOv3_mobilenet_v3_large_270e_voc_origin/OpenVINO/YOLOv3.bin
[ SUCCESS ] Total execution time: 24.99 seconds. [ SUCCESS ] Memory consumed: 575 MB.
在继续下去之前我们应该先检验一下这个模型是否真的转换成功。在运行如下代码之前,请换一个命令行窗口,并且启动之前创建的 Anaconda 环境,这样做是为了确保 OV 的环境变量和Conda 的环境变量不互相冲突,产生错误。
幸运的是,在 Paddle2ONNX 代码库的 release/0.9 分支有提供给我们一个检测 IR 模型的代码。所以我们只需要在 Paddle2Onnx代码库的根目录下创建一个文件 YOLOv3_infer.py,代码如下( 请替换相应的文件路径 ):
from experimental.openvino_ppdet.YOLOv3_infer import YOLOv3
xml_file ="/Intel/Models/Paddle/Detection/YOLOv3_mobilenet_v3_large_270e_voc/OpenVINO/YOLOv3.xml”bin_file = "/Intel/Models/Paddle/Detection/YOLOv3_mobilenet_v3_large_270e_voc/OpenVINO/YOLOv3.bin"model = YOLOv3(xml_file=xml_file,bin_file=bin_file,model_input_shape=[608,608])
boxes = model.predict(“street.jpeg”,visualize_out=“result.jpg”,threshold=0.1)
这里如果不需要可视化结果 只要得到检测框和分类的话 那么便不需要 visualize_out 参数。 boxes 里面装的东西是检测结果。每一个 Box 是一个装载了 6 个数字的数组,分别代表了 分类的 ID(14 代表人类 ),确定度,以及检测框的左上角和右下角的坐标。
测试好模型之后, 我们还可以检查一下模型的性能和吞吐量。 幸运的是,Intel DevCloud已经提供了现有的工具来帮助我们快速完成这项工作。这里是它的Jupyter Notebooks平台。 在使用前需要先注册账户。
任意挑选了几套硬件搭配,来看一下刚转换好的 IR 模型性能。
由此可见更好的 GPU,CPU 会有更少的延迟更高的输出量, 但低端集成 GPU 反而不如 CPU 的表现好。本教程使用了图像尺寸为 608608 的大小,而目标检测任务其实不需要很高的分辨率便可以达到较好的效果,所以在适当权衡速度和精确度之后 可以稍微降低图像的输入尺寸,这样也能大幅度提升模型的性能。
表格 2 展示的是同样的 YOLOv3 构架,但在减小输入图像的分辨率至 320320 后,模型的整体 吞吐量 (Throughput) 提升了 4 倍左右,延迟 (Latency) 降低了 3.5 到 4.2 倍左右。
最后,我们来回顾一下。本文介绍了目标识别任务的内容, 阐述了使用 OpenVINO™ 工具包部署模型的重要性,简单介绍了百度 PaddlePaddle 框架,然后一步一步展示了如何将您已有的模型转换到 ONNX 格式,最后直至 OpenVINO™ 工具套件的 IR 格式。然后通过一段代码展示了如何使用和验证转换后的 IR 模型。用户可以根据自己的需求做适当的改变,便能轻松快速开发,部署属于自己的 AI 应用程序。
那么恭喜大家跟完了整个教程,期待看到更多的精彩应用。最后贴上本文对应的 Github 仓:https://github.com/franva/Intel-OpenVINO-Paddle/tree/main/PaddleDetection, 欢迎大家提出宝贵的意见。
来源:
[1]: Object Detection from Papers With Code. https://paperswithcode.com/task/object-detection
[2]: Yolo Object Detection. https://pjreddie.com/darknet/yolo/
[3]: Inference Time. https://pjreddie.com/darknet/yolo/