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

OpenVINO? Notebooks教程-中篇

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

第二章?OpenVINO? 的核心組件

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

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

2.1、核心組件與工作流程

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

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

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

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

圖2-1? 先導步驟準備模型

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

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

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

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

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

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

source $HOME/openvino_env/bin/activate

jupyter-lab openvino_notebooks/notebooks

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

2.2 推力引擎詳解

2.1.1 Hello World

學習目標:

認識OpenVINO? 推理引擎

掌握使用推理引擎基礎步驟

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

Hello World,Hello OpenVINO? ??吹紿ello World,這代表將會用最簡潔的代碼展示將要學習的內(nèi)容,我們開始操練。

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

圖2-5? hello-world筆記

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

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

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

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

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

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

1、導入程序所需要的python模塊

圖2-9 hello-world導入模塊

import?json

import?cv2

import?matplotlib.pyplot?as?plt

import?numpy?as?np

from?openvino.inference_engine?import?IECore

認識新模塊:

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

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

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

numpy(Numerical Python)是一個開源的數(shù)值計算擴展。這個工具可用來存儲和處理大型矩陣,支持大量的維度數(shù)組與矩陣運算,此外也針對數(shù)組運算提供大量的數(shù)學函數(shù)庫。

OpenVINO? .inference_engine 推理引擎模塊

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

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

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

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研究者們設計的一類卷積神經(jīng)網(wǎng)絡,模型具有計算消耗小、運行速度快、運行效果準的特點,非常適合在移動設備上運行。

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庫默認讀取圖片的格式為BGR,mobilenetv3需要輸入的色彩空間為RGB,因此在讀出圖片后需要進行色彩空間轉(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文件中的類名進行匹配,具有更好的可讀性。

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

2.2.2? ?推理引擎API詳解

學習目標:

掌握推理引擎API使用

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

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

加載推理引擎及信息顯示

加載不同模型

IR模型

ONNX模型

獲取模型信息

模型輸入

模型輸出

使用模型進行推理

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

改變圖像大小

改變批量大小

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

1、 導入模塊并初始化引擎

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

from?openvino.inference_engine?import?IECore

ie?=?IECore()

2、 查詢支持的硬件設備并顯示

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

devices?=?ie.available_devices

for?device?in?devices:

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

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

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

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()將其加載到指定設備上。IR模型IR(Intermediate Representation)模型由一個包含模型信息的.xml文件和一個包含權(quán)重的.bin文件組成。read_network()希望權(quán)重文件與xml文件位于同一目錄下,文件名相同,擴展名為.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、 獲取關于模型的信息

OpenVINO??IENetwork實例存儲了關于模型的信息。關于模型的輸入和輸出的信息在net.input_info和net.output中。這些也是ExecutableNetwork實例的屬性。在下面的單元格中我們使用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

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

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

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

input_layer

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

圖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ù)的批量大?。∟)為1,3個通道(C),圖像的高度(H)和寬度(W)為224。預計輸入數(shù)據(jù)的精度為FP32(浮點)。

5、 模型輸出

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

圖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}")

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

6、 使用模型進行推理

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

1) 準備工作:加載網(wǎng)絡

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

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) 準備工作:加載圖像并轉(zhuǎn)換為輸入形狀。

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

圖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個顏色通道。我們得到一個網(wǎng)絡期望的高度和寬度的參考,并調(diào)整到這個尺寸

圖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)絡所期望的。它仍然是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) 進行推理

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

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

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

result

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

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

output?=?result[output_layer]

output.shape

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

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

調(diào)整圖像大小

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

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

 

改變批處理大小

我們也可以使用.reshape()來設置批量大小,通過增加_new_shape_的第一個元素。例如,要設置2個批次的大小,在上面的單元格中設置new_shape = (2,3,544,544)。如果你只想改變批量大小,你也可以直接設置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}")

輸出顯示,通過設置批量大小為2,輸入和輸出形狀的第一個元素(N)現(xiàn)在的值為2。讓我們看看如果我們將輸入圖像通過網(wǎng)絡傳播會發(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)絡輸出將有2的批次大小,即使只有一個圖像通過網(wǎng)絡傳播。不管批次大小如何,你總是可以在一個圖像上做推理。在這種情況下,只有第一個網(wǎng)絡輸出包含有意義的信息。通過創(chuàng)建批次大小為2的隨機數(shù)據(jù)來驗證對兩幅圖像的推理是否有效。

圖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}")

通過上面的學習,我們可以總結(jié)出使用推理引擎進行推理的流程,我們只要按照流程步驟進行編程便可得到結(jié)果。我們再來回顧下完整流程,在后續(xù)的章節(jié)中我們會通過不同的案例不斷練習這個流程,直至熟練掌握:

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

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

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

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

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

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

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

2.3.3? ?Hello Segmentation

學習目標:

鞏固學習推理引擎API

掌握推理引擎使用流程

認識道路分割模型

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

1、 導入模塊

圖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 模塊提供訪問解釋器使用或維護的變量,和與解釋器進行交互的函數(shù)。通俗來講,sys 模塊為程序與 Python 解釋器的交互,提供了一系列的函數(shù)和變量,用于操控 Python 運行時的環(huán)境。sys 模塊是 Python 中內(nèi)置的模塊,所以不需要再單獨安裝,只需在使用前 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)絡模型、加載網(wǎng)絡、配置輸入輸出的操作。

3、 加載圖像

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

圖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)絡模型輸入需要調(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、 準備數(shù)據(jù)可視化

圖2-37 hello-segmentation可視化準備

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ù)進行圖像色彩空間轉(zhuǎn)換,創(chuàng)建帶有掩膜的圖像。下一步進行數(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ù)可視化我們得到了原始圖像,分割圖像以及原始圖像與分割圖像進行疊加的圖像,可以更直觀的展示推理結(jié)果。

2.2.4? ?Hello Detection

本節(jié)目標:

強化學習推理引擎API

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

了解文本檢測模型

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

下面我們開始練習。

1、 導入所需模塊

圖2-39 hello-detection導入模塊

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)絡模型

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

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)絡模型讀取、網(wǎng)絡加載、輸入輸出配置工作。與前幾節(jié)代碼相比,代碼中加入了條件判斷來確定是否包含需要的模型文件,如果沒有文件則需要先行下載,代碼加入的目的是讓程序更為健壯。

3、加載并處理圖片

圖2-41 hello-detection圖片預處理

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ù)要求對圖像進行處理以滿足網(wǎng)絡模型輸入要求,最終顯示圖像。

 

4、進行推理

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

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é)學習我們掌握了推理引擎API函數(shù)、掌握了使用推理引擎進行開發(fā)的完整流程,同時通過案例我們學習了Mobilenetv3分類模型、基于PyTorch框架的道路分割模型以及文本檢測模型。

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

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

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

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

改變格式

削減部分網(wǎng)絡

支持自定義層

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

生成文件為IR中間層

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

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

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

學習目標:

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

1、 導入模塊

圖2-44 tensorflow-to-OpenVINO??導入模塊

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

認識新模塊

pathlib 是python自帶的用于處理文件路徑的模塊,使用pathlib可以創(chuàng)建路徑對象。使用路徑對象而不是字符串的一個重要優(yōu)點是,我們可以在路徑對象上調(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。模型被保存到當前目錄。我們將平均值添加到模型中,并通過--scale_values將輸出與標準偏差進行縮放。有了這些選項,在通過網(wǎng)絡傳播之前,沒有必要對輸入數(shù)據(jù)進行標準化處理。原始模型希望輸入的圖像是RGB格式的。轉(zhuǎn)換后的模型也希望是RGB格式的圖像。如果你想讓轉(zhuǎn)換后的模型適用于BGR圖像,你可以使用--反轉(zhuǎn)輸入通道選項。參見模型優(yōu)化器開發(fā)者指南以了解更多關于模型優(yōu)化器的信息,包括命令行選項的描述。查看模型文檔,了解有關模型的信息,包括輸入形狀、預期顏色順序和平均值。

圖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)化過程會花一些時間,根據(jù)運行設備不同時間會有差異。當我們看到輸出結(jié)果的最后幾行包括`[ SUCCESS ] Generated IR version 10 model.`則模型優(yōu)化是成功的。同時我們在model文件夾可以看到新生成的xml及bin文件。

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

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

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)絡需要的格式

圖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) 性能測試

測量在一千張圖片上進行推理所需的時間。以便于顯示出模型優(yōu)化后的性能。對于更精確的基準測試,請使用OpenVINO? 基準測試工具。我們在后面的章節(jié)會學習如何使用OpenVINO? Benchmark進行基準測試。

圖2-52 tensorflow-to-OpenVINO? 性能測試結(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模型,并完成了推理及簡單的性能測試。

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

學習目標:

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

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

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

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

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

我們開始實操練習

1、 導入模塊

圖2-53 pytorch-onnx-to-OpenVINO? 導入模塊

由于安裝命令是依賴網(wǎng)絡將軟件包下載至本地環(huán)境,網(wǎng)絡環(huán)境不同所用安裝時間不盡相同,若網(wǎng)絡順暢,我們終將順利迎來安裝成功的提示。至此,環(huán)境安裝成功,我們已經(jīng)具備了運行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

認識新模塊:

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

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

fastseg fastseg算法模型模塊

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

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

圖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")

設置圖片高度為1024,設置存儲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預訓練模型存儲在model文件夾中。這是我們在開發(fā)應用中用到的獲取模型方式之一,在后續(xù)章節(jié)中我們還將介紹如何利用OpenVINO? Model Zoo開放模型庫獲取模型。

4、 將PyTorch模型導出為ONNX格式

我們使用torch模塊onnx.export功能將PyTorch模型轉(zhuǎn)換為ONNX模型,如果在輸出顯示一些警告,我們可以忽略。如果輸出的最后一行顯示 "ONNX模型導出到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。模型被保存到當前目錄。我們在模型中加入平均值,并用--scale_values對輸出的標準偏差進行縮放。有了這些選項,在通過網(wǎng)絡傳播之前,沒有必要對輸入數(shù)據(jù)進行標準化。執(zhí)行這個命令可能需要一些時間。輸出中可能有一些錯誤或警告。如果輸出的最后幾行包括[ SUCCESS ] 生成了IR版本10模型,則模型優(yōu)化是成功的。

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

圖2-57 pytorch-onnx-to-OpenVINO? 準備模型優(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、 模型對比

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

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

對于OpenVINO??模型,歸一化被移到模型中。對于ONNX和PyTorch模型,圖像在通過網(wǎng)絡傳播之前需要進行標準化處理。

圖2-59 pytorch-onnx-to-OpenVINO? 圖片預處理

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模型進行推理驗證

推理引擎可以直接加載ONNX模型。我們首先加載ONNX模型,進行推理并顯示結(jié)果。之后,我們加載用模型優(yōu)化器轉(zhuǎn)換為中間表征(IR)的模型,對該模型進行推理并顯示結(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模型進行推理

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

 

PyTorch原始模型推理

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

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

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

1)???? 性能比較

測量在五幅圖像上進行推理所需的時間,給出簡版的性能的對比。

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

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}"

)

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

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

學習目標:

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

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

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

模型來源是:

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

1、 導入模塊

圖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}")

認識新模塊:

time 用于時間處理的模塊

paddlehub paddlepaddle框架提供的預訓練模型庫

Python 是交互式shell庫,支持變量自動補全、自動縮進以及多種功能函數(shù)

paddle PaddlePaddle飛槳模型模塊

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

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

2、 PaddlePaddle飛槳模型下載配置

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

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

IMAGE_FILENAME?=?"coco_close.png"

MODEL_NAME?=?"mobilenet_v3_large_imagenet_ssld"

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

3、 PaddlePaddle模型推理

我們從PaddleHub加載并下載模型,讀取并顯示一幅圖像,對該圖像進行推理,并顯示前三個預測結(jié)果。第一次運行時,我們會從PaddleHub下載所需要的模型

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

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

我們通過process_image()函數(shù)查看PaddlePaddle的分類函數(shù)以及加載和預處理數(shù)據(jù)的實現(xiàn),可以看到裁剪和調(diào)整大小的效果。由于歸一化,顏色看起來會很奇怪,而且matplotlib會對剪裁值發(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) 準備工作

PaddlePaddle的MobileNet模型包含了關于輸入形狀、平均值和比例值的信息,我們可以用它來轉(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,詳細信息請參考(https://github.com/PaddlePaddle/paddle2onnx)執(zhí)行完成后我們在model文件夾得到了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。這些模型被保存到當前目錄中。我們可以用--mean_values將均值添加到模型中,用--scale_values將輸出與標準差進行縮放。有了這些選項,在通過網(wǎng)絡傳播之前,沒有必要對輸入數(shù)據(jù)進行標準化處理。然而,為了得到與PaddlePaddle模型完全相同的輸出,有必要以同樣的方式對圖像進行預處理。因此,在本教程中,我們不向模型添加平均值和比例值,我們使用process_image函數(shù),如上節(jié)所述,以確保IR和PaddlePaddle模型使用相同的預處理方法。

圖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) 使用推理引擎進行推理

加載IR模型,獲取模型信息,加載圖像,進行推理,將推理結(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ōu)化流程是成功的。

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

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

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

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

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

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

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

學習目標:

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

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

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

關于Open Model Zoo開放模型庫的工具

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

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

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

信息挖掘器 omz_info_dumper ?? 打印關于Open Model Zoo模型的信息。

基準測試工具benchmark_app ??? 通過計算推理時間對模型性能進行基準測試。

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

1、 準備工作

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

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

圖2-73 model-tool 設置模型名稱

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

model_name?=?"mobilenet-v2-pytorch"

2、 導入模塊

圖2-74 model-tool 導入模塊

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

認識新模塊:

subprocess 模塊允許我們啟動一個新進程,并連接到它們的輸入/輸出/錯誤管道,從而獲取返回值

3、 環(huán)境配置

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

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

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

omz_cache_dir: Open Model Zoo的緩存文件夾。對于模型下載器和模型轉(zhuǎn)換器來說,指定一個緩存目錄不是必須的,但它可以加速后續(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下載模型

指定、顯示和運行模型下載器命令以下載模型

圖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

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

 

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

我們成功下載了PyTorch模型,但推理引擎無法直接加載,因此我們需要進行模型轉(zhuǎn)換。模型轉(zhuǎn)換器的作用是將非IR格式的模型轉(zhuǎn)換為IR格式。通過指定、顯示和運行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模型時需要先轉(zhuǎn)為ONNX,然后在運行模型優(yōu)化器將ONNX模型轉(zhuǎn)為IR模型,此處我們使用模型轉(zhuǎn)換器這一命令,可以完成全部操作,加快了開發(fā)進度。

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

通過輸出結(jié)果我們不難發(fā)現(xiàn),模型轉(zhuǎn)換器為我們自動執(zhí)行了模型轉(zhuǎn)換以及模型優(yōu)化工作,這也是Open Model Zoo提供的便捷命令。當然我們也可以需要自行修改參數(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會打印出Open Model Zoo模型的下列信息。

模型名稱

描述

用來訓練模型的框架

許可證網(wǎng)址

模型所支持的精確性

子目錄:下載模型的位置

任務類型

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

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

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

 

7、 運行基準測試工具

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

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

 

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

-d 用于推理的設備。例如。cpu, gpu, multi. 默認值。CPU

-t 運行推理的時間,以秒數(shù)計。默認值:60

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

-b 批量大小。默認值: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設備,指定異步處理,推理時間15秒,批量設置為1,得到了測試結(jié)果。由于測試設備中并沒有進行GPU配置,因此沒有得到GPU推理的參考結(jié)果。

2.3.5? ?小結(jié)

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

2.4 本章小結(jié)

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

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

《下篇》將于下周更新。

英特爾

英特爾

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

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

查看更多

相關推薦

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

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