PyTorch モデルから変換

PyTorch モデルを変換するには、openvino.convert_model 関数を使用します。

torchvision のモデルを使用した PyTorch モデル変換の例を次に示します。

import torchvision
import torch
import openvino as ov

model = torchvision.models.resnet50(weights='DEFAULT')
ov_model = ov.convert_model(model)

openvino.convert_model 関数は、次の PyTorch モデル・オブジェクト・タイプをサポートします。

  • torch.nn.Module 派生クラス

  • torch.jit.ScriptModule

  • torch.jit.ScriptFunction

torch.nn.Module を入力モデルとして使用する場合、openvino.convert_model では、example_input パラメーターが必要になることがあります。内部的には、torch.jit.trace 関数の機能を使用して、モデル変換プロセス中にモデルのトレースをトリガーします。

example_input を使用すると、example_input なしの変換と比較して、正確性とパフォーマンスの点で OpenVINO モデルの品質が向上します。example_input の必要性は特定の PyTorch モデルの実装によって異なりますが、使用可能であれば example_input パラメーターを常に設定することを推奨します。

example_input パラメーターの値は、入力テンソルの要素のタイプと形状を知ることで簡単に分かります。すべてのケースに適しているわけではありませんが、乱数は多くの場合、この用途に有用です。

import torchvision
import torch
import openvino as ov

model = torchvision.models.resnet50(weights='DEFAULT')
ov_model = ov.convert_model(model, example_input=torch.rand(1, 3, 224, 224))

通常、PyTorch モデルを評価またはテストするコードが、モデル自体に提供されており、適切な example_input 値を生成するのに使用できます。torchvisionresnet50 モデルを使用する変更例を以下に示します。既存の PyTorch アプリケーションの推論を OpenVINO に切り替える方法と、example_input の値を取得する方法を示します。

from torchvision.io import read_image
from torchvision.models import resnet50, ResNet50_Weights
import requests, PIL, io, torch

# Get a picture of a cat from the web:
img = PIL.Image.open(io.BytesIO(requests.get("https://placekitten.com/200/300").content))

# Torchvision model and input data preparation from https://pytorch.org/vision/stable/models.html

weights = ResNet50_Weights.DEFAULT
model = resnet50(weights=weights)
model.eval()
preprocess = weights.transforms()
batch = preprocess(img).unsqueeze(0)

# PyTorch model inference and post-processing

prediction = model(batch).squeeze(0).softmax(0)
class_id = prediction.argmax().item()
score = prediction[class_id].item()
category_name = weights.meta["categories"][class_id]
print(f"{category_name}: {100 * score:.1f}% (with PyTorch)")

# OpenVINO model preparation and inference with the same post-processing

import openvino as ov
compiled_model = ov.compile_model(ov.convert_model(model, example_input=batch))

prediction = torch.tensor(compiled_model(batch)[0]).squeeze(0).softmax(0)
class_id = prediction.argmax().item()
score = prediction[class_id].item()
category_name = weights.meta["categories"][class_id]
print(f"{category_name}: {100 * score:.1f}% (with OpenVINO)")

対話型の Python チュートリアルでその他の例を確認してください。

上記の例では、openvino.save_model 関数は使用されていません。それは、この関数の使用法に関する PyTorch 固有の詳細情報がないためです。すべての例で、変換された OpenVINO モデルは、ov.save_model(ov_model, 'model.xml') を呼び出すことで IR に保存できます。

サポートされる入力パラメーター・タイプ

モデルに単一の入力がある場合、example_input では次の入力タイプがサポートされます。

  • openvino.Tensor

  • torch.Tensor

  • tuple またはネストされたタプルの任意の組み合わせ

モデルに複数の入力がある場合、入力値は listtuple、または dict に結合されます。

  • list または tuple 内の値は、元のモデルが指定したのと同じ順序である必要があります。

  • dict には、元のモデルの引数名の名前からのキーがあります。

listtuple、または dict は、複数の入力だけでなく単一の入力にも使用できます。

モデルに単一の入力パラメーターがあり、この入力タイプが tuple である場合、複数の入力の場合と同様に、常に追加の listtuple、または dict に囲んで渡す必要があります。この場合、model((a, b))model(a, b) 間のあいまいさを解消する必要があります。

非テンソル・データ・タイプ

tupledict などの非テンソル・データ・タイプがモデルの入出力に出現するとフラット化されます。フラット化とは、tuple 内の各要素が個別の入力または出力として表現されることを意味します。同じことが dict 値にも当てはまり、dict のキーはモデルの入出力名を形成するために使用されます。元の非テンソル入力または出力は、このフラット化プロセスの結果として生じる新しい入力または出力に置き換えられます。このフラット化手順は、最もネストされたデータタイプがテンソルであると仮定されるまで、tupleslists、および dicts によるネストへは再帰的に適用されます。

例えば、元のモデルが example_input=(a, (b, c, (d, e))) で呼び出された場合 (ab、… e はテンソル)、元のモデルには 2 つの入力があることを意味します。1 つ目はテンソル a で、2 つ目は 2 つのテンソル bc とネストされたタプル (d, e) を含むタプル (b, c, (d, e)) です。次に、結果として得られる OpenVINO モデルにはシグネチャー (a, b, c, d, e) が含まれます。これは、元のモデルの 2 つの入力の代わりに、すべてテンソルタイプの 5 つの入力を持つことを意味します。

モデルに {"x": a, "y": b, "z": c} などの dict 入力がある場合、OpenVINO モデル・シグネチャーの複数の入力に分解されます: (a, b, c)。ここで、入力はそれぞれ xy、および z の名前を想定します。

フラット化の重要な点は、固定数の要素とキー値を持つ tupledict のみがサポートされることです。このような入力構造は、convert_modelexample_input パラメーターで明確にする必要があります。出力のフラット化は、与えられた example_input を使用して再現する必要があり、変換が完了すると変更できなくなります。

次のチュートリアルで、非テンソル・データ・タイプを使用したモデル変換の例を確認してください。

PyTorch モデルを ONNX 形式にエクスポート

PyTorch モデルを変換する別の方法は、最初に torch.onnx.export を使用して PyTorch モデルを ONNX にエクスポートし、次に、結果の .onnx ファイルを openvino.convert_model で OpenVINO モデルに変換することです。上位の章で説明したように、モデルを PyTorch から OpenVINO に直接変換できない場合のバックアップ・ソリューションとして検討できます。ONNX を介した変換は、コード、変換時間、使用するメモリーの点でコストが高くなる可能性があります。

  1. PyTorch から ONNX にモデルをエクスポートする方法については、PyTorch モデルを ONNX 形式にエクスポートを参照してください。

  2. ONNX モデルを変換に従って、OpenVINO モデルを作成します。

これら 2 つのステップを組み合わせて使用する例を示します。

import torchvision
import torch
import openvino as ov

model = torchvision.models.resnet50(weights='DEFAULT')
# 1. Export to ONNX
torch.onnx.export(model, (torch.rand(1, 3, 224, 224), ), 'model.onnx')
# 2. Convert to OpenVINO
ov_model = ov.convert_model('model.onnx')

バージョン 1.8.1 では、すべての PyTorch 操作をデフォルトで使用される ONNX opset 9 にエクスポートできるわけではありません。デフォルトの opset 9 へのエクスポートが機能しない場合は、モデルを opset 11 以降にエクスポートすることを推奨します。その場合は、torch.onnx.exportopset_version オプションを使用してください。ONNX opset の詳細については、オペレータースキーマを参照してください。