作者: 英特爾物聯(lián)網(wǎng)行業(yè)創(chuàng)新大使 戰(zhàn)鵬州
本文將介紹基于 OpenVINO 模型優(yōu)化器或預(yù)處理 API 將數(shù)據(jù)預(yù)處理嵌入 AI 模型的常見(jiàn)技巧,幫助讀者在硬件投入不變的情況下,進(jìn)一步提升端到端的 AI 推理程序的性能。本文所有范例程序已開(kāi)源:
https://gitee.com/ppov-nuc/resnet_ov_ppp.git,
并在基于第12 代英特爾酷睿處理器的 AI 開(kāi)發(fā)者套件上完成測(cè)試。
以 YOLOv5 模型轉(zhuǎn)換為例,使用模型優(yōu)化器命令:
mo --input_model yolov5s.onnx --data_type FP16
向右滑動(dòng)查看完整代碼
將 yolov5s.onnx 模型轉(zhuǎn)為 IR 格式模型,并將模型精度從 FP32 轉(zhuǎn)為 FP16——這是最常見(jiàn)的模型優(yōu)化器使用方式?;谏鲜?IR 模型,在編寫 AI 推理程序時(shí),由于圖像數(shù)據(jù)的數(shù)值精度和形狀,跟模型輸入節(jié)點(diǎn)要求的數(shù)值精度和形狀不一樣,所以還需要將數(shù)據(jù)在輸入模型前對(duì)其進(jìn)行預(yù)處理。
以YOLOv5模型為例,使用YOLOv5代碼倉(cāng)自帶的zidane.jpg圖像,打印出圖像的數(shù)值精度和形狀,以及模型輸入節(jié)點(diǎn)的數(shù)值精度和形狀,對(duì)比如下,如圖1-1所示。
圖1-1 OpenCV 讀入的圖像 vs 模型輸入節(jié)點(diǎn)
從上圖可以看出,通過(guò) OpenCV 的 imread() 函數(shù)讀取的圖像數(shù)據(jù),在數(shù)據(jù)形狀、數(shù)值精度、數(shù)值范圍等地方,與模型輸入節(jié)點(diǎn)的要求不一樣,如下表所示:
由于存在上述的差異,數(shù)據(jù)在傳入模型前必須進(jìn)行預(yù)處理,以滿足模型輸入節(jié)點(diǎn)的要求。數(shù)據(jù)預(yù)處理可以在推理代碼中編程實(shí)現(xiàn),也可以用模型優(yōu)化器實(shí)現(xiàn),或者用OpenVINO 預(yù)處理 API 實(shí)現(xiàn),本文將依次詳細(xì)介紹。
1.1用模型優(yōu)化器實(shí)現(xiàn)數(shù)據(jù)預(yù)處理
1.1.1模型優(yōu)化器預(yù)處理參數(shù)
模型優(yōu)化器可以將顏色通道順序調(diào)整、圖像數(shù)據(jù)歸一化等預(yù)處理操作嵌入模型,參考《OpenVINO 模型轉(zhuǎn)換技術(shù)要點(diǎn)解讀》。通過(guò)指定參數(shù):
--mean_values:所有輸入數(shù)據(jù)將減去 mean_values, 即 input - mean_values
--scale_values:所有輸入數(shù)據(jù)將除以 scales_values,當(dāng)同時(shí)指定 mean_values 和 scale_values 時(shí),模型優(yōu)化器執(zhí)行(input - mean_values)÷scales_values
--reverse_input_channels:將輸入通道順序從 RGB 轉(zhuǎn)換為 BGR(反之亦然)
當(dāng)上述三個(gè)操作同時(shí)指定時(shí),預(yù)處理順序?yàn)椋?/p>
輸入數(shù)據(jù)
→→reverse_input_channels→→mean_values→→scale_values→→原始模型
在轉(zhuǎn)換模型時(shí),假設(shè)推理程序使用 OpenCV 庫(kù)讀取圖像,則可以在模型優(yōu)化器中增加 mean_values、scale_values 和 reverse_input_channels 三個(gè)參數(shù),把顏色通道順序調(diào)整和圖像數(shù)據(jù)歸一化操作嵌入模型。若推理程序使用非 OpenCV 庫(kù)讀取圖像,例如 PIL.Image,則無(wú)需添加 --reverse_input_channels 參數(shù)。
下面本文將以 ResNet 模型為例,展示使用模型優(yōu)化器將預(yù)處理嵌入模型的完整過(guò)程。
1.1.2將 ResNet 模型的預(yù)處理嵌入模型
ResNet 不僅是2015年 ILSVRC 大賽冠軍,還是產(chǎn)業(yè)實(shí)踐中常用的卷積神經(jīng)網(wǎng)絡(luò)模型。PyTorch 已將 ResNet 集成到 torchvision 中,將 PyTorch 格式的 ResNet 模型轉(zhuǎn)為 ONNX 格式,完整代碼如下:
from torchvision.models import resnet50, ResNet50_Weights import torch # https://pytorch.org/vision/stable/models/generated/torchvision.models.resnet50.html weights = ResNet50_Weights.IMAGENET1K_V2 model = resnet50(weights=weights, progress=False).cpu().eval() # define input and output node dummy_input = torch.randn(1, 3, 224, 224, device="cpu") input_names, output_names = ["images"], ['output'] torch.onnx.export(model, dummy_input, "resnet50.onnx", verbose=True, input_names=input_names, output_names=output_names, opset_version=13 )
向右滑動(dòng)查看完整代碼
在導(dǎo)出 PyTorch 格式模型為 ONNX 格式時(shí),需要注意的是算子版本(opset_version)最好≥11。
另外,OpenVINO 2022.2支持ONNX 1.8.1,即 opset_version=13, 所以本文將 opset_version 設(shè)置為13。
基于 ImageNet 1k 數(shù)據(jù)集訓(xùn)練的 ResNet 模型的歸一化參數(shù)為:
mean_values= [123.675,116.28,103.53]
scale_values=[58.395,57.12,57.375]
將 ONNX 模型轉(zhuǎn)換為 OpenVINO IR 模型的命令為:
mo -m resnet50.onnx --mean_values=[123.675,116.28,103.53] -- scale_values=[58.395,57.12,57.375] --data_type FP16 --reverse_input_channels
向右滑動(dòng)查看完整代碼
當(dāng)獲得 ResNet50 的 IR 模型后,可以使用下面的程序,完成推理計(jì)算
from openvino.runtime import Core import cv2 import numpy as np core = Core() resnet50 = core.compile_model("resnet50.xml", "CPU") output_node = resnet50.outputs[0] # Resize img = cv2.resize(cv2.imread("cat.jpg"), [224,224]) # Layout: HWC -> NCHW blob = np.expand_dims(np.transpose(img, (2,0,1)), 0) result = resnet50(blob)[output_node] print(np.argmax(result))
向右滑動(dòng)查看完整代碼
在上面的推理代碼中,仍有調(diào)整圖像尺寸,改變圖像數(shù)據(jù)布局等操作在推理代碼中實(shí)現(xiàn),接下來(lái),本文將介紹用 OpenVINO 預(yù)處理 API,將更多預(yù)處理操作嵌入模型中。
1.2用OpenVINO 預(yù)處理 API 實(shí)現(xiàn)數(shù)據(jù)預(yù)處理
從 OpenVINO2022.1開(kāi)始,OpenVINO提供一套預(yù)處理 API,將數(shù)據(jù)預(yù)處理嵌入模型,參考《使用 OpenVINO 預(yù)處理 API 進(jìn)一步提升 YOLOv5 推理性能》。將數(shù)據(jù)預(yù)處理嵌入模型的好處是:
提高 AI 模型的移植性(推理代碼無(wú)需考慮編寫預(yù)處理程序)
提高推理設(shè)備(例如,英特爾集成顯卡/獨(dú)立顯卡)的利用率
提高 AI 程序端到端的性能
使用 OpenVINO 預(yù)處理 API 將預(yù)處理嵌入模型的完整范例程序 export_resnet_ov_ppp.py,如下所示:
from openvino.preprocess import PrePostProcessor, ColorFormat, ResizeAlgorithm from openvino.runtime import Core, Layout, Type, serialize # ======== Step 0: read original model ========= core = Core() model = core.read_model("resnet50.onnx") # ======== Step 1: Preprocessing ================ ppp = PrePostProcessor(model) # Declare section of desired application's input format ppp.input("images").tensor() .set_element_type(Type.u8) .set_spatial_dynamic_shape() .set_layout(Layout('NHWC')) .set_color_format(ColorFormat.BGR) # Specify actual model layout ppp.input("images").model().set_layout(Layout('NCHW')) # Explicit preprocessing steps. Layout conversion will be done automatically as last step ppp.input("images").preprocess() .convert_element_type() .convert_color(ColorFormat.RGB) .resize(ResizeAlgorithm.RESIZE_LINEAR) .mean([123.675, 116.28, 103.53]) .scale([58.624, 57.12, 57.375]) # Dump preprocessor print(f'Dump preprocessor: {ppp}') model = ppp.build() # ======== Step 2: Save the model with preprocessor================ serialize(model, 'resnet50_ppp.xml', 'resnet50_ppp.bin')
向右滑動(dòng)查看完整代碼
export_resnet_ov_ppp.py 運(yùn)行結(jié)果,如下圖所示:
從上面的代碼可見(jiàn),使用 OpenVINO 預(yù)處理 API,可以將圖像尺寸調(diào)整、彩色通道轉(zhuǎn)換、數(shù)據(jù)歸一化、數(shù)據(jù)布局轉(zhuǎn)換全部集成到模型中,并且無(wú)需運(yùn)行模型優(yōu)化器,即可以將 ONNX 模型導(dǎo)出為 IR 模型。
基于 resnet50_ppp.xml 的完整推理程序,如下所示:
from openvino.runtime import Core import cv2 import numpy as np core = Core() resnet50_ppp = core.compile_model("resnet50_ppp.xml", "CPU") output_node = resnet50_ppp.outputs[0] blob = np.expand_dims(cv2.imread("cat.jpg"),0) result = resnet50_ppp(blob)[output_node] print(np.argmax(result))
向右滑動(dòng)查看完整代碼
如上所示,基于內(nèi)嵌預(yù)處理的 IR 模型,OpenVINO 推理程序變得更加簡(jiǎn)單清晰,易讀易懂了。五行 Python 核心代碼實(shí)現(xiàn)了內(nèi)嵌預(yù)處理的 ResNet 模型推理!
1.3使用模型緩存技術(shù)進(jìn)一步縮短首次推理時(shí)延
在《在蝰蛇峽谷上實(shí)現(xiàn) YOLOv5 模型的 OpenVINO異步推理程序》討論了 AI 應(yīng)用程序端到端的性能。對(duì)于首次推理時(shí)延來(lái)說(shuō),模型的載入和編譯時(shí)間,會(huì)極大增加首次推理的端到端的運(yùn)行時(shí)間。
使用模型緩存技術(shù),將極大的縮短首次推理時(shí)延,如下圖所示。
使用模型緩存技術(shù),只需要添加一行代碼:
core.set_property({'CACHE_DIR': './cache/ppp'})
完整范例代碼如下所示:
from openvino.runtime import Core import cv2 import numpy as np core = Core() core.set_property({'CACHE_DIR': './cache/ppp'}) # 使用模型緩存技術(shù) resnet50_ppp = core.compile_model("resnet50_ppp.xml", "CPU") output_node = resnet50_ppp.outputs[0] blob = np.expand_dims(cv2.imread("cat.jpg"),0) result = resnet50_ppp(blob)[output_node] print(np.argmax(result))
向右滑動(dòng)查看完整代碼
當(dāng)?shù)诙芜\(yùn)行推理程序時(shí),OpenVINO 運(yùn)行時(shí)將從緩存文件夾直接加載已編譯好的模型,極大的優(yōu)化了首次推理時(shí)延。
1.4總結(jié)
本文詳細(xì)介紹了通過(guò)模型優(yōu)化器和 OpenVINO預(yù)處理 API,將數(shù)據(jù)預(yù)處理嵌入 AI 模型的技術(shù)。將數(shù)據(jù)預(yù)處理嵌入模型,簡(jiǎn)化了推理程序編寫,提升推理計(jì)算設(shè)備利用率并提升了 AI 程序端到端的性能。最后,本文還介紹了通過(guò)模型緩存技術(shù),進(jìn)一步優(yōu)化 AI 程序端到端的首次推理時(shí)延性能。
審核編輯:湯梓紅
-
處理器
+關(guān)注
關(guān)注
68文章
19801瀏覽量
233517 -
英特爾
+關(guān)注
關(guān)注
61文章
10166瀏覽量
173919 -
AI
+關(guān)注
關(guān)注
87文章
34173瀏覽量
275333 -
模型
+關(guān)注
關(guān)注
1文章
3483瀏覽量
49987
原文標(biāo)題:將數(shù)據(jù)預(yù)處理嵌入AI模型的常見(jiàn)技巧 | 開(kāi)發(fā)者實(shí)戰(zhàn)
文章出處:【微信號(hào):英特爾物聯(lián)網(wǎng),微信公眾號(hào):英特爾物聯(lián)網(wǎng)】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。
發(fā)布評(píng)論請(qǐng)先 登錄
機(jī)器學(xué)習(xí)為什么需要數(shù)據(jù)預(yù)處理

請(qǐng)教大家一下關(guān)于數(shù)據(jù)預(yù)處理
Python數(shù)據(jù)預(yù)處理方法
數(shù)據(jù)探索與數(shù)據(jù)預(yù)處理
如何將AI模型部署到嵌入式系統(tǒng)中
C預(yù)處理與C語(yǔ)言基本數(shù)據(jù)類型
嵌入式邊緣AI應(yīng)用開(kāi)發(fā)指南
Python數(shù)據(jù)清洗和預(yù)處理入門完整指南
什么是大數(shù)據(jù)采集和預(yù)處理
嵌入式C預(yù)處理器的基本概念和常用指令
PyTorch教程之數(shù)據(jù)預(yù)處理

華為發(fā)布大模型時(shí)代ai存儲(chǔ)技術(shù)
AI大模型對(duì)數(shù)據(jù)存儲(chǔ)技術(shù)的發(fā)展趨勢(shì)

評(píng)論