OpenVINO™ ランタイム API チュートリアル

この Jupyter ノートブックはオンラインで起動でき、ブラウザーのウィンドウで対話型環境を開きます。ローカルにインストールすることもできます。次のオプションのいずれかを選択します。

Binder Google Colab GitHub

このノートブックでは、OpenVINO ランタイム API の基本について説明します。

ノートブックはヘッダーとセクションに分かれています。次のセルには、インストールとインポートのグローバル要件が含まれています。各セクションはスタンドアロンであり、前のセクションに依存しません。このチュートリアルで使用されるすべてのモデルは、あくまで例として提供されています。これらのモデルファイルは独自のモデルに置き換えることができます。正確な出力は異なりますが、プロセスは同一です

目次

# Required imports. Please execute this cell first.
%pip install -q "openvino>=2023.1.0"
%pip install requests tqdm ipywidgets

# Fetch `notebook_utils` module
import urllib.request
urllib.request.urlretrieve(
    url='https://raw.githubusercontent.com/openvinotoolkit/openvino_notebooks/main/notebooks/utils/notebook_utils.py',
    filename='notebook_utils.py'
)

from notebook_utils import download_file
Note: you may need to restart the kernel to use updated packages.
Requirement already satisfied: requests in /opt/home/k8sworker/ci-ai/cibuilds/ov-notebook/OVNotebookOps-609/.workspace/scm/ov-notebook/.venv/lib/python3.8/site-packages (2.31.0)
Requirement already satisfied: tqdm in /opt/home/k8sworker/ci-ai/cibuilds/ov-notebook/OVNotebookOps-609/.workspace/scm/ov-notebook/.venv/lib/python3.8/site-packages (4.66.1)
Requirement already satisfied: ipywidgets in /opt/home/k8sworker/ci-ai/cibuilds/ov-notebook/OVNotebookOps-609/.workspace/scm/ov-notebook/.venv/lib/python3.8/site-packages (8.1.2)
Requirement already satisfied: charset-normalizer<4,>=2 in /opt/home/k8sworker/ci-ai/cibuilds/ov-notebook/OVNotebookOps-609/.workspace/scm/ov-notebook/.venv/lib/python3.8/site-packages (from requests) (3.3.2)
Requirement already satisfied: idna<4,>=2.5 in /opt/home/k8sworker/ci-ai/cibuilds/ov-notebook/OVNotebookOps-609/.workspace/scm/ov-notebook/.venv/lib/python3.8/site-packages (from requests) (3.6)
Requirement already satisfied: urllib3<3,>=1.21.1 in /opt/home/k8sworker/ci-ai/cibuilds/ov-notebook/OVNotebookOps-609/.workspace/scm/ov-notebook/.venv/lib/python3.8/site-packages (from requests) (2.2.0)
Requirement already satisfied: certifi>=2017.4.17 in /opt/home/k8sworker/ci-ai/cibuilds/ov-notebook/OVNotebookOps-609/.workspace/scm/ov-notebook/.venv/lib/python3.8/site-packages (from requests) (2024.2.2)
Requirement already satisfied: comm>=0.1.3 in /opt/home/k8sworker/ci-ai/cibuilds/ov-notebook/OVNotebookOps-609/.workspace/scm/ov-notebook/.venv/lib/python3.8/site-packages (from ipywidgets) (0.2.1)
Requirement already satisfied: ipython>=6.1.0 in /opt/home/k8sworker/ci-ai/cibuilds/ov-notebook/OVNotebookOps-609/.workspace/scm/ov-notebook/.venv/lib/python3.8/site-packages (from ipywidgets) (8.12.3)
Requirement already satisfied: traitlets>=4.3.1 in /opt/home/k8sworker/ci-ai/cibuilds/ov-notebook/OVNotebookOps-609/.workspace/scm/ov-notebook/.venv/lib/python3.8/site-packages (from ipywidgets) (5.14.1)
Requirement already satisfied: widgetsnbextension~=4.0.10 in /opt/home/k8sworker/ci-ai/cibuilds/ov-notebook/OVNotebookOps-609/.workspace/scm/ov-notebook/.venv/lib/python3.8/site-packages (from ipywidgets) (4.0.10)
Requirement already satisfied: jupyterlab-widgets~=3.0.10 in /opt/home/k8sworker/ci-ai/cibuilds/ov-notebook/OVNotebookOps-609/.workspace/scm/ov-notebook/.venv/lib/python3.8/site-packages (from ipywidgets) (3.0.10)
Requirement already satisfied: backcall in /opt/home/k8sworker/ci-ai/cibuilds/ov-notebook/OVNotebookOps-609/.workspace/scm/ov-notebook/.venv/lib/python3.8/site-packages (from ipython>=6.1.0->ipywidgets) (0.2.0)
Requirement already satisfied: decorator in /opt/home/k8sworker/ci-ai/cibuilds/ov-notebook/OVNotebookOps-609/.workspace/scm/ov-notebook/.venv/lib/python3.8/site-packages (from ipython>=6.1.0->ipywidgets) (5.1.1)
Requirement already satisfied: jedi>=0.16 in /opt/home/k8sworker/ci-ai/cibuilds/ov-notebook/OVNotebookOps-609/.workspace/scm/ov-notebook/.venv/lib/python3.8/site-packages (from ipython>=6.1.0->ipywidgets) (0.19.1)
Requirement already satisfied: matplotlib-inline in /opt/home/k8sworker/ci-ai/cibuilds/ov-notebook/OVNotebookOps-609/.workspace/scm/ov-notebook/.venv/lib/python3.8/site-packages (from ipython>=6.1.0->ipywidgets) (0.1.6)
Requirement already satisfied: pickleshare in /opt/home/k8sworker/ci-ai/cibuilds/ov-notebook/OVNotebookOps-609/.workspace/scm/ov-notebook/.venv/lib/python3.8/site-packages (from ipython>=6.1.0->ipywidgets) (0.7.5)
Requirement already satisfied: prompt-toolkit!=3.0.37,<3.1.0,>=3.0.30 in /opt/home/k8sworker/ci-ai/cibuilds/ov-notebook/OVNotebookOps-609/.workspace/scm/ov-notebook/.venv/lib/python3.8/site-packages (from ipython>=6.1.0->ipywidgets) (3.0.43)
Requirement already satisfied: pygments>=2.4.0 in /opt/home/k8sworker/ci-ai/cibuilds/ov-notebook/OVNotebookOps-609/.workspace/scm/ov-notebook/.venv/lib/python3.8/site-packages (from ipython>=6.1.0->ipywidgets) (2.17.2)
Requirement already satisfied: stack-data in /opt/home/k8sworker/ci-ai/cibuilds/ov-notebook/OVNotebookOps-609/.workspace/scm/ov-notebook/.venv/lib/python3.8/site-packages (from ipython>=6.1.0->ipywidgets) (0.6.3)
Requirement already satisfied: typing-extensions in /opt/home/k8sworker/ci-ai/cibuilds/ov-notebook/OVNotebookOps-609/.workspace/scm/ov-notebook/.venv/lib/python3.8/site-packages (from ipython>=6.1.0->ipywidgets) (4.9.0)
Requirement already satisfied: pexpect>4.3 in /opt/home/k8sworker/ci-ai/cibuilds/ov-notebook/OVNotebookOps-609/.workspace/scm/ov-notebook/.venv/lib/python3.8/site-packages (from ipython>=6.1.0->ipywidgets) (4.9.0)
Requirement already satisfied: parso<0.9.0,>=0.8.3 in /opt/home/k8sworker/ci-ai/cibuilds/ov-notebook/OVNotebookOps-609/.workspace/scm/ov-notebook/.venv/lib/python3.8/site-packages (from jedi>=0.16->ipython>=6.1.0->ipywidgets) (0.8.3)
Requirement already satisfied: ptyprocess>=0.5 in /opt/home/k8sworker/ci-ai/cibuilds/ov-notebook/OVNotebookOps-609/.workspace/scm/ov-notebook/.venv/lib/python3.8/site-packages (from pexpect>4.3->ipython>=6.1.0->ipywidgets) (0.7.0)
Requirement already satisfied: wcwidth in /opt/home/k8sworker/ci-ai/cibuilds/ov-notebook/OVNotebookOps-609/.workspace/scm/ov-notebook/.venv/lib/python3.8/site-packages (from prompt-toolkit!=3.0.37,<3.1.0,>=3.0.30->ipython>=6.1.0->ipywidgets) (0.2.13)
Requirement already satisfied: executing>=1.2.0 in /opt/home/k8sworker/ci-ai/cibuilds/ov-notebook/OVNotebookOps-609/.workspace/scm/ov-notebook/.venv/lib/python3.8/site-packages (from stack-data->ipython>=6.1.0->ipywidgets) (2.0.1)
Requirement already satisfied: asttokens>=2.1.0 in /opt/home/k8sworker/ci-ai/cibuilds/ov-notebook/OVNotebookOps-609/.workspace/scm/ov-notebook/.venv/lib/python3.8/site-packages (from stack-data->ipython>=6.1.0->ipywidgets) (2.4.1)
Requirement already satisfied: pure-eval in /opt/home/k8sworker/ci-ai/cibuilds/ov-notebook/OVNotebookOps-609/.workspace/scm/ov-notebook/.venv/lib/python3.8/site-packages (from stack-data->ipython>=6.1.0->ipywidgets) (0.2.2)
Requirement already satisfied: six>=1.12.0 in /opt/home/k8sworker/ci-ai/cibuilds/ov-notebook/OVNotebookOps-609/.workspace/scm/ov-notebook/.venv/lib/python3.8/site-packages (from asttokens>=2.1.0->stack-data->ipython>=6.1.0->ipywidgets) (1.16.0)
Note: you may need to restart the kernel to use updated packages.

OpenVINO ランタイムのロードと情報の表示

ov.Core() で OpenVINO ランタイムを初期化します。

import openvino as ov

core = ov.Core()

OpenVINO ランタイムは、デバイスにネットワークをロードできます。ここでデバイスとは、CPU、インテル® GPU、ニューラル・コンピュート・スティック 2 などを意味します。 available_devices プロパティーは、システムで使用可能なデバイスを示します。core.get_property() の “FULL_DEVICE_NAME” オプションはデバイスの名前を表示します。

このノートブックでは、CPU デバイスが使用されます。統合 GPU を使用する場合、代わりに device_name="GPU" を指定します。GPU でのネットワークのロードは CPU ネットワークのロードよりも遅くなりますが、推論は高速になる可能性があることに留意してください。

devices = core.available_devices

for device in devices:
    device_name = core.get_property(device, "FULL_DEVICE_NAME")
    print(f"{device}: {device_name}")
CPU: Intel(R) Core(TM) i9-10920X CPU @ 3.50GHz

モデルのロード

OpenVINO ランタイムを初期化した後、まず read_model() でモデルファイルを読み取り、次に compile_model() メソッドで指定したデバイスにコンパイルします。

OpenVINO™ はいくつかのモデル形式をサポートしており、開発者はこのタスク専用のツールを使用してモデル形式を独自の OpenVINO IR 形式に変換できます。

OpenVINO IR モデル

OpenVINO IR (中間表現) モデルは、ネットワーク・トポロジーに関する情報を含む .xml ファイルと、重みとバイアスのバイナリ ーデータを含む .bin ファイルで構成されます。OpenVINO IR 形式のモデルは、モデル変換 API を使用して取得されます。read_model() 関数は、重みファイル .bin が同じファイル名を持ち、.xml ファイルと同じディレクトリーに配置されていることを想定しています: model_weights_file == Path(model_xml).with_suffix(".bin")。この場合、重みファイルの指定はオプションです。重みファイルのファイル名が異なる場合は、read_model()weights パラメーターで指定できます。

OpenVINO モデル変換 API ツールは、モデルを OpenVINO IR 形式に変換するために使用されます。モデル変換 API は元のモデルを読み取り、OpenVINO IR モデル (.xml および .bin) 作成のため、形式変換による遅延なく推論を実行できます。オプションで、モデル変換 API は、入力形状を交互に変更したり、前処理を埋め込んだり、トレーニング部分を切り取ったりすることで、モデルを推論により適したものに調整できます。モデル変換 API を使用して既存の TensorFlow、PyTorch、または ONNX モデルを OpenVINO IR 形式に変換する方法は、tensorflow-to-openvino および pytorch-onnx-to-openvino のノートブックを参照してください。

ir_model_url = 'https://storage.openvinotoolkit.org/repositories/openvino_notebooks/models/002-example-models/'
ir_model_name_xml = 'classification.xml'
ir_model_name_bin = 'classification.bin'

download_file(ir_model_url + ir_model_name_xml, filename=ir_model_name_xml, directory='model')
download_file(ir_model_url + ir_model_name_bin, filename=ir_model_name_bin, directory='model')
model/classification.xml:   0%|          | 0.00/179k [00:00<?, ?B/s]
model/classification.bin:   0%|          | 0.00/4.84M [00:00<?, ?B/s]
PosixPath('/opt/home/k8sworker/ci-ai/cibuilds/ov-notebook/OVNotebookOps-609/.workspace/scm/ov-notebook/notebooks/002-openvino-api/model/classification.bin')
import openvino as ov

core = ov.Core()
classification_model_xml = "model/classification.xml"

model = core.read_model(model=classification_model_xml)
compiled_model = core.compile_model(model=model, device_name="CPU")

ONNX モデル

ONNX は、マシンラーニング・モデルを表現するために構築されたオープン形式です。ONNX は、マシンラーニングおよびディープラーニング・モデルの構成要素であるオペレーターの共通セットと、AI 開発者がさまざまなフレームワーク、ツール、ランタイム、コンパイラーでモデルを使用できるようにする共通のファイル形式を定義します。OpenVINO は、ONNX 形式のモデルの直接読み取りをサポートしています。つまり、事前に変換することなく OpenVINO ランタイムで使用できます。

単一の .onnx ファイルである ONNX モデルの読み取りとロードは、OpenVINO IR モデルと同じように機能します。model 引数は、ONNX モデルのファイル名を指します。

onnx_model_url = 'https://storage.openvinotoolkit.org/repositories/openvino_notebooks/models/002-example-models/segmentation.onnx'
onnx_model_name = 'segmentation.onnx'

download_file(onnx_model_url, filename=onnx_model_name, directory='model')
model/segmentation.onnx:   0%|          | 0.00/4.41M [00:00<?, ?B/s]
PosixPath('/opt/home/k8sworker/ci-ai/cibuilds/ov-notebook/OVNotebookOps-609/.workspace/scm/ov-notebook/notebooks/002-openvino-api/model/segmentation.onnx')
import openvino as ov

core = ov.Core()
onnx_model_path = "model/segmentation.onnx"

model_onnx = core.read_model(model=onnx_model_path)
compiled_model_onnx = core.compile_model(model=model_onnx, device_name="CPU")

ONNX モデルは、save_model() を使用して OpenVINO IR にエクスポートできます。

ov.save_model(model_onnx, output_model="model/exported_onnx_model.xml")

PaddlePaddle モデル

推論用に保存された PaddlePaddle モデルは、変換なしで OpenVINO ランタイムに渡すこともできます。拡張子付きのファイル名を read_model に渡し、save_model で OpenVINO IR をエクスポートしました。

paddle_model_url = 'https://storage.openvinotoolkit.org/repositories/openvino_notebooks/models/002-example-models/'
paddle_model_name = 'inference.pdmodel'
paddle_params_name = 'inference.pdiparams'

download_file(paddle_model_url + paddle_model_name, filename=paddle_model_name, directory='model')
download_file(paddle_model_url + paddle_params_name, filename=paddle_params_name, directory='model')
model/inference.pdmodel:   0%|          | 0.00/1.03M [00:00<?, ?B/s]
model/inference.pdiparams:   0%|          | 0.00/21.0M [00:00<?, ?B/s]
PosixPath('/opt/home/k8sworker/ci-ai/cibuilds/ov-notebook/OVNotebookOps-609/.workspace/scm/ov-notebook/notebooks/002-openvino-api/model/inference.pdiparams')
import openvino as ov

core = ov.Core()
paddle_model_path = 'model/inference.pdmodel'

model_paddle = core.read_model(model=paddle_model_path)
compiled_model_paddle = core.compile_model(model=model_paddle, device_name="CPU")
ov.save_model(model_paddle, output_model="model/exported_paddle_model.xml")

TensorFlow モデル

凍結グラフ形式で保存された TensorFlow モデルも read_model に渡すことができます。

pb_model_url = 'https://storage.openvinotoolkit.org/repositories/openvino_notebooks/models/002-example-models/classification.pb'
pb_model_name = 'classification.pb'

download_file(pb_model_url, filename=pb_model_name, directory='model')
model/classification.pb:   0%|          | 0.00/9.88M [00:00<?, ?B/s]
PosixPath('/opt/home/k8sworker/ci-ai/cibuilds/ov-notebook/OVNotebookOps-609/.workspace/scm/ov-notebook/notebooks/002-openvino-api/model/classification.pb')
import openvino as ov

core = ov.Core()
tf_model_path = "model/classification.pb"

model_tf = core.read_model(model=tf_model_path)
compiled_model_tf = core.compile_model(model=model_tf, device_name="CPU")
ov.save_model(model_tf, output_model="model/exported_tf_model.xml")

TensorFlow Lite モデル

推論用に保存された TFLite モデルを OpenVINO ランタイムに渡すこともできます。拡張子 .tflite が付いたファイル名を read_model に渡し、save_model で OpenVINO IR をエクスポートしました。

このチュートリアルでは、画像分類モデル inception_v4_quant を使用しています。これは、TensorFlow Lite で動作するように最適化された事前トレーニング済みモデルです。

from pathlib import Path

tflite_model_url = 'https://www.kaggle.com/models/tensorflow/inception/frameworks/tfLite/variations/v4-quant/versions/1?lite-format=tflite'
tflite_model_path = Path('model/classification.tflite')

download_file(tflite_model_url, filename=tflite_model_path.name, directory=tflite_model_path.parent)
model/classification.tflite:   0%|          | 0.00/40.9M [00:00<?, ?B/s]
PosixPath('/opt/home/k8sworker/ci-ai/cibuilds/ov-notebook/OVNotebookOps-609/.workspace/scm/ov-notebook/notebooks/002-openvino-api/model/classification.tflite')
import openvino as ov

core = ov.Core()

model_tflite = core.read_model(tflite_model_path)
compiled_model_tflite = core.compile_model(model=model_tflite, device_name="CPU")
ov.save_model(model_tflite, output_model="model/exported_tflite_model.xml")

PyTorch モデル

PyTorch モデルを core.read_model に直接渡すことはできません。このフレームワークのモデル・オブジェクトの ov.Model は、ov.convert_model を使用して取得できます。詳細については、pytorch-to-openvino ノートブックを参照してください。このチュートリアルでは、torchvision ライブラリーの resnet18 モデルを使用します。ov.convert_model を使用してモデルを変換した後、core.compile_model を使用してデバイス上でコンパイルするか、ov.save_model を使用して次回の使用に備えてディスクに保存できます。

import openvino as ov
import torch
from torchvision.models import resnet18, ResNet18_Weights

core = ov.Core()

pt_model = resnet18(weights=ResNet18_Weights.IMAGENET1K_V1)
example_input = torch.zeros((1, 3, 224, 224))
ov_model_pytorch = ov.convert_model(pt_model, example_input=example_input)

compiled_model_pytorch = core.compile_model(ov_model_pytorch, device_name="CPU")

ov.save_model(ov_model_pytorch, "model/exported_pytorch_model.xml")

モデルに関する情報の取得

OpenVINO Model インスタンスには、モデルに関する情報が保存されます。モデルの入力と出力に関する情報は、model.inputsmodel.outputs にあります。これらは CompiledModel インスタンスのプロパティーでもあります。以下のセルで model.inputsmodel.outputs を使用しているときに、compiled_model.inputscompiled_model.outputs を使用することもできます。

ir_model_url = 'https://storage.openvinotoolkit.org/repositories/openvino_notebooks/models/002-example-models/'
ir_model_name_xml = 'classification.xml'
ir_model_name_bin = 'classification.bin'

download_file(ir_model_url + ir_model_name_xml, filename=ir_model_name_xml, directory='model')
download_file(ir_model_url + ir_model_name_bin, filename=ir_model_name_bin, directory='model')
'model/classification.xml' already exists.
'model/classification.bin' already exists.
PosixPath('/opt/home/k8sworker/ci-ai/cibuilds/ov-notebook/OVNotebookOps-609/.workspace/scm/ov-notebook/notebooks/002-openvino-api/model/classification.bin')

モデルの入力

すべての入力レイヤーに関する情報は、inputs 辞書に保存されます。

import openvino as ov

core = ov.Core()
classification_model_xml = "model/classification.xml"
model = core.read_model(model=classification_model_xml)
model.inputs
[<Output: names[input, input:0] shape[1,3,224,224] type: f32>]

上のセルは、ロードされたモデルが input という名前の 1 つの入力を受け入れることを示しています。別のモデルをロードした場合、別の入力レイヤー名が表示され、さらに多くの入力が表示される場合があります。また、model.input(index) を使用して各入力レイヤーに関する情報を取得することもできます。ここで、index はモデル内の入力レイヤーの数値インデックスです。モデルの入力が 1 つだけの場合は、index を省略できます。

input_layer = model.input(0)

多くの場合、最初の入力レイヤー名への参照があると便利です。入力が 1 つのモデルの場合、model.input(0).any_name がこの名前を取得します。

input_layer.any_name
'input'

次のセルには、入力レイアウト、精度、形状が出力されます。

print(f"input precision: {input_layer.element_type}")
print(f"input shape: {input_layer.shape}")
input precision: <Type: 'float32'>
input shape: [1,3,224,224]

このセルは、モデルが [1,3,224,224] の形状の入力を予期していること、および NCHW レイアウトであることを示しています。これは、モデルがバッチサイズ 1 (N)、3 チャネル (C) の入力データ、および高さ (H) と幅 (W) が 224 に等しい画像を期待することを意味します。入力データは FP32 (浮動小数点) 精度であることが期待されます。

モデルの出力

import openvino as ov

core = ov.Core()
classification_model_xml = "model/classification.xml"
model = core.read_model(model=classification_model_xml)
model.outputs
[<Output: names[MobilenetV3/Predictions/Softmax] shape[1,1001] type: f32>]

モデルの出力情報は、model.outputs に保存されます。上のセルは、モデルが MobilenetV3/Predictions/Softmax という名前の 1 つの出力を返すことを示しています。別のモデルをロードすると、出力レイヤー名が異なり、さらに多くの出力が返される可能性があります。入力と同様に、model.output(index) を使用して各出力に関する情報を個別に取得することもできます。

このモデルの出力は 1 つであるため、入力レイヤーの場合と同じ方法に従って名前を取得します。

output_layer = model.output(0)
output_layer.any_name
'MobilenetV3/Predictions/Softmax'

出力の精度と形状の取得は、入力の精度と形状の取得と似ています。

print(f"output precision: {output_layer.element_type}")
print(f"output shape: {output_layer.shape}")
output precision: <Type: 'float32'>
output shape: [1,1001]

このセルは、モデルが [1, 1001] の形状の出力を返すことを示しています。ここで、1 はバッチサイズ (N)、1001 はクラス数 (C) です。出力は 32 ビット浮動小数点として返されます。

モデルの推論実行

注: このノートブックでは、基本的な同期推論 API のみを説明します。非同期推論の例については、非同期 API ノートブックを参照してください。

以下の図は、OpenVINO を使用した一般的な推論パイプラインを示しています。

image.png

image.png

OpenVINO コアの作成とモデルのコンパイルについては、前のステップで説明しています。次のステップは入力の準備です。サポートされる形式のいずれかで入力を指定できます。キーとして入力の名前を含む辞書と、値として入力テンソルを表す np.arrays、入力テンソルを表す np.arrays のリストまたはタプル (順序はモデル入力の順序と一致する必要があります) を指定します。モデルに単一の入力がある場合、辞書またはリストへのラップを省略できます。モデルで推論を行うには、core.compile_model を使用して取得したコンパイル済みモデル・オブジェクトに、準備された入力を渡します。推論結果は辞書として表され、キーはモデル出力であり、np.arrays は生成されたデータ値を表します。

# Install opencv package for image handling
%pip install -q opencv-python
Note: you may need to restart the kernel to use updated packages.

ネットワークのロード

ir_model_url = 'https://storage.openvinotoolkit.org/repositories/openvino_notebooks/models/002-example-models/'
ir_model_name_xml = 'classification.xml'
ir_model_name_bin = 'classification.bin'

download_file(ir_model_url + ir_model_name_xml, filename=ir_model_name_xml, directory='model')
download_file(ir_model_url + ir_model_name_bin, filename=ir_model_name_bin, directory='model')
'model/classification.xml' already exists.
'model/classification.bin' already exists.
PosixPath('/opt/home/k8sworker/ci-ai/cibuilds/ov-notebook/OVNotebookOps-609/.workspace/scm/ov-notebook/notebooks/002-openvino-api/model/classification.bin')
import openvino as ov

core = ov.Core()
classification_model_xml = "model/classification.xml"
model = core.read_model(model=classification_model_xml)
compiled_model = core.compile_model(model=model, device_name="CPU")
input_layer = compiled_model.input(0)
output_layer = compiled_model.output(0)

画像ロードして入力形状に変換

ネットワークを介して画像を伝播するには、画像を配列にロードし、ネットワークが期待する形状にサイズ変更して、ネットワークの入力レイアウトに変換する必要があります。

import cv2

image_filename = download_file(
    "https://storage.openvinotoolkit.org/repositories/openvino_notebooks/data/data/image/coco_hollywood.jpg",
    directory="data"
)
image = cv2.imread(str(image_filename))
image.shape
data/coco_hollywood.jpg:   0%|          | 0.00/485k [00:00<?, ?B/s]
(663, 994, 3)

画像の形状は (663,994,3) です。高さは 663 ピクセル、幅は 994 ピクセルで、3 つのカラーチャネルがあります。ネットワークによって期待される高さと幅への参照が取得され、画像のサイズがこれらの次元に変更されます。

# N,C,H,W = batch size, number of channels, height, width.
N, C, H, W = input_layer.shape
# OpenCV resize expects the destination size as (width, height).
resized_image = cv2.resize(src=image, dsize=(W, H))
resized_image.shape
(224, 224, 3)

これで、画像はネットワークが期待する幅と高さになりました。これはまだ HWC 形式であるため、NCHW 形式に変更する必要があります。まず、np.transpose() メソッドを呼び出して CHW に変更し、次に np.expand_dims() メソッドを呼び出して N 次元 (N= 1) を追加します。次に np.astype() メソッドで FP32 に変換します。

import numpy as np

input_data = np.expand_dims(np.transpose(resized_image, (2, 0, 1)), 0).astype(np.float32)
input_data.shape
(1, 3, 224, 224)

推論を行います

入力データが正しい形式になったので、推論を実行します。CompiledModel の推論結果は、キーが Output クラスのインスタンス (compiled_model.output(index) でも取得できる、compiled_model.outputs の同じキー) と、値は np.array 形式で予測された結果である辞書になります。

# for single input models only
result = compiled_model(input_data)[output_layer]

# for multiple inputs in a list
result = compiled_model([input_data])[output_layer]

# or using a dictionary, where the key is input tensor name or index
result = compiled_model({input_layer.any_name: input_data})[output_layer]

InferRequest を作成し、要求に応じて infer メソッドを実行することもできます。

request = compiled_model.create_infer_request()
request.infer(inputs={input_layer.any_name: input_data})
result = request.get_output_tensor(output_layer.index).data

.infer() 関数は、get_output_tensor() を使用して到達可能な出力テンソルを設定します。このネットワークは 1 つの出力を返し、出力レイヤーへの参照は output_layer.index パラメーターにあるため、request.get_output_tensor(output_layer.index) でデータを取得できます。出力から numpy 配列を取得するには、.data パラメーターを使用します。

result.shape
(1, 1001)

出力形状は (1,1001) で、これは予想される出力形状です。この形状は、ネットワークが 1001 クラスの確率を返すことを示しています。この概念の詳細は、hello world ノートブックを参照してください。

形状変更とサイズ変更

画像サイズの変更

モデルに合わせて画像を再形成する代わりに、画像に合わせてモデルを再形成することもできます。すべてのモデルが再形成をサポートしているわけではなく、サポートしているモデルでもすべての入力形状をサポートしているわけではないことに注意してください。モデルの入力形状を変更すると、モデルの精度が低下する可能性があります。

まずモデルの入力形状を確認し、それを新しい入力形状に再形状します。

ir_model_url = 'https://storage.openvinotoolkit.org/repositories/openvino_notebooks/models/002-example-models/'
ir_model_name_xml = 'segmentation.xml'
ir_model_name_bin = 'segmentation.bin'

download_file(ir_model_url + ir_model_name_xml, filename=ir_model_name_xml, directory='model')
download_file(ir_model_url + ir_model_name_bin, filename=ir_model_name_bin, directory='model')
model/segmentation.xml:   0%|          | 0.00/1.38M [00:00<?, ?B/s]
model/segmentation.bin:   0%|          | 0.00/1.09M [00:00<?, ?B/s]
PosixPath('/opt/home/k8sworker/ci-ai/cibuilds/ov-notebook/OVNotebookOps-609/.workspace/scm/ov-notebook/notebooks/002-openvino-api/model/segmentation.bin')
import openvino as ov

core = ov.Core()
segmentation_model_xml = "model/segmentation.xml"
segmentation_model = core.read_model(model=segmentation_model_xml)
segmentation_input_layer = segmentation_model.input(0)
segmentation_output_layer = segmentation_model.output(0)

print("~~~~ ORIGINAL MODEL ~~~~")
print(f"input shape: {segmentation_input_layer.shape}")
print(f"output shape: {segmentation_output_layer.shape}")

new_shape = ov.PartialShape([1, 3, 544, 544])
segmentation_model.reshape({segmentation_input_layer.any_name: new_shape})
segmentation_compiled_model = core.compile_model(model=segmentation_model, device_name="CPU")
# help(segmentation_compiled_model)
print("~~~~ RESHAPED MODEL ~~~~")
print(f"model input shape: {segmentation_input_layer.shape}")
print(
    f"compiled_model input shape: "
    f"{segmentation_compiled_model.input(index=0).shape}"
)
print(f"compiled_model output shape: {segmentation_output_layer.shape}")
~~~~ ORIGINAL MODEL ~~~~
input shape: [1,3,512,512]
output shape: [1,1,512,512]
~~~~ RESHAPED MODEL ~~~~
model input shape: [1,3,544,544]
compiled_model input shape: [1,3,544,544]
compiled_model output shape: [1,1,544,544]

セグメント化ネットワークの入力形状は、NCHW レイアウトの [1,3,512,512] です。ネットワークは、幅と高さが 512、バッチサイズが 1 の 3 チャネル画像を想定しています。IENetwork.reshape() メソッドを使用してネットワークを再形成し、幅と高さが 544 の入力イメージを受け入れるようにします。このセグメント化ネットワークは常に、入力の幅と高さが等しい値の配列を返します。したがって、入力次元を 544x544 に設定すると、出力次元も変更されます。再形成後、ネットワークを再コンパイルします。

バッチサイズの変更

.reshape() メソッドを使用して、new_shape の最初の要素を増やしてバッチサイズを設定します。例えば、バッチサイズを 2 に設定するには、上のセルに new_shape = (2,3,544,544) を設定します。

import openvino as ov

segmentation_model_xml = "model/segmentation.xml"
segmentation_model = core.read_model(model=segmentation_model_xml)
segmentation_input_layer = segmentation_model.input(0)
segmentation_output_layer = segmentation_model.output(0)
new_shape = ov.PartialShape([2, 3, 544, 544])
segmentation_model.reshape({segmentation_input_layer.any_name: new_shape})
segmentation_compiled_model = core.compile_model(model=segmentation_model, device_name="CPU")

print(f"input shape: {segmentation_input_layer.shape}")
print(f"output shape: {segmentation_output_layer.shape}")
input shape: [2,3,544,544]
output shape: [2,1,544,544]

出力は、バッチサイズを 2 に設定することにより、入力および出力形状の最初の要素 (N) の値が 2 になることを示しています。入力画像をネットワーク経由で伝播して、結果を確認します。

import numpy as np
import openvino as ov

core = ov.Core()
segmentation_model_xml = "model/segmentation.xml"
segmentation_model = core.read_model(model=segmentation_model_xml)
segmentation_input_layer = segmentation_model.input(0)
segmentation_output_layer = segmentation_model.output(0)
new_shape = ov.PartialShape([2, 3, 544, 544])
segmentation_model.reshape({segmentation_input_layer.any_name: new_shape})
segmentation_compiled_model = core.compile_model(model=segmentation_model, device_name="CPU")
input_data = np.random.rand(2, 3, 544, 544)

output = segmentation_compiled_model([input_data])

print(f"input data shape: {input_data.shape}")
print(f"result data data shape: {segmentation_output_layer.shape}")
input data shape: (2, 3, 544, 544)
result data data shape: [2,1,544,544]

モデルのキャッシュ

GPU などの一部のデバイスでは、モデルのロードに時間がかかる場合があります。モデルキャッシュは、モデルをキャッシュ・ディレクトリーにキャッシュすることでこの問題を解決します。core.compile_model(model=net, device_name=device_name, config=config_dict) が設定されているとキャッシュが使用されます。このオプションは、モデルがキャッシュに存在するかどうかを確認します。存在する場合は、キャッシュからロードします。存在しない場合は、モデルを定期的にロードしてキャッシュに保存します。そのため、このオプションが設定され次回モデルがロードされるとき、モデルはキャッシュからロードされます。

以下のセルで、model_cache ディレクトリーを model のサブディレクトリーとして作成します。ここに、指定されたデバイスのモデルがキャッシュされます。モデルは GPU にロードされます。このセルを 1 度実行するとモデルがキャッシュされるため、このセルをその後実行するとモデルがキャッシュから読み込まれます。

注: モデルキャッシュは CPU デバイスでも利用できます

ir_model_url = 'https://storage.openvinotoolkit.org/repositories/openvino_notebooks/models/002-example-models/'
ir_model_name_xml = 'classification.xml'
ir_model_name_bin = 'classification.bin'

download_file(ir_model_url + ir_model_name_xml, filename=ir_model_name_xml, directory='model')
download_file(ir_model_url + ir_model_name_bin, filename=ir_model_name_bin, directory='model')
'model/classification.xml' already exists.
'model/classification.bin' already exists.
PosixPath('/opt/home/k8sworker/ci-ai/cibuilds/ov-notebook/OVNotebookOps-609/.workspace/scm/ov-notebook/notebooks/002-openvino-api/model/classification.bin')
import time
from pathlib import Path

import openvino as ov

core = ov.Core()

device_name = "GPU"

if device_name in core.available_devices:
    cache_path = Path("model/model_cache")
    cache_path.mkdir(exist_ok=True)
    # Enable caching for OpenVINO Runtime. To disable caching set enable_caching = False
    enable_caching = True
    config_dict = {"CACHE_DIR": str(cache_path)} if enable_caching else {}

    classification_model_xml = "model/classification.xml"
    model = core.read_model(model=classification_model_xml)

    start_time = time.perf_counter()
    compiled_model = core.compile_model(model=model, device_name=device_name, config=config_dict)
    end_time = time.perf_counter()
    print(f"Loading the network to the {device_name} device took {end_time-start_time:.2f} seconds.")

前のセルを実行した後、モデルがキャッシュ・ディレクトリーに存在することが分かります。次に、コンパイルされたモデルを削除し、再度ロードします。では、現在かかる時間を計測します。

if device_name in core.available_devices:
    del compiled_model
    start_time = time.perf_counter()
    compiled_model = core.compile_model(model=model, device_name=device_name, config=config_dict)
    end_time = time.perf_counter()
    print(f"Loading the network to the {device_name} device took {end_time-start_time:.2f} seconds.")