Ultralyticsを使用した非YOLO PyTorchモデルのエクスポート方法#
Ultralytics は、複数のバックエンドを1つの統一されたインターフェースでラップするスタンドアロンのエクスポートユーティリティを ultralytics.utils.export の下で提供しています。timm の画像モデル、torchvision の分類器や検出器、あるいは独自のカスタムアーキテクチャを含むあらゆる torch.nn.Module を、個別のバックエンドを個別に学ぶことなく、ONNX、TorchScript、OpenVINO、CoreML、NCNN、PaddlePaddle、MNN、ExecuTorch、TensorFlow SavedModel にエクスポートできます。
PyTorch モデルの本番環境へのデプロイでは通常、ターゲットごとに異なるエクスポーター(ONNX には torch.onnx.export、Apple デバイスには coremltools、TensorFlow には onnx2tf、NCNN には pnnx など)を使い分ける必要があります。それぞれのツールには独自の API、依存関係の癖、出力規約があります。これらのユーティリティは、それを単一の呼び出しパターンに統合します。
非YOLOモデルのエクスポートにUltralyticsを使用する理由#
- 10種類のフォーマットに対応した単一のAPI: 多数の呼び出し規約を覚える必要はなく、一つだけ学習すれば済みます。
- 共有ユーティリティサーフェス: エクスポートヘルパーは
ultralytics.utils.exportの下に配置されているため、バックエンドパッケージをインストールすれば、フォーマット間で同じ呼び出しパターンを維持できます。 - YOLOエクスポートと同じコードパス: すべてのUltralytics YOLOエクスポートを支えるのと同じヘルパーが使用されています。
- FP16およびINT8量子化: 対応するフォーマット(OpenVINO、CoreML、MNN、NCNN)には標準で組み込まれています。
- CPUで動作可能: エクスポート手順自体にGPUは不要なため、どのノートパソコンからでもローカルで実行できます。
クイックスタート#
最も早い方法は、YOLOコードを使用せず、pip install ultralytics onnx timm 以外のセットアップも必要とせずに、2行で ONNX にエクスポートすることです。
import timm
import torch
from ultralytics.utils.export import torch2onnx
model = timm.create_model("resnet18", pretrained=True).eval()
torch2onnx(model, torch.randn(1, 3, 224, 224), output_file="resnet18.onnx")サポートされているエクスポート形式#
torch2* 関数は、標準的な torch.nn.Module と入力テンソルの例を受け取ります。MNN、TF SavedModel、TF Frozen Graph は、中間形式の ONNX または Keras アーティファクトを経由します。どちらの場合も、YOLO 固有の属性は必要ありません。
| 形式 | 関数 | インストール | 出力 |
|---|---|---|---|
| ONNX | torch2onnx() | pip install onnx | .onnx ファイル |
| TorchScript | torch2torchscript() | PyTorchに含まれる | .torchscript ファイル |
| OpenVINO | torch2openvino() | pip install openvino | _openvino_model/ ディレクトリ |
| CoreML | torch2coreml() | pip install coremltools | .mlpackage |
| TF SavedModel | onnx2saved_model() | 以下の詳細な要件をご覧ください | _saved_model/ ディレクトリ |
| TF Frozen Graph | keras2pb() | 以下の詳細な要件をご覧ください | .pb ファイル |
| NCNN | torch2ncnn() | pip install ncnn pnnx | _ncnn_model/ ディレクトリ |
| MNN | onnx2mnn() | pip install MNN | .mnn ファイル |
| PaddlePaddle | torch2paddle() | pip install paddlepaddle x2paddle | _paddle_model/ ディレクトリ |
| ExecuTorch | torch2executorch() | pip install executorch | _executorch_model/ ディレクトリ |
MNN、TF SavedModel、および TF Frozen Graph のエクスポートは、中間ステップとして ONNX を経由します。最初に ONNX にエクスポートしてから変換してください。
一部のエクスポート関数は、オプションの metadata 辞書(例: torch2torchscript(..., metadata={"author": "me"}))を受け付けます。これにより、フォーマットがサポートしている場合、エクスポートされたアーティファクトにカスタムのキーと値のペアを埋め込むことができます。
ステップバイステップの例#
以下のすべての例では、timmから取得した評価モードの事前学習済みResNet-18を使用する同じセットアップを用います。
import timm
import torch
model = timm.create_model("resnet18", pretrained=True).eval()
im = torch.randn(1, 3, 224, 224)ドロップアウト、バッチ正規化、およびその他の訓練専用レイヤーは、推論時に異なる動作をします。.eval() をスキップすると、不正確な出力を持つエクスポートが生成されます。
ONNXへのエクスポート#
from ultralytics.utils.export import torch2onnx
torch2onnx(model, im, output_file="resnet18.onnx")動的バッチサイズの場合は、dynamic 辞書を渡します。
torch2onnx(model, im, output_file="resnet18_dyn.onnx", dynamic={"images": {0: "batch_size"}})デフォルトの opset は 14 であり、デフォルトの入力名は "images" です。opset、input_names、または output_names の引数でオーバーライドします。
TorchScriptへのエクスポート#
追加の依存関係は不要です。内部で torch.jit.trace を使用します。
from ultralytics.utils.export import torch2torchscript
torch2torchscript(model, im, output_file="resnet18.torchscript")OpenVINOへのエクスポート#
from ultralytics.utils.export import torch2openvino
ov_model = torch2openvino(model, im, output_dir="resnet18_openvino_model")ディレクトリには、固定名の model.xml と model.bin のペアが含まれています。
resnet18_openvino_model/
├── model.xml
└── model.bin動的な入力形状には dynamic=True を、FP16 には quantize=16 を、INT8 量子化には quantize=8 を渡します。INT8 には追加で calibration_dataset 引数が必要です。
openvino>=2024.0.0(または macOS 15.4+ では >=2025.2.0)と torch>=2.1 が必要です。
CoreMLへのエクスポート#
import coremltools as ct
from ultralytics.utils.export import torch2coreml
inputs = [ct.TensorType("input", shape=(1, 3, 224, 224))]
ct_model = torch2coreml(model, inputs, im, classifier_names=None, output_file="resnet18.mlpackage")分類モデルの場合、クラス名のリストを classifier_names に渡して、CoreML モデルに分類ヘッドを追加します。
coremltools>=9.0、torch>=1.11、および numpy<=2.3.5 が必要です。Windows ではサポートされていません。
coremltools>=9.0 は、macOS および Linux 向けの Python 3.10〜3.13 のホイールを提供しています。新しい Python バージョンでは、ネイティブ C 拡張の読み込みに失敗します。CoreML エクスポートには Python 3.10〜3.13 を使用してください。
TensorFlow SavedModelへのエクスポート#
TF SavedModelへのエクスポートは、中間ステップとしてONNXを経由します:
from ultralytics.utils.export import onnx2saved_model, torch2onnx
torch2onnx(model, im, output_file="resnet18.onnx")
keras_model = onnx2saved_model("resnet18.onnx", output_dir="resnet18_saved_model")この関数は Keras モデルを返し、出力ディレクトリ内に TFLite ファイル(.tflite)も生成します。
resnet18_saved_model/
├── saved_model.pb
├── variables/
├── resnet18_float32.tflite
├── resnet18_float16.tflite
└── resnet18_int8.tflite要件:
tensorflow>=2.0.0,<=2.19.0onnx2tf>=1.26.3,<1.29.0tf_keras<=2.19.0sng4onnx>=1.0.1onnx_graphsurgeon>=0.3.26- macOS では
ai-edge-litert>=1.2.0,<1.4.0(他のプラットフォームではai-edge-litert>=1.2.0) onnxslim>=0.1.82onnx>=1.12.0,<2.0.0protobuf>=5
TensorFlow Frozen Graphへのエクスポート#
上記の SavedModel エクスポートに続き、返された keras_model を凍結された .pb グラフに変換します。
from pathlib import Path
from ultralytics.utils.export import keras2pb
keras2pb(keras_model, output_file=Path("resnet18_saved_model/resnet18.pb"))NCNNへのエクスポート#
from ultralytics.utils.export import torch2ncnn
torch2ncnn(model, im, output_dir="resnet18_ncnn_model")ディレクトリには、Pythonラッパーとともに固定名のparamおよびbinファイルが含まれます:
resnet18_ncnn_model/
├── model.ncnn.param
├── model.ncnn.bin
└── model_ncnn.pytorch2ncnn() は、初回使用時に ncnn と pnnx をチェックします。
MNNへのエクスポート#
MNNエクスポートには、入力としてONNXファイルが必要です。最初にONNXへエクスポートしてから変換してください:
from ultralytics.utils.export import onnx2mnn, torch2onnx
torch2onnx(model, im, output_file="resnet18.onnx")
onnx2mnn("resnet18.onnx", output_file="resnet18.mnn")FP16 の場合は quantize=16 を、INT8 量子化の場合は quantize=8 をサポートします。MNN>=2.9.6 と torch>=1.10 が必要です。
PaddlePaddleへのエクスポート#
from ultralytics.utils.export import torch2paddle
torch2paddle(model, im, output_dir="resnet18_paddle_model")ディレクトリにはPaddlePaddleモデルとパラメータファイルが含まれます:
resnet18_paddle_model/
├── model.pdmodel
└── model.pdiparamsx2paddle と、プラットフォームに一致する PaddlePaddle ディストリビューションが必要です。
- CUDA上の
paddlepaddle-gpu>=3.0.0,<3.3.0 - ARM64 CPU上の
paddlepaddle==3.0.0 - その他のCPU上の
paddlepaddle>=3.0.0,<3.3.0
NVIDIA Jetsonではサポートされていません。
ExecuTorchへのエクスポート#
from ultralytics.utils.export import torch2executorch
torch2executorch(model, im, output_dir="resnet18_executorch_model")エクスポートされた .pte ファイルは出力ディレクトリ内に保存されます。
resnet18_executorch_model/
└── model.ptetorch>=2.9.0 と一致する ExecuTorch ランタイム(pip install executorch)が必要です。ランタイムの使用方法については、ExecuTorch インテグレーションを参照してください。
エクスポートしたモデルの検証#
エクスポート後、本番稼働の前に元の PyTorch モデルとの数値の一致を検証してください。ultralytics.nn.backends からの ONNXBackend を使用した簡単なスモークテストにより、出力が比較され、トレーシングや量子化のエラーが早期にフラグ付けされます。
import numpy as np
import timm
import torch
from ultralytics.nn.backends import ONNXBackend
model = timm.create_model("resnet18", pretrained=True).eval()
im = torch.randn(1, 3, 224, 224)
with torch.no_grad():
pytorch_output = model(im).numpy()
onnx_model = ONNXBackend("resnet18.onnx", device=torch.device("cpu"))
onnx_output = onnx_model(im)[0]
diff = np.abs(pytorch_output - onnx_output).max()
print(f"Max difference: {diff:.6f}") # typically ~1e-5, well under 1e-4 for FP32FP32 エクスポートの場合、最大絶対差は通常 1e-5 程度であり、1e-4 を大きく下回る必要があります。差が大きい場合は、サポートされていない演算、不正な入力形状、または評価モードになっていないモデルを示しています。FP16 および INT8 エクスポートの許容誤差はより緩やかです。ランダムなテンソルではなく、実際のデータで検証してください。
他のランタイムでは、入力テンソル名が異なる場合があります。たとえば、OpenVINO はモデルの順伝播引数名(汎用モデルの場合は通常 x)を使用し、torch2onnx はデフォルトで "images" になります。
既知の制限事項#
- マルチ入力のサポートは不均一です:
torch2onnxとtorch2openvinoは、複数の入力を持つモデルに対してテンソルのタプルまたはリストを受け入れます。torch2torchscript、torch2coreml、torch2ncnn、torch2paddle、torch2executorchは、単一の入力テンソルを前提としています。 - ExecuTorch には
flatcが必要です: ExecuTorch ランタイムには FlatBuffers コンパイラが必要です。macOS ではbrew install flatbuffers、Ubuntu ではapt install flatbuffers-compilerでインストールしてください。 - Ultralytics による推論なし: エクスポートされた非 YOLO モデルは、推論のために
YOLO()を介して再度読み込むことはできません。各フォーマットのネイティブランタイム(ONNX Runtime、OpenVINO Runtime など)を使用してください。 - YOLO専用フォーマット: Axelera および Sony IMX500 のエクスポートには YOLO 固有のモデル属性が必要であり、汎用モデルでは利用できません。
- プラットフォーム固有のフォーマット: TensorRT には NVIDIA GPU が必要です。RKNN には
rknn-toolkit2SDK(Linux のみ)が必要です。Edge TPU にはedgetpu_compilerバイナリ(Linux のみ)が必要です。
結論#
これらのユーティリティは、プレーンな torch.nn.Module から、デプロイ準備が整った ONNX、OpenVINO、CoreML、TensorFlow、またはモバイルランタイムのアーティファクトまで、一貫した API を介して任意の PyTorch モデルを変換します。ターゲットハードウェアに一致するフォーマットを選択し、元のモデルに対して数値的パリティを検証してから、ランタイム固有のデプロイ手順について一致するインテグレーションガイドに従ってください。
よくある質問 (FAQ)#
任意の
torch.nn.Module。これには、timm、torchvision、または任意のカスタム PyTorch モデルからのモデルが含まれます。モデルはエクスポート前に評価モード(model.eval())である必要があります。ONNX および OpenVINO は、マルチ入力モデル用の例示テンソルのタプルも追加で受け付けます。サポートされているすべてのフォーマット(TorchScript、ONNX、OpenVINO、CoreML、TF SavedModel、TF Frozen Graph、NCNN、PaddlePaddle、MNN、ExecuTorch)は CPU 上でエクスポート可能です。エクスポートプロセス自体に GPU は不要です。TensorRT のみが NVIDIA GPU を必要とする唯一のフォーマットです。
Ultralytics の
>=8.4.38を使用します。これには、ultralytics.utils.exportモジュールと、標準化されたoutput_file/output_dir引数が含まれています。はい。torchvision の分類器、検出器、およびセグメンテーションモデルは、
torch2coremlを介して.mlpackageにエクスポートされます。画像分類モデルの場合は、分類ヘッドを組み込むためにクラス名のリストをclassifier_namesに渡します。 macOS または Linux でエクスポートを実行してください。CoreML は Windows ではサポートされていません。iOS デプロイの詳細については、CoreML 統合 をご覧ください。はい、いくつかのフォーマットで可能です。OpenVINO、CoreML、MNN、または NCNN にエクスポートする場合は、FP16 の場合は
quantize=16を、INT8 の場合はquantize=8を渡します。OpenVINO での INT8 には、さらに ポストトレーニング量子化 用のcalibration_dataset引数が必要です。量子化のトレードオフについては、各フォーマットの統合ページをご覧ください。元の PyTorch モデルとエクスポートされたモデルを同じ入力で実行し、出力を比較します。一致するバックエンド(ONNX の場合は
ONNXBackendなど)を使用してエクスポートされたファイルを読み込み、最大絶対差を確認します。FP32 エクスポートの場合、通常は1e-5程度であり、1e-4を大幅に下回る必要があります。ギャップが大きい場合は、サポートされていない演算、誤った入力形状、または評価モードになっていないモデルを示しています。実行可能な例については、エクスポートしたモデルの検証を参照してください。