Link to this sectionCome esportare modelli PyTorch non-YOLO con Ultralytics#
Il deploy di modelli PyTorch in produzione solitamente comporta destreggiarsi tra un exporter diverso per ogni target: torch.onnx.export per ONNX, coremltools per dispositivi Apple, onnx2tf per TensorFlow, pnnx per NCNN, e così via. Ogni strumento ha le proprie API, stranezze nelle dipendenze e convenzioni di output.
Ultralytics fornisce utility di esportazione standalone che racchiudono molteplici backend dietro un'interfaccia coerente. Puoi esportare qualsiasi torch.nn.Module, inclusi i modelli di immagine timm, i classificatori e 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.
Link to this sectionPerché usare Ultralytics per l'esportazione non-YOLO?#
- Una sola API per 10 formati: impara una singola convenzione di chiamata invece di una dozzina.
- Superficie di utility condivisa: gli helper di esportazione risiedono in
ultralytics.utils.export, quindi una volta installati i pacchetti di backend puoi mantenere lo stesso schema di chiamata tra i vari formati. - Stesso percorso di codice delle esportazioni YOLO: gli stessi helper alimentano ogni esportazione Ultralytics YOLO.
- Quantizzazione FP16 e INT8 integrata per i formati che la supportano (OpenVINO, CoreML, MNN, NCNN).
- Funziona su CPU: nessuna GPU richiesta per il passaggio di esportazione stesso, quindi puoi eseguirlo localmente su qualsiasi laptop.
Link to this sectionAvvio rapido#
Il percorso più veloce è un'esportazione in due righe verso ONNX senza codice YOLO e senza setup 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")Link to this sectionFormati 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. Non sono richiesti attributi specifici YOLO in nessuno dei due casi.
| 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 requisiti dettagliati sotto | Directory _saved_model/ |
| TF Frozen Graph | keras2pb() | vedi requisiti dettagliati sotto | 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, poi converti.
Diverse funzioni di esportazione accettano un dizionario metadata opzionale (ad es. torch2torchscript(..., metadata={"author": "me"})) che incorpora coppie chiave-valore personalizzate nell'artefatto esportato, dove il formato lo supporta.
Link to this sectionEsempi 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)Dropout, batch normalization e altri layer usati solo durante l'addestramento si comportano in modo diverso durante l'inferenza. Saltare .eval() produce esportazioni con output errati.
Link to this sectionEsporta in ONNX#
from ultralytics.utils.export import torch2onnx
torch2onnx(model, im, output_file="resnet18.onnx")Per una dimensione 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.
Link to this sectionEsportazione in TorchScript#
Nessuna dipendenza extra necessaria. Utilizza torch.jit.trace internamente.
from ultralytics.utils.export import torch2torchscript
torch2torchscript(model, im, output_file="resnet18.torchscript")Link to this sectionEsportazione in OpenVINO#
from ultralytics.utils.export import torch2openvino
ov_model = torch2openvino(model, im, output_dir="resnet18_openvino_model")La directory contiene una coppia model.xml e model.bin a nome fisso:
resnet18_openvino_model/
├── model.xml
└── model.binPassa dynamic=True per forme di input dinamiche, half=True per FP16 o int8=True per la quantizzazione INT8. INT8 richiede inoltre un argomento calibration_dataset.
Richiede openvino>=2024.0.0 (o >=2025.2.0 su macOS 15.4+) e torch>=2.1.
Link to this sectionEsportazione 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, output_file="resnet18.mlpackage")Per i modelli di classificazione, passa un elenco di nomi di classi a classifier_names per aggiungere una testa 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.
Link to this sectionEsportazione 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.26(installa con--extra-index-url https://pypi.ngc.nvidia.com)ai-edge-litert>=1.2.0,<1.4.0su macOS (ai-edge-litert>=1.2.0su altre piattaforme)onnxslim>=0.1.71onnx>=1.12.0,<2.0.0protobuf>=5
Link to this sectionEsportazione in TensorFlow Frozen Graph#
Proseguendo dall'esportazione SavedModel qui sopra, converti il modello Keras restituito in un grafo .pb frozen:
from pathlib import Path
from ultralytics.utils.export import keras2pb
keras2pb(keras_model, output_file=Path("resnet18_saved_model/resnet18.pb"))Link to this sectionEsportazione in NCNN#
from ultralytics.utils.export import torch2ncnn
torch2ncnn(model, im, output_dir="resnet18_ncnn_model")La directory contiene file param e bin a nome fisso 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.
Link to this sectionEsportazione in MNN#
L'esportazione MNN richiede un file ONNX come input. Esporta prima in ONNX, poi converti:
from ultralytics.utils.export import onnx2mnn, torch2onnx
torch2onnx(model, im, output_file="resnet18.onnx")
onnx2mnn("resnet18.onnx", output_file="resnet18.mnn")Supporta half=True per FP16 e int8=True per la quantizzazione INT8. Richiede MNN>=2.9.6 e torch>=1.10.
Link to this sectionEsportazione 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.
Link to this sectionEsporta 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 compatibile (pip install executorch). Per l'utilizzo del runtime, consulta l'integrazione con ExecuTorch.
Link to this sectionVerifica il tuo modello esportato#
Dopo l'esportazione, verifica la parità numerica con il modello PyTorch originale prima del rilascio. 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}") # should be < 1e-5Per le esportazioni FP32, la differenza assoluta massima dovrebbe essere inferiore a 1e-5. Differenze maggiori indicano operazioni non supportate, forma dell'input errata o un modello non in modalità eval. Le esportazioni FP16 e INT8 hanno tolleranze più ampie. Convalida su dati reali invece che su tensori casuali.
Per altri runtime, il nome del tensore di input potrebbe differire. OpenVINO, ad esempio, utilizza il nome dell'argomento forward del modello (tipicamente x per i modelli generici), mentre torch2onnx utilizza di default "images".
Link to this sectionLimitazioni note#
- Supporto multi-input irregolare:
torch2onnxetorch2openvinoaccettano una tupla o una lista di tensori di esempio per modelli con input multipli.torch2torchscript,torch2coreml,torch2ncnn,torch2paddleetorch2executorchpresuppongono un singolo tensore di input. - ExecuTorch necessita di
flatc: Il runtime ExecuTorch richiede il compilatore FlatBuffers. Installalo 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. Utilizza il runtime nativo per ciascun formato (ONNX Runtime, OpenVINO Runtime, ecc.). - Formati solo YOLO: Le esportazioni verso Axelera e Sony IMX500 richiedono attributi del modello specifici per YOLO e non sono disponibili per i modelli generici.
- Formati specifici per piattaforma: TensorRT richiede una GPU NVIDIA. RKNN richiede l'SDK
rknn-toolkit2(solo Linux). Edge TPU richiede il binarioedgetpu_compiler(solo Linux).
Link to this sectionFAQ#
Link to this sectionQuali modelli posso esportare con Ultralytics?#
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 modelli multi-input.
Link to this sectionQuali formati di esportazione funzionano senza GPU?#
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 stesso. TensorRT è l'unico formato che richiede una GPU NVIDIA.
Link to this sectionQuale versione di Ultralytics mi serve?#
Utilizza Ultralytics >=8.4.38, che include il modulo ultralytics.utils.export e gli argomenti standardizzati output_file/output_dir.
Link to this sectionPosso esportare un modello torchvision in CoreML per il deployment su iOS?#
Sì. I classificatori, i detector e i modelli di segmentazione torchvision si esportano in .mlpackage tramite torch2coreml. Per i modelli di classificazione delle immagini, passa una lista di nomi di classe a classifier_names per integrare una head di classificazione. Esegui l'esportazione su macOS o Linux. CoreML non è supportato su Windows. Consulta l'integrazione con CoreML per i dettagli sul deployment su iOS.
Link to this sectionPosso quantizzare il mio modello esportato in INT8 o FP16?#
Sì, per diversi formati. Passa half=True per FP16 o int8=True per INT8 durante l'esportazione verso OpenVINO, CoreML, MNN o NCNN. INT8 in OpenVINO richiede inoltre un argomento calibration_dataset per la quantizzazione post-addestramento. Consulta la pagina di integrazione di ciascun formato per i compromessi relativi alla quantizzazione.