So exportierst du PyTorch-Modelle ohne YOLO mit Ultralytics
Das Bereitstellen von PyTorch-Modellen für die Produktion bedeutet normalerweise, für jedes Ziel einen anderen Exporter zu jonglieren:torch.onnx.export für ONNX, coremltools für Apple-Geräte, onnx2tf für TensorFlow, pnnx für NCNN und so weiter. Jedes Tool hat seine eigene API, Abhängigkeitsbesonderheiten und Ausgabekonventionen.
Ultralytics bietet eigenständige Export-Utilities, die mehrere Backends unter einer konsistenten Schnittstelle zusammenfassen. Du kannst beliebige torch.nn.Module erweitern, einschließlich timm Bildmodelle, torchvision Klassifikatoren und Detektoren oder deine eigenen benutzerdefinierten Architekturen nach ONNX, TorchScript, OpenVINO, CoreML, NCNN, PaddlePaddle, MNN, ExecuTorch, und TensorFlow SavedModel exportieren, ohne jedes Backend einzeln lernen zu müssen.
Warum Ultralytics für Exporte ohne YOLO nutzen?
- Eine API für 10 Formate: lerne eine einzige Aufrufkonvention anstelle eines Dutzends.
- Gemeinsame Utility-Oberfläche: die Export-Hilfsmittel befinden sich unter
ultralytics.utils.export, sodass du nach der Installation der Backend-Pakete das gleiche Aufrufmuster über alle Formate hinweg beibehalten kannst. - Gleicher Code-Pfad wie bei YOLO-Exporten: dieselben Hilfsmittel treiben jeden Ultralytics YOLO-Export an.
- FP16 und INT8 Quantisierung integriert für Formate, die dies unterstützen (OpenVINO, CoreML, MNN, NCNN).
- Funktioniert auf der CPU: kein GPU für den Export-Schritt selbst erforderlich, sodass du ihn lokal auf jedem Laptop ausführen kannst.
Schnellstart
Der schnellste Weg ist ein Export in zwei Zeilen zu ONNX 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 torch2* Funktionen akzeptieren einen Standard torch.nn.Module und einen Beispiel-Input-Tensor. MNN, TF SavedModel und TF Frozen Graph durchlaufen ein zwischengeschaltetes ONNX- oder Keras-Artefakt. In keinem Fall sind YOLO-spezifische Attribute erforderlich.
| Format | Funktion | Installieren | Ausgabe |
|---|---|---|---|
| ONNX | torch2onnx() | pip install onnx | .onnx Datei |
| TorchScript | torch2torchscript() | in PyTorch enthalten | .torchscript Datei |
| OpenVINO | torch2openvino() | pip install openvino | _openvino_model/ Verzeichnis |
| CoreML | torch2coreml() | pip install coremltools | .mlpackage |
| TF SavedModel | onnx2saved_model() | siehe detaillierte Anforderungen unten | _saved_model/ Verzeichnis |
| TF Frozen Graph | keras2pb() | siehe detaillierte Anforderungen unten | .pb Datei |
| NCNN | torch2ncnn() | pip install ncnn pnnx | _ncnn_model/ Verzeichnis |
| MNN | onnx2mnn() | pip install MNN | .mnn Datei |
| PaddlePaddle | torch2paddle() | pip install paddlepaddle x2paddle | _paddle_model/ Verzeichnis |
| ExecuTorch | torch2executorch() | pip install executorch | _executorch_model/ Verzeichnis |
MNN, TF SavedModel, und TF Frozen Graph-Exporte durchlaufen ONNX als Zwischenschritt. Exportiere zuerst nach ONNX und konvertiere dann.
Mehrere Exportfunktionen akzeptieren ein optionales metadata Dictionary (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
Jedes Beispiel unten verwendet das gleiche Setup, 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 Normalization und andere reine Trainings-Layer verhalten sich während der Inferenz anders. Das Überspringen von .eval() führt zu Exporten mit falschen Ausgaben.
Export nach ONNX
from ultralytics.utils.export import torch2onnx
torch2onnx(model, im, output_file="resnet18.onnx")Für dynamische Batch-Größen übergib ein dynamic Dictionary:
torch2onnx(model, im, output_file="resnet18_dyn.onnx", dynamic={"images": {0: "batch_size"}})Der Standard-Opset ist 14 und der Standard-Input-Name ist "images". Überschreibe dies mit den opset, input_names, oder output_names Argumenten.
Export nach TorchScript
Keine zusätzlichen Abhängigkeiten erforderlich. Verwendet torch.jit.trace unter der Haube.
from ultralytics.utils.export import torch2torchscript
torch2torchscript(model, im, output_file="resnet18.torchscript")Export nach OpenVINO
from ultralytics.utils.export import torch2openvino
ov_model = torch2openvino(model, im, output_dir="resnet18_openvino_model")Das Verzeichnis enthält ein model.xml und Fortschritten im Bereich model.bin Paar mit festem Namen:
resnet18_openvino_model/
├── model.xml
└── model.binÜbergib dynamic=True für dynamische Input-Formen, half=True für FP16 oder int8=True für INT8 Quantisierung. INT8 erfordert zusätzlich ein calibration_dataset Arguments.
Erfordert openvino>=2024.0.0 (oder >=2025.2.0 unter macOS 15.4+) und torch>=2.1.
Export nach 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, output_file="resnet18.mlpackage")Für Klassifizierung Modelle, übergib eine Liste von Klassennamen an classifier_names, um dem CoreML-Modell einen Klassifizierungskopf hinzuzufügen.
Erfordert coremltools>=9.0, torch>=1.11, und numpy<=2.3.5. Unter Windows nicht unterstützt.
coremltools>=9.0 liefert Wheels für Python 3.10–3.13 unter macOS und Linux aus. Bei neueren Python-Versionen kann die native C-Erweiterung nicht geladen werden. Verwende Python 3.10–3.13 für den CoreML-Export.
Export nach TensorFlow SavedModel
Der TF SavedModel-Export erfolgt über ONNX als Zwischenschritt:
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 generiert auch TFLite-Dateien (.tflite) im Ausgabeverzeichnis:
resnet18_saved_model/
├── saved_model.pb
├── variables/
├── resnet18_float32.tflite
├── resnet18_float16.tflite
└── resnet18_int8.tfliteAnforderungen:
tensorflow>=2.0.0,<=2.19.0onnx2tf>=1.26.3,<1.29.0tf_keras<=2.19.0sng4onnx>=1.0.1onnx_graphsurgeon>=0.3.26(installiere mit--extra-index-url https://pypi.ngc.nvidia.com)ai-edge-litert>=1.2.0,<1.4.0auf macOS (ai-edge-litert>=1.2.0auf anderen Plattformen)onnxslim>=0.1.71onnx>=1.12.0,<2.0.0protobuf>=5
Export nach TensorFlow Frozen Graph
Weiterführend vom obigen SavedModel-Export, konvertiere das zurückgegebene Keras-Modell in einen eingefrorenen .pb Graph:
from pathlib import Path
from ultralytics.utils.export import keras2pb
keras2pb(keras_model, output_file=Path("resnet18_saved_model/resnet18.pb"))Export nach NCNN
from ultralytics.utils.export import torch2ncnn
torch2ncnn(model, im, output_dir="resnet18_ncnn_model")Das Verzeichnis enthält param- und bin-Dateien mit festem Namen sowie einen Python-Wrapper:
resnet18_ncnn_model/
├── model.ncnn.param
├── model.ncnn.bin
└── model_ncnn.pytorch2ncnn() prüft auf ncnn und Fortschritten im Bereich pnnx heruntergeladen.
Export nach MNN
Der MNN-Export erfordert eine ONNX-Datei als Eingabe. Exportiere zuerst nach ONNX und konvertiere dann:
from ultralytics.utils.export import onnx2mnn, torch2onnx
torch2onnx(model, im, output_file="resnet18.onnx")
onnx2mnn("resnet18.onnx", output_file="resnet18.mnn")Unterstützt half=True für FP16 und int8=True für INT8 Quantisierung. Erfordert MNN>=2.9.6 und Fortschritten im Bereich torch>=1.10.
Export nach PaddlePaddle
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/
├── model.pdmodel
└── model.pdiparamsErfordert x2paddle und die korrekte PaddlePaddle-Distribution für deine Plattform:
paddlepaddle-gpu>=3.0.0,<3.3.0auf CUDApaddlepaddle==3.0.0auf ARM64 CPUpaddlepaddle>=3.0.0,<3.3.0auf anderen CPUs
Auf NVIDIA Jetson nicht unterstützt.
Export nach ExecuTorch
from ultralytics.utils.export import torch2executorch
torch2executorch(model, im, output_dir="resnet18_executorch_model")Die exportierte .pte Datei wird im Ausgabeverzeichnis gespeichert:
resnet18_executorch_model/
└── model.pteErfordert torch>=2.9.0 und eine passende ExecuTorch-Laufzeitumgebung (pip install executorch). Informationen zur Nutzung der Laufzeitumgebung findest du in der ExecuTorch-Integration.
Verifiziere dein exportiertes Modell
Verifiziere nach dem Export die numerische Parität mit dem ursprünglichen PyTorch-Modell, bevor du es bereitstellst. Ein schneller Rauchtest mit ONNXBackend von ultralytics.nn.backends vergleicht die Ausgaben und zeigt Fehler bei der Tracing- oder Quantisierung frühzeitig an:
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}") # should be < 1e-5Bei FP32-Exporten sollte die maximale absolute Differenz unter 1e-5 liegen. Größere Unterschiede deuten auf nicht unterstützte Operationen, eine falsche Eingabeform oder ein Modell hin, das sich nicht im Evaluierungsmodus befindet. FP16- und INT8-Exporte haben größere Toleranzen. Validiere auf echten Daten statt auf zufälligen Tensoren.
Für andere Laufzeitumgebungen kann der Name des Eingabetensors abweichen. OpenVINO verwendet beispielsweise den Namen des Forward-Arguments des Modells (typischerweise x für generische Modelle), während torch2onnx standardmäßig "images".
Bekannte Einschränkungen
- Unterstützung für mehrere Eingaben ist uneinheitlich:
torch2onnxund Fortschritten im Bereichtorch2openvinoakzeptieren ein Tupel oder eine Liste von Beispiel-Tensoren für Modelle mit mehreren Eingaben.torch2torchscript,torch2coreml,torch2ncnn,torch2paddle, undtorch2executorchgehen von einem einzelnen Eingabetensor aus. - ExecuTorch benötigt
flatc: Die ExecuTorch-Laufzeitumgebung erfordert den FlatBuffers-Compiler. Installiere ihn mitbrew install flatbuffersauf macOS oderapt install flatbuffers-compilerauf Ubuntu. - Keine Inferenz über Ultralytics: Exportierte Nicht-YOLO-Modelle können nicht zur Inferenz zurück in
YOLO()geladen werden. Verwende die native Laufzeitumgebung für jedes Format (ONNX Runtime, OpenVINO Runtime, etc.). - YOLO-spezifische Formate: Axelera und Fortschritten im Bereich Sony IMX500 Exporte erfordern YOLO-spezifische Modellattribute und sind für generische Modelle nicht verfügbar.
- Plattformspezifische Formate: TensorRT erfordert eine NVIDIA GPU. RKNN erfordert das
rknn-toolkit2SDK (nur Linux). Edge TPU erfordert dasedgetpu_compilerBinary (nur Linux).
FAQ
Welche Modelle kann ich mit Ultralytics exportieren?
Jedes torch.nn.Module. Dies schließt Modelle von timm, torchvision oder jedes benutzerdefinierte PyTorch-Modell ein. Das Modell muss sich vor dem Export im Evaluierungsmodus befinden (model.eval()). ONNX und OpenVINO akzeptieren zusätzlich ein Tupel von Beispiel-Tensoren für Modelle mit mehreren Eingaben.
Welche Exportformate funktionieren ohne GPU?
Alle unterstützten Formate (TorchScript, ONNX, OpenVINO, CoreML, TF SavedModel, TF Frozen Graph, NCNN, PaddlePaddle, MNN, ExecuTorch) können auf der CPU exportiert werden. Für den Exportvorgang selbst ist keine GPU erforderlich. TensorRT ist das einzige Format, das eine NVIDIA GPU erfordert.
Welche Ultralytics-Version benötige ich?
Verwende Ultralytics >=8.4.38, das das ultralytics.utils.export Modul und die standardisierte output_file/output_dir Argumenten.
Kann ich ein torchvision-Modell für die iOS-Bereitstellung nach CoreML exportieren?
Ja. torchvision-Klassifizierungs-, Detektions- und Segmentierungsmodelle exportieren nach .mlpackage via torch2coreml. Für Bildklassifizierungsmodelle übergibst du eine Liste von Klassennamen an classifier_names um einen Klassifizierungskopf zu integrieren. Führe den Export auf macOS oder Linux aus. CoreML wird unter Windows nicht unterstützt. Siehe die CoreML-Integration für Details zur iOS-Bereitstellung.
Kann ich mein exportiertes Modell auf INT8 oder FP16 quantisieren?
Ja, für verschiedene Formate. Übergebe half=True für FP16 oder int8=True für INT8 beim Export nach OpenVINO, CoreML, MNN oder NCNN. INT8 in OpenVINO erfordert zusätzlich ein calibration_dataset Argument für post-training quantization. Siehe die Integrationsseite des jeweiligen Formats für Kompromisse bei der Quantisierung.