Come esportare modelli PyTorch non-YOLO con Ultralytics#
Ultralytics fornisce utility di esportazione autonome sotto ultralytics.utils.export che incapsulano più backend dietro un'unica interfaccia coerente. Puoi esportare qualsiasi torch.nn.Module, inclusi i modelli di immagine timm, i classificatori e i rilevatori torchvision o le tue architetture personalizzate, in ONNX, TorchScript, OpenVINO, CoreML, NCNN, PaddlePaddle, MNN, ExecuTorch e TensorFlow SavedModel senza dover imparare ogni backend separatamente.
Distribuire i modelli PyTorch in produzione solitamente significa destreggiarsi tra un esportatore diverso per ogni destinazione: torch.onnx.export per ONNX, coremltools per i dispositivi Apple, onnx2tf per TensorFlow, pnnx per NCNN e così via. Ogni strumento ha la sua API, particolarità di dipendenza e convenzioni di output. Queste utility riducono tutto ciò a un unico pattern di chiamata.
Perché usare Ultralytics per l'esportazione non-YOLO?#
- Un'unica API su 10 formati: impara una sola convenzione di chiamata invece di una dozzina.
- Superficie di utility condivisa: gli helper di esportazione si trovano sotto
ultralytics.utils.export, quindi una volta installati i pacchetti del backend puoi mantenere lo stesso pattern di chiamata tra diversi formati. - Stesso percorso del codice delle esportazioni YOLO: gli stessi helper alimentano ogni esportazione YOLO di Ultralytics.
- Quantizzazione FP16 e INT8 integrata per i formati che la supportano (OpenVINO, CoreML, MNN, NCNN).
- Funziona su CPU: nessuna GPU richiesta per la fase di esportazione stessa, quindi puoi eseguirla localmente su qualsiasi portatile.
Avvio rapido#
Il percorso più rapido è un'esportazione in due righe verso ONNX senza codice YOLO e senza alcuna configurazione oltre a 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")Formati di esportazione supportati#
Le funzioni torch2* accettano un torch.nn.Module standard e un tensore di input di esempio. MNN, TF SavedModel e TF Frozen Graph passano attraverso un artefatto intermedio ONNX o Keras. In nessun dei due casi sono richiesti attributi specifici per YOLO.
| Formato | Funzione | Installa | Output |
|---|---|---|---|
| ONNX | torch2onnx() | pip install onnx | file .onnx |
| TorchScript | torch2torchscript() | incluso con PyTorch | file .torchscript |
| OpenVINO | torch2openvino() | pip install openvino | directory _openvino_model/ |
| CoreML | torch2coreml() | pip install coremltools | .mlpackage |
| TF SavedModel | onnx2saved_model() | vedi i requisiti dettagliati di seguito | directory _saved_model/ |
| TF Frozen Graph | keras2pb() | vedi i requisiti dettagliati di seguito | file .pb |
| NCNN | torch2ncnn() | pip install ncnn pnnx | directory _ncnn_model/ |
| MNN | onnx2mnn() | pip install MNN | file .mnn |
| PaddlePaddle | torch2paddle() | pip install paddlepaddle x2paddle | directory _paddle_model/ |
| ExecuTorch | torch2executorch() | pip install executorch | directory _executorch_model/ |
Le esportazioni MNN, TF SavedModel e TF Frozen Graph passano attraverso ONNX come passaggio intermedio. Esporta prima in ONNX, quindi converti.
Diverse funzioni di esportazione accettano un dizionario opzionale metadata (ad esempio, torch2torchscript(..., metadata={"author": "me"})) che incorpora coppie chiave-valore personalizzate nell'artefatto esportato laddove il formato lo supporta.
Esempi passo dopo passo#
Ogni esempio di seguito utilizza la stessa configurazione, una ResNet-18 preaddestrata da timm in modalità valutazione:
import timm
import torch
model = timm.create_model("resnet18", pretrained=True).eval()
im = torch.randn(1, 3, 224, 224)Il dropout, la normalizzazione batch e altri strati esclusivi dell'addestramento si comportano in modo diverso durante l'inferenza. Saltare .eval() produce esportazioni con output errati.
Esportazione in ONNX#
from ultralytics.utils.export import torch2onnx
torch2onnx(model, im, output_file="resnet18.onnx")Per una dimensione del batch dinamica, passa un dizionario dynamic:
torch2onnx(model, im, output_file="resnet18_dyn.onnx", dynamic={"images": {0: "batch_size"}})L'opset predefinito è 14 e il nome dell'input predefinito è "images". Esegui l'override con gli argomenti opset, input_names o output_names.
Esportazione in TorchScript#
Nessuna dipendenza extra necessaria. Utilizza torch.jit.trace sotto il cofano.
from ultralytics.utils.export import torch2torchscript
torch2torchscript(model, im, output_file="resnet18.torchscript")Esportazione in OpenVINO#
from ultralytics.utils.export import torch2openvino
ov_model = torch2openvino(model, im, output_dir="resnet18_openvino_model")La directory contiene una coppia di model.xml e model.bin a nome fisso:
resnet18_openvino_model/
├── model.xml
└── model.binPassa dynamic=True per forme di input dinamiche, quantize=16 per FP16 o quantize=8 per la quantizzazione INT8. La quantizzazione INT8 richiede inoltre un argomento calibration_dataset.
Richiede openvino>=2024.0.0 (o >=2025.2.0 su macOS 15.4+) e torch>=2.1.
Esportazione in 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")Per i modelli di classificazione, passa un elenco di nomi di classe a classifier_names per aggiungere una testina di classificazione al modello CoreML.
Richiede coremltools>=9.0, torch>=1.11 e numpy<=2.3.5. Non supportato su Windows.
coremltools>=9.0 fornisce wheel per Python 3.10–3.13 su macOS e Linux. Sulle versioni più recenti di Python l'estensione C nativa non riesce a caricarsi. Usa Python 3.10–3.13 per l'esportazione CoreML.
Esportazione in TensorFlow SavedModel#
L'esportazione TF SavedModel passa attraverso ONNX come passaggio intermedio:
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")La funzione restituisce un modello Keras e genera anche file TFLite (.tflite) all'interno della directory di output:
resnet18_saved_model/
├── saved_model.pb
├── variables/
├── resnet18_float32.tflite
├── resnet18_float16.tflite
└── resnet18_int8.tfliteRequisiti:
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.0su macOS (ai-edge-litert>=1.2.0su altre piattaforme)onnxslim>=0.1.82onnx>=1.12.0,<2.0.0protobuf>=5
Esportazione in TensorFlow Frozen Graph#
Continuando dall'esportazione SavedModel precedente, converti il keras_model restituito in un grafo .pb bloccato:
from pathlib import Path
from ultralytics.utils.export import keras2pb
keras2pb(keras_model, output_file=Path("resnet18_saved_model/resnet18.pb"))Esportazione in NCNN#
from ultralytics.utils.export import torch2ncnn
torch2ncnn(model, im, output_dir="resnet18_ncnn_model")La directory contiene file param e bin con nomi fissi insieme a un wrapper Python:
resnet18_ncnn_model/
├── model.ncnn.param
├── model.ncnn.bin
└── model_ncnn.pytorch2ncnn() verifica la presenza di ncnn e pnnx al primo utilizzo.
Esportazione in MNN#
L'esportazione MNN richiede un file ONNX come input. Esporta prima in ONNX, quindi converti:
from ultralytics.utils.export import onnx2mnn, torch2onnx
torch2onnx(model, im, output_file="resnet18.onnx")
onnx2mnn("resnet18.onnx", output_file="resnet18.mnn")Supporta quantize=16 per FP16 e quantize=8 per la quantizzazione INT8. Richiede MNN>=2.9.6 e torch>=1.10.
Esportazione in PaddlePaddle#
from ultralytics.utils.export import torch2paddle
torch2paddle(model, im, output_dir="resnet18_paddle_model")La directory contiene il modello PaddlePaddle e i file dei parametri:
resnet18_paddle_model/
├── model.pdmodel
└── model.pdiparamsRichiede x2paddle e la distribuzione PaddlePaddle corretta per la tua piattaforma:
paddlepaddle-gpu>=3.0.0,<3.3.0su CUDApaddlepaddle==3.0.0su CPU ARM64paddlepaddle>=3.0.0,<3.3.0su altre CPU
Non supportato su NVIDIA Jetson.
Esporta in ExecuTorch#
from ultralytics.utils.export import torch2executorch
torch2executorch(model, im, output_dir="resnet18_executorch_model")Il file .pte esportato viene salvato all'interno della directory di output:
resnet18_executorch_model/
└── model.pteRichiede torch>=2.9.0 e un runtime ExecuTorch corrispondente (pip install executorch). Per l'utilizzo del runtime, consulta l'integrazione ExecuTorch.
Verifica il tuo modello esportato#
Dopo l'esportazione, verifica la parità numerica con il modello PyTorch originale prima della distribuzione. Un rapido smoke test con ONNXBackend da ultralytics.nn.backends confronta gli output e segnala tempestivamente errori di tracciamento o quantizzazione:
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 FP32Per le esportazioni FP32, la differenza assoluta massima è tipicamente intorno a 1e-5 e dovrebbe rimanere ben al di sotto di 1e-4. Differenze maggiori indicano operazioni non supportate, una forma di input errata o un modello non in modalità di valutazione. Le esportazioni FP16 e INT8 hanno tolleranze più ampie. Effettua la convalida su dati reali anziché su tensori casuali.
Per altri runtime, il nome del tensore di input potrebbe differire. OpenVINO, ad esempio, utilizza il nome dell'argomento di forward del modello (tipicamente x per i modelli generici), mentre torch2onnx predefinisce "images".
Limitazioni note#
- Il supporto per input multipli non è uniforme:
torch2onnxetorch2openvinoaccettano una tupla o un elenco di tensori di esempio per i modelli con input multipli.torch2torchscript,torch2coreml,torch2ncnn,torch2paddleetorch2executorchassumono un singolo tensore di input. - ExecuTorch richiede
flatc: Il runtime ExecuTorch richiede il compilatore FlatBuffers. Installa conbrew install flatbufferssu macOS oapt install flatbuffers-compilersu Ubuntu. - Nessuna inferenza tramite Ultralytics: i modelli non YOLO esportati non possono essere ricaricati tramite
YOLO()per l'inferenza. Usa il runtime nativo per ciascun formato (ONNX Runtime, OpenVINO Runtime, ecc.). - Formati esclusivi per YOLO: le esportazioni Axelera e Sony IMX500 richiedono attributi del modello specifici per YOLO e non sono disponibili per i modelli generici.
- Formati specifici per la piattaforma: TensorRT richiede una GPU NVIDIA. RKNN richiede l'SDK
rknn-toolkit2(solo Linux). Edge TPU richiede il binarioedgetpu_compiler(solo Linux).
Conclusione#
Queste utility portano qualsiasi modello PyTorch da un semplice torch.nn.Module a un artefatto ONNX, OpenVINO, CoreML, TensorFlow o per runtime mobile pronto per la distribuzione tramite un'unica API coerente. Scegli il formato che corrisponde all'hardware di destinazione, verifica la parità numerica rispetto al modello originale, quindi segui la guida all'integrazione corrispondente per i passaggi di distribuzione specifici del runtime.
FAQ#
Qualsiasi
torch.nn.Module. Ciò include modelli da timm, torchvision o qualsiasi modello PyTorch personalizzato. Il modello deve essere in modalità di valutazione (model.eval()) prima dell'esportazione. ONNX e OpenVINO accettano inoltre una tupla di tensori di esempio per i modelli con input multipli.Tutti i formati supportati (TorchScript, ONNX, OpenVINO, CoreML, TF SavedModel, TF Frozen Graph, NCNN, PaddlePaddle, MNN, ExecuTorch) possono essere esportati su CPU. Non è richiesta alcuna GPU per il processo di esportazione in sé. TensorRT è l'unico formato che richiede una GPU NVIDIA.
Usa
>=8.4.38di Ultralytics, che include il moduloultralytics.utils.exporte gli argomenti standardizzatioutput_file/output_dir.Sì. I classificatori, i rilevatori e i modelli di segmentazione torchvision vengono esportati in
.mlpackagetramitetorch2coreml. Per i modelli di classificazione delle immagini, passa un elenco di nomi di classe aclassifier_namesper incorporare una testina di classificazione. Esegui l'esportazione su macOS o Linux. CoreML non è supportato su Windows. Consulta l'integrazione CoreML per i dettagli sulla distribuzione su iOS.Sì, per diversi formati. Passa
quantize=16per FP16 oquantize=8per INT8 durante l'esportazione in OpenVINO, CoreML, MNN o NCNN. INT8 in OpenVINO richiede inoltre un argomentocalibration_datasetper la quantizzazione post-addestramento. Consulta la pagina di integrazione di ciascun formato per i compromessi legati alla quantizzazione.Esegui il modello PyTorch originale e il modello esportato sullo stesso input, quindi confronta gli output. Carica il file esportato con il backend corrispondente (ad esempio,
ONNXBackendper ONNX) e controlla la differenza assoluta massima. Per le esportazioni FP32 è tipicamente intorno a1e-5e dovrebbe rimanere ben al di sotto di1e-4; scostamenti maggiori indicano operazioni non supportate, una forma di input errata o un modello non in modalità di valutazione. Vedi Verifica il tuo modello esportato per un esempio eseguibile.