Monitora lo stato e la precisione
Consulta le metriche degli endpoint e le statistiche delle previsioni della piattaforma, configura avvisi tramite un controllo programmato dello stato e rileva il calo di precisione con un processo sul set di controllo.
Un endpoint può restituire 200 OK a ogni richiesta mentre la sua precisione cala di 5 punti perché durante il turno di notte le luci sono state abbassate. La piattaforma mostra il comportamento di ogni endpoint, ma non invia notifiche e non può rilevare la precisione senza etichette. In questa lezione creerai i due controlli programmati che colmano questa lacuna e proverai l'avviso sulla precisione simulando un turno di notte.
Pratico
Cosa mostra la piattaforma#

| Segnale | Dove | Durata della conservazione |
|---|---|---|
| Richieste HTTP, tasso di errore (4xx e 5xx), latenza P95 | Schede nella pagina della distribuzione e nella scheda Deployments, aggiornate ogni minuto | Le schede coprono 24 ore; l'API fornisce dati da 1 ora a 30 giorni |
| Stato | Scheda Endpoint nella scheda Overview | In tempo reale; viene ritentato automaticamente finché lo stato non torna regolare |
| Log | Scheda Logs: i 20 più recenti, con il filtro Errors | L'API restituisce fino a 200 voci per richiesta, con paginazione |
| Statistiche delle previsioni ed esempi temporanei (fino a 100 immagini) | Scheda Monitoring | Solo nella memoria dell'istanza di servizio |

Due limitazioni influiscono su tutto il resto. Le metriche vengono raccolte solo mentre l'endpoint è Ready e, se elimini una distribuzione, non puoi più accedere alla relativa cronologia. Le statistiche e gli esempi della scheda Monitoring vanno persi ogni volta che l'endpoint si arresta, si riavvia, cambia dimensioni o sostituisce il modello: sono una vista in tempo reale, non un archivio.
Esempio pratico: un controllo programmato dell'endpoint#
La piattaforma mostra in rosso la scheda del tasso di errore quando supera il 5% e Slack può annunciare quando una distribuzione è pronta o non riesce ad avviarsi, ma non ci sono avvisi basati su soglie. Esegui questo controllo ogni 5 minuti tramite cron, CI o il tuo agente di monitoraggio e invia una notifica in caso di codice di uscita diverso da zero:
from ultralytics_platform import Platform
OWNER, DEPLOYMENT = "your-username", "yolo26n-iowa" # from the deployment page URL
P95_BUDGET_MS, MAX_ERROR_RATE = 300, 1.0 # errorRate is a percentage
with Platform() as client: # reads ULTRALYTICS_API_KEY
health = client.deployments.health(OWNER, DEPLOYMENT)
summary = client.deployments.metrics(OWNER, DEPLOYMENT, range="1h", view="overview")["summary"]
print(
f"healthy={health['healthy']} requests={summary['totalRequests']} "
f"p95={summary['p95LatencyMs']:.0f} ms errors={summary['errorRate']:.2f}%"
)
if not health["healthy"] or summary["p95LatencyMs"] > P95_BUDGET_MS or summary["errorRate"] > MAX_ERROR_RATE:
for entry in client.deployments.logs(OWNER, DEPLOYMENT, severity="ERROR,WARNING", limit=5)["entries"]:
print(entry["timestamp"], entry["severity"], entry["message"][:120])
raise SystemExit(1) # non-zero exit lets cron, CI, or your pager treat it as an alertEseguito con uno stub API che restituisce un endpoint integro, stampa una riga e termina con codice 0; con P95_BUDGET_MS = 100, gli stessi dati fanno terminare il processo con codice 1:
healthy=True requests=1200 p95=180 ms errors=0.40%healthverifica l'endpoint e restituiscehealthy,statuselatencyMs. Inoltre riattiva un endpoint ridimensionato fino a zero, quindi una pianificazione ogni 5 minuti funge anche da ping per mantenerlo attivo.metrics(..., view="overview")restituiscetotalRequests,errorRate(una percentuale) ep95LatencyMsper l'intervallo.logsrecupera gli errori e gli avvisi più recenti, così l'avviso include già un primo indizio.
Installa l'SDK con pip install -U ultralytics-platform (l'SDK richiede Python 3.11 o versione successiva). Invia avvisi solo per problemi persistenti, ad esempio dopo tre controlli consecutivi non riusciti, e accompagna ogni avviso con una voce di una riga nel runbook.
Esempio pratico: monitora la precisione con un set di controllo#
Le metriche delle richieste non rilevano la precisione. Un set di controllo sì: 200–500 immagini realistiche della produzione, etichettate con cura in una versione del dataset privata e separata, mai usate per l'addestramento. Valuta settimanalmente il checkpoint distribuito e aggiungi i risultati a un file cronologico:
import json
import sys
from datetime import date
from pathlib import Path
from ultralytics import YOLO
DEPLOYED = "pills-v1.pt" # the exact best.pt behind the endpoint
HOLDOUT = sys.argv[1] if len(sys.argv) > 1 else "medical-pills.yaml" # labeled, never trained on
metrics = YOLO(DEPLOYED).val(data=HOLDOUT, split="val", plots=False, verbose=False)
history = Path("holdout_history.jsonl")
rows = [json.loads(line) for line in history.read_text().splitlines()] if history.exists() else []
row = {"date": date.today().isoformat(), "data": HOLDOUT, "map50_95": round(float(metrics.box.map), 4)}
history.write_text("".join(json.dumps(r) + "\n" for r in [*rows, row]))
baseline = rows[0]["map50_95"] if rows else row["map50_95"]
drop = baseline - row["map50_95"]
print(f"holdout mAP50-95 {row['map50_95']:.3f} (baseline {baseline:.3f}, drop {drop:+.3f})")
if drop > 0.01: # more than 1 mAP point below the deployment-day baseline
raise SystemExit("ALERT: holdout accuracy regressed - open the retraining runbook")La prima esecuzione registra il valore di riferimento del giorno della distribuzione. Poi prova l'avviso prima di averne bisogno: questo script crea una copia del set di controllo per il «turno di notte», con le stesse etichette e immagini impostate al 15% di luminosità:
import shutil
from pathlib import Path
import cv2
from ultralytics.data.utils import check_det_dataset
src = Path(check_det_dataset("medical-pills.yaml")["path"])
dst = Path("pills-night")
(dst / "images/val").mkdir(parents=True, exist_ok=True)
for img in (src / "images/val").glob("*.jpg"): # darken every holdout image to mimic a dim night shift
cv2.imwrite(str(dst / "images/val" / img.name), (cv2.imread(str(img)) * 0.15).astype("uint8"))
shutil.copytree(src / "labels/val", dst / "labels/val", dirs_exist_ok=True) # same labels, darker pixels
Path("pills-night.yaml").write_text(f"path: {dst.resolve()}\ntrain: images/val\nval: images/val\nnames:\n 0: pill\n")
print("wrote pills-night.yaml")$ python holdout_check.py
holdout mAP50-95 0.659 (baseline 0.659, drop +0.000)
$ python simulate_night_shift.py
wrote pills-night.yaml
$ python holdout_check.py pills-night.yaml
holdout mAP50-95 0.609 (baseline 0.659, drop +0.050)
ALERT: holdout accuracy regressed - open the retraining runbookDurante il turno di notte ogni richiesta continuerebbe a restituire 200 in pochi millisecondi, eppure il modello avrebbe perso 5 punti mAP. Solo il set di controllo rileva il problema. Ogni trimestre aggiorna il set di controllo con nuove immagini di produzione etichettate e reimposta il valore di riferimento ogni volta che distribuisci un nuovo modello. La guida al monitoraggio dei modelli e la lezione Osservabilità e deriva trattano i test di deriva statistica.
Leggi la scheda Monitoring per rilevare la deriva#

Annota la forma dei grafici nella settimana in cui distribuisci il modello, poi confrontali. La confidenza misura il grado di certezza, non la correttezza: esamina questi dati insieme al set di controllo:
| Situazione | Causa probabile | Azione |
|---|---|---|
| La confidenza cala, ma il set di controllo resta stabile | Variazione non problematica del dominio | Monitora la situazione; salva gli esempi per la prossima versione del dataset |
| Calano sia la confidenza sia i risultati sul set di controllo | Regressione effettiva della precisione | Riaddestra il modello (lezione 10) |
| Dimensioni o posizioni delle box cambiano improvvisamente | La videocamera è stata spostata oppure l'obiettivo o il sito sono cambiati | Controlla la videocamera prima di intervenire sul modello |
| Diminuiscono le previsioni per immagine, ma la confidenza resta stabile | La videocamera è offline, la scena è meno movimentata o c'è un bug nel client | Indaga sui sistemi a monte |
| La latenza P95 aumenta, ma il tempo di inferenza resta stabile | Gestione delle richieste, dimensione del payload o capacità | È un problema dell'infrastruttura, non del modello |
Riutilizza le immagini di produzione#
Nella scheda Monitoring, seleziona gli esempi e fai clic su Save to dataset; vengono acquisiti tramite il normale processo di importazione insieme alle relative previsioni e conservano nei metadati deploymentId e la regione. Il modello Collect Uncertain Detections degli Agents fa lo stesso per un intero dataset: esegue previsioni tramite la tua distribuzione e copia in un dataset di revisione le immagini con rilevamenti la cui confidenza rientra in un intervallo specificato.

Insidie#
Sintomo: gli esempi che volevi etichettare non ci sono più dopo un ridimensionamento o una sostituzione del modello. Soluzione: sono conservati nella memoria dell'istanza di serving. Salvali in un dataset e attendi il completamento dell'importazione prima di arrestare, ridimensionare o sostituire il modello.
Sintomo: l'avviso del set di holdout scatta subito dopo la distribuzione di un modello migliore oppure non scatta mai più. Soluzione: il baseline è la prima riga della cronologia. Avvia un nuovo holdout_history.jsonl (oppure registra una nuova riga di baseline) ogni volta che sostituisci il modello.
Sintomo: il tasso di errore aumenta durante un picco di traffico, mentre lo stato del servizio è verde. Soluzione: le risposte 429 vengono conteggiate come errori, ma significano «capacità massima raggiunta». Controlla i log; se si tratta di 429, distribuisci il traffico su più endpoint oppure usa una dimensione personalizzata maggiore.
Mostra la soluzione
Soluzione svolta per l'endpoint delle pillole: una voce cron */5 * * * * python endpoint_check.py || ./page-oncall.sh con P95_BUDGET_MS = 300 e MAX_ERROR_RATE = 1.0; impostare il limite a 100 ms rispetto a un P95 reale di 180 ms termina con codice 1 e invia una notifica, quindi il collegamento funziona. Il job CI settimanale esegue holdout_check.py con DEPLOYED = "pills-v2.pt" sulla versione privata del holdout da 300 immagini: baseline 0.69. La simulazione del turno di notte lo riduce di 0.05 e stampa la riga ALERT con codice di uscita 1, facendo fallire il job CI e inviando una notifica al canale. Dodici esempi di monitoraggio del turno serale vengono aggiunti a pill-review tramite Salva nel dataset, ciascuno contrassegnato con deploymentId e europe-west1.