YOLO Vision 2026:

非YOLO PyTorchモデルをUltralyticsでエクスポートする方法#

Ultralytics は、複数のバックエンドを1つの統一されたインターフェースの背後にラップする単体のエクスポートユーティリティを ultralytics.utils.export で提供しています。timm 画像モデル、torchvision の分類器や検出器、あるいは独自のカスタムアーキテクチャを含むあらゆる torch.nn.Module を、各バックエンドを個別に学習することなく、ONNXTorchScriptOpenVINOCoreMLNCNNPaddlePaddleMNNExecuTorchCore AITensorFlow SavedModelTensorFlow Frozen Graph にエクスポートできます。

PyTorchモデルを本番環境にデプロイする場合、通常はターゲットごとに異なるエクスポーターを使い分ける必要があります。ONNXにはtorch.onnx.export、Appleデバイスにはcoremltools、TensorFlowにはonnx2tf、NCNNにはpnnxなどを使用します。各ツールには独自のAPI、依存関係に関する癖、出力規約があります。これらのユーティリティでは、それらを単一の呼び出しパターンに統合しています。

非YOLOエクスポートにUltralyticsを使用する理由#

  • 11フォーマットにわたる1つのAPI: 多数の呼び出し規則を覚える代わりに、単一の呼び出し規則を学習できます。
  • 共通のユーティリティインターフェース: エクスポートヘルパーはultralytics.utils.export配下にあるため、バックエンドパッケージをインストールすれば、形式をまたいで同じ呼び出しパターンを使用できます。
  • YOLOエクスポートと同じコードパス: すべてのUltralytics YOLOエクスポートで同じヘルパーを使用します。
  • FP16 および INT8 量子化は、それをサポートするフォーマット(OpenVINO、CoreML、MNN。NCNN および Core AI は FP16 のみ)に対して組み込まれています。
  • CPU で動作: エクスポートステップ自体に GPU は不要なため、ラップトップ上でローカルに実行できます。ただし、CoreML のエクスポートは Windows ではサポートされておらず、Core AI のエクスポートには Apple シリコン上の macOS 26 以降が必要です。

クイックスタート#

最も迅速な方法は、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固有の属性は必要ありません。

形式関数インストール出力
ONNXtorch2onnx()pip install onnx.onnxファイル
TorchScripttorch2torchscript()PyTorchに含まれる.torchscriptファイル
OpenVINOtorch2openvino()pip install openvino_openvino_model/ディレクトリ
CoreMLtorch2coreml()pip install coremltools.mlpackage
TF SavedModelonnx2saved_model()詳細な要件はこちら_saved_model/ディレクトリ
TF Frozen Graphkeras2pb()詳細な要件はこちら.pbファイル
NCNNtorch2ncnn()pip install ncnn pnnx_ncnn_model/ディレクトリ
MNNonnx2mnn()pip install MNN.mnnファイル
PaddlePaddletorch2paddle()pip install paddlepaddle x2paddle_paddle_model/ディレクトリ
ExecuTorchtorch2executorch()pip install executorch_executorch_model/ディレクトリ
Core AItorch2coreai()pip install coreai-torch(Apple シリコン上の macOS 26+).aimodelディレクトリ
中間形式としてのONNX

MNNTF 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)
エクスポート前に必ず`model.eval()`を呼び出してください

Dropout、バッチ正規化、その他の学習時専用レイヤーは、推論時には異なる動作をします。.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"です。opsetinput_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.xmlmodel.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.0torch>=1.11numpy<=2.3.5が必要です。Windowsではサポートされていません。

`BlobWriter not loaded`エラー

coremltools>=9.0は、macOSおよびLinux向けにPython 3.10~3.13のwheelを提供しています。より新しい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モデルを返し、出力ディレクトリ内にFP32およびFP16のLiteRTファイル(.tflite)も生成します。

resnet18_saved_model/
├── saved_model.pb
├── variables/
├── assets/
├── fingerprint.pb
├── resnet18_float32.tflite
└── resnet18_float16.tflite

quantize=8を渡すと、これらと同じ場所にINT8の.tfliteを追加できます。

要件:

  • tensorflow>=2.0.0,<=2.19.0
  • onnx2tf>=1.26.3,<1.29.0
  • tf_keras<=2.19.0
  • sng4onnx>=1.0.1
  • onnx_graphsurgeon>=0.3.26
  • macOSではai-edge-litert>=1.2.0,<1.4.0(その他のプラットフォームではai-edge-litert>=1.2.0
  • onnxslim>=0.1.82
  • onnx>=1.12.0,<2.0.0
  • protobuf>=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")

ディレクトリには、固定名のparamファイルとbinファイル、およびPythonラッパーが含まれます。

resnet18_ncnn_model/
├── model.ncnn.param
├── model.ncnn.bin
└── model_ncnn.py

torch2ncnn()は、初回使用時にncnnpnnxを確認します。

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.6torch>=1.10が必要です。

PaddlePaddleへのエクスポート#

from ultralytics.utils.export import torch2paddle

torch2paddle(model, im, output_dir="resnet18_paddle_model")

ディレクトリには、PaddlePaddleモデルとパラメータファイルが含まれます。

resnet18_paddle_model/
├── model.pdmodel
└── model.pdiparams

x2paddleおよびプラットフォームに適した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.pte

torch>=2.9.0および対応するExecuTorchランタイム(pip install executorch)が必要です。ランタイムでの使用方法については、ExecuTorch統合を参照してください。

Core AI へのエクスポート#

from ultralytics.utils.export import torch2coreai

torch2coreai(model, im, output_file="resnet18.aimodel")

.aimodel アセットはディレクトリです:

resnet18.aimodel/
├── main.mlirb
├── main.hash
└── metadata.json

エクスポートは Apple シリコン上の macOS 26 以降(pip install coreai-torch)で実行され、quantize=16 は float16 入力を受け取る FP16 アセットを書き込みます。このアセットは iOS 27 および macOS 27 で実行されます。ロード時にアブortする FP16 アセットに関する注意事項を含め、Core AI 統合を参照してください。

エクスポートしたモデルを検証する#

エクスポート後、本番環境に出荷する前に、元のPyTorchモデルとの数値的な一致を検証してください。ultralytics.nn.backendsONNXBackendを使用した簡単なスモークテストで出力を比較し、トレースや量子化のエラーを早期に検出できます。

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}")  # ~1e-6 for an FP32 ONNX export
想定される差分

許容値はグローバルではなく、形式ごとに異なります。ResNet-18では、FP32エクスポートはONNX、TF SavedModel、LiteRTで1e-6付近になり、TorchScriptでは正確に0になります。NCNNは例外で、およそ1e-2です。NCNNのCPUランタイムではデフォルトでFP16パッキングと演算が有効になるため、FP32エクスポートでも半精度で実行されます。形式固有のベースラインを大幅に上回る差分は、未サポートの演算、誤った入力形状、またはモデルが評価モードでないことを示します。FP16およびINT8エクスポートでは、より緩い許容値が適用されます。ランダムテンソルではなく、実データで検証してください。

その他のランタイムでは、入力テンソル名が異なる場合があります。たとえばOpenVINOでは、モデルのforward引数名(汎用モデルでは通常x)を使用します。一方、torch2onnxのデフォルトは"images"です。

エクスポートしたモデルを実行する#

エクスポートした非YOLOモデルは、通常のYOLO() APIを介して再読み込みできます。上記のエクスポートにはUltralyticsのタスクや入力サイズのメタデータが含まれないため、taskを明示的に渡し、エクスポート時に使用したサンプルテンソルに対応するimgszも指定してください。

from ultralytics import YOLO

results = YOLO("resnet18.onnx", task="classify")("path/to/image.jpg", imgsz=224)
print(results[0].probs.top1)

エクスポートが固定入力形状の場合、imgszが重要になります。上記のONNXおよびTF SavedModelエクスポートは、デフォルトの640を受け付けません。上記のTorchScriptおよびNCNNエクスポートは他のサイズも受け付けますが、どちらのエクスポーターもそれを保証していません。どちらもサンプルテンソルからトレースするため、Linearレイヤーにフラット化するモデルは固定されたままです。ご自身のエクスポートを確認してください。

その値は、メタデータがない場合は32であるモデルのストライドの倍数に切り上げられます。そのため、200x200での固定形状エクスポートは224x224にして入力され、imgsz=200が一致していても拒否されます。32の倍数ではない入力サイズを使用する場合は、バックエンドを直接呼び出してください。

バックエンドを直接呼び出す#

Ultralyticsの前処理や後処理を行わずに生のテンソルを扱う場合は、ultralytics.nn.backends内の形式ごとのクラスを使用します。上記の検証例でも使用しています。各クラスはエクスポートしたアーティファクトとデバイスを受け取り、呼び出し可能です。

形式バックエンド入力レイアウト
ONNXONNXBackendBCHW
TorchScriptTorchScriptBackendBCHW
OpenVINOOpenVINOBackendBCHW
CoreMLCoreMLBackendBHWC
TF SavedModel、Frozen GraphTensorFlowBackendBHWC
LiteRTLiteRTBackendBCHW
NCNNNCNNBackendBCHW
PaddlePaddlePaddleBackendBCHW
MNNMNNBackendBCHW
ExecuTorchExecuTorchBackendBCHW
Core AICoreAIBackendBCHW

TensorFlowBackendは2つの形式を扱い、デフォルトではformat="saved_model"を使用するため、Frozen Graphにはformat="pb"を渡してください。

YOLO()経由では処理されますが、直接呼び出しでは処理されない3つの事項:

  • 入力レイアウト: CoreMLBackendTensorFlowBackendはBHWCを想定します。まずim.permute(0, 2, 3, 1)で転置してください。BCHWテンソルを渡すと形状不一致が発生します。
  • Autograd: 呼び出しをtorch.inference_mode()でラップしてください。TorchScriptBackendは、勾配グラフを保持したテンソルを返します。
  • 後処理: メタデータがない場合、バックエンドはtaskNoneとして残し、namesを空のままにします。LiteRTBackendは、YOLOボックスを保持しているという前提で、画像サイズに基づいて3次元出力を非正規化します。これは、3次元出力を持つ非YOLOモデルでは誤りです。分類器のロジットなどの2次元出力には影響しません。

既知の制限事項#

  • マルチ入力のサポートは不均一です: torch2onnx および torch2openvino は、複数の入力を持つモデルに対してサンプルテンソルのタプルまたはリストを受け入れます。torch2torchscripttorch2coremltorch2ncnntorch2paddletorch2executorchtorch2coreai は単一の入力テンソルを想定しています。
  • ExecuTorchにはflatcが必要です: ExecuTorchランタイムにはFlatBuffersコンパイラーが必要です。macOSではbrew install flatbuffers、Ubuntuではapt install flatbuffers-compilerを使用してインストールしてください。
  • 埋め込みメタデータはありません: 上記のエクスポートにはUltralyticsのタスクや入力サイズのメタデータが含まれないため、YOLO()はどちらも推測できず、両方を明示的に渡す必要があります。エクスポートしたモデルを実行するを参照してください。
  • YOLO専用形式: AxeleraおよびSony IMX500のエクスポートにはYOLO固有のモデル属性が必要であり、汎用モデルでは利用できません。
  • プラットフォーム固有の形式: TensorRTにはNVIDIA GPUが必要です。RKNNにはrknn-toolkit2 SDK(Linuxのみ)が必要です。Edge TPUにはedgetpu_compilerバイナリ(Linuxのみ)が必要です。

まとめ#

これらのユーティリティを使用すると、プレーンなtorch.nn.Moduleから、デプロイ可能なONNX、OpenVINO、CoreML、TensorFlow、またはモバイルランタイム用アーティファクトまで、任意のPyTorchモデルを一貫した単一のAPIで変換できます。ターゲットハードウェアに適した形式を選び、元のモデルとの数値的一致を検証してから、ランタイム固有のデプロイ手順について対応する統合ガイドに従ってください。

FAQ#

  • 任意のtorch.nn.Moduleです。timm、torchvisionのモデルや、任意のカスタムPyTorchモデルが含まれます。エクスポート前にモデルを評価モード(model.eval())にする必要があります。ONNXとOpenVINOでは、複数入力モデル用にサンプルテンソルのタプルも受け付けます。

  • サポートされているすべてのフォーマット(TorchScript、ONNX、OpenVINO、CoreML、TF SavedModel、TF Frozen Graph、NCNN、PaddlePaddle、MNN、ExecuTorch、Core AI)は CPU 上でエクスポートできます。エクスポートプロセス自体に GPU は必要ありません。NVIDIA GPU を必要とするのは TensorRT のみです。

  • ultralytics.utils.exportモジュールと、標準化されたoutput_file/output_dir引数を含むUltralyticsの>=8.4.38を使用してください。

  • はい。torchvisionの分類器、検出器、セグメンテーションモデルは、torch2coremlを介して.mlpackageへエクスポートできます。画像分類モデルでは、クラス名のリストをclassifier_namesに渡して、分類ヘッドを組み込んでください。エクスポートはmacOSまたはLinux上で実行してください。CoreMLはWindowsではサポートされていません。iOSへのデプロイの詳細については、CoreML統合を参照してください。

  • はい、いくつかのフォーマットで可能です。OpenVINO、CoreML、または MNN にエクスポートする場合は、FP16 の場合は quantize=16 を、INT8 の場合は quantize=8 を渡します。NCNN および Core AI のエクスポートはデフォルトで FP32 であり、FP16 の場合は quantize=16 を受け取りますが、INT8 のパスはありません。OpenVINO における INT8 には、さらに学習後量子化用の calibration_dataset 引数が必要です。量子化のトレードオフについては、各フォーマットの統合ページを参照してください。

  • 同じ入力に対して元のPyTorchモデルとエクスポートしたモデルを実行し、出力を比較します。対応するバックエンドでエクスポートしたファイルを読み込み(たとえば、ONNXの場合はONNXBackend)、最大絶対差を確認します。その差を、形式ごとの独自のベースラインと照らし合わせて判断してください。上記のResNet-18の例では、FP32 ONNX、TF SavedModel、LiteRTは1e-6付近、TorchScriptは0付近にあり、NCNNはCPUランタイムのデフォルトがFP16であるため1e-2付近にあります。差が大幅に大きい場合は、未対応の演算、誤った入力形状、またはモデルがevalモードになっていないことが原因として考えられます。実行可能な例については、エクスポートしたモデルの検証をご覧ください。

コメント