Valutare e mettere in produzione ogni attività
Definisci la soglia di accettazione di ogni attività in base alla sua metrica e alla risoluzione di messa in produzione, convalida tutte le attività in un unico ciclo ed esporta ogni modello in ONNX verificando che le predizioni siano corrette.
Ogni attività ha una propria definizione di correttezza: sovrapposizione dei pixel, somiglianza dei punti chiave, IoU dei riquadri ruotati, una corrispondenza top-1 o un rapporto di profondità. I team che riutilizzano la checklist di rilevamento mettono in produzione modelli di segmentazione con soglie basate sulla mAP dei riquadri e modelli di posa con soglie basate su riquadri che non erano mai il prodotto. E anche un modello che supera la propria soglia può non funzionare dopo l'esportazione: in questa lezione, gli stessi pesi del modello di posa rilevano 5 persone a una risoluzione di input e 3 a un'altra, mentre le distanze del modello di profondità quasi raddoppiano.
Pratico
Una soglia per ogni attività#
| Task | Imposta la soglia in base a | Chiave results_dict | Attributo Python | Valutato con |
|---|---|---|---|---|
| segmentazione | mAP50-95 delle maschere | metrics/mAP50-95(M) | metrics.seg.map | IoU dei pixel per istanza |
| semantica | mIoU (+ IoU per classe) | metrics/mIoU | metrics.miou | IoU dei pixel per classe |
| posa | mAP50-95 della posa | metrics/mAP50-95(P) | metrics.pose.map | OKS |
| obb | mAP50-95 OBB | metrics/mAP50-95(B) | metrics.box.map | IoU dei riquadri ruotati |
| classificazione | accuratezza top-1 | metrics/accuracy_top1 | metrics.top1 | classe top corretta |
| profondità | δ1 (+ AbsRel) | metrics/delta1 | metrics.delta1 | percentuale di pixel con profondità entro un fattore di 1.25 dalla profondità reale |
La guida alle metriche di prestazione spiega ogni punteggio. Le esecuzioni di segmentazione e posa riportano anche le metriche dei riquadri: conservale come diagnostica — una differenza tra riquadri e maschere indica un problema nella qualità dei contorni — ma non sono il prodotto. Le analisi specifiche per il rilevamento, come le valutazioni con soglie diverse e la matrice di confusione, si applicano anche a Convalida e diagnosi.
Convalida ogni attività in un unico ciclo#
La modalità Val accetta i pesi di qualsiasi attività insieme al dataset corrispondente, così un unico ciclo produce i valori della tabella di rilascio:
from ultralytics import YOLO
runs = {
"yolo26n-seg.pt": ("coco8-seg.yaml", "metrics/mAP50-95(M)"),
"yolo26n-sem.pt": ("cityscapes8.yaml", "metrics/mIoU"),
"yolo26n-pose.pt": ("coco8-pose.yaml", "metrics/mAP50-95(P)"),
"yolo26n-obb.pt": ("dota8.yaml", "metrics/mAP50-95(B)"),
"yolo26n-depth.pt": ("depth8.yaml", "metrics/delta1"),
}
for weights, (data, key) in runs.items():
metrics = YOLO(weights).val(data=data, device="cpu", plots=False, verbose=False)
print(f"{weights:17s} {key:22s} {metrics.results_dict[key]:.3f}")yolo26n-seg.pt metrics/mAP50-95(M) 0.538
yolo26n-sem.pt metrics/mIoU 0.610
yolo26n-pose.pt metrics/mAP50-95(P) 0.419
yolo26n-obb.pt metrics/mAP50-95(B) 0.857
yolo26n-depth.pt metrics/delta1 0.377Senza specificare imgsz, ogni modello viene convalidato alla risoluzione di addestramento: 640 per segmentazione e posa, 768 per profondità, 1024 per semantica e OBB. Questi valori dei modelli preaddestrati sono superiori a quelli ottenuti con le esecuzioni di addestramento a 320 pixel presentate prima nel corso: in parte grazie all'addestramento, in parte alla risoluzione. Quattro immagini di convalida rendono ogni valore qui una semplice verifica preliminare; per esempio, la pagina dell'attività di profondità riporta δ1 sull'intero benchmark NYU. La classificazione è esclusa di proposito: convalida il classificatore ottimizzato sulle sue cartelle, come nella lezione sulla classificazione.
Gli stessi pesi ottengono punteggi diversi a seconda di imgsz. Registra imgsz accanto a ogni valore, convalida alla dimensione che userai in produzione e non confrontare mai valori misurati a dimensioni diverse.
Esporta ogni attività#
Ogni attività viene esportata in ONNX con la stessa chiamata della modalità Esportazione. L'attività è memorizzata nei metadati del modello, quindi YOLO("model.onnx") applica la post-elaborazione corretta. La scelta dei runtime, i controlli di equivalenza e l'ottimizzazione per TensorRT o OpenVINO rientrano in Esporta in ONNX (e verifica l'equivalenza); questo ciclo controlla che ogni attività superi il passaggio di andata e ritorno:
from ultralytics import YOLO
for weights in ["yolo26n-seg.pt", "yolo26n-sem.pt", "yolo26n-pose.pt", "yolo26n-obb.pt", "yolo26n-cls.pt", "yolo26n-depth.pt"]:
onnx_path = YOLO(weights).export(format="onnx", imgsz=320)
onnx_model = YOLO(onnx_path) # task comes from the ONNX metadata
result = onnx_model("https://ultralytics.com/images/bus.jpg", imgsz=320, verbose=False)[0]
print(f"{onnx_model.task:9s} {result.verbose()}")segment 4 persons, 1 bus,
semantic
pose 3 persons,
obb (no detections),
classify minibus 0.38, police_van 0.21, trolleybus 0.05, amphibian 0.05, bullet_train 0.03,
depth depth 4.67-26.91m,Ogni esportazione è stata ricaricata con l'attività corretta. Tre risultati meritano un secondo controllo:
- La posa ha rilevato 3 persone a 320 pixel, mentre l'esecuzione PyTorch a 640 pixel ne aveva rilevate 5.
- La profondità ha interpretato la scena come compresa tra 4.7 e 26.9 m, mentre gli stessi pesi, alla risoluzione nativa di 768 pixel, indicavano un intervallo tra 2.1 e 14.9 m.
- OBB non ha rilevato nulla in una foto di strada: è il comportamento corretto per un modello addestrato su immagini aeree, non un bug di esportazione.
PyTorch a imgsz=320 restituisce gli stessi valori di posa e profondità di ONNX, quindi nemmeno in questo caso si tratta di un bug di esportazione: è stata la risoluzione di input a cambiare il risultato. Esporta alla risoluzione imgsz che hai convalidato. I risultati semantici non hanno una riga di riepilogo per oggetto, quindi controlla invece result.semantic_mask.
Esegui una predizione con ciascun modello esportato su un'immagine simile a quelle usate per addestrarlo — scene stradali per i modelli COCO, riquadri aerei per OBB, scene interne o stradali alla scala corretta per la profondità — prima di considerare difettosa un'esportazione o distribuirla.
Se scrivi la tua post-elaborazione, questi sono gli output ONNX grezzi a imgsz=320, tratti dal log di esportazione:
| Task | Forma degli output ONNX | Contenuto |
|---|---|---|
| segmentazione | (1, 116, 2100) e (1, 32, 80, 80) | riquadri + 80 punteggi di classe + 32 coefficienti della maschera; prototipi delle maschere |
| semantica | (1, 320, 320) | mappa delle classi, argmax già nel grafo |
| posa | (1, 56, 2100) | riquadri + 1 punteggio + 17 × 3 valori dei punti chiave |
| obb | (1, 20, 2100) | riquadri + 15 punteggi di classe + 1 angolo |
| classificazione | (1, 1000) | probabilità delle classi |
| profondità | (1, 1, 320, 320) | profondità in metri per pixel |
Su Ultralytics Platform, la pagina del modello mostra le metriche specifiche dell'attività (mAP delle maschere per un modello di segmentazione) sopra una scheda Esportazione che produce gli stessi formati:

ONNX è il formato di interscambio: un unico file esportato può essere eseguito in ONNX Runtime o convertito per altri runtime.

Checklist per la messa in produzione#
- La metrica usata come soglia nella tabella sopra raggiunge il valore obiettivo su un insieme di dati escluso dall'addestramento, alla risoluzione di messa in produzione
imgsz. - Il modello esportato viene ricaricato con
taskprevisto e restituisce predizioni corrispondenti a quelle di PyTorch su un insieme fisso di immagini. - I percorsi di codice per ogni attività gestiscono i risultati vuoti:
masks is None, zero punti chiave, zero OBB. - I valori a valle (aree, angoli, distanze, probabilità delle classi) vengono registrati per monitorarne le variazioni, come descritto in Osservabilità e deriva.
Quando la soglia non viene raggiunta, "tornare ai dati" di solito significa intervenire su una di queste tre leve:

Correggi prima la qualità dei dati e il processo di annotazione — i controlli delle etichette delle lezioni 2 e 6 sono il punto di partenza meno costoso — e modifica il modello solo quando i dati sono puliti.
Mostra la soluzione
from ultralytics import YOLO
checks = {
"runs/segment/train/weights/best.pt": ("coco8-seg.yaml", "metrics/mAP50-95(M)", "https://ultralytics.com/images/bus.jpg"),
"runs/obb/train/weights/best.pt": ("dota8.yaml", "metrics/mAP50-95(B)", "https://ultralytics.com/images/boats.jpg"),
}
for weights, (data, key, image) in checks.items():
model = YOLO(weights)
gate = model.val(data=data, imgsz=320, plots=False, verbose=False).results_dict[key]
onnx_model = YOLO(model.export(format="onnx", imgsz=320))
result = onnx_model(image, imgsz=320, verbose=False)[0]
print(f"{onnx_model.task:8s} {key} @320 = {gate:.3f} | ONNX: {result.verbose()}")Modifica i percorsi runs/... in modo che puntino alle cartelle stampate dalle esecuzioni di addestramento (Results saved to ...). Con le esecuzioni di un'epoca delle lezioni 2 e 7:
segment metrics/mAP50-95(M) @320 = 0.377 | ONNX: 4 persons, 1 bus,
obb metrics/mAP50-95(B) @320 = 0.832 | ONNX: 185 ships, 3 harbors,| Modello | Metrica di soglia | Valore | dimensione immagine | ONNX |
|---|---|---|---|---|
| segmentazione | mAP50-95 delle maschere | 0.377 | 320 | si ricarica come segment e rileva l'autobus e 4 persone |
| obb | mAP50-95 OBB | 0.832 | 320 | si ricarica come obb e rileva 185 navi e 3 porti |
Ogni verifica usa un'immagine del proprio dominio: il modello OBB riceve la foto aerea del porto, non la scena di strada. Entrambe le righe superano il controllo dell'esportazione; nessuno dei due modelli è pronto per la messa in produzione, perché un'epoca su quattro immagini di convalida è una semplice verifica preliminare, non una soglia di accettazione.