Esporta per la distribuzione
Esporta best.pt in ONNX, OpenVINO, TensorRT, CoreML, LiteRT o QNN, poi verifica che l'esportazione corrisponda al modello PyTorch prima di distribuirla.
Per funzionare, il tuo best.pt richiede Python e PyTorch; in genere telefoni, browser, Jetson e server di produzione non li hanno. La modalità Export converte il modello in un file autonomo per questi runtime con una sola chiamata. Attenzione: il fatto che un'esportazione venga caricata non significa che sia corretta; inoltre, un confronto eseguito senza la dovuta attenzione può far sembrare difettosa un'esportazione corretta o nascondere i problemi di una non corretta.
In questa lezione esporterai il modello per il rilevamento delle pillole in ONNX, lo eseguirai tramite la stessa API YOLO, verificherai che corrisponda a PyTorch nei riquadri e nella mAP di validazione con impostazioni uniformi e sceglierai il formato richiesto dalla piattaforma di destinazione: ONNX, OpenVINO, TensorRT, CoreML, LiteRT o QNN.
Pratico
Esempio svolto: esportare in ONNX#

yolo export model=runs/detect/pills_v1/weights/best.pt format=onnxPyTorch: starting from 'runs/detect/pills_v1/weights/best.pt' with input shape (1, 3, 320, 320) BCHW and output shape(s) (1, 5, 2100) (5.2 MB)
ONNX: export success ✅ 0.9s, saved as 'runs/detect/pills_v1/weights/best.onnx' (9.3 MB)
Predict: yolo predict task=detect model=runs/detect/pills_v1/weights/best.onnx imgsz=320
Validate: yolo val task=detect model=runs/detect/pills_v1/weights/best.onnx imgsz=320 data=my_dataset/data.yamlAnalisi riga per riga:
input shape (1, 3, 320, 320): un'immagine, 3 canali di colore, un quadrato fisso di 320×320: la dimensioneimgszusata durante l'addestramento, incorporata nel file.output shape(s) (1, 5, 2100): 4 valori per il riquadro più 1 punteggio di classe per 2.100 riquadri candidati; per impostazione predefinita, NMS viene eseguita all'esterno del grafo.9.3 MB: il file ONNX memorizza i pesi FP32, quindi è più grande di.ptin FP16.Predict:/Validate:: comandi già pronti per il file esportato, con il valore corretto diimgsz.
Bastano pochi argomenti per la maggior parte dei casi; la guida all'integrazione ONNX elenca gli altri.
| Argomento | Predefinita | A cosa serve |
|---|---|---|
imgsz | Dimensione di addestramento | Esporta con una dimensione di input fissa diversa, ad esempio imgsz=640 |
dynamic | False | Accetta dimensioni di input variabili invece di una sola forma fissa |
quantize | Nessuna (FP32) | 16 per i pesi FP16 (la dimensione di yolo26n.onnx passa da 9.5 MB a 4.8 MB); 8 per INT8, se supportato dal formato |
nms | Nessuna | nms=True incorpora NMS nel grafo, così il runtime restituisce i riquadri finali |
Esempio svolto: verifica che l'esportazione corrisponda al modello#
Anche la classe YOLO carica i file esportati, quindi il codice di predict visto in precedenza funziona senza modifiche. Confronta entrambi i file sulla stessa immagine di validazione:
from ultralytics import YOLO
image = "my_dataset/images/val/Frame_144.jpg"
pt = YOLO("runs/detect/pills_v1/weights/best.pt")(image, rect=False, verbose=False)[0] # square input, like ONNX
onnx = YOLO("runs/detect/pills_v1/weights/best.onnx")(image, verbose=False)[0]
print(f"pt: {len(pt.boxes)} pills, mean conf {pt.boxes.conf.mean():.3f}")
print(f"onnx: {len(onnx.boxes)} pills, mean conf {onnx.boxes.conf.mean():.3f}")
print(f"max box difference: {(pt.boxes.xyxy - onnx.boxes.xyxy).abs().max():.4f} px")pt: 25 pills, mean conf 0.870
onnx: 25 pills, mean conf 0.870
max box difference: 0.0002 pxStesso conteggio, stessa confidenza, riquadri identici fino a una frazione di pixel. Ora esegui il controllo più rigoroso: la validazione sull'intero split:
from ultralytics import YOLO
pt = YOLO("runs/detect/pills_v1/weights/best.pt").val(data="my_dataset/data.yaml", rect=False, verbose=False)
onnx = YOLO("runs/detect/pills_v1/weights/best.onnx").val(data="my_dataset/data.yaml", verbose=False)
print(f".pt mAP50-95 {pt.box.map:.4f}")
print(f".onnx mAP50-95 {onnx.box.map:.4f}").pt mAP50-95 0.6570
.onnx mAP50-95 0.6570Identici. (La validazione rettangolare predefinita del file .pt ha ottenuto 0.659: una piccola differenza dovuta al padding dell'input, non all'esportazione.)
Una volta verificata la corrispondenza, misura i tempi con yolo benchmark sul dispositivo di destinazione, così saprai quanto è veloce prima di distribuirlo.
Scegli un formato per la piattaforma di destinazione#

| Obiettivo | Formato | Note |
|---|---|---|
| Scelta predefinita portabile: server e computer desktop con Linux, Windows e Mac | onnx | ONNX Runtime su CPU o GPU; l'esportazione più rapida da verificare |
| GPU NVIDIA e Jetson | engine (TensorRT) | Il più veloce su NVIDIA; esegui l'esportazione sul dispositivo. Vedi Ottimizzare con TensorRT |
| CPU e iGPU Intel | openvino | Incrementi reali di velocità della CPU grazie ai kernel Intel. Vedi OpenVINO su CPU |
| App per iPhone, iPad e Mac | coreml | Nativo; usa l'Apple Neural Engine |
| Android e altri dispositivi mobili o embedded | litert | INT8 consigliato per dispositivi mobili |
| NPU Snapdragon | qnn | Accelerazione Hexagon HTP; pesi INT8 con attivazioni a 16 bit per impostazione predefinita; scegli l'architettura HTP con name |
| Browser web | onnx con ONNX Runtime Web | I modelli più piccoli sono una scelta concreta: n e s |
from ultralytics import YOLO
model = YOLO("runs/detect/pills_v1/weights/best.pt")
model.export(format="onnx") # multipiattaforma: ONNX Runtime
model.export(format="openvino") # CPU / iGPU Intel
model.export(format="engine", quantize=16) # NVIDIA TensorRT, FP16 (esegui sulla GPU di destinazione)
model.export(format="coreml") # Apple iOS / macOS
model.export(format="litert", quantize=8, data="my_dataset/data.yaml") # Android / edge, INT8
model.export(format="qnn", name="73", data="my_dataset/data.yaml") # NPU Qualcomm Snapdragon (HTP v73); calibra sui tuoi datiOgni esportazione scrive i file accanto ai pesi: best.onnx, best_openvino_model/, best.engine e così via. Inizia con ONNX anche se alla fine userai un altro formato: è il più rapido da verificare e costituisce l'input per diverse altre toolchain. La guida alle opzioni di deployment confronta tutti i formati, mentre Scegliere una destinazione di deployment ti accompagna nella scelta.
La quantizzazione del modello scambia precisione con dimensioni e velocità. FP16 (quantize=16) dimezza le dimensioni del file con una precisione quasi invariata. INT8 (quantize=8) riduce ulteriormente le dimensioni e aumenta la velocità, ma richiede immagini di calibrazione: fotogrammi rappresentativi che l'esportazione elabora per scegliere gli intervalli dei valori; Ultralytics ne consiglia almeno 300. Convalida sempre un modello INT8 prima della distribuzione: la perdita può essere trascurabile o notevole, a seconda del modello e del set di calibrazione.
Evita questi errori#
Sintomo: il modello .pt rileva 35 pillole su Frame_144.jpg, mentre il file ONNX ne rileva 25, e l'esportazione sembra non funzionare. Causa: l'inferenza PyTorch riempie ogni immagine fino al rettangolo più piccolo allineato allo stride (192×320 per questi frame in formato 16:9), mentre un modello ONNX statico accetta sempre un quadrato di 320×320. Input diversi producono rilevazioni diverse a bassa confidenza. Soluzione: durante il confronto passa rect=False al modello .pt, come in parity.py.
Sintomo: passi imgsz=640 a best.onnx, ma il log indica ancora 320x320. Causa: un'esportazione statica ha un'unica dimensione di input, impostata al momento dell'esportazione. Soluzione: esporta alla dimensione che userai (imgsz=640) oppure esporta con dynamic=True.
Un .engine creato su un A100 non funzionerà su un Jetson Orin e potrebbe non essere compatibile con un aggiornamento di TensorRT. Esporta sul dispositivo di destinazione, usando la versione di TensorRT che verrà eseguita. ONNX è portabile; i motori non lo sono.
Se ometti data da un'esportazione INT8, Ultralytics mostra un avviso e poi esegue la calibrazione sul campione COCO8 predefinito: otto immagini che non assomigliano affatto alle tue pillole. Passa il tuo campione: model.export(format="litert", quantize=8, data="my_dataset/data.yaml").
Hai completato la distribuzione#
Ora hai un best.pt addestrato, i risultati della convalida accanto a un valore di riferimento, un file esportato per il tuo runtime e la prova che l'esportazione corrisponde all'originale. Hai completato l'intero ciclo — dati, addestramento, convalida, esportazione, deployment — che i team di produzione eseguono secondo una pianificazione. Ultralytics YOLO in Production riparte dalla tua esportazione verificata e tratta runtime ottimizzati, pipeline di tracking, gestione di più flussi e monitoraggio.
Mostra la soluzione
from ultralytics import YOLO
# Train
model = YOLO("yolo26n.pt")
model.train(data="my_dataset/data.yaml", epochs=10, imgsz=320, name="pills_e2e")
# Validate
metrics = model.val()
print(f"mAP50-95 = {metrics.box.map:.3f}") # 0.659
# Export
model.export(format="onnx")parity.py: pt 25 pills, onnx 25 pills, max box difference 0.0002 px
without rect: pt 35 pills (192x320 input) vs onnx 25 (320x320): input mismatch, not an export bug
val_export.py: .pt 0.6570, .onnx 0.6570
Target: Intel laptop CPU -> openvino, for faster CPU inference than ONNX Runtime