Ultralytics YOLO27: Iscriviti alla lista d'attesa.
Get Started
Ultralytics YOLO in produzione·Scala e osservazione·Lezione 8/9
Lezioneintermedio

Osservabilità e deriva

Registra le metriche che rivelano il calo silenzioso della precisione, verifica la deriva con le distribuzioni di confidenza e invia avvisi solo per segnali che richiedono un'azione.

Un servizio di visione può essere attivo, veloce e sbagliato. Una telecamera viene spostata, l'illuminazione cambia, arriva una nuova linea di prodotti e il modello continua a restituire riquadri mentre tutte le dashboard dell'infrastruttura restano verdi. In questa lezione, scurire una clip per simulare il crepuscolo ha spostato la confidenza media di appena 0.01, una variazione invisibile su un grafico, eppure un test KS a due campioni l'ha rilevata con p = 0.007. Realizzerai questo controllo e la registrazione dei dati che lo alimenta.

Esito

Emetti metriche JSON per ogni frame, esegui un test KS di deriva rispetto a una baseline iniziale, convalida un set di holdout e definisci avvisi associati ciascuno a un'azione.

Percorso rapido
Se sai già come muoverti, ecco la versione breve.
  1. Per ogni frame: telecamera, r.speed["inference"], numero di rilevamenti, confidenza media, valori di confidenza grezzi.

  2. Salva le confidenze iniziali come baseline; confronta ogni giorno con scipy.stats.ks_2samp.

  3. Convalida ogni settimana un set di holdout etichettato con yolo val; invia un avviso se la mAP cala di oltre 1 punto.

  4. Invia avvisi solo per segnali con una prossima azione definita per iscritto; tutto il resto va mostrato in una dashboard.

Pratico

Tre livelli di segnali#

LivelloDomandaSegnali
InfrastrutturaIl servizio è attivo e riesce a tenere il passo?Latenza, throughput, frame persi, utilizzo di CPU e GPU
Comportamento del modelloIl modello si comporta come la settimana scorsa?Rilevamenti per frame, confidenza media, distribuzione delle classi, dimensioni dei riquadri
Precisione del modelloIl modello continua a fornire risultati corretti?mAP sul set di holdout (metriche di prestazione), revisione umana a campione, tasso di falsi allarmi

La maggior parte dei team copre il primo livello con strumenti standard e si ferma lì. È nel secondo e nel terzo che i sistemi di visione falliscono senza farsi notare; la guida al monitoraggio dei modelli descrive l'intero ciclo di manutenzione.

Pagina di distribuzione della Ultralytics Platform nella scheda Logs, con i filtri Errors e All sopra le righe INFO delle richieste con data e ora per il monitoraggio e le chiamate di esempio

Se distribuisci tramite Ultralytics Platform, la pagina della distribuzione ti fornisce i dati dell'infrastruttura (richieste, tasso di errori, latenza P95) e i log delle richieste, filtrabili per errori come nell'esempio qui sopra; la lezione Monitorare lo stato e la precisione tratta questi aspetti. I livelli relativi al comportamento e alla precisione sono a tuo carico: il resto di questa lezione ti mostra come realizzarli.

Emetti metriche per ogni frame#

Ogni oggetto Results contiene tempi e riquadri. Scrivi una riga JSON per frame e inviala al sistema di metriche che usi:

import json
import time

from ultralytics import YOLO

model = YOLO("yolo26n.pt")
video = "https://github.com/ultralytics/assets/releases/download/v0.0.0/solutions_ci_demo.mp4"
with open("metrics.jsonl", "w") as log:
    for r in model.predict(video, stream=True, verbose=False):
        conf = r.boxes.conf
        record = {
            "ts": time.time(),
            "camera": "lobby-1",
            "inference_ms": round(r.speed["inference"], 1),
            "detections": len(r.boxes),
            "mean_conf": round(conf.mean().item(), 3) if len(conf) else None,
            "confs": [round(c, 3) for c in conf.tolist()],  # valori grezzi per il test di deriva
        }
        log.write(json.dumps(record) + "\n")
print({k: v for k, v in record.items() if k != "confs"})
{'ts': 1792003254.33, 'camera': 'lobby-1', 'inference_ms': 34.7, 'detections': 22, 'mean_conf': 0.543}

A cosa serve ciascun campo:

  • inference_ms: genera un avviso quando p95 supera il tuo budget.
  • detections: un calo improvviso quasi a zero di solito indica una telecamera bloccata o guasta; un aumento indica un cambio di scena o falsi positivi.
  • mean_conf: una rapida linea di tendenza, ma troppo approssimativa per rilevare da sola la deriva.
  • confs: la distribuzione completa, necessaria per il test di deriva qui sotto.

Verificare la deriva nelle distribuzioni di confidenza#

La deriva dei dati si manifesta nei valori di confidenza molto prima che qualcuno etichetti nuovi dati. Raccogli i valori di confidenza al lancio come riferimento, raccogli una finestra recente e confronta le due distribuzioni con un test di Kolmogorov-Smirnov a due campioni (pip install scipy). Questo script simula il crepuscolo scurendo lo stesso video:

import cv2
import numpy as np
from scipy.stats import ks_2samp

from ultralytics import YOLO
from ultralytics.utils.downloads import safe_download

model = YOLO("yolo26n.pt")
video = str(safe_download("https://github.com/ultralytics/assets/releases/download/v0.0.0/solutions_ci_demo.mp4"))

def confidences(darken=1.0):
    """Collect every detection confidence from the clip, optionally darkened to simulate dusk."""
    cap, out = cv2.VideoCapture(video), []
    while True:
        ok, frame = cap.read()
        if not ok:
            break
        out += model((frame * darken).astype(np.uint8), verbose=False)[0].boxes.conf.tolist()
    return np.array(out)

baseline = confidences()  # what "normal" looked like at launch
for name, recent in (("same scene", confidences()), ("dusk (35% brightness)", confidences(darken=0.35))):
    stat, p = ks_2samp(baseline, recent)
    print(f"{name:22s} n={len(recent):4d} mean_conf={recent.mean():.3f} KS={stat:.3f} p={p:.2g}")
same scene             n=1376 mean_conf=0.519 KS=0.000 p=1
dusk (35% brightness)  n=1337 mean_conf=0.508 KS=0.064 p=0.0068

Esaminiamole una per una:

  • Stessa scena: distribuzioni identiche producono una statistica KS pari a 0 e p = 1: il controllo.
  • Crepuscolo: 39 rilevamenti in meno e una media inferiore di appena 0.011, cosa che nessuno noterebbe su un grafico. La statistica KS (la distanza massima tra le due distribuzioni cumulative) è 0.064 e p = 0.0068 < 0.01 indica che lo spostamento è reale.

Un avviso di deriva è un motivo per esaminare alcuni fotogrammi campione, non la prova di un malfunzionamento. Quando la deriva è reale, raccogli ed etichetta i fotogrammi delle telecamere interessate: la guida alla raccolta e all'annotazione dei dati spiega cosa raccogliere, mentre la guida al fine-tuning spiega come eseguire il nuovo addestramento. Anche le dimensioni dei riquadri (larghezza × altezza) forniscono un secondo indicatore semplice di deriva: i nuovi supporti e le nuove ottiche si notano prima lì.

Convalida settimanalmente un set di holdout#

I segnali comportamentali indicano che qualcosa è cambiato; solo le etichette dicono se la precisione è diminuita. Conserva un set di holdout di 200–500 immagini di produzione etichettate e convalida ogni versione del modello, oltre a farlo ogni settimana:

yolo val model=yolo26n.pt data=coco8.yaml > weekly_metrics.txt  # use your production model and holdout YAML

Registra mAP50-95 e AP per classe nel tempo e genera un avviso quando mAP cala di più di 1 punto da una settimana all'altra. La causa più comune è la sostituzione del modello che avrebbe dovuto essere ininfluente; la seconda è la deriva. Una matrice di confusione sullo stesso set di holdout rende evidenti le regressioni per classe.

Qualità del modello nel tempo: la qualità si mantiene mentre arrivano nuovi dati etichettati, poi cala dopo il punto previsto; resta da decidere se eseguire subito il nuovo addestramento o aspettare

Il set di holdout permette di rispondere alla domanda del grafico. Esegui il nuovo addestramento quando mostra che la qualità inizia a calare o quando hai raccolto abbastanza nuovi dati etichettati nelle condizioni soggette a deriva, non seguendo un calendario fisso.

Genera avvisi sulle azioni, non sui numeri#

SegnaleQuando scattaAzione
p95 inference_msSopra il budget per più di 3 minutiAumenta la capacità o passa all'esportazione ottimizzata
Rilevamenti per fotogrammaIn calo di almeno il 50% per 5 minutiControlla il flusso della telecamera, poi la versione del modello
Fotogrammi persiOltre il 5% per 10 minutiAggiungi capacità o riduci gli FPS per flusso
Test KS dei valori di confidenzap < 0.01 nelle finestre giornaliereEsamina i fotogrammi, poi esegui la convalida del set di holdout
mAP50-95 del set di holdoutIn calo di almeno 1 punto da una settimana all'altraRaccogli, etichetta ed esegui il fine-tuning

Insidie#

Confrontare finestre non omogenee

Sintomo: il test KS si attiva ogni sera e ogni lunedì. Soluzione: i cicli giornalieri e settimanali sono cambiamenti reali nella distribuzione. Confronta dati omogenei (stesse telecamere, stesse ore, stesso giorno della settimana) e usa finestre di migliaia di rilevamenti.

Un set di test ormai obsoleto

Sintomo: la mAP sul set di test sembra buona mentre gli utenti segnalano mancate rilevazioni. Soluzione: il set di test deve rispecchiare la produzione attuale. Aggiornalo ogni trimestre con fotogrammi appena etichettati, provenienti dalle telecamere più importanti.

Se nessuno agirebbe di conseguenza, non inviare un avviso

Ogni avviso deve indicare per iscritto la prossima azione da intraprendere. Un segnale che vuoi solo monitorare va inserito in una dashboard, non inviato al sistema di paging.

Provalo

Aggiungi la registrazione JSON alla pipeline e falla funzionare per un'ora (o durante un video lungo). Conserva la prima finestra come baseline.jsonl, poi esegui il controllo KS della soluzione confrontandola con una seconda finestra: un orario diverso della giornata, una telecamera diversa o una copia scurita. Fornisci la statistica KS e il p-value, oltre alla tabella degli avvisi con un'azione per ogni riga.

Criteri di completamento
La lezione è completata quando tutte le seguenti condizioni sono soddisfatte.
  • La pipeline scrive una riga JSON per fotogramma con latenza, numero di rilevamenti, confidenza media e valori di confidenza grezzi.

  • Hai eseguito un test KS tra una finestra di riferimento e una recente e ne hai registrato la statistica e il p-value.

  • Ogni avviso definito ha una soglia, una durata e un'azione successiva descritta per iscritto.

Mostra la soluzione

Conserva la prima finestra sana di output di monitor.py come baseline.jsonl, poi confronta ogni nuova finestra con essa:

import json

import numpy as np
from scipy.stats import ks_2samp

def load(path):
    """Flatten the per-frame 'confs' lists written by monitor.py."""
    with open(path) as f:
        return np.array([c for line in f for c in json.loads(line)["confs"]])

baseline, recent = load("baseline.jsonl"), load("metrics.jsonl")
stat, p = ks_2samp(baseline, recent)
print(f"KS={stat:.3f} p={p:.2g} -> {'review frames' if p < 0.01 else 'ok'}")
KS=0.000 p=1 -> ok

È il risultato previsto quando entrambi i file provengono dallo stesso filmato. Esegui il test ogni giorno tramite uno scheduler, invia la statistica e il p-value allo stesso sistema di metriche dei log per fotogramma e inoltra review frames a una persona, non a un sistema di pager.

Prossimi passi

Ultima lezione: quando i dashboard indicano che latenza o costo superano il budget, quale leva azionare per prima.

Accedi per salvare i progressi