Meet YOLO26: next-gen vision AI.

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.

FormatoFunzioneInstallaOutput
ONNXtorch2onnx()pip install onnxFile .onnx
TorchScripttorch2torchscript()incluso con PyTorchFile .torchscript
OpenVINOtorch2openvino()pip install openvinoDirectory _openvino_model/
CoreMLtorch2coreml()pip install coremltools.mlpackage
TF SavedModelonnx2saved_model()vedi requisiti dettagliati sottoDirectory _saved_model/
TF Frozen Graphkeras2pb()vedi requisiti dettagliati sottoFile .pb
NCNNtorch2ncnn()pip install ncnn pnnxDirectory _ncnn_model/
MNNonnx2mnn()pip install MNNFile .mnn
PaddlePaddletorch2paddle()pip install paddlepaddle x2paddleDirectory _paddle_model/
ExecuTorchtorch2executorch()pip install executorchDirectory _executorch_model/
ONNX come formato intermedio

Le esportazioni MNN, TF SavedModel e TF Frozen Graph passano attraverso ONNX come passaggio intermedio. Esporta prima in ONNX, poi converti.

Metadati di embedding

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)
Chiama sempre `model.eval()` prima di esportare

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.bin

Passa 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.

Errore `BlobWriter not loaded`

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.tflite

Requisiti:

  • 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 (installa con --extra-index-url https://pypi.ngc.nvidia.com)
  • ai-edge-litert>=1.2.0,<1.4.0 su macOS (ai-edge-litert>=1.2.0 su altre piattaforme)
  • onnxslim>=0.1.71
  • onnx>=1.12.0,<2.0.0
  • protobuf>=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.py

torch2ncnn() 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.pdiparams

Richiede x2paddle e la distribuzione PaddlePaddle corretta per la tua piattaforma:

  • paddlepaddle-gpu>=3.0.0,<3.3.0 su CUDA
  • paddlepaddle==3.0.0 su CPU ARM64
  • paddlepaddle>=3.0.0,<3.3.0 su 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.pte

Richiede 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-5
Differenza prevista

Per 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: torch2onnx e torch2openvino accettano una tupla o una lista di tensori di esempio per modelli con input multipli. torch2torchscript, torch2coreml, torch2ncnn, torch2paddle e torch2executorch presuppongono un singolo tensore di input.
  • ExecuTorch necessita di flatc: Il runtime ExecuTorch richiede il compilatore FlatBuffers. Installalo con brew install flatbuffers su macOS o apt install flatbuffers-compiler su 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 binario edgetpu_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.

Commenti