【ATU Book-i.MX8系列 - ONNX】ONNX 进行优化与推理

一.   概述

经由上几篇文章介绍了 ONNX 的模组转换方法后,本篇章将说明如何对 ONNX模组(.onnx) 进行优化? 如何利用 ONNX 模组(.onnx) 进行推理 ? ONNX 效能如何? 后续将一步步带领各位在 Windows + Colab 环境上运行 !! 如下图所示,为系列博文之示意架构图。此架构图隶属于 i.MX8M Plus 的方案博文中,并属于机器学习内的推理引擎(Inference Engine) 的 ONNX 部分,目前章节介绍 “ONNX 进行优化与推理”

 

若欲理解与架设 Tensorflow 框架,请参考另一个博文系列

 大大通精彩博文     AI 即将来临 !! 利用 Tensorflow 与 i.MX8 迈入新领域  

 大大通精彩博文   【ATU Book-i.MX8系列】博文索引

 

ONNX 系列博文-文章架构示意图 (1) 

 

 

ONNX 系列博文-文章架构示意图 (2) 

   

二.  ONNX  Runtime 使用方式

这里整理上述的资讯,可以将ONNX 使用方式分为三大步骤

第一步 : 取得 ONNX 模型。

第二步 : 优化 ONNX 模型。

第三步 : 执行 ONNX Runtime 推理引擎

 

第一步 : 取得 ONNX 模型

 可直接下载官方的标准模型或是利用其他框架转换而得。

 

第二步 : ONNX 优化模型

可利用 ONNX 模型优化 来获得更好的推理结果

载入模型 :

import onnx
import onnxoptimizer
onnx_model = onnx.load("faster_rcnn_R_50_FPN_1x.onnx")
onnx.checker.check_model(onnx_model)

进行优化(基础) :

optimized_model = optimizer.optimize(onnx_model)

进行优化(进阶) :

# Pick one pass as example
passes = ['fuse_consecutive_transposes']
# Apply the optimization on the original model
optimized_model = optimizer.optimize(original_model, passes)

官方文件指出有提供数种方式来进行优化,分别为

--> eliminate_deadend(消除无作用的节点)
--> eliminate_identity(消除理想值的节点)
--> eliminate_nop_transpose(消除无操作转置的节点)
--> eliminate_nop_pad(消除无操作补值的节点)
--> fuse_consecutive_transposes(断开连续转置的节点)
--> fuse_pad_into_transpose(断开补值至转置的节点) 

 

第三步 :  执行 ONNX Runtime 推理引擎

 ONNX Rutime 推理引擎能够支援大部分的神经网路架构,目标以最小的计算延迟和资源占用进行推理,适用于各硬体平台上。如下图所示,此推理引擎能够活用各硬体资源,像是 CPU、GPU、NPU、FPGA 皆能提供最佳化演算。

 

 

ONNX 合作企业,如下图所示。故有支援常见的 Nvidia GPU 加速器、 Intel AI 芯片、Cadence DNA 处理器等等…

 

 

顺带一提,NXP 于 2018 年 11月发布支援 ONNX 推理界面,能够运行在 S32V、i.MX8 系列的平台之中。如下图所示,为 i.MX8 的 eIQ 机器学习开发环境的架构,其中所提供的开源资料库就含有 ONNX 。

 

ONNX Runtime 进行推理方式 :

ONNX Runtime 推理引擎的使用方式是非常简单的 !! 仅须要引用相应的资料库并指下以下代码即可…

$import onnxruntime
$onnxruntime.InferenceSession( *.onnx )

 

 

三.  ONNX Object Detection

为了加深读者印象,下列直接以一个范例来实现 ONNX Runtime 的物件识别范例之演示 !! 读者们不访随著进行演练以下代码,或是直接运行 Colab 代码 !!

安装必要套件 :

!pip install onnx==1.5.0

!pip install onnxruntime==0.4.0
!pip install numpy==1.15.1
!pip install onnxoptimizer

 

运行范例 :

import onnx
import onnxruntime
import numpy as np
from PIL import Image
import matplotlib.pyplot as plt
import matplotlib.patches as patches
import urllib.request # urllib is a built-in Python library to download files from URLs

# ---------------------------------------------------------------------------------------
# 下载官方模组、标签、图片
# ---------------------------------------------------------------------------------------
onnx_model_url = "https://github.com/onnx/models/blob/master/vision/object_detection_segmentation/faster-rcnn/model/FasterRCNN-10.onnx"
output_classes_url = "https://github.com/onnx/models/blob/master/vision/object_detection_segmentation/faster-rcnn/dependencies/coco_classes.txt"
test_image_url = "https://github.com/onnx/models/raw/master/vision/object_detection_segmentation/faster-rcnn/dependencies/demo.jpg"
urllib.request.urlretrieve(onnx_model_url, filename="faster_rcnn_R_50_FPN_1x.onnx")
urllib.request.urlretrieve(output_classes_url, filename="coco_classes.txt")
urllib.request.urlretrieve(test_image_url, filename="frcnn_demo.jpg")

# ---------------------------------------------------------------------------------------
# API
# ---------------------------------------------------------------------------------------
# Image Preprocess 影像预处理
def preprocess(image):
# Resize
ratio = 800.0 / min(image.size[0], image.size[1])
image = image.resize((int(ratio * image.size[0]), int(ratio * image.size[1])), Image.BILINEAR)

# Convert to BGR
image = np.array(image)[:, :, [2, 1, 0]].astype('float32')

# HWC -> CHW
image = np.transpose(image, [2, 0, 1])

# Normalize
mean_vec = np.array([102.9801, 115.9465, 122.7717])
for i in range(image.shape[0]):
image[i, :, :] = image[i, :, :] - mean_vec[i]

# Pad to be divisible of 32
import math
padded_h = int(math.ceil(image.shape[1] / 32) * 32)
padded_w = int(math.ceil(image.shape[2] / 32) * 32)

padded_image = np.zeros((3, padded_h, padded_w), dtype=np.float32)
padded_image[:, :image.shape[1], :image.shape[2]] = image
image = padded_image

return image

# Show Result 结果展示
def display_objdetect_image(image, boxes, labels, scores, score_threshold=0.7):
# Resize boxes
ratio = 800.0 / min(image.size[0], image.size[1])
boxes = boxes / ratio

_, ax = plt.subplots(1, figsize=(12,9))
ax.imshow(image)

# Showing boxes with score > 0.7
for box, label, score in zip(boxes, labels, scores):
if score > score_threshold:
rect = patches.Rectangle((box[0], box[1]), box[2] - box[0], box[3] - box[1],\
linewidth=1, edgecolor='b',facecolor='none')
ax.annotate(classes[label] + ':' + str(np.round(score, 2)), (box[0], box[1]),\
color='w', fontsize=12)
ax.add_patch(rect)
plt.show()



# ---------------------------------------------------------------------------------------
# MAIN
# ---------------------------------------------------------------------------------------

import time
start = time.time()

#载入标签
classes = [line.rstrip('\n') for line in open('coco_classes.txt')]

#使用 onnxruntime 载入模组
session = onnxruntime.InferenceSession('faster_rcnn_R_50_FPN_1x.onnx')

#载入影像
img = Image.open('frcnn_demo.jpg')
img_data = preprocess(img)

#开始预测
boxes, labels, scores = session.run(None, {session.get_inputs()[0].name: img_data});end = time.time()
print(end-start)
print('Boxes:', boxes.shape);print('Labels:', labels.shape);print('Scores:', scores.shape)

#显示结果 & 标示
display_objdetect_image(img, boxes, labels, scores)

 

运行结果 :

目前以 Google Colab 进行实际测试的硬体配置,如下图所示:

Colab CPU Info

​在未优化模型的情况下,进行运行则花费时间约 11.8 ms 。
在已优化模型的情况下,进行运行则花费时间约 7.88 ms 。


 

 

四.  结语

经由上述的介绍,相信各位已经完成一支 ONNX Runtime 物件侦测的程式 !! 并大致上理解 ONNX 是如何优化,是如何进行推理,并也得知目前官方所提供的优化几种方式。这里利用 CPU 进行测试,实际运行 ONNX 物件侦测范例程式大约花费 7.88 ms 是个不算太差的运行速度 !!  因此由 ONNX 的优化与推理是有期望可以得到更好的成果 !! 本系列的最后,会将此范例移至 NXP i.MX8 的平台上实现 !! 敬请期待 !!

 

五.  参考文件

[1] 官方网站 - ONNX
[2] 官方网站 - ONNX Tutorials
[3] 官方网站 – Netron
[4] 官方网站 – VisualDL
[5] 参考文献 - VisualDL 工具简介
[6] 参考文献 - Object Detection with ONNX Runtime: Faster RCNN

如有任何相关 ONNX 技术问题,欢迎至博文底下留言提问 !!
接下来还会分享更多 ONNX 的技术文章 !!敬请期待 【ATU Book-i.MX8 系列 - ONNX】系列 !!

★博文内容均由个人提供,与平台无关,如有违法或侵权,请与网站管理员联系。

★文明上网,请理性发言。内容一周内被举报5次,发文人进小黑屋喔~

评论