• 正文
    • 第二章?OpenVINO? 的核心組件
    • 2.1、核心組件與工作流程
    • 2.2 推力引擎詳解
    • 2.3 模型優(yōu)化器詳解
    • 2.4 本章小結(jié)
  • 相關(guān)推薦
申請(qǐng)入駐 產(chǎn)業(yè)圖譜

OpenVINO? Notebooks教程-中篇

02/25 11:22
231
加入交流群
掃碼加入
獲取工程師必備禮包
參與熱點(diǎn)資訊討論

第二章?OpenVINO? 的核心組件

在上篇中我們了解到OpenVINO??是為加速人工智能應(yīng)用和解決方案開發(fā)而生的工具包,基于最新一代的深度學(xué)習(xí)人工神經(jīng)網(wǎng)絡(luò)-包括卷積神經(jīng)網(wǎng)絡(luò) (CNN)、遞歸神經(jīng)網(wǎng)絡(luò)(RNN),能夠部署于從邊緣到云端的各種架構(gòu)中,從而實(shí)現(xiàn)包括機(jī)器視覺、自動(dòng)語音識(shí)別、自然語言處理和推薦系統(tǒng)等多種人工智能應(yīng)用。

我們知道如果從零開始進(jìn)行人工智能應(yīng)用及方案開發(fā)將是一項(xiàng)巨大的工程,搜集數(shù)據(jù)、清洗數(shù)據(jù)、框架選擇、模型訓(xùn)練、調(diào)教模型、應(yīng)用開發(fā)、測(cè)試驗(yàn)證、部署運(yùn)營(yíng),需要投入大量的人力、物力、財(cái)力才能完成這一復(fù)雜的項(xiàng)目。在上一篇中我們也提到,利用OpenVINO? 工具包,開發(fā)者在不了解算法細(xì)節(jié)的前提下同樣可以快速完成人工智能應(yīng)用開發(fā),是如何實(shí)現(xiàn)的呢?在下面的章節(jié)中,我們結(jié)合OpenVINO? 筆記一一解密。在本章節(jié)中我們依舊遵循實(shí)訓(xùn)原則,邊學(xué)邊練,少說多練,不斷鞏固知識(shí)點(diǎn)學(xué)習(xí)。

2.1、核心組件與工作流程

知其然,知其所以然。我們先來了解OpenVINO? 工具包核心組件以及組件之間是如何配合相互完成全部工作流程。推理引擎 Inferece Engine、模型優(yōu)化器Model Optimizer、優(yōu)是加速人工智能應(yīng)用開發(fā)的利劍。

推理引擎管理經(jīng)過優(yōu)化的神經(jīng)網(wǎng)絡(luò)模型的加載和編譯,進(jìn)行推理運(yùn)算,并輸出結(jié)果;推理引擎提供統(tǒng)一API接口可以在英特爾多種硬件上進(jìn)行高性能推理。

模型優(yōu)化器是一個(gè)跨平臺(tái)命令行工具,將經(jīng)過訓(xùn)練的神經(jīng)網(wǎng)絡(luò)從源框架轉(zhuǎn)換為與 nGraph 兼容的開源中間表示 (IR),用于推理運(yùn)算。模型優(yōu)化器支持Caffe、TensorFlow、MXNet、Kaldi 、Pytorch、PaddlePaddle和 ONNX等常用框架預(yù)訓(xùn)練的模型輸入,進(jìn)行一些優(yōu)化,去除冗余的層,并在可能的情況下將操作分組為更簡(jiǎn)單、更快速的圖層用于加速推理運(yùn)算。

下圖展示的是OpenVINO??從準(zhǔn)備模型至完成推理完整的工作流程:

圖2-1? 先導(dǎo)步驟準(zhǔn)備模型

圖2-2? 模型優(yōu)化至推理部署流程

圖2-3? 推理引擎與模型優(yōu)化器協(xié)同工作

通過以上介紹我們已了解,模型優(yōu)化器可以對(duì)主流框架的預(yù)處理模型進(jìn)行優(yōu)化及轉(zhuǎn)化,充分利用已有資源不必從零開始加快了應(yīng)用開發(fā)進(jìn)程;推理引擎提供統(tǒng)一的API可以運(yùn)行在不同的硬件平臺(tái)上,并且可以指定模型運(yùn)行在特定的硬件設(shè)備上,一次編程永久使用,加快了推理進(jìn)程;優(yōu)化工具集以及行業(yè)應(yīng)用演示案例即提供了參考代碼又提供了性能優(yōu)化工具,加快了應(yīng)用開發(fā)流程;核心組件三劍客協(xié)同作用,我們使用OpenVINO??工具包既可以作為學(xué)習(xí)人工智能開發(fā)的技術(shù)指導(dǎo)又可以作為快速開發(fā)應(yīng)用從而加速產(chǎn)品進(jìn)入市場(chǎng)的好工具。

筆者認(rèn)為實(shí)訓(xùn)教程比較好的展現(xiàn)形式就是少說多練,用較為精煉的語言突出重點(diǎn),通過大量的實(shí)踐案例鞏固學(xué)習(xí)成果。這也是我們推薦使用OpenVINO? 筆記作為教程的原因。

從下一節(jié)開始,我們利用OpenVINO? 筆記深入學(xué)習(xí)核心組件使用,詳解核心組件API從而掌握推理引擎及模型優(yōu)化器使用技能。

我們執(zhí)行Jupyter命令開啟學(xué)習(xí)之旅。

source $HOME/openvino_env/bin/activate

jupyter-lab openvino_notebooks/notebooks

圖2-4? OpenVINO? 筆記工作環(huán)境

2.2 推力引擎詳解

2.1.1 Hello World

學(xué)習(xí)目標(biāo):

認(rèn)識(shí)OpenVINO? 推理引擎

掌握使用推理引擎基礎(chǔ)步驟

了解筆記使用的模型及軟件模塊

Hello World,Hello OpenVINO? 。看到Hello World,這代表將會(huì)用最簡(jiǎn)潔的代碼展示將要學(xué)習(xí)的內(nèi)容,我們開始操練。

在OpenVINO??筆記工程中雙擊001-hello-world進(jìn)入子目錄,雙擊001-hello-world.ipynb打開筆記文件。

圖2-5? hello-world筆記

我們使用筆記執(zhí)行全部單元格命令,快速獲得最終結(jié)果。進(jìn)入運(yùn)行菜單-點(diǎn)擊運(yùn)行全部單元格按鈕。

圖2-6 hello-world筆記執(zhí)行全部單元格

不需要等待太久,我們就得到了對(duì)輸入圖片進(jìn)行分類推理結(jié)果,顯示結(jié)果圖片中是短毛尋回犬。

圖2-7 hello-world運(yùn)行結(jié)果

演示筆記僅用19行代碼就實(shí)現(xiàn)了人工智能分類應(yīng)用,恭喜我們正式開啟了人工智能應(yīng)用開發(fā)之路。接下來我們通過解讀代碼來學(xué)習(xí)筆記是如何實(shí)現(xiàn)圖片分類識(shí)別的功能。我們使用筆記單步執(zhí)行功能,查看每一步的執(zhí)行情況。在單步執(zhí)行研讀代碼之前,我們選擇內(nèi)核菜單欄,點(diǎn)擊重啟內(nèi)核并清楚所有結(jié)果為我們接下來單步操作做好準(zhǔn)備。

圖2-8 hello-world單步執(zhí)行

1、導(dǎo)入程序所需要的python模塊

圖2-9 hello-world導(dǎo)入模塊

import?json

import?cv2

import?matplotlib.pyplot?as?plt

import?numpy?as?np

from?openvino.inference_engine?import?IECore

認(rèn)識(shí)新模塊:

json(JavaScript Object Notation) 是一種輕量級(jí)的數(shù)據(jù)交換格式,易于閱讀和編寫。

cv2大名鼎鼎的openCV機(jī)器視覺函數(shù)庫(kù)

matplotlib 是一個(gè)2D繪圖庫(kù),它以各種硬拷貝格式和跨平臺(tái)的交互式環(huán)境生成出版質(zhì)量級(jí)別的圖形。通過 matplotlib開發(fā)者可以僅需要幾行代碼,便可以生成繪圖,直方圖,功率譜,條形圖,錯(cuò)誤圖,散點(diǎn)圖等。

numpy(Numerical Python)是一個(gè)開源的數(shù)值計(jì)算擴(kuò)展。這個(gè)工具可用來存儲(chǔ)和處理大型矩陣,支持大量的維度數(shù)組與矩陣運(yùn)算,此外也針對(duì)數(shù)組運(yùn)算提供大量的數(shù)學(xué)函數(shù)庫(kù)。

OpenVINO? .inference_engine 推理引擎模塊

2、加載網(wǎng)絡(luò)模型

初始化推理引擎、讀入網(wǎng)絡(luò)模型、配置使用的硬件設(shè)備并加載網(wǎng)絡(luò)、配置輸入輸出

圖2-10 hello-world加載網(wǎng)絡(luò)模型

ie?=?IECore()

net?=?ie.read_network(model="model/v3-small_224_1.0_float.xml")

exec_net?=?ie.load_network(net,?"CPU")

input_key?=?next(iter(exec_net.input_info))

output_key?=?next(iter(exec_net.outputs.keys()))

MobileNetV3模型介紹

MobileNet是由Gooogle研究者們?cè)O(shè)計(jì)的一類卷積神經(jīng)網(wǎng)絡(luò),模型具有計(jì)算消耗小、運(yùn)行速度快、運(yùn)行效果準(zhǔn)的特點(diǎn),非常適合在移動(dòng)設(shè)備上運(yùn)行。

3、 加載圖片

圖2-11 hello-world加載顯示圖片

image?=?cv2.cvtColor(cv2.imread("data/coco.jpg"),?cv2.COLOR_BGR2RGB)

input_image?=?cv2.resize(image,?(224,?224))

input_image?=?np.expand_dims(input_image.transpose(2,?0,?1),?0)

plt.imshow(image);

讀取圖片、色彩空間轉(zhuǎn)換openCV庫(kù)默認(rèn)讀取圖片的格式為BGR,mobilenetv3需要輸入的色彩空間為RGB,因此在讀出圖片后需要進(jìn)行色彩空間轉(zhuǎn)換;調(diào)整輸入圖片尺寸為224x224以適配模型需要。代碼執(zhí)行完成,將顯示需要推理的圖片。

4、 執(zhí)行推理

result?=?exec_net.infer(inputs={input_key:?input_image})[output_key]

result_index?=?np.argmax(result)

5、處理并顯示結(jié)果

imagenet_classes=json.loads(open("utils/imagenet_class_index.json").read())

imagenet_classes={int(key)?+?1:?value?for?key,?value?in?imagenet_classes.items()}

imagenet_classes[result_index]

將推理結(jié)果與json文件中的類名進(jìn)行匹配,具有更好的可讀性。

圖2-12 hello-world顯示推理結(jié)果

2.2.2? ?推理引擎API詳解

學(xué)習(xí)目標(biāo):

掌握推理引擎API使用

在上一節(jié)中我們學(xué)習(xí)了利用推理引擎開僅用十幾行代碼便完成分類任務(wù)的案例,在本節(jié)中我們深入學(xué)習(xí)推理引擎的API,掌握完整的開發(fā)流程。

雙擊002-OpenVINO? -api目錄,雙擊打開002-OpenVINO? -api.ipynb筆記。本節(jié)解釋了OpenVINO? 推理引擎API的基礎(chǔ)知識(shí)。它包括:

加載推理引擎及信息顯示

加載不同模型

IR模型

ONNX模型

獲取模型信息

模型輸入

模型輸出

使用模型進(jìn)行推理

重塑和調(diào)整大小

改變圖像大小

改變批量大小

為便于學(xué)習(xí)筆記本被劃分為帶有標(biāo)題的章節(jié)。每一節(jié)都是獨(dú)立的,不依賴于前面的章節(jié)。同時(shí),筆記提供了一個(gè)分割和分類的IR模型和一個(gè)分割的ONNX模型作為例子。我們同樣使用Juypter筆記單步執(zhí)行的功能進(jìn)行學(xué)習(xí)。

1、 導(dǎo)入模塊并初始化引擎

圖2-11 OpenVINO? -api初始化推理引擎

from?openvino.inference_engine?import?IECore

ie?=?IECore()

2、 查詢支持的硬件設(shè)備并顯示

圖2-14 OpenVINO? -api查詢系統(tǒng)支持的推理設(shè)備

devices?=?ie.available_devices

for?device?in?devices:

device_name?=?ie.get_metric(device,?"FULL_DEVICE_NAME")

print(f"{device}:?{device_name}")

推理引擎可以將網(wǎng)絡(luò)模型加載導(dǎo)特定的硬件設(shè)備上。這里的設(shè)備指的是CPU、Intel GPU、Neural Compute Stick 2等。`available_devices`屬性顯示了當(dāng)前系統(tǒng)上可用的設(shè)備。`ie.get_metric()`的 "FULL_DEVICE_NAME "選項(xiàng)顯示設(shè)備的名稱。在本節(jié)筆記本中,使用的是CPU設(shè)備。要使用集成的GPU,請(qǐng)使用`device_name="GPU"`代替。請(qǐng)注意,在GPU上加載網(wǎng)絡(luò)會(huì)比在CPU上加載網(wǎng)絡(luò)慢,但推理可能會(huì)更快。

3、 加載模型

圖2-15 OpenVINO? -api加載模型

from?openvino.inference_engine?import?IECore

ie?=?IECore()

classification_model_xml?=?"model/classification.xml"

net?=?ie.read_network(model=classification_model_xml)

exec_net?=?ie.load_network(network=net,?device_name="CPU")

在初始化推理引擎后,首先用read_network()讀取模型文件,然后用load_network()將其加載到指定設(shè)備上。IR模型IR(Intermediate Representation)模型由一個(gè)包含模型信息的.xml文件和一個(gè)包含權(quán)重的.bin文件組成。read_network()希望權(quán)重文件與xml文件位于同一目錄下,文件名相同,擴(kuò)展名為.bin:model_weights_file == Path(model_xml).with_suffix(".bin")。如果是這種情況,指定權(quán)重文件是可選的。如果權(quán)重文件有不同的文件名,可以通過read_network()的weights參數(shù)來指定。

新版本的推理引擎支持直接讀取ONNX模型,讀取和加載ONNX模型的方法與讀取和加載IR模型的方法相同。model參數(shù)指向ONNX文件名。

圖2-16 OpenVINO? -api加載ONNX模型

from?openvino.inference_engine?import?IECore

ie?=?IECore()

onnx_model?=?"model/segmentation.onnx"

net_onnx?=?ie.read_network(model=onnx_model)

exec_net_onnx?=?ie.load_network(network=net_onnx,?device_name="CPU")

4、 獲取關(guān)于模型的信息

OpenVINO??IENetwork實(shí)例存儲(chǔ)了關(guān)于模型的信息。關(guān)于模型的輸入和輸出的信息在net.input_info和net.output中。這些也是ExecutableNetwork實(shí)例的屬性。在下面的單元格中我們使用net.input_info和net.output,你也可以使用exec_net.input_info和exec_net.output。

圖2-17 OpenVINO? -api模型信息

from?openvino.inference_engine?import?IECore

ie?=?IECore()

classification_model_xml?=?"model/classification.xml"

net?=?ie.read_network(model=classification_model_xml)

net.input_info

模型輸入,上面的單元格顯示,加載的模型期望有一個(gè)輸入,名稱為_input_。如果加載了一個(gè)不同的模型,你可能會(huì)看到一個(gè)不同的輸入層名稱,而且你可能會(huì)看到更多的輸入。有一個(gè)對(duì)第一個(gè)輸入層名稱的引用通常是有用的。對(duì)于一個(gè)只有一個(gè)輸入的模型,next(iter(net.input_info))得到這個(gè)名稱。

圖2-18 OpenVINO? -api模型輸入

input_layer?=?next(iter(net.input_info))

input_layer

這個(gè)輸入層的信息被存儲(chǔ)在input_info中。下一個(gè)單元格會(huì)打印出輸入的布局、精度和形狀。

圖2-19 OpenVINO? -api模型信息

print(f"input?layout:?{net.input_info[input_layer].layout}")

print(f"input?precision:?{net.input_info[input_layer].precision}")

print(f"input?shape:?{net.input_info[input_layer].tensor_desc.dims}")

這里的輸出告訴我們,模型期望輸入的形狀是[1,3,224,224],而且是以N、C、H、W布局。這意味著模型期望的輸入數(shù)據(jù)的批量大小(N)為1,3個(gè)通道(C),圖像的高度(H)和寬度(W)為224。預(yù)計(jì)輸入數(shù)據(jù)的精度為FP32(浮點(diǎn))。

5、 模型輸出

模型輸出信息存儲(chǔ)在net.output中。上面的單元格顯示,該模型返回一個(gè)輸出,名稱為_MobilenetV3/Predictions/Softmax_。如果你加載了一個(gè)不同的模型,你可能會(huì)看到一個(gè)不同的輸出層名稱,你可能會(huì)看到更多的輸出。因?yàn)檫@個(gè)模型有一個(gè)輸出,所以按照輸入層的方法來獲取它的名字。

圖2-20 OpenVINO? -api模型輸出

from?openvino.inference_engine?import?IECore

ie?=?IECore()

classification_model_xml?=?"model/classification.xml"

net?=?ie.read_network(model=classification_model_xml)

net.outputs

devices?=?ie.available_devices

for?device?in?devices:

device_name?=?ie.get_metric(device,?"FULL_DEVICE_NAME")

print(f"{device}:?{device_name}")

獲取輸出布局、精度和形狀與獲取輸入布局、精度和形狀類似

圖2-21 OpenVINO? -api模型輸出信息

print(f"output?layout:?{net.outputs[output_layer].layout}")

print(f"output?precision:?{net.outputs[output_layer].precision}")

print(f"output?shape:?{net.outputs[output_layer].shape}")

這個(gè)單元格的輸出顯示,模型返回的輸出形狀為[1, 1001],其中1是批處理規(guī)模(N),1001是類的數(shù)量(C)。輸出以32位浮點(diǎn)形式返回。

6、 使用模型進(jìn)行推理

要使用模型進(jìn)行推理,請(qǐng)調(diào)用_ExecutableNetwork_的infer()方法,即我們用load_network()加載的exec_net。infer()需要帶有參數(shù),_inputs_是一個(gè)字典,將輸入層名稱映射到輸入數(shù)據(jù)。

1) 準(zhǔn)備工作:加載網(wǎng)絡(luò)

圖2-22 OpenVINO? -api初始化引擎并加載網(wǎng)絡(luò)

from?openvino.inference_engine?import?IECore

ie?=?IECore()

classification_model_xml?=?"model/classification.xml"

net?=?ie.read_network(model=classification_model_xml)

exec_net?=?ie.load_network(network=net,?device_name="CPU")

input_layer?=?next(iter(net.input_info))

output_layer?=?next(iter(net.outputs))

2) 準(zhǔn)備工作:加載圖像并轉(zhuǎn)換為輸入形狀。

為了在網(wǎng)絡(luò)中處理圖像,需要將其加載到一個(gè)數(shù)組中,調(diào)整為網(wǎng)絡(luò)所期望的形狀,并轉(zhuǎn)換為網(wǎng)絡(luò)的輸入布局。

圖2-23 OpenVINO? -api讀入圖片信息

import?cv2

image_filename?=?"data/coco_hollywood.jpg"

image?=?cv2.imread(image_filename)

image.shape

該圖像的形狀為(663,994,3)。它的高度為663像素,寬度為994像素,并有3個(gè)顏色通道。我們得到一個(gè)網(wǎng)絡(luò)期望的高度和寬度的參考,并調(diào)整到這個(gè)尺寸

圖2-16 OpenVINO? -api加載ONNX模型

N,?C,?H,?W?=?net.input_info[input_layer].tensor_desc.dims

resized_image?=?cv2.resize(src=image,?dsize=(W,?H))

resized_image.shape

現(xiàn)在,圖像的寬度和高度是網(wǎng)絡(luò)所期望的。它仍然是H,C,W格式。我們首先調(diào)用np.transpose()將其改為N,C,H,W格式(其中N=1),然后通過調(diào)用np.expand_dims()添加N維。用np.astype()將數(shù)據(jù)轉(zhuǎn)換為FP32。

圖2-25 OpenVINO? -api處理圖片符合模型要求

import?numpy?as?np

input_data?=?np.expand_dims(np.transpose(resized_image,?(2,?0,?1)),?0).astype(np.float32)

input_data.shape

3) 進(jìn)行推理

現(xiàn)在,輸入數(shù)據(jù)的形狀是正確的,僅用一個(gè)簡(jiǎn)單的命令即可進(jìn)行推理。

圖2-26 OpenVINO? -api 推理獲得結(jié)果

result?=?exec_net.infer({input_layer:?input_data})

result

.infer()返回一個(gè)字典,將輸出層映射到數(shù)據(jù)。由于我們知道這個(gè)網(wǎng)絡(luò)返回一個(gè)輸出,并且我們?cè)趏utput_layer變量中存儲(chǔ)了對(duì)輸出層的引用,我們可以用result[output_layer]獲得數(shù)據(jù)。

圖2-27 OpenVINO? -api 推理結(jié)果

output?=?result[output_layer]

output.shape

輸出的形狀是(1,1001),我們看到這是輸出的預(yù)期形狀。這個(gè)輸出形狀表明,該網(wǎng)絡(luò)返回了1001個(gè)類的概率

5) 重塑和調(diào)整大小

調(diào)整圖像大小

我們可以不使用重塑圖像來適應(yīng)模型,而是通過重塑模型來適應(yīng)圖像。注意不是所有的模型都支持重塑,而支持重塑的模型可能不支持所有的輸入形狀。如果你重塑模型的輸入形狀,模型的準(zhǔn)確性也可能受到影響。我們首先檢查模型的輸入形狀,然后重塑為新的輸入形狀。

圖2-28 OpenVINO? -api 調(diào)整圖像尺寸

from?OpenVINO.inference_engine?import?IECore

ie?=?IECore()

segmentation_model_xml?=?"model/segmentation.xml"

segmentation_net?=?ie.read_network(model=segmentation_model_xml)

segmentation_input_layer?=?next(iter(segmentation_net.input_info))

segmentation_output_layer?=?next(iter(segmentation_net.outputs))

print("~~~~?ORIGINAL?MODEL?~~~~")

print(f"input?layout:?{segmentation_net.input_info[segmentation_input_layer].layout}")

print(f"input?shape:?{segmentation_net.input_info[segmentation_input_layer].tensor_desc.dims}")

print(f"output?shape:?{segmentation_net.outputs[segmentation_output_layer].shape}")

new_shape?=?(1,?3,?544,?544)

segmentation_net.reshape({segmentation_input_layer:?new_shape})

segmentation_exec_net?=?ie.load_network(network=segmentation_net,?device_name="CPU")

print("~~~~?RESHAPED?MODEL?~~~~")

print(f"net?input?shape:?{segmentation_net.input_info[segmentation_input_layer].tensor_desc.dims}")

print(

f"exec_net?input?shape:?"

f"{segmentation_exec_net.input_info[segmentation_input_layer].tensor_desc.dims}"

)

print(f"output?shape:?{segmentation_net.outputs[segmentation_output_layer].shape}")

分割網(wǎng)絡(luò)的輸入形狀是[1,3,512,512],采用NHCW布局:網(wǎng)絡(luò)期望3通道圖像的寬度和高度為512,批量大小為1。我們用IENetwork的.reshape()方法重新塑造網(wǎng)絡(luò),使其接受寬度和高度為544的輸入圖像。這個(gè)分割網(wǎng)絡(luò)總是返回寬度和高度與輸入寬度和高度相同的數(shù)組,所以將輸入尺寸設(shè)置為544x544也會(huì)修改輸出尺寸。重塑之后,再次將網(wǎng)絡(luò)加載到設(shè)備上。

 

改變批處理大小

我們也可以使用.reshape()來設(shè)置批量大小,通過增加_new_shape_的第一個(gè)元素。例如,要設(shè)置2個(gè)批次的大小,在上面的單元格中設(shè)置new_shape = (2,3,544,544)。如果你只想改變批量大小,你也可以直接設(shè)置batch_size屬性。

圖2-29 OpenVINO? -api 調(diào)整批處理大小

from?OpenVINO.inference_engine?import?IECore

ie?=?IECore()

segmentation_model_xml?=?"model/segmentation.xml"

segmentation_net?=?ie.read_network(model=segmentation_model_xml)

segmentation_input_layer?=?next(iter(segmentation_net.input_info))

segmentation_output_layer?=?next(iter(segmentation_net.outputs))

segmentation_net.batch_size?= 2

segmentation_exec_net?=?ie.load_network(network=segmentation_net,?device_name="CPU")

print(f"input?layout:?{segmentation_net.input_info[segmentation_input_layer].layout}")

print(f"input?shape:?{segmentation_net.input_info[segmentation_input_layer].tensor_desc.dims}")

print(f"output?shape:?{segmentation_net.outputs[segmentation_output_layer].shape}")

輸出顯示,通過設(shè)置批量大小為2,輸入和輸出形狀的第一個(gè)元素(N)現(xiàn)在的值為2。讓我們看看如果我們將輸入圖像通過網(wǎng)絡(luò)傳播會(huì)發(fā)生什么。

圖2-30 OpenVINO??-api批量為2的情況

import?numpy?as?np

from?OpenVINO.inference_engine?import?IECore

ie?=?IECore()

segmentation_model_xml?=?"model/segmentation.xml"

segmentation_net?=?ie.read_network(model=segmentation_model_xml)

segmentation_input_layer?=?next(iter(segmentation_net.input_info))

segmentation_output_layer?=?next(iter(segmentation_net.outputs))

input_data?=?np.random.rand(*segmentation_net.input_info[segmentation_input_layer].tensor_desc.dims)

segmentation_net.batch_size?=?2

segmentation_exec_net?=?ie.load_network(network=segmentation_net,?device_name="CPU")

result_batch?=?segmentation_exec_net.infer({segmentation_input_layer:?input_data})

 

print(f"input?data?shape:?{input_data.shape}")

print(f"result?data?data?shape:?{result_batch[segmentation_output_layer].shape}")

輸出顯示,如果批次大小為2,網(wǎng)絡(luò)輸出將有2的批次大小,即使只有一個(gè)圖像通過網(wǎng)絡(luò)傳播。不管批次大小如何,你總是可以在一個(gè)圖像上做推理。在這種情況下,只有第一個(gè)網(wǎng)絡(luò)輸出包含有意義的信息。通過創(chuàng)建批次大小為2的隨機(jī)數(shù)據(jù)來驗(yàn)證對(duì)兩幅圖像的推理是否有效。

圖2-31 OpenVINO? -api批次為2的輸出結(jié)果

import?numpy?as?np

from?OpenVINO.inference_engine?import?IECore

 

ie?=?IECore()

segmentation_model_xml?=?"model/segmentation.xml"

segmentation_net?=?ie.read_network(model=segmentation_model_xml)

segmentation_input_layer?=?next(iter(segmentation_net.input_info))

segmentation_output_layer?=?next(iter(segmentation_net.outputs))

segmentation_net.batch_size?=?2

input_data?=?np.random.rand(*segmentation_net.input_info[segmentation_input_layer].tensor_desc.dims)

segmentation_exec_net?=?ie.load_network(network=segmentation_net,?device_name="CPU")

result_batch?=?segmentation_exec_net.infer({segmentation_input_layer:?input_data})

 

print(f"input?data?shape:?{input_data.shape}")

print(f"result?data?shape:?{result_batch[segmentation_output_layer].shape}")

通過上面的學(xué)習(xí),我們可以總結(jié)出使用推理引擎進(jìn)行推理的流程,我們只要按照流程步驟進(jìn)行編程便可得到結(jié)果。我們?cè)賮砘仡櫹峦暾鞒?,在后續(xù)的章節(jié)中我們會(huì)通過不同的案例不斷練習(xí)這個(gè)流程,直至熟練掌握:

初始化載入硬件插件,所有AI計(jì)算硬件的插件都由IECore對(duì)象自行內(nèi)部管理。讀取IR文件,用類IECore將IR文件使用read_network()方法讀入到IENetwork類對(duì)象中去。

配置輸入輸出,將模型載入內(nèi)存后,用inputs和outputs指定模型輸入輸出張量的精度和布局(layout)。

載入模型,模型載入AI計(jì)算硬件后,會(huì)獲得一個(gè)ExecutableNetwork對(duì)象,該對(duì)象執(zhí)行推理計(jì)算。read_network()方法中的deviceName參數(shù)指定使用哪個(gè)AI計(jì)算硬件。

準(zhǔn)備輸入數(shù)據(jù)通過OpenCV采集圖像數(shù)據(jù)到Mat對(duì)象,然后用frameToBlob()函數(shù)將OpenCV Mat對(duì)象中的圖像數(shù)據(jù)傳給InferenceEngine Blob對(duì)象,AI模型將從InferenceEngine Blob對(duì)象中獲取圖像數(shù)據(jù)。

執(zhí)行推理計(jì)算,用infer()方法執(zhí)行同步推理計(jì)算,或者用StartAsync()和Wait()方法執(zhí)行異步推理計(jì)算。

處理模型輸出輸出為模型輸出的張量outputs,此時(shí)可以對(duì)結(jié)果進(jìn)行讀取、打標(biāo)簽或畫框等操作。

圖2-32 OpenVINO? -api推理引擎使用流程

2.3.3? ?Hello Segmentation

學(xué)習(xí)目標(biāo):

鞏固學(xué)習(xí)推理引擎API

掌握推理引擎使用流程

認(rèn)識(shí)道路分割模型

在上節(jié)中我們?cè)敿?xì)學(xué)習(xí)了推理引擎的API使用,我們按照初始化推理引擎-讀取網(wǎng)絡(luò)模型-配置輸入輸出-載入模型-準(zhǔn)備數(shù)據(jù)-執(zhí)行推理-處理輸出數(shù)據(jù)的流程即可完成人工智能應(yīng)用的開發(fā)。在本節(jié)中,我們使用Open Model Zoo的[road-segmentation-adas-0001]模型進(jìn)行練習(xí),鞏固推理引擎的API學(xué)習(xí)成果。ADAS是高級(jí)駕駛輔助服務(wù)的縮寫。該模型識(shí)別了四個(gè)類別:背景、道路、路邊和標(biāo)志。該模型的原框架為PyTorch,輸入圖像大小896x512。了解背景后我們開始操練。

1、 導(dǎo)入模塊

圖2-33 hello-segmentation

import?cv2

import?matplotlib.pyplot?as?plt

import?numpy?as?np

import?sys

from?OpenVINO.inference_engine?import?IECore

sys.path.append("../utils")

from?notebook_utils?import?segmentation_map_to_image

sys模塊 sys 模塊提供訪問解釋器使用或維護(hù)的變量,和與解釋器進(jìn)行交互的函數(shù)。通俗來講,sys 模塊為程序與 Python 解釋器的交互,提供了一系列的函數(shù)和變量,用于操控 Python 運(yùn)行時(shí)的環(huán)境。sys 模塊是 Python 中內(nèi)置的模塊,所以不需要再單獨(dú)安裝,只需在使用前 import sys 即可。

2、 加載模型

圖2-34 hello-segmentation初始化引擎及加載模型

ie?=?IECore()

net?=?ie.read_network(

model="model/road-segmentation-adas-0001.xml")

exec_net?=?ie.load_network(net,?"CPU")

output_layer_ir?=?next(iter(exec_net.outputs))

input_layer_ir?=?next(iter(exec_net.input_info))

遵循OpenVINO? 推理引擎使用流程,在這一步中,完成了推理引擎初始化、讀取網(wǎng)絡(luò)模型、加載網(wǎng)絡(luò)、配置輸入輸出的操作。

3、 加載圖像

根據(jù)網(wǎng)絡(luò)模型輸入要求,對(duì)圖像進(jìn)行處理并顯示原始圖像

圖2-35 hello-segmentation圖像處理

image?=?cv2.imread("data/empty_road_mapillary.jpg")

rgb_image?=?cv2.cvtColor(image,?cv2.COLOR_BGR2RGB)

image_h,?image_w,?_?=?image.shape

N,?C,?H,?W?=?net.input_info[input_layer_ir].tensor_desc.dims

resized_image?=?cv2.resize(image,?(W,?H))

input_image?=?np.expand_dims(

resized_image.transpose(2,?0,?1),?0

)

plt.imshow(rgb_image)

讀入圖像、將圖像色彩空間由BGR轉(zhuǎn)換為RGB、根據(jù)網(wǎng)絡(luò)模型輸入需要調(diào)整圖像尺寸,顯示圖像。

4、 執(zhí)行推理并顯示結(jié)果

圖2-36 hello-segmentation推理結(jié)果

result?=?exec_net.infer(inputs={input_layer_ir:?input_image})

result_ir?=?result[output_layer_ir]

segmentation_mask?=?np.argmax(result_ir,?axis=1)

plt.imshow(segmentation_mask[0])

5、 準(zhǔn)備數(shù)據(jù)可視化

圖2-37 hello-segmentation可視化準(zhǔn)備

alpha?=?0.3

mask?=?segmentation_map_to_image(segmentation_mask,?colormap)

resized_mask?=?cv2.resize(mask,?(image_w,?image_h))

image_with_mask?=?cv2.addWeighted(resized_mask,?alpha,?rgb_image,?1?-?alpha,?0)

在這一步中,定義顏色圖,每種類別以一種顏色表示,定義了分割圖層的透明度,使用工具函數(shù)進(jìn)行圖像色彩空間轉(zhuǎn)換,創(chuàng)建帶有掩膜的圖像。下一步進(jìn)行數(shù)據(jù)可視化展示。

6、 數(shù)據(jù)可視化展示

圖2-38 hello-segmentation可視化展示

data?=?{"Base?Photo":?rgb_image,?"Segmentation":?mask,?"Masked?Photo":?image_with_mask}

f,?axs?=?plt.subplots(1,?len(data.items()),?figsize=(15,?10))

for?ax,?(name,?image)?in?zip(axs,?data.items()):

ax.axis('off')

ax.set_title(name)

ax.imshow(image)

plt.show(f)

通過數(shù)據(jù)可視化我們得到了原始圖像,分割圖像以及原始圖像與分割圖像進(jìn)行疊加的圖像,可以更直觀的展示推理結(jié)果。

2.2.4? ?Hello Detection

本節(jié)目標(biāo):

強(qiáng)化學(xué)習(xí)推理引擎API

熟練掌握推理引擎使用流程

了解文本檢測(cè)模型

本節(jié)學(xué)習(xí)使用推理引擎完成檢測(cè)模型的應(yīng)用,學(xué)習(xí)如何在一個(gè)給定的IR模型上進(jìn)行文本檢測(cè)。我們使用Open Model Zoo中的[horizontal-text-detection-0001]模型。它檢測(cè)圖像中的文本,并返回形狀為[100, 5]的blob數(shù)據(jù)。對(duì)于每個(gè)檢測(cè)的描述都有[x_min, y_min, x_max, y_max, conf]格式。該模型是基于FCOS架構(gòu)的文本檢測(cè)器,以類似MobileNetV2為骨干,適用于有或多或少水平文字的室內(nèi)/室外場(chǎng)景。源框架為PyTorch,與基礎(chǔ)模型相比,該模型的主要優(yōu)點(diǎn)是尺寸更小,性能更快。

下面我們開始練習(xí)。

1、 導(dǎo)入所需模塊

圖2-39 hello-detection導(dǎo)入模塊

import?cv2

import?matplotlib.pyplot?as?plt

import?numpy?as?np

from?OpenVINO.inference_engine?import?IECore

from?os.path?import?isfile

2、 加載網(wǎng)絡(luò)模型

圖2-40 hello-detection加載網(wǎng)絡(luò)模型

ie?=?IECore()

model_folder?=?"model"

model_name?=?"horizontal-text-detection-0001"

model_extensions?=?("bin",?"xml")

for?extension?in?model_extensions:

if?not?isfile(f'{model_folder}/{model_name}.{extension}'):

raise?FileNotFoundError(f"Missing?model?file!?Please?download?missing?file:?{model_name}.{extension}")

net?=?ie.read_network(

model="model/horizontal-text-detection-0001.xml"

)

exec_net?=?ie.load_network(net,?"CPU")

output_layer_ir?=?next(iter(exec_net.outputs))

input_layer_ir?=?next(iter(exec_net.input_info))

又到了熟悉的流程、在這一步中完成了推理引擎初始化、網(wǎng)絡(luò)模型讀取、網(wǎng)絡(luò)加載、輸入輸出配置工作。與前幾節(jié)代碼相比,代碼中加入了條件判斷來確定是否包含需要的模型文件,如果沒有文件則需要先行下載,代碼加入的目的是讓程序更為健壯。

3、加載并處理圖片

圖2-41 hello-detection圖片預(yù)處理

image?=?cv2.imread("data/intel_rnb.jpg")

N,?C,?H,?W?=?net.input_info[input_layer_ir].tensor_desc.dims

resized_image?=?cv2.resize(image,?(W,?H))

input_image?=?np.expand_dims(

resized_image.transpose(2,?0,?1),?0

)

plt.imshow(image)

獲取模型輸入的要求,并根據(jù)要求對(duì)圖像進(jìn)行處理以滿足網(wǎng)絡(luò)模型輸入要求,最終顯示圖像。

 

4、進(jìn)行推理

圖2-42 hello-detection加載網(wǎng)絡(luò)模型

result?=?exec_net.infer(inputs={input_layer_ir:?input_image})

boxes?=?result['boxes']

boxes?=?boxes[~np.all(boxes==0,?axis=1)]

完成推理并保存推理結(jié)果。

 

5、 數(shù)據(jù)可視化

圖2-43 hello-detection結(jié)果展示

def?convert_result_to_image(bgr_image,?resized_image,?boxes,?threshold=0.3,?conf_labels=True):

def?multiply_by_ratio(ratio_x,?ratio_y,?box):

return?[max(shape?*?ratio_y,?10)?if?idx?%?2?else?shape?*?ratio_x?for?idx,?shape?in?enumerate(box[:-1])]

colors?=?{'red':?(255,?0,?0),?'green':?(0,?255,?0)}

(real_y,?real_x),?(resized_y,?resized_x)?=?image.shape[:2],?resized_image.shape[:2]

ratio_x,?ratio_y?=?real_x/resized_x,?real_y/resized_y

rgb_image?=?cv2.cvtColor(bgr_image,?cv2.COLOR_BGR2RGB)

for?box?in?boxes:

conf?=?box[-1]

if?conf?>?threshold:

(x_min,?y_min,?x_max,?y_max)?=?map(int,?multiply_by_ratio(ratio_x,?ratio_y,?box))

rgb_image?=?cv2.rectangle(

rgb_image,

(x_min,?y_min),

(x_max,?y_max),

colors['green'],

3

)

if?conf_labels:

rgb_image?=?cv2.putText(

rgb_image,

f"{conf:.2f}",

(x_min,?y_min?-?10),

cv2.FONT_HERSHEY_SIMPLEX,

0.8,

colors['red'],

1,

cv2.LINE_AA

)

return?rgb_image

plt.figure(figsize=(10,6))

plt.axis('off')

plt.imshow(convert_result_to_image(image,?resized_image,?boxes,?conf_labels=False))

2.1.5? ?小結(jié)

通過本節(jié)學(xué)習(xí)我們掌握了推理引擎API函數(shù)、掌握了使用推理引擎進(jìn)行開發(fā)的完整流程,同時(shí)通過案例我們學(xué)習(xí)了Mobilenetv3分類模型、基于PyTorch框架的道路分割模型以及文本檢測(cè)模型。

2.3 模型優(yōu)化器詳解

我們一直在學(xué)習(xí)探討深度學(xué)習(xí)、神經(jīng)網(wǎng)絡(luò)。其實(shí),神經(jīng)網(wǎng)絡(luò)并不復(fù)雜,就是多個(gè)神經(jīng)元的堆疊。多個(gè)神經(jīng)元之間通過網(wǎng)絡(luò)拓?fù)?/a>結(jié)構(gòu)相連,具備一定的分類能力,謂之“神經(jīng)網(wǎng)絡(luò)”。通常情況,網(wǎng)絡(luò)層數(shù)越多、參數(shù)越多,數(shù)據(jù)越多推理的精度越高。但并不是所有的網(wǎng)絡(luò)層都有助于進(jìn)行推理。OpenVINO? 的模型優(yōu)化器可以自動(dòng)識(shí)別推理過程中是無用的,并且可能會(huì)增加推理時(shí)間的圖層,比如對(duì)于訓(xùn)練很重要的Dropout圖層。通過對(duì)于無用層的裁剪完成模型優(yōu)化功能。

我們先了解下模型優(yōu)化器提供的功能及特點(diǎn):

優(yōu)化網(wǎng)絡(luò)

改變格式

削減部分網(wǎng)絡(luò)

支持自定義層

支持主流框架格式包括TensorFlow、Caffe、MXNet、Kaidi和ONNX格式

生成文件為IR中間層

模型優(yōu)化器后準(zhǔn)確度、精度基本不變,但性能必定會(huì)提升。模型生成IR中間層

在了解完模型優(yōu)化器的工作原理后,我們開始實(shí)訓(xùn)環(huán)節(jié),在后續(xù)章節(jié)中我們將練習(xí)將Tensoflow模型、PyTorch模型、PaddlePaddle模型進(jìn)行優(yōu)化并完成推理。

2.3.1?? Tensorflow模型優(yōu)化

學(xué)習(xí)目標(biāo):

掌握將TensorFlow模型轉(zhuǎn)換為OpenVINO??IR格式

1、 導(dǎo)入模塊

圖2-44 tensorflow-to-OpenVINO??導(dǎo)入模塊

import?json

import?sys

import?time

from?pathlib?import?Path

import?cv2

import?matplotlib.pyplot?as?plt

import?mo_tf

import?numpy?as?np

from?openvino . inference_engine?import?IECore

認(rèn)識(shí)新模塊

pathlib 是python自帶的用于處理文件路徑的模塊,使用pathlib可以創(chuàng)建路徑對(duì)象。使用路徑對(duì)象而不是字符串的一個(gè)重要優(yōu)點(diǎn)是,我們可以在路徑對(duì)象上調(diào)用方法。

mo_tf 模型優(yōu)化器用于處理tensorflow模型的轉(zhuǎn)換的模塊

圖2-45 tensorflow-to-OpenVINO? 定義模型名稱

model_path?=?Path("model/v3-small_224_1.0_float.pb")

ir_path?=?Path(model_path).with_suffix(".xml")

在本節(jié)演示中,我們使用tensorflow MobileNetV3模型。

2、 構(gòu)建轉(zhuǎn)換命令

調(diào)用OpenVINO? 模型優(yōu)化工具,將TensorFlow模型轉(zhuǎn)換為OpenVINO??IR,精度為FP16。模型被保存到當(dāng)前目錄。我們將平均值添加到模型中,并通過--scale_values將輸出與標(biāo)準(zhǔn)偏差進(jìn)行縮放。有了這些選項(xiàng),在通過網(wǎng)絡(luò)傳播之前,沒有必要對(duì)輸入數(shù)據(jù)進(jìn)行標(biāo)準(zhǔn)化處理。原始模型希望輸入的圖像是RGB格式的。轉(zhuǎn)換后的模型也希望是RGB格式的圖像。如果你想讓轉(zhuǎn)換后的模型適用于BGR圖像,你可以使用--反轉(zhuǎn)輸入通道選項(xiàng)。參見模型優(yōu)化器開發(fā)者指南以了解更多關(guān)于模型優(yōu)化器的信息,包括命令行選項(xiàng)的描述。查看模型文檔,了解有關(guān)模型的信息,包括輸入形狀、預(yù)期顏色順序和平均值。

圖2-46 tensorflow-to-OpenVINO??構(gòu)建優(yōu)化命令

mo_path?=?str(Path(mo_tf.__file__))

mo_command?=?f""""{sys.executable}"

"{mo_path}"

--input_model?"{model_path}"

--input_shape?"[1,224,224,3]"

--mean_values="[127.5,127.5,127.5]"

--scale_values="[127.5]"

--data_type?FP16

--output_dir?"{model_path.parent}"

"""

mo_command?=?"?".join(mo_command.split())

print("Model?Optimizer?command?to?convert?TensorFlow?to?OpenVINO? :")

print(mo_command)

3、 執(zhí)行優(yōu)化命令

模型優(yōu)化過程會(huì)花一些時(shí)間,根據(jù)運(yùn)行設(shè)備不同時(shí)間會(huì)有差異。當(dāng)我們看到輸出結(jié)果的最后幾行包括`[ SUCCESS ] Generated IR version 10 model.`則模型優(yōu)化是成功的。同時(shí)我們?cè)趍odel文件夾可以看到新生成的xml及bin文件。

圖2-47 tensorflow-to-OpenVINO? 執(zhí)行模型優(yōu)化及模型輸出

4、 對(duì)轉(zhuǎn)換后的模型進(jìn)行推理測(cè)試

1) 加載模型

圖2-48 tensorflow-to-OpenVINO? 加載模型

ie?=?IECore()

net?=?ie.read_network(str(ir_path))

exec_net?=?ie.load_network(net,?"CPU")

2)? ? 獲取模型信息

圖2-49 tensorflow-to-OpenVINO? 獲取模型信息

input_key?=?list(exec_net.input_info)[0]

output_key?=?list(exec_net.outputs.keys())[0]

network_input_shape?=?exec_net.input_info[input_key].tensor_desc.dims

3) 加載圖像并處理為適合網(wǎng)絡(luò)需要的格式

圖2-50 tensorflow-to-OpenVINO? 獲取模型信息

image?=?cv2.cvtColor(cv2.imread("data/coco.jpg"),?cv2.COLOR_BGR2RGB)

resized_image?=?cv2.resize(image,?(224,?224))

input_image?=?np.reshape(resized_image,?network_input_shape)?/?255

input_image?=?np.expand_dims(np.transpose(resized_image,?(2,?0,?1)),?0)

plt.imshow(image)

4)?執(zhí)行推理

圖2-51 tensorflow-to-OpenVINO?執(zhí)行推理并輸出結(jié)果

esult?=?exec_net.infer(inputs={input_key:?input_image})[output_key]

result_index?=?np.argmax(result)

imagenet_classes?=?json.loads(open("utils/imagenet_class_index.json").read())

imagenet_classes?=?{

int(key)?+?1:?value?for?key,?value?in?imagenet_classes.items()

}

imagenet_classes[result_index]

5) 性能測(cè)試

測(cè)量在一千張圖片上進(jìn)行推理所需的時(shí)間。以便于顯示出模型優(yōu)化后的性能。對(duì)于更精確的基準(zhǔn)測(cè)試,請(qǐng)使用OpenVINO? 基準(zhǔn)測(cè)試工具。我們?cè)诤竺娴恼鹿?jié)會(huì)學(xué)習(xí)如何使用OpenVINO? Benchmark進(jìn)行基準(zhǔn)測(cè)試。

圖2-52 tensorflow-to-OpenVINO? 性能測(cè)試結(jié)果

num_images?=?1000

start?=?time.perf_counter()

for?_?in?range(num_images):

exec_net.infer(inputs={input_key:?input_image})

end?=?time.perf_counter()

time_ir?=?end?-?start

print(

f"IR?model?in?Inference?Engine/CPU:?{time_ir/num_images:.4f}?"

f"seconds?per?image,?FPS:?{num_images/time_ir:.2f}"

)

至此,我們使用模型優(yōu)化器將TensorFlow模型轉(zhuǎn)化為推理引擎可以使用的IR模型,并完成了推理及簡(jiǎn)單的性能測(cè)試。

2.1.2? ?PyTorch模型優(yōu)化

學(xué)習(xí)目標(biāo):

掌握PyTorch模型轉(zhuǎn)化為ONNX格式的方法

掌握將ONNX轉(zhuǎn)化為IR格式的方法

本節(jié)演示了使用OpenVINO??對(duì)PyTorch語義分割模型進(jìn)行優(yōu)化并使用轉(zhuǎn)換后的模型進(jìn)行推理的逐步說明。

PyTorch模型需要先被轉(zhuǎn)換為ONNX格式,然后再使用模型優(yōu)化器將ONNX模型轉(zhuǎn)化為OpenVINO? 中間表示(IR)格式。ONNX和IR模型被加載到OpenVINO? 推理引擎中以顯示模型預(yù)測(cè)。該模型在CityScapes上進(jìn)行了預(yù)訓(xùn)練。模型來源是https://github.com/ekzhang/fastseg? 。

Fastseg是用于實(shí)時(shí)語義分割的MobileNetV3的PyTorch實(shí)現(xiàn),具有預(yù)訓(xùn)練的權(quán)重和最先進(jìn)的性能。

我們開始實(shí)操練習(xí)

1、 導(dǎo)入模塊

圖2-53 pytorch-onnx-to-OpenVINO? 導(dǎo)入模塊

由于安裝命令是依賴網(wǎng)絡(luò)將軟件包下載至本地環(huán)境,網(wǎng)絡(luò)環(huán)境不同所用安裝時(shí)間不盡相同,若網(wǎng)絡(luò)順暢,我們終將順利迎來安裝成功的提示。至此,環(huán)境安裝成功,我們已經(jīng)具備了運(yùn)行OpenVINO? Notebooks工程的全部環(huán)境。

import?sys

import?time

import?os

from?pathlib?import?Path

import?cv2

import?matplotlib.pyplot?as?plt

import?mo_onnx

import?numpy?as?np

import?torch

from?fastseg?import?MobileV3Large

from?openvino.inference_engine?import?IECore

sys.path.append("../utils")

from?notebook_utils?import?CityScapesSegmentation,?segmentation_map_to_image,?viz_result_image

認(rèn)識(shí)新模塊:

mo_onnx 模型優(yōu)化器轉(zhuǎn)換ONNX格式模塊

torch PyTorch框架的功能模塊,包含卷積函數(shù)、池化功能等

fastseg fastseg算法模型模塊

2、 模型轉(zhuǎn)換配置

設(shè)置模型的名稱,以及將用于網(wǎng)絡(luò)的圖像寬度和高度。CityScapes是在2048x1024的圖像上進(jìn)行預(yù)訓(xùn)練的。使用更小的尺寸會(huì)影響模型的準(zhǔn)確性,但會(huì)提高推理速度。

圖2-54 pytorch-onnx-to-OpenVINO? 模型轉(zhuǎn)換配置

IMAGE_WIDTH?=?1024

IMAGE_HEIGHT?=?1024?if?IMAGE_WIDTH?==?2048?else?512

DIRECTORY_NAME?=?'model'

BASE_MODEL_NAME?=?DIRECTORY_NAME?+?f"/fastseg{IMAGE_WIDTH}"

model_path?=?Path(BASE_MODEL_NAME).with_suffix(".pth")

onnx_path?=?model_path.with_suffix(".onnx")

ir_path?=?model_path.with_suffix(".xml")

設(shè)置圖片高度為1024,設(shè)置存儲(chǔ)PyTorch、ONNX以及IR模型的路徑

3、 下載Fastseg模型

圖2-55 pytorch-onnx-to-OpenVINO? 下載模型

print("Downloading?the?Fastseg?model?(if?it?has?not?been?downloaded?before)....")

model?=?MobileV3Large.from_pretrained().cpu().eval()

print("Loaded?PyTorch?Fastseg?model")

path_to_dir?=?f"{os.getcwd()}/{DIRECTORY_NAME}"

os.makedirs(path_to_dir,?exist_ok=True)

print("nSaving?the?model")

torch.save(model.state_dict(),?str(model_path))

print(f"Model?saved?at?{model_path}")

在本節(jié)中,我們直接從github下載Fastseg預(yù)訓(xùn)練模型存儲(chǔ)在model文件夾中。這是我們?cè)陂_發(fā)應(yīng)用中用到的獲取模型方式之一,在后續(xù)章節(jié)中我們還將介紹如何利用OpenVINO? Model Zoo開放模型庫(kù)獲取模型。

4、 將PyTorch模型導(dǎo)出為ONNX格式

我們使用torch模塊onnx.export功能將PyTorch模型轉(zhuǎn)換為ONNX模型,如果在輸出顯示一些警告,我們可以忽略。如果輸出的最后一行顯示 "ONNX模型導(dǎo)出到fastseg1024.onnx.`",則轉(zhuǎn)換成功。

圖2-56 pytorch-onnx-to-OpenVINO? 模型轉(zhuǎn)換

if?not?onnx_path.exists():

dummy_input?=?torch.randn(1,?3,?IMAGE_HEIGHT,?IMAGE_WIDTH)

torch.onnx.export(

model,

dummy_input,

onnx_path,

opset_version=11,

do_constant_folding=False,

)

print(f"ONNX?model?exported?to?{onnx_path}.")

else:

print(f"ONNX?model?{onnx_path}?already?exists.")

5、 將ONNX模型轉(zhuǎn)換為OpenVINO? IR格式

調(diào)用OpenVINO??模型優(yōu)化工具,將ONNX模型轉(zhuǎn)換成OpenVINO? IR,精度為FP16。模型被保存到當(dāng)前目錄。我們?cè)谀P椭屑尤肫骄担⒂?-scale_values對(duì)輸出的標(biāo)準(zhǔn)偏差進(jìn)行縮放。有了這些選項(xiàng),在通過網(wǎng)絡(luò)傳播之前,沒有必要對(duì)輸入數(shù)據(jù)進(jìn)行標(biāo)準(zhǔn)化。執(zhí)行這個(gè)命令可能需要一些時(shí)間。輸出中可能有一些錯(cuò)誤或警告。如果輸出的最后幾行包括[ SUCCESS ] 生成了IR版本10模型,則模型優(yōu)化是成功的。

1)???? 準(zhǔn)備轉(zhuǎn)換命令

圖2-57 pytorch-onnx-to-OpenVINO? 準(zhǔn)備模型優(yōu)化命令

mo_path?=?str(Path(mo_onnx.__file__))

mo_command?=?f""""{sys.executable}"

"{mo_path}"

--input_model?"{onnx_path}"

--input_shape?"[1,3,?{IMAGE_HEIGHT},?{IMAGE_WIDTH}]"

--mean_values="[123.675,?116.28?,?103.53]"

--scale_values="[58.395,?57.12?,?57.375]"

--data_type?FP16

--output_dir?"{model_path.parent}"

"""

mo_command?=?"?".join(mo_command.split())

print("Model?Optimizer?command?to?convert?the?ONNX?model?to?OpenVINO:")

print(mo_command)

2)???? 執(zhí)行模型優(yōu)化

圖2-58 pytorch-onnx-to-OpenVINO? 執(zhí)行模型優(yōu)化

if?not?ir_path.exists():

print("Exporting?ONNX?model?to?IR...?This?may?take?a?few?minutes.")

mo_result?=?%sx?$mo_command

print("n".join(mo_result))

else:

print(f"IR?model?{ir_path}?already?exists.")

 

6、 模型對(duì)比

通過前面的操作,我們已有了原始模型、ONNX模型以及IR模型,通過比較ONNX、IR和PyTorch模型的預(yù)測(cè)結(jié)果,以確認(rèn)分割結(jié)果與預(yù)期相符。

1)???? 加載和預(yù)處理輸入圖像

對(duì)于OpenVINO??模型,歸一化被移到模型中。對(duì)于ONNX和PyTorch模型,圖像在通過網(wǎng)絡(luò)傳播之前需要進(jìn)行標(biāo)準(zhǔn)化處理。

圖2-59 pytorch-onnx-to-OpenVINO? 圖片預(yù)處理

def?normalize(image:?np.ndarray)?->?np.ndarray:

"""

Normalize?the?image?to?the?given?mean?and?standard?deviation

for?CityScapes?models.

"""

image?=?image.astype(np.float32)

mean?=?(0.485,?0.456,?0.406)

std?=?(0.229,?0.224,?0.225)

image?/=?255.0

image?-=?mean

image?/=?std

return?image

image_filename?=?"data/coco_cross.png"

image?=?cv2.cvtColor(cv2.imread(image_filename),?cv2.COLOR_BGR2RGB)

 

resized_image?=?cv2.resize(image,?(IMAGE_WIDTH,?IMAGE_HEIGHT))

normalized_image?=?normalize(resized_image)

input_image?=?np.expand_dims(np.transpose(resized_image,?(2,?0,?1)),?0)

normalized_input_image?=?np.expand_dims(np.transpose(normalized_image,?(2,?0,?1)),?0)

2)???? 使用ONNX及IR模型進(jìn)行推理驗(yàn)證

推理引擎可以直接加載ONNX模型。我們首先加載ONNX模型,進(jìn)行推理并顯示結(jié)果。之后,我們加載用模型優(yōu)化器轉(zhuǎn)換為中間表征(IR)的模型,對(duì)該模型進(jìn)行推理并顯示結(jié)果。我們已經(jīng)熟悉推理引擎的使用步驟,此處不多贅述。

推理引擎中的ONNX模型

圖2-60 pytorch-onnx-to-OpenVINO??onnx模型推理結(jié)果

ie?=?IECore()

net_onnx?=?ie.read_network(model=onnx_path)

exec_net_onnx?=?ie.load_network(network=net_onnx,?device_name="CPU")

input_layer_onnx?=?next(iter(exec_net_onnx.input_info))

output_layer_onnx?=?next(iter(exec_net_onnx.outputs))

res_onnx?=?exec_net_onnx.infer(inputs={input_layer_onnx:?normalized_input_image})

res_onnx?=?res_onnx[output_layer_onnx]

result_mask_onnx?=?np.squeeze(np.argmax(res_onnx,?axis=1)).astype(np.uint8)

viz_result_image(

image,?segmentation_map_to_image(result_mask_onnx,?CityScapesSegmentation.get_colormap()),?resize=True

)

使用IR模型進(jìn)行推理

圖2-61 pytorch-onnx-to-OpenVINO??IR模型推理結(jié)果

 

PyTorch原始模型推理

在PyTorch模型上做推理,以驗(yàn)證輸出在視覺上看起來與ONNX/IR模型的輸出相同。

圖2-62pytorch-onnx-to-OpenVINO?原始模型推理結(jié)果

從結(jié)果看,三種模型都成功輸出了結(jié)果。接下來我們進(jìn)行性能測(cè)試。

1)???? 性能比較

測(cè)量在五幅圖像上進(jìn)行推理所需的時(shí)間,給出簡(jiǎn)版的性能的對(duì)比。

圖2-63 pytorch-onnx-to-OpenVINO? 模型結(jié)果對(duì)比

num_images?=?5

start?=?time.perf_counter()

for?_?in?range(num_images):

exec_net_onnx.infer(inputs={input_layer_onnx:?input_image})

end?=?time.perf_counter()

time_onnx?=?end?-?start

print(

f"ONNX?model?in?Inference?Engine/CPU:?{time_onnx/num_images:.3f}?"

f"seconds?per?image,?FPS:?{num_images/time_onnx:.2f}"

)

start?=?time.perf_counter()

for?_?in?range(num_images):

exec_net_ir.infer(inputs={input_layer_ir:?input_image})

end?=?time.perf_counter()

time_ir?=?end?-?start

print(

f"IR?model?in?Inference?Engine/CPU:?{time_ir/num_images:.3f}?"

f"seconds?per?image,?FPS:?{num_images/time_ir:.2f}"

)

with?torch.no_grad():

start?=?time.perf_counter()

for?_?in?range(num_images):

model(torch.as_tensor(input_image).float())

end?=?time.perf_counter()

time_torch?=?end?-?start

print(

f"PyTorch?model?on?CPU:?{time_torch/num_images:.3f}?seconds?per?image,?"

f"FPS:?{num_images/time_torch:.2f}"

)

從對(duì)比結(jié)果顯示經(jīng)過模型優(yōu)化器處理再經(jīng)推理引擎執(zhí)行的模型,要比在同一設(shè)備上使用原始模型進(jìn)行推理的效率成倍提升。

2.3.3? ?PaddlePaddle模型優(yōu)化

學(xué)習(xí)目標(biāo):

掌握PaddlePaddle模型轉(zhuǎn)化為ONNX模型的方法

掌握ONNX模型轉(zhuǎn)化為IR格式模型的方法

本節(jié)學(xué)習(xí)如何將在ImageNet數(shù)據(jù)集上預(yù)訓(xùn)練的MobileNet V3 PaddleHub模型轉(zhuǎn)換ONNX及OpenVINO? IR模型。同時(shí)我們繼續(xù)強(qiáng)化學(xué)習(xí)如何使用OpenVINO? Inference Engine對(duì)圖像進(jìn)行分類推理,并比較使用PaddlePaddle原始模型與模型優(yōu)化器轉(zhuǎn)化后的IR模型推理結(jié)果差異。

模型來源是:

https://www.paddlepaddle.org.cn/hubdetail?name=mobilenet_v3_large_imagenet_ssld&en_category=ImageClassification

1、 導(dǎo)入模塊

圖2-64 paddle-onnx-to-OpenVINO? 原始模型推理結(jié)果

print(f"output?layout:?{net.outputs[output_layer].layout}")

print(f"output?precision:?{net.outputs[output_layer].precision}")

print(f"output?shape:?{net.outputs[output_layer].shape}")

認(rèn)識(shí)新模塊:

time 用于時(shí)間處理的模塊

paddlehub paddlepaddle框架提供的預(yù)訓(xùn)練模型庫(kù)

Python 是交互式shell庫(kù),支持變量自動(dòng)補(bǔ)全、自動(dòng)縮進(jìn)以及多種功能函數(shù)

paddle PaddlePaddle飛槳模型模塊

PIL python圖像處理庫(kù),用于圖像處理例如創(chuàng)建、打開、顯示、保存圖像、合成、裁剪等等。

scipy 是一個(gè)高級(jí)的科學(xué)計(jì)算庫(kù),包含線性代數(shù)、優(yōu)化、集成和統(tǒng)計(jì)的模塊,該模塊包含致力于科學(xué)計(jì)算中常見問題的各個(gè)工具箱。

2、 PaddlePaddle飛槳模型下載配置

設(shè)置IMAGE_FILENAME為要使用的圖片的文件名。設(shè)置MODEL_NAME為要從PaddleHub下載的PaddlePaddle模型。MODEL_NAME也將是轉(zhuǎn)換后的ONNX和IR模型的基本名稱。本節(jié)使用mobilenet_v3_large_imagenet_ssld模型進(jìn)行測(cè)試。其他模型可能使用不同的預(yù)處理方法,可根據(jù)需要進(jìn)行一些修改,以便在原始模型和轉(zhuǎn)換模型上得到相同的結(jié)果。hub.config.server是PaddleHub服務(wù)器的URL。你應(yīng)該不需要修改這個(gè)設(shè)置。

圖2-65 paddle-onnx-to-OpenVINO? 定義模型及下載服務(wù)器

IMAGE_FILENAME?=?"coco_close.png"

MODEL_NAME?=?"mobilenet_v3_large_imagenet_ssld"

hub.config.server?=?"https://paddlepaddle.org.cn/paddlehub"

3、 PaddlePaddle模型推理

我們從PaddleHub加載并下載模型,讀取并顯示一幅圖像,對(duì)該圖像進(jìn)行推理,并顯示前三個(gè)預(yù)測(cè)結(jié)果。第一次運(yùn)行時(shí),我們會(huì)從PaddleHub下載所需要的模型

圖2-66 paddle-onnx-to-OpenVINO? 原始模型推理結(jié)果

classifier.classification()將一張圖片作為輸入,并返回圖片的類別名稱。默認(rèn)情況下,返回最佳網(wǎng)絡(luò)結(jié)果。使用top_k'參數(shù),將返回最佳的k'結(jié)果,其中k是一個(gè)數(shù)字。對(duì)圖像的預(yù)處理和將網(wǎng)絡(luò)結(jié)果轉(zhuǎn)換為類別名稱是在幕后完成的。分類模型返回一個(gè)數(shù)組,其中包含1000個(gè)ImageNet類別中每個(gè)類別的浮點(diǎn)值。該值越高,網(wǎng)絡(luò)就越有信心認(rèn)為該值對(duì)應(yīng)的類號(hào)(該值在網(wǎng)絡(luò)輸出數(shù)組中的索引)是該圖像的類號(hào)。classification()函數(shù)將這些數(shù)字轉(zhuǎn)換為類別名稱和softmax概率。

我們通過process_image()函數(shù)查看PaddlePaddle的分類函數(shù)以及加載和預(yù)處理數(shù)據(jù)的實(shí)現(xiàn),可以看到裁剪和調(diào)整大小的效果。由于歸一化,顏色看起來會(huì)很奇怪,而且matplotlib會(huì)對(duì)剪裁值發(fā)出警告。

圖2-67 paddle-onnx-to-OpenVINO? process_image結(jié)果

4、 將模型轉(zhuǎn)換為OpenVINO? 的IR格式

為了將PaddlePaddle模型轉(zhuǎn)換為IR格式,我們首先將模型轉(zhuǎn)換為ONNX,然后將ONNX模型轉(zhuǎn)換為IR格式。

1) 準(zhǔn)備工作

PaddlePaddle的MobileNet模型包含了關(guān)于輸入形狀、平均值和比例值的信息,我們可以用它來轉(zhuǎn)換模型。

圖2-68 paddle-onnx-to-OpenVINO??獲取模型信息

input_shape?=?list(classifier.cpu_predictor.get_input_tensor_shape().values())

print("input?shape:",?input_shape)

print("mean:",?classifier.get_pretrained_images_mean())

print("std:",?classifier.get_pretrained_images_std())

2) 將PaddlePaddle模型轉(zhuǎn)換為ONNX模型

我們用paddle2onnx.export_onnx_model()方法將PaddlePaddle模型轉(zhuǎn)換為ONNX,詳細(xì)信息請(qǐng)參考(https://github.com/PaddlePaddle/paddle2onnx)執(zhí)行完成后我們?cè)趍odel文件夾得到了ONNX模型。

圖2-69 paddle-onnx-to-OpenVINO? 獲取模型信息

target_height,?target_width?=?next(iter(input_shape))[2:]

x_spec?=?InputSpec([1,?3,?target_height,?target_width],?"float32",?"x")

print(

"Exporting?PaddlePaddle?model?to?ONNX?with?target_height?"

f"{target_height}?and?target_width?{target_width}"

)

classifier.export_onnx_model(".",?input_spec=[x_spec],?opset_version=11)

3) 將ONNX模型轉(zhuǎn)換為OpenVINO? IR格式

調(diào)用OpenVINO? 模型優(yōu)化工具,將PaddlePaddle模型轉(zhuǎn)換為OpenVINO? IR,精度為FP32。這些模型被保存到當(dāng)前目錄中。我們可以用--mean_values將均值添加到模型中,用--scale_values將輸出與標(biāo)準(zhǔn)差進(jìn)行縮放。有了這些選項(xiàng),在通過網(wǎng)絡(luò)傳播之前,沒有必要對(duì)輸入數(shù)據(jù)進(jìn)行標(biāo)準(zhǔn)化處理。然而,為了得到與PaddlePaddle模型完全相同的輸出,有必要以同樣的方式對(duì)圖像進(jìn)行預(yù)處理。因此,在本教程中,我們不向模型添加平均值和比例值,我們使用process_image函數(shù),如上節(jié)所述,以確保IR和PaddlePaddle模型使用相同的預(yù)處理方法。

圖2-70 paddle-onnx-to-OpenVINO?? 轉(zhuǎn)換為IR模型

model_xml?=?f"{MODEL_NAME}.xml"

if?not?os.path.exists(model_xml):

mo_command?=?f'mo?--input_model?{MODEL_NAME}.onnx?--input_shape?"[1,3,{target_height},{target_width}]"'

display(Markdown(f"Model?Optimizer?command?to?convert?the?ONNX?model?to?IR:?`{mo_command}`"))

display(Markdown("_Converting?model?to?IR.?This?may?take?a?few?minutes..._"))

!?$mo_command

else:

print(f"{model_xml}?already?exists.")

使用模型優(yōu)化器完成轉(zhuǎn)換后,在model文件夾生成.xml以及.bin的IR模型。

4) 使用推理引擎進(jìn)行推理

加載IR模型,獲取模型信息,加載圖像,進(jìn)行推理,將推理結(jié)果轉(zhuǎn)換成有意義的結(jié)果,并顯示輸出

ie?=?IECore()

net?=?ie.read_network(f"{MODEL_NAME}.xml")

exec_net?=?ie.load_network(net,?"CPU")

input_layer?=?next(iter(net.input_info))

output_layer?=?next(iter(net.outputs))

image?=?Image.open(IMAGE_FILENAME)

plt.imshow(image)

input_image?=?process_image(image)

ie_result?=?exec_net.infer({input_layer:?input_image})[output_layer][0]

softmax_result?=?softmax(ie_result)

top_indices?=?np.argsort(softmax_result)[-3:][::-1]

top_softmax?=?softmax_result[top_indices]

for?index,?softmax_probability?in?zip(top_indices,?top_softmax):

print(f"{classifier.label_list[index]},?{softmax_probability:.5f}")

ie?=?IECore()

net?=?ie.read_network(f"{MODEL_NAME}.xml")

exec_net?=?ie.load_network(net,?"CPU")

input_layer?=?next(iter(net.input_info))

output_layer?=?next(iter(net.outputs))

image?=?Image.open(IMAGE_FILENAME)

plt.imshow(image)

input_image?=?process_image(image)

ie_result?=?exec_net.infer({input_layer:?input_image})[output_layer][0]

softmax_result?=?softmax(ie_result)

top_indices?=?np.argsort(softmax_result)[-3:][::-1]

top_softmax?=?softmax_result[top_indices]

for?index,?softmax_probability?in?zip(top_indices,?top_softmax):

print(f"{classifier.label_list[index]},?{softmax_probability:.5f}")

由輸出結(jié)果也可以驗(yàn)證我們的優(yōu)化流程是成功的。

1) 執(zhí)行效率對(duì)比

測(cè)量在50張圖片上進(jìn)行推理所需的時(shí)間,并比較結(jié)果。時(shí)間信息給出了一個(gè)性能的指示。為了進(jìn)行公平的比較,我們把處理圖像的時(shí)間也包括在內(nèi)。

圖2-71 paddle-onnx-to-OpenVINO? 原始模型推理

使用PaddlePaddle原始模型在CPU上進(jìn)行推理,每幅圖像推理時(shí)間為0.0506秒,F(xiàn)PS為19.76推理結(jié)果為拉布拉多尋回犬。

圖2-72 paddle-onnx-to-OpenVINO? IR模型推理

使用優(yōu)化后的IR模型在CPU上進(jìn)行推理,每幅圖像推理時(shí)間為0.0093秒,F(xiàn)PS為107.74推理結(jié)果為拉布拉多尋回犬, 在推理精度沒有降低的同時(shí)推理效率大幅度提升。

2.3.4? ?模型下載器及轉(zhuǎn)換工具

學(xué)習(xí)目標(biāo):

掌握使用模型下載器下載模型

掌握使用模型轉(zhuǎn)換器轉(zhuǎn)換公共模型

從前面章節(jié)的學(xué)習(xí)中,我們認(rèn)識(shí)到獲取模型、選擇模型是人工智能應(yīng)用開發(fā)基礎(chǔ)環(huán)節(jié)同時(shí)也是最重要的環(huán)節(jié),我們從github、PaddleHub下載了預(yù)訓(xùn)練模型,此外Pytorch Hub、Tensorflow都提供了預(yù)訓(xùn)練模型供開發(fā)者使用。OpenVINO? 工具包同樣提供了Open Model Zoo開放模型庫(kù)內(nèi)置了大量的可以商用的預(yù)訓(xùn)練模型以及公開模型供我們使用。與此同時(shí),為了方便管理、下載使用這些模型,OpenVINO?工具包提供了模型加載器以及模型轉(zhuǎn)換器工具。本節(jié)我們學(xué)習(xí)使用下載器及轉(zhuǎn)換器,如何從Open Model Zoo下載一個(gè)模型,將其轉(zhuǎn)換為OpenVINO? 的IR格式,顯示模型的信息,并對(duì)該模型進(jìn)行基準(zhǔn)測(cè)試。讓我們站在巨人肩膀上加速前進(jìn)。

關(guān)于Open Model Zoo開放模型庫(kù)的工具

模型下載配套的工具有模型下載器、模型轉(zhuǎn)換器、信息轉(zhuǎn)儲(chǔ)器和基準(zhǔn)工具。

模型下載器 omz_downloader從Open Model Zoo下載模型

模型轉(zhuǎn)換器 omz_converter將不是OpenVINO? 的IR格式的Open Model Zoo模型轉(zhuǎn)換成IR格式

信息挖掘器 omz_info_dumper ?? 打印關(guān)于Open Model Zoo模型的信息。

基準(zhǔn)測(cè)試工具benchmark_app ??? 通過計(jì)算推理時(shí)間對(duì)模型性能進(jìn)行基準(zhǔn)測(cè)試。

了解以上信息后,我們正式進(jìn)入操練環(huán)節(jié)。

1、 準(zhǔn)備工作

設(shè)置模型名稱,設(shè)置model_name是下載的Open Model Zoo中模型的名稱,演示中我們依舊使MobileNet模型。更多信息可以從官方站點(diǎn)獲得:

https://docs.OpenVINO?toolkit.org/cn/latest/index.html

圖2-73 model-tool 設(shè)置模型名稱

#?model_name?=?"resnet-50-pytorch"

model_name?=?"mobilenet-v2-pytorch"

2、 導(dǎo)入模塊

圖2-74 model-tool 導(dǎo)入模塊

import?json

import?os.path

import?subprocess

import?sys

from?pathlib?import?Path

from?IPython.display?import?Markdown

from?OpenVINO.inference_engine?import?IECore

sys.path.append("../utils")

from?notebook_utils?import?DeviceNotFoundAlert,?NotebookAlert

認(rèn)識(shí)新模塊:

subprocess 模塊允許我們啟動(dòng)一個(gè)新進(jìn)程,并連接到它們的輸入/輸出/錯(cuò)誤管道,從而獲取返回值

3、 環(huán)境配置

設(shè)置文件和目錄的路徑。默認(rèn)情況下,本演示筆記本從Open Model Zoo下載模型到你的$HOME目錄下的open_model_zoo_models目錄。在Windows上,$HOME目錄通常是c:usersusername,在Linux上是/home/username。如果你想改變文件夾,在下面的單元格中改變base_model_dir。

為了便于模型管理我們可以根據(jù)需要修改以下設(shè)置。

base_model_dir。模型將被下載到這個(gè)目錄下的intel和public文件夾。

omz_cache_dir: Open Model Zoo的緩存文件夾。對(duì)于模型下載器和模型轉(zhuǎn)換器來說,指定一個(gè)緩存目錄不是必須的,但它可以加速后續(xù)的下載。

precision: 如果指定,只下載此精度的模型。

圖2-75 model-tool 環(huán)節(jié)配置

base_model_dir?=?Path("~/open_model_zoo_models").expanduser()

omz_cache_dir?=?Path("~/open_model_zoo_cache").expanduser()

precision?=?"FP16"

ie?=?IECore()

gpu_available?=?"GPU"?in?ie.available_devices

print(

f"base_model_dir:?{base_model_dir},?omz_cache_dir:?{omz_cache_dir},?gpu_availble:?{gpu_available}"

)

4、?從Open Model Zoo下載模型

指定、顯示和運(yùn)行模型下載器命令以下載模型

圖2-76 model-tool 下載模型

download_command?=?(

f"omz_downloader?--name?{model_name}?--output_dir?{base_model_dir}?--cache_dir?{omz_cache_dir}"

)

display(Markdown(f"Download?command:?`{download_command}`"))

display(Markdown(f"Downloading?{model_name}..."))

!?$download_command

我們成功下載了模型,存儲(chǔ)在open_model_zoo_models/public/mobilenet-v2-pytorch目錄下,需要注意,在下載模型時(shí)一定要保證網(wǎng)絡(luò)暢通。

 

5、 將模型轉(zhuǎn)換為OpenVINO? 的IR格式

我們成功下載了PyTorch模型,但推理引擎無法直接加載,因此我們需要進(jìn)行模型轉(zhuǎn)換。模型轉(zhuǎn)換器的作用是將非IR格式的模型轉(zhuǎn)換為IR格式。通過指定、顯示和運(yùn)行Model Converter命令,將模型轉(zhuǎn)換為IR格式。如果輸出的最后幾行包括[ SUCCESS ] Generated IR version 10 model。

圖2-77 model-tool 模型轉(zhuǎn)換命令

convert_command?=?f"omz_converter?--name?{model_name}?--precisions?{precision}?--download_dir?{base_model_dir}?--output_dir?{base_model_dir}"

display(Markdown(f"Convert?command:?`{convert_command}`"))

display(Markdown(f"Converting?{model_name}..."))

!?$convert_command

在前面的小節(jié)中,在處理PyTorch模型時(shí)需要先轉(zhuǎn)為ONNX,然后在運(yùn)行模型優(yōu)化器將ONNX模型轉(zhuǎn)為IR模型,此處我們使用模型轉(zhuǎn)換器這一命令,可以完成全部操作,加快了開發(fā)進(jìn)度。

圖2-78 model-tool 模型轉(zhuǎn)換結(jié)果

通過輸出結(jié)果我們不難發(fā)現(xiàn),模型轉(zhuǎn)換器為我們自動(dòng)執(zhí)行了模型轉(zhuǎn)換以及模型優(yōu)化工作,這也是Open Model Zoo提供的便捷命令。當(dāng)然我們也可以需要自行修改參數(shù)分步執(zhí)行。

接下來,info dumper功能查看下我們得到的模型信息。

6、 獲取模型信息

圖2-78 model-tool 獲取模型信息

model_info_output?=?%sx?omz_info_dumper?--name?$model_name

model_info?=?json.loads(model_info_output.get_nlstr())

if?len(model_info)?>?1:

NotebookAlert(

f"There?are?multiple?IR?files?for?the?{model_name}?model.?The?first?model?in?the?"

"omz_info_dumper?output?will?be?used?for?benchmarking.?Change?"

"`selected_model_info`?in?the?cell?below?to?select?a?different?model?from?the?list.",

"warning",

)

model_info

Info Dumper會(huì)打印出Open Model Zoo模型的下列信息。

模型名稱

描述

用來訓(xùn)練模型的框架

許可證網(wǎng)址

模型所支持的精確性

子目錄:下載模型的位置

任務(wù)類型

這些信息可以通過在終端運(yùn)行omz_info_dumper --name model_name來顯示。這些信息也可以被解析并在腳本中使用。

圖2-78 model-tool info_dumper輸出結(jié)果

現(xiàn)在,我們有了可以執(zhí)行推理的模型,接下來我們使用benchmark工具進(jìn)行基準(zhǔn)性能測(cè)試,來驗(yàn)證我們模型轉(zhuǎn)換的效果。

 

7、 運(yùn)行基準(zhǔn)測(cè)試工具

默認(rèn)情況下,Benchmark Tool在CPU上以異步模式運(yùn)行推理60秒。它以延遲(每幅圖像毫秒)和吞吐量(每秒幀數(shù))的形式返回推理速度。

圖2-78 model-tool benchmark_app輸出結(jié)果

 

用Benchmark工具,我們可以準(zhǔn)確跟蹤到每一步執(zhí)行所耗時(shí)間以及最終的統(tǒng)計(jì)時(shí)間,便于我們更好的優(yōu)化模型及優(yōu)化程序。此外我們還可以利用基準(zhǔn)測(cè)試工具提供的擴(kuò)展參數(shù),進(jìn)行不同的測(cè)試配置,例如指定推理設(shè)備、指定運(yùn)行推理時(shí)間、指定同步或一步執(zhí)行方式以及設(shè)置批量大小等等,通過設(shè)置不同參數(shù)組合,對(duì)模型進(jìn)行多維度測(cè)試。下面的單元格顯示了一些benchmark_app與不同參數(shù)的例子。一些有用的參數(shù)是。

-d 用于推理的設(shè)備。例如。cpu, gpu, multi. 默認(rèn)值。CPU

-t 運(yùn)行推理的時(shí)間,以秒數(shù)計(jì)。默認(rèn)值:60

-api 使用異步(async)或同步(sync)推理。默認(rèn)值:async

-b 批量大小。默認(rèn)值:1

圖2-78 model-tool benchmark輸出

def?benchmark_model(model,?device="CPU",?seconds=60,?api="async",?batch=1):

ie?=?IECore()

 

if?("GPU"?in?device)?and?("GPU"?not?in?ie.available_devices):

DeviceNotFoundAlert("GPU")

else:

benchmark_command?=?f"benchmark_app?-m?{model_path}?-d?{device}?-t?{seconds}?-api?{api}?-b?{batch}"

display(Markdown(f"**Benchmark?{model_name}?with?{device}?for?{seconds}?seconds?with?{api}?inference**"))

display(Markdown(f"Benchmark?command:?`{benchmark_command}`"))

 

benchmark_output?=?%sx?$benchmark_command

benchmark_result?=?[line?for?line?in?benchmark_output?if?not?(line.startswith(r"[")?or?line.startswith("??")?or?line=="")]

print("n".join(benchmark_result))

ie?=?IECore()

for?device?in?ie.available_devices:

device_name?=?ie.get_metric(device,?"FULL_DEVICE_NAME")

print(f"{device}:?{device_name}")

benchmark_model(model_path,?device="CPU",?seconds=15,?api="async")

benchmark_model(model_path,?device="AUTO",?seconds=15,?api="async")

benchmark_model(model_path,?device="GPU",?seconds=15,?api="async")

在筆記中我們指定了CPU設(shè)備,指定異步處理,推理時(shí)間15秒,批量設(shè)置為1,得到了測(cè)試結(jié)果。由于測(cè)試設(shè)備中并沒有進(jìn)行GPU配置,因此沒有得到GPU推理的參考結(jié)果。

2.3.5? ?小結(jié)

通過本節(jié)學(xué)習(xí)我們掌握了模型優(yōu)化器的使用;掌握了如何將tensorflow、PyTorch、PaddlePaddle模型轉(zhuǎn)化為OpenVINO??IR模型;此外,我們也學(xué)習(xí)了如何利用模型下載器從Open Model Zoo開放模型庫(kù)下載模型,以及使用模型轉(zhuǎn)化器將下載的模型轉(zhuǎn)換為推理引擎支持的IR模型。最后我們也學(xué)習(xí)了利用Benchmark基準(zhǔn)測(cè)試工具對(duì)模型進(jìn)行基準(zhǔn)測(cè)試,為優(yōu)化模型以及優(yōu)化程序提供參考。

2.4 本章小結(jié)

通過本章學(xué)習(xí)相信大家已經(jīng)掌握了OpenVINO??推理引擎以及模型優(yōu)化器的使用,通過多個(gè)筆記實(shí)操,相信大家也熟練掌握了利用OpenVINO? 快速開發(fā)人工智能應(yīng)用的精髓:使用模型優(yōu)化器準(zhǔn)備模型,對(duì)需要推理的圖片進(jìn)行預(yù)處理以滿足模型輸入的需要,使用推理引擎執(zhí)行推理獲得結(jié)果,最后對(duì)推理結(jié)果進(jìn)行可視化操作以便于查看。

通過實(shí)訓(xùn)相信大家也認(rèn)識(shí)了分類模型、文字檢測(cè)模型、語義分割模型的使用。在下一章我們繼續(xù)實(shí)戰(zhàn),用OpenVINO??工具包開發(fā)更復(fù)雜、更有趣的應(yīng)用,同時(shí),我們也會(huì)學(xué)習(xí)從訓(xùn)練到推理的人工智能全流程開發(fā),并借助OpenVINO? 對(duì)訓(xùn)練結(jié)果進(jìn)行性能優(yōu)化。

《下篇》將于下周更新。

英特爾

英特爾

英特爾在云計(jì)算、數(shù)據(jù)中心、物聯(lián)網(wǎng)和電腦解決方案方面的創(chuàng)新,為我們所生活的智能互連的數(shù)字世界提供支持。

英特爾在云計(jì)算、數(shù)據(jù)中心、物聯(lián)網(wǎng)和電腦解決方案方面的創(chuàng)新,為我們所生活的智能互連的數(shù)字世界提供支持。收起

查看更多

相關(guān)推薦

登錄即可解鎖
  • 海量技術(shù)文章
  • 設(shè)計(jì)資源下載
  • 產(chǎn)業(yè)鏈客戶資源
  • 寫文章/發(fā)需求
立即登錄

英特爾致力于加快智能設(shè)備的開發(fā)和部署,通過智能多層系統(tǒng)和端到端分析,在智能駕駛、智能零售、智能安防、智能制造等領(lǐng)域,推動(dòng)企業(yè)業(yè)務(wù)轉(zhuǎn)型,改善人們的生活和工作方式,英特爾驅(qū)動(dòng)物聯(lián)網(wǎng)變革。