Nicht-YOLO-PyTorch-Modelle mit Ultralytics exportieren#
Ultralytics stellt eigenständige Exportwerkzeuge unter ultralytics.utils.export bereit, die mehrere Backends hinter einer einheitlichen Schnittstelle bündeln. Du kannst jedes torch.nn.Module exportieren, darunter Bildmodelle von timm, Klassifikatoren und Detektoren von torchvision sowie eigene Architekturen, und zwar nach TorchScript, ONNX, OpenVINO, CoreML, Core AI, TensorFlow SavedModel, TensorFlow Frozen Graph, PaddlePaddle, MNN, NCNN und ExecuTorch, ohne dich separat in jedes Backend einarbeiten zu müssen.
PyTorch-Modelle für den Produktionseinsatz bereitzustellen bedeutet meist, für jedes Ziel einen anderen Exporter zu verwenden: torch.onnx.export für ONNX, coremltools für Apple-Geräte, onnx2tf für TensorFlow, pnnx für NCNN und so weiter. Jedes Werkzeug hat seine eigene API, spezielle Abhängigkeiten und Ausgabeformate. Diese Dienstprogramme fassen das in einem einzigen Aufrufmuster zusammen.
Warum Ultralytics für den Export von Nicht-YOLO-Modellen verwenden?#
- Eine API für 11 Formate: Lerne eine einzige Aufrufkonvention statt einem Dutzend.
- Derselbe Codepfad wie bei YOLO-Exporten: Dieselben Hilfsfunktionen werden für alle Ultralytics-YOLO-Exporte verwendet.
- FP16- und INT8-Quantisierung über ein einziges Argument
quantizefür Formate, die dies unterstützen. - Funktioniert auf der CPU: Für den Export selbst ist keine GPU erforderlich, sodass du ihn lokal auf einem Laptop ausführen kannst; der CoreML-Export wird unter Windows nicht unterstützt, und für den Core AI-Export ist macOS 26 oder neuer auf Apple silicon oder x86_64 Linux mit glibc 2.34 oder neuer sowie Python 3.11 bis 3.14 erforderlich.
Schnellstart#
Der schnellste Weg ist ein Export nach ONNX in zwei Zeilen – ohne YOLO-Code und ohne weitere Einrichtung als pip install ultralytics onnx timm:
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")Unterstützte Exportformate#
Die Funktionen torch2* erwarten ein standardmäßiges torch.nn.Module und einen Beispiel-Eingabetensor. MNN, TF SavedModel und TF Frozen Graph verwenden ein zwischengeschaltetes ONNX- oder Keras-Artefakt. In beiden Fällen sind keine YOLO-spezifischen Attribute erforderlich.
| Format | Funktion | Installation | Ausgabe |
|---|---|---|---|
| TorchScript | torch2torchscript() | in PyTorch enthalten | .torchscript-Datei |
| ONNX | torch2onnx() | pip install onnx | .onnx-Datei |
| OpenVINO | torch2openvino() | pip install openvino | _openvino_model/-Verzeichnis |
| CoreML | torch2coreml() | pip install coremltools | .mlpackage |
| Core AI | torch2coreai() | pip install coreai-torch (Apple silicon macOS 26+, x86_64 Linux glibc 2.34+; Python 3.11-3.14) | .aimodel-Verzeichnis |
| TF SavedModel | onnx2saved_model() | siehe detaillierte Anforderungen unten | _saved_model/-Verzeichnis |
| TF Frozen Graph | keras2pb() | siehe detaillierte Anforderungen unten | .pb-Datei |
| PaddlePaddle | torch2paddle() | pip install paddlepaddle x2paddle | _paddle_model/-Verzeichnis |
| MNN | onnx2mnn() | pip install MNN | .mnn-Datei |
| NCNN | torch2ncnn() | pip install ncnn pnnx | _ncnn_model/-Verzeichnis |
| ExecuTorch | torch2executorch() | pip install executorch | _executorch_model/-Verzeichnis |
Mehrere Exportfunktionen akzeptieren ein optionales metadata-Wörterbuch (z. B. torch2torchscript(..., metadata={"author": "me"})), das benutzerdefinierte Schlüssel-Wert-Paare in das exportierte Artefakt einbettet, sofern das Format dies unterstützt.
Schritt-für-Schritt-Beispiele#
Alle folgenden Beispiele verwenden dieselbe Konfiguration: ein vortrainiertes ResNet-18 von timm im Evaluierungsmodus:
import timm
import torch
model = timm.create_model("resnet18", pretrained=True).eval()
im = torch.randn(1, 3, 224, 224)Dropout, Batch-Normalisierung und andere ausschließlich beim Training verwendete Schichten verhalten sich bei der Inferenz anders. Wenn du .eval() überspringst, entstehen Exporte mit falschen Ausgaben.
Ins ONNX-Format exportieren#
from ultralytics.utils.export import torch2onnx
torch2onnx(model, im, output_file="resnet18.onnx")Übergib für eine dynamische Batchgröße ein dynamic-Wörterbuch:
torch2onnx(model, im, output_file="resnet18_dyn.onnx", dynamic={"images": {0: "batch_size"}})Das Standard-Opset ist 14, und der Standardname der Eingabe ist "images". Du kannst diese Werte mit den Argumenten opset, input_names oder output_names überschreiben.
Nach TorchScript exportieren#
Keine zusätzlichen Abhängigkeiten erforderlich. Verwendet intern torch.jit.trace.
from ultralytics.utils.export import torch2torchscript
torch2torchscript(model, im, output_file="resnet18.torchscript")Nach OpenVINO exportieren#
from ultralytics.utils.export import torch2openvino
ov_model = torch2openvino(model, im, output_dir="resnet18_openvino_model")Das Verzeichnis enthält ein Paar aus model.xml und model.bin mit festen Dateinamen:
resnet18_openvino_model/
├── model.xml
└── model.binÜbergib dynamic=True für dynamische Eingabeformen, quantize=16 für FP16 oder quantize=8 für INT8-Quantisierung. Für INT8 ist zusätzlich das Argument calibration_dataset erforderlich.
Erfordert openvino>=2024.0.0 (oder unter macOS 15.4+ >=2025.2.0) sowie torch>=2.1.
Nach CoreML exportieren#
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")Übergib für Klassifikationsmodelle eine Liste mit Klassennamen an classifier_names, um dem CoreML-Modell einen Klassifikationskopf hinzuzufügen.
Erfordert coremltools>=9.0, torch>=1.11 und numpy<=2.3.5. Unter Windows nicht unterstützt.
coremltools>=9.0 stellt Wheels für Python 3.10–3.13 unter macOS und Linux bereit. Bei neueren Python-Versionen kann die native C-Erweiterung nicht geladen werden. Verwende Python 3.10–3.13 für den CoreML-Export.
Nach Core AI exportieren#
from ultralytics.utils.export import torch2coreai
torch2coreai(model, im, output_file="resnet18.aimodel")Das .aimodel-Artefakt ist ein Verzeichnis:
resnet18.aimodel/
├── main.mlirb
├── main.hash
└── metadata.jsonDer Export läuft unter macOS 26 oder neuer auf Apple silicon oder unter x86_64 Linux mit glibc 2.34 oder neuer und Python 3.11 bis 3.14 (pip install coreai-torch), und quantize=16 schreibt ein FP16-Asset, das Eingaben vom Typ float16 erwartet; das Asset läuft unter iOS 27 und macOS 27. Weitere Informationen findest du in der Core-AI-Integration, einschließlich des Hinweises zu FP16-Assets, die beim Laden einen Abbruch verursachen.
Nach TensorFlow SavedModel exportieren#
Beim TF-SavedModel-Export wird ONNX als Zwischenschritt verwendet:
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")Die Funktion gibt ein Keras-Modell zurück und erzeugt außerdem FP32- und FP16-Dateien für LiteRT (.tflite) im Ausgabeverzeichnis:
resnet18_saved_model/
├── saved_model.pb
├── variables/
├── assets/
├── fingerprint.pb
├── resnet18_float32.tflite
└── resnet18_float16.tfliteÜbergib quantize=8, um zusätzlich zu diesen Dateien ein INT8-.tflite hinzuzufügen.
Der TensorFlow-Export funktioniert unter macOS nicht mit Python 3.13 oder neuer. Verwende unter macOS Python 3.12 oder älter oder nutze Linux.
Anforderungen für Python 3.12 oder älter (mit Python 3.13 oder neuer erfordert der Export stattdessen tensorflow>2.19.0, tf_keras>2.19.0,
onnx2tf>=2.3.0,<2.3.16 und protobuf>=6.31.1,<7.0.0):
tensorflow>=2.0.0,<=2.19.0onnx2tf>=1.26.3,<1.29.0tf_keras<=2.19.0sng4onnx>=1.0.1onnx_graphsurgeon>=0.3.26ai-edge-litert>=1.2.0,<1.4.0unter macOS (ai-edge-litert>=1.2.0auf anderen Plattformen)onnxslim>=0.1.82onnx>=1.12.0,<2.0.0protobuf>=5
Nach TensorFlow Frozen Graph exportieren#
Fahre mit dem oben beschriebenen SavedModel-Export fort und wandle das zurückgegebene keras_model in einen eingefrorenen .pb-Graphen um:
from pathlib import Path
from ultralytics.utils.export import keras2pb
keras2pb(keras_model, output_file=Path("resnet18_saved_model/resnet18.pb"))Nach NCNN exportieren#
from ultralytics.utils.export import torch2ncnn
torch2ncnn(model, im, output_dir="resnet18_ncnn_model")Das Verzeichnis enthält Dateien mit festen Namen für param und bin sowie einen Python-Wrapper:
resnet18_ncnn_model/
├── model.ncnn.param
├── model.ncnn.bin
└── model_ncnn.pyNach MNN exportieren#
Für den MNN-Export wird eine ONNX-Datei als Eingabe benötigt. Exportiere zuerst nach ONNX und konvertiere anschließend:
from ultralytics.utils.export import onnx2mnn, torch2onnx
torch2onnx(model, im, output_file="resnet18.onnx")
onnx2mnn("resnet18.onnx", output_file="resnet18.mnn")Unterstützt quantize=16 für FP16 und quantize=8 für INT8-Quantisierung. Erfordert MNN>=2.9.6 und torch>=1.10.
Nach PaddlePaddle exportieren#
from ultralytics.utils.export import torch2paddle
torch2paddle(model, im, output_dir="resnet18_paddle_model")Das Verzeichnis enthält das PaddlePaddle-Modell und die Parameterdateien:
resnet18_paddle_model/
├── inference_model/
│ ├── model.json
│ └── model.pdiparams
├── model.pdparams
└── x2paddle_code.pyErfordert x2paddle und die passende PaddlePaddle-Distribution für deine Plattform:
paddlepaddle-gpu>=3.0.0,<3.3.0unter CUDApaddlepaddle==3.0.0auf einer ARM64-CPUpaddlepaddle>=3.0.0,<3.3.0auf anderen CPUs
Unter NVIDIA Jetson nicht unterstützt.
Nach ExecuTorch exportieren#
from ultralytics.utils.export import torch2executorch
torch2executorch(model, im, output_dir="resnet18_executorch_model")Die exportierte Datei .pte wird im Ausgabeverzeichnis gespeichert:
resnet18_executorch_model/
└── model.pteErfordert torch>=2.9.0 und eine passende ExecuTorch-Laufzeit (pip install executorch). Informationen zur Verwendung der Laufzeit findest du in der ExecuTorch-Integration.
Exportiertes Modell überprüfen#
Überprüfe nach dem Export die numerische Übereinstimmung mit dem ursprünglichen PyTorch-Modell, bevor du es bereitstellst. Ein schneller Rauchtest mit ONNXBackend aus ultralytics.nn.backends vergleicht die Ausgaben und erkennt frühzeitig Fehler beim Tracing oder bei der Quantisierung:
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 exportBei ResNet-18 liegen die meisten FP32-Exporte höchstens etwa 1e-5 von PyTorch entfernt, und TorchScript stimmt exakt überein. Drei Laufzeitumgebungen können einen FP32-Export dennoch mit reduzierter Genauigkeit berechnen und nahe bei 1e-2 bis 1e-1 liegen: NCNN aktiviert FP16-Arithmetik auf CPUs, die diese unterstützen, MNNBackend lädt Modelle mit precision="low", und das OpenVINO-CPU-Plugin läuft auf bestimmter Hardware, etwa Apple silicon, im standardmäßigen Ausführungsmodus PERFORMANCE automatisch mit FP16. Eine Abweichung, die deutlich über der formatspezifischen Baseline liegt, weist auf nicht unterstützte Ops, eine falsche Eingabeform oder ein Modell hin, das sich nicht im Evaluierungsmodus befindet. Bei FP16- und INT8-Exporten gelten großzügigere Toleranzen. Validiere mit echten Daten statt mit Zufallstensoren.
Bei anderen Laufzeitumgebungen kann der Name des Eingabetensors abweichen. OpenVINO verwendet beispielsweise den Namen des Forward-Arguments des Modells (bei allgemeinen Modellen normalerweise x), während torch2onnx standardmäßig "images" verwendet.
Exportiertes Modell ausführen#
Exportierte Nicht-YOLO-Modelle lassen sich über die normale YOLO()-API laden. Die oben erstellten Exporte enthalten keine Ultralytics-Metadaten zur Aufgabe oder Eingabegröße. Übergib daher task explizit und gib für imgsz den Wert des Beispiel-Tensors an, mit dem du exportiert hast:
from ultralytics import YOLO
results = YOLO("resnet18.onnx", task="classify")("path/to/image.jpg", imgsz=224)
print(results[0].probs.top1)imgsz ist wichtig, wenn der Export eine feste Eingabeform hat: Die oben gezeigten ONNX- und TF-SavedModel-Exporte weisen den Standardwert 640 zurück. Die oben gezeigten TorchScript- und NCNN-Exporte akzeptieren zwar auch andere Größen, aber keiner der beiden Exporter garantiert dies: Beide erstellen einen Trace anhand des Beispiel-Tensors. Ein Modell, das in eine Linear-Schicht abflacht, behält daher eine feste Form. Überprüfe deinen Export.
Der Wert wird anschließend auf das nächste Vielfache des Modell-Strides aufgerundet, der ohne Metadaten 32 beträgt. Ein Export mit fester Form von 200x200 erhält daher eine Eingabe von 224x224 und wird zurückgewiesen, obwohl imgsz=200 dazu passt. Bei Eingabegrößen, die kein Vielfaches von 32 sind, rufe das Backend direkt auf.
Ein Backend direkt aufrufen#
Für rohe Tensoren ohne Ultralytics-Vorverarbeitung und -Nachverarbeitung verwende die formatspezifischen Klassen in ultralytics.nn.backends, wie im Überprüfungsbeispiel oben. Jede Klasse erwartet das exportierte Artefakt und ein Gerät und ist aufrufbar:
| Format | Backend | Eingabelayout |
|---|---|---|
| TorchScript | TorchScriptBackend | BCHW |
| ONNX | ONNXBackend | BCHW |
| OpenVINO | OpenVINOBackend | BCHW |
| CoreML | CoreMLBackend | BHWC |
| Core AI | CoreAIBackend | BCHW |
| TF SavedModel, Frozen Graph | TensorFlowBackend | BHWC |
| LiteRT | LiteRTBackend | BCHW |
| PaddlePaddle | PaddleBackend | BCHW |
| MNN | MNNBackend | BCHW |
| NCNN | NCNNBackend | BCHW |
| ExecuTorch | ExecuTorchBackend | BCHW |
TensorFlowBackend unterstützt zwei Formate und verwendet standardmäßig format="saved_model". Übergib für einen Frozen Graph daher format="pb".
Drei Dinge, die der Weg über YOLO() für dich übernimmt, ein direkter Aufruf jedoch nicht:
- Eingabelayout:
CoreMLBackendundTensorFlowBackenderwarten BHWC. Transponiere den Tensor zuerst mitim.permute(0, 2, 3, 1). Ein BCHW-Tensor führt zu einer nicht übereinstimmenden Form. - Autograd: Umschließe Aufrufe mit
torch.inference_mode().TorchScriptBackendgibt einen Tensor zurück, der weiterhin einen Gradienten-Graphen enthält. - Nachverarbeitung: Ohne Metadaten gibt ein Backend
taskalsNoneundnamesleer zurück.LiteRTBackendskaliert weiterhin jede 3D-Ausgabe anhand der Bildgröße zurück, da es von YOLO-Boxen ausgeht. Bei einem Nicht-YOLO-Modell mit einer 3D-Ausgabe ist das falsch. Zweidimensionale Ausgaben wie Klassifikator-Logits sind davon nicht betroffen.
Bekannte Einschränkungen#
- Die Unterstützung mehrerer Eingaben ist uneinheitlich:
torch2onnx,torch2openvinoundtorch2torchscriptakzeptieren bei Modellen mit mehreren Eingaben ein Tupel von Beispiel-Tensoren.torch2coreml,torch2coreai,torch2ncnn,torch2paddleundtorch2executorchsetzen einen einzelnen Eingabe-Tensor voraus. - Nur für YOLO verfügbare Formate: Exporte für Axelera und Sony IMX500 erfordern YOLO-spezifische Modellattribute und sind für allgemeine Modelle nicht verfügbar.
- Plattformspezifische Formate: Für TensorRT ist eine NVIDIA-GPU erforderlich. Für RKNN ist das
rknn-toolkit2SDK erforderlich (nur Linux). Für Edge TPU wird die Binärdateiedgetpu_compilerbenötigt (nur Linux).
Fazit#
Mit diesen Dienstprogrammen kannst du jedes PyTorch-Modell – vom einfachen torch.nn.Module bis hin zu einem einsatzbereiten ONNX-, OpenVINO-, CoreML-, TensorFlow- oder Mobile-Runtime-Artefakt – über eine einheitliche API exportieren. Wähle das Format passend zu deiner Zielhardware, überprüfe die numerische Übereinstimmung mit dem ursprünglichen Modell und befolge anschließend die passende Integrationsanleitung für die plattformspezifischen Bereitstellungsschritte.
Häufig gestellte Fragen#
Beliebiges
torch.nn.Module. Dazu gehören Modelle von timm, torchvision und alle benutzerdefinierten PyTorch-Modelle. Das Modell muss vor dem Export im Evaluierungsmodus sein (model.eval()). ONNX, OpenVINO und TorchScript akzeptieren außerdem ein Tupel von Beispiel-Tensoren für Modelle mit mehreren Eingaben.Alle unterstützten Formate (TorchScript, ONNX, OpenVINO, CoreML, Core AI, TF SavedModel, TF Frozen Graph, PaddlePaddle, MNN, NCNN und ExecuTorch) können auf der CPU exportiert werden. Für den Export selbst ist keine GPU erforderlich. TensorRT ist das einzige Format, das eine NVIDIA-GPU voraussetzt.
Verwende die neueste Version. Für das Argument
quantizeist Ultralytics>=8.4.81erforderlich, und für den Core-AI-Export wird>=8.4.131benötigt (>=8.4.163unter Linux oder mitcoreai-torch>=0.4.3).Ja. Klassifikations-, Erkennungs- und Segmentierungsmodelle aus torchvision lassen sich über
torch2coremlnach.mlpackageexportieren. Übergib bei Bildklassifizierungsmodellen eine Liste mit Klassennamen anclassifier_names, um einen Klassifikationskopf einzubinden. Führe den Export unter macOS oder Linux aus. CoreML wird unter Windows nicht unterstützt. Einzelheiten zum Einsatz unter iOS findest du in der CoreML-Integration.Ja, bei mehreren Formaten. Übergib beim Export nach OpenVINO, CoreML oder MNN
quantize=16für FP16 oderquantize=8für INT8;onnx2saved_modelbenötigtquantize=8für eine INT8-LiteRT-Datei, und NCNN sowie der Core-AI-Export verwenden standardmäßig FP32, akzeptierenquantize=16für FP16 und bieten keine INT8-Option. INT8 in OpenVINO erfordert zusätzlich ein Argumentcalibration_datasetfür die Quantisierung nach dem Training. Auf der Integrationsseite des jeweiligen Formats findest du Informationen zu den Kompromissen bei der Quantisierung.Führe das ursprüngliche PyTorch-Modell und das exportierte Modell mit derselben Eingabe aus und vergleiche anschließend die Ausgaben. Lade die exportierte Datei mit dem passenden Backend (zum Beispiel
ONNXBackendfür ONNX) und prüfe die maximale absolute Abweichung. Beurteile die Differenz anhand der formatspezifischen Baseline: NCNN,MNNBackendund OpenVINO auf einigen CPUs können FP32-Exporte mit reduzierter Genauigkeit ausführen und nahe bei1e-2bis1e-1liegen, während die meisten anderen Formate nahe bei1e-5liegen. Eine deutlich größere Differenz weist auf nicht unterstützte Ops, eine falsche Eingabeform oder ein Modell hin, das sich nicht im Evaluierungsmodus befindet. Ein ausführbares Beispiel findest du unter Exportiertes Modell überprüfen.