【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次,發文人進小黑屋喔~

評論