PaddlePaddle モデルを OpenVINO™ IR に変換#

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

BinderGoogle ColabGitHub

このノートブックでは、ImageNet データセットで事前トレーニングされた MobileNetV3 モデルを PaddleHub から OpenVINO IR に変換する方法を示します。また、OpenVINO ランタイムを使用してサンプル画像に対して分類推論を実行する方法と、PaddlePaddle モデルの結果を IR モデルと比較する方法も示します。

モデルのソース。

目次:

準備#

インポート#

import platform 

if platform.system() == "Windows":
     %pip install -q "paddlepaddle>=2.5.1,<2.6.0" 
else:
     %pip install -q "paddlepaddle>=2.5.1" 
%pip install -q "paddleclas>=2.5.2" --no-deps 
%pip install -q "prettytable" "ujson" "visualdl>=2.5.3" "faiss-cpu>=1.7.1" Pillow tqdm 
# openvino パッケージをインストール 
%pip install -q "openvino>=2023.1.0"
Note: you may need to restart the kernel to use updated packages.
Note: you may need to restart the kernel to use updated packages.
エラー: pip の依存関係リゾルバーは現在、インストールされているすべてのパッケージを考慮していません。この動作が次の依存関係の競合の原因となります。 
paddleclas 2.5.2 には easydict が必要ですが、インストールされていません。 
paddleclas 2.5.2 には gast==0.3.3 が必要ですが、互換性のない gast 0.4.0 があります。
paddleclas 2.5.2 には opencv-python==4.6.0.66 が必要ですが、互換性のない opencv-python 4.10.0.84 がインストールされています。  
Note: you may need to restart the kernel to use updated packages.
Note: you may need to restart the kernel to use updated packages.
if platform.system() == "Linux":     !wget http://nz2.archive.ubuntu.com/ubuntu/pool/main/o/openssl/libssl1.1_1.1.1f-1ubuntu2.19_amd64.deb 
    !sudo dpkg -i libssl1.1_1.1.1f-1ubuntu2.19_amd64.deb
--2024-07-13 01:22:03-- http://nz2.archive.ubuntu.com/ubuntu/pool/main/o/openssl/libssl1.1_1.1.1f-1ubuntu2.19_amd64.deb 
Resolving proxy-dmz.intel.com (proxy-dmz.intel.com)...10.241.208.166 
Connecting to proxy-dmz.intel.com (proxy-dmz.intel.com)|10.241.208.166|:911... connected. Proxy request sent, awaiting response... 404 Not Found 
2024-07-13 01:22:03 ERROR 404: Not Found. 

dpkg: error: cannot access archive 'libssl1.1_1.1.1f-1ubuntu2.19_amd64.deb': No such file or directory
import time 
import tarfile 
from pathlib import Path 

import matplotlib.pyplot as plt 
import numpy as np 
import openvino as ov 
from paddleclas import PaddleClas 
from PIL import Image 

# `notebook_utils` モジュールを取得 
import requests 

r = requests.get( 

url="https://raw.githubusercontent.com/openvinotoolkit/openvino_notebooks/latest/utils/notebook_utils.py", 
) 

open("notebook_utils.py", "w").write(r.text) 

from notebook_utils import download_file
2024-07-13 01:22:05 INFO: Loading faiss with AVX512 support. 
2024-07-13 01:22:05 INFO: Successfully loaded faiss with AVX512 support.

設定#

IMAGE_FILENAME を、使用する画像のファイル名に設定します。MODEL_NAME を PaddleHub からダウンロードする PaddlePaddle モデルに設定します。MODEL_NAME は、IR モデルのベース名にもなります。ノートブックは MobileNetV3_large_x1_0 モデルでテストされています。他のモデルでは異なる前処理が使用される場合があるため、元のモデルと変換されたモデルで同じ結果を得るには、何らかの変更が必要になります。

まず、モデルファイルをダウンロードして解凍する必要があります。このノートブックを初めて実行すると、PaddlePaddle モデルが PaddleHub からダウンロードされます。これには時間がかかる場合があります。

# openvino_notebooks ストレージから画像をダウンロード 
img = download_file( 
    "https://storage.openvinotoolkit.org/repositories/openvino_notebooks/data/data/image/coco_close.png", 
    directory="data", 
) 

IMAGE_FILENAME = img.as_posix() 

MODEL_NAME = "MobileNetV3_large_x1_0" 
MODEL_DIR = Path("model") 
if not MODEL_DIR.exists():
    MODEL_DIR.mkdir() 
MODEL_URL = "https://paddle-imagenet-models-name.bj.bcebos.com/dygraph/inference/{}_infer.tar".format(MODEL_NAME) 
download_file(MODEL_URL, directory=MODEL_DIR) 
file = tarfile.open(MODEL_DIR / "{}_infer.tar".format(MODEL_NAME)) 
res = file.extractall(MODEL_DIR) 
if not res: 
    print(f'Model Extracted to "./{MODEL_DIR}".') 
else: 
    print("Error Extracting the model.Please check the network.")
data/coco_close.png: 0%|          | 0.00/133k [00:00<?, ?B/s]
model/MobileNetV3_large_x1_0_infer.tar: 0%|          | 0.00/19.5M [00:00<?, ?B/s]
Model Extracted to "./model".

PaddlePaddle モデルの推論を表示#

次のセルでは、モデルをロードし、画像をロードして表示し、その画像に対して推論を実行して、上位 3 つの予測結果を表示します。

classifier = PaddleClas(inference_model_dir=MODEL_DIR / "{}_infer".format(MODEL_NAME)) 
result = next(classifier.predict(IMAGE_FILENAME)) 
class_names = result[0]["label_names"] 
scores = result[0]["scores"] 
image = Image.open(IMAGE_FILENAME) 
plt.imshow(image) 
for class_name, softmax_probability in zip(class_names, scores): 
    print(f"{class_name}, {softmax_probability:.5f}")
[2024/07/13 01:22:31] ppcls WARNING: The current running environment does not support the use of GPU. CPU has been used instead. 
Labrador retriever, 0.75138 
German short-haired pointer, 0.02373 
Great Dane, 0.01848 
Rottweiler, 0.01435 
flat-coated retriever, 0.01144
../_images/paddle-to-openvino-classification-with-output_8_1.png

classifier.predict() は画像ファイル名を取得し、画像を読み取り、入力を前処理してから、画像のクラスのラベルとスコアを返します。画像の前処理はバックグラウンドで行われます。分類モデルは、1000 個の ImageNet クラスごとに浮動小数点値を含む配列を返します。値が大きいほど、ネットワークは、その値に対応するクラス番号 (ネットワーク出力配列内のその値のインデックス) が画像のクラス番号であると確信できます。

PaddlePaddle の分類関数とデータのロードと前処理の実装を確認するには、次の 2 つのセルのコメントを解除します。

# classifier??
# classifier.get_config()

classifier.get_config() モジュールは、モデルの前処理構成を表示します。画像が正規化、サイズ変更、トリミングされていること、および BGR 画像がネットワークを介して伝播される前に RGB に変換されていることを示す必要があります。次のセルでは、同じメソッドを使用して OpenVINO IR モデルで推論を行う前処理操作のリストを返す classifier.predictror.preprocess_ops プロパティーを取得します。

preprocess_ops = classifier.predictor.preprocess_ops 

def process_image(image): 
    for op in preprocess_ops: 
        image = op(image) 
    return image

process_image() 関数の出力を表示して、トリミングとサイズ変更の効果を確認すると便利です。正規化により色が奇妙に見えるため、matplotlib は値のクリッピングについて警告します。

pil_image = Image.open(IMAGE_FILENAME) 
processed_image = process_image(np.array(pil_image)) 
print(f"Processed image shape: {processed_image.shape}") 
# 処理された画像は (C、H、W) 形式です。画像を表示するには (H、W、C) に変換します 
plt.imshow(np.transpose(processed_image, (1, 2, 0)))
2024-07-13 01:22:31 WARNING: Clipping input data to the valid range for imshow with RGB data ([0..1] for floats or [0..255] for integers).
Processed image shape: (3, 224, 224)
<matplotlib.image.AxesImage at 0x7fa888475730>
../_images/paddle-to-openvino-classification-with-output_15_3.png

モデルによって予測されたラベルをクラス名にデコードするには、それらのマッピングが必要です。モデル設定には、マッピングを保存する class_id_map_file に関する情報が含まれています。次のコードは、OpenVINO モデルで使用する辞書へのマッピングを解析する方法を示しています。

class_id_map_file = classifier.get_config()["PostProcess"]["Topk"]["class_id_map_file"] 
class_id_map = {} 
with open(class_id_map_file, "r") as fin: 
    lines = fin.readlines() 
    for line in lines: 
        partition = line.split("\n")[0].partition(" ") 
        class_id_map[int(partition[0])] = str(partition[-1])

モデルを OpenVINO IR 形式に変換#

OpenVINO モデル・トランスフォーメーション API を呼び出して、FP32 精度で PaddlePaddle モデルを OpenVINO IR に変換します。ov.convert_model 関数は、PaddlePaddle モデルへのパスを受け入れ、このモデルを表す OpenVINO Model クラスのインスタンスを返します。取得したモデルはすぐに使用でき、ov.compile_model を使用してデバイスにロードするか、ov.save_model 関数を使用してディスクに保存できます。モデル・トランスフォーメーション API の詳細については、モデル変換ガイドを参照してください。

model_xml = Path(MODEL_NAME).with_suffix(".xml") 
if not model_xml.exists(): 
    ov_model = ov.convert_model("model/MobileNetV3_large_x1_0_infer/inference.pdmodel") 
    ov.save_model(ov_model, str(model_xml)) 
else: 
    print(f"{model_xml} already exists.")

推論デバイスの選択#

OpenVINO を使用して推論を実行するためにドロップダウン・リストからデバイスを選択します

import ipywidgets as widgets 

core = ov.Core() 
device = widgets.Dropdown( 
    options=core.available_devices + ["AUTO"], 
    value="AUTO", 
    description="Device:", 
    disabled=False, 
) 

device
Dropdown(description='Device:', index=1, options=('CPU', 'AUTO'), value='AUTO')

OpenVINO モデルの推論を表示#

IR モデルをロードし、モデル情報を取得し、画像をロードし、推論を実行し、推論を意味のある結果に変換して、出力を表示します。詳細については、OpenVINO ランタイム API ノートブックを参照してください。

# OpenVINO ランタイムと OpenVINO IR モデルをロード 
core = ov.Core() 
model = core.read_model(model_xml) 
compiled_model = core.compile_model(model=model, device_name=device.value) 

# モデル出力を取得 
output_layer = compiled_model.output(0) 

# 入力画像の読み取り、表示、前処理 
# process_image のソースについては、"PaddlePaddle モデルの推論を表示" セクションを参照 
image = Image.open(IMAGE_FILENAME) 
plt.imshow(image) 
input_image = process_image(np.array(image))[None,] 

# 推論を実行 
ov_result = compiled_model([input_image])[output_layer][0] 

# 上位 3 つの値を見つける 
top_indices = np.argsort(ov_result)[-3:][::-1] 
top_scores = ov_result[top_indices] 

# PaddlePaddle 分類器と同じラベルを使用して、推論結果をクラス名に変換 
for index, softmax_probability in zip(top_indices, top_scores): 
    print(f"{class_id_map[index]}, {softmax_probability:.5f}")
Labrador retriever, 0.74909 
German short-haired pointer, 0.02368 
Great Dane, 0.01873
../_images/paddle-to-openvino-classification-with-output_23_1.png

タイミングと比較#

50 枚の画像の推論にかかる時間を測定し、結果を比較します。タイミング情報はパフォーマンスを示します。公平に比較するため、画像の処理にかかる時間を含めます。より正確なベンチマークを行うには、OpenVINO ベンチマーク・ツールを使用します。パフォーマンスを向上するには多くの最適化が可能であることに注意してください。

num_images = 50 

image = Image.open(fp=IMAGE_FILENAME)
# デバイス情報を表示 
core = ov.Core() 
devices = core.available_devices 

for device_name in devices: 
    device_full_name = core.get_property(device_name, "FULL_DEVICE_NAME") 
    print(f"{device_name}: {device_full_name}")
CPU: Intel(R) Core(TM) i9-10920X CPU @ 3.50GHz
# PaddlePaddle モデルでの推論速度を表示 
start = time.perf_counter() 
for _ in range(num_images): 
    result = next(classifier.predict(np.array(image))) 
end = time.perf_counter() 
time_ir = end - start 
print(f"PaddlePaddle model on CPU: {time_ir/num_images:.4f} " f"seconds per image, FPS: {num_images/time_ir:.2f}\n") 
print("PaddlePaddle result:") 
class_names = result[0]["label_names"] 
scores = result[0]["scores"] 
for class_name, softmax_probability in zip(class_names, scores): 
    print(f"{class_name}, {softmax_probability:.5f}") 
plt.imshow(image);
PaddlePaddle model on CPU: 0.0076 seconds per image, FPS: 131.17 

PaddlePaddle result: Labrador retriever, 0.75138 
German short-haired pointer, 0.02373 
Great Dane, 0.01848 
Rottweiler, 0.01435 
flat-coated retriever, 0.01144
../_images/paddle-to-openvino-classification-with-output_27_1.png

推論デバイスの選択#

OpenVINO を使用して推論を実行するためにドロップダウン・リストからデバイスを選択します

device
Dropdown(description='Device:', index=1, options=('CPU', 'AUTO'), value='AUTO')
# OpenVINO IR モデルの推論速度を表示 
compiled_model = core.compile_model(model=model, device_name=device.value) 
output_layer = compiled_model.output(0) 

start = time.perf_counter() 
input_image = process_image(np.array(image))[None,] 
for _ in range(num_images): 
    ie_result = compiled_model([input_image])[output_layer][0] 
    top_indices = np.argsort(ie_result)[-5:][::-1] 
    top_softmax = ie_result[top_indices] 

end = time.perf_counter() 
time_ir = end - start 

print(f"OpenVINO IR model in OpenVINO Runtime ({device.value}): {time_ir/num_images:.4f} " f"seconds per image, FPS: {num_images/time_ir:.2f}") 
print() 
print("OpenVINO result:") 
for index, softmax_probability in zip(top_indices, top_softmax): 
    print(f"{class_id_map[index]}, {softmax_probability:.5f}") 
plt.imshow(image);
OpenVINO IR model in OpenVINO Runtime (AUTO): 0.0029 seconds per image, FPS: 348.21 

OpenVINO result: Labrador retriever, 0.74909 
German short-haired pointer, 0.02368 
Great Dane, 0.01873 
Rottweiler, 0.01448 
flat-coated retriever, 0.01153
../_images/paddle-to-openvino-classification-with-output_30_1.png

関連情報#