PyTorch モデルの変換#

PyTorch Hub または Hugging Face から 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.export.ExportedProgram

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 

# ウェブから猫の写真を取得: 
img = PIL.Image.open(io.BytesIO(requests.get("https://placekitten.com/200/300").content)) 

# Torchvision モデルと入力データの準備: 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 モデルの推論と後処理 

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 モデルの準備と推論 

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 は、TorchScript 表現のモデル入力と出力に関連する名前を生成しません。OpenVINO は、モデルの forward メソッドのシグネチャーまたは example_input で提供される dict キーに基づいて入力名を割り当てます。出力に dict がある場合、または TorchScript モデル表現で使用可能な内部名がある場合に、出力名が割り当てられます。通常、出力名は割り当てられず、空のままになります。モデル出力は、名前ではなくインデックスで指定することを推奨します。

torch.export のサポート#

torch.export は、モデルのグラフ表現を取得する現在の方法です (PyTorch 2.1 以降)。FX 形式のグラフ表現を含む ExportedProgram を生成します。TorchScript 表現よりも優れている理由については、PyTorch のドキュメントを参照してください。

以下は、torch.export で取得したモデルを変換する方法の例です:

from torchvision.models import resnet50, ResNet50_Weights 
from torch.export import export 
from openvino import convert_model 

model = resnet50(weights=ResNet50_Weights.DEFAULT) 
model.eval() 
exported_model = export(model, (torch.randn(1, 3, 224, 224),)) 
ov_model = convert_model(exported_model)

これは試験的な機能です。必要だと判明している場合にのみ使用してください。PyTorch バージョン 2.2 が推奨されます。動的形状はまだサポートされていません。

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. ONNX へエクスポート 
torch.onnx.export(model, (torch.rand(1, 3, 224, 224), ), 'model.onnx') 
# 2. 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 の詳細については、オペレーター・スキーマを参照してください。