Ultralytics YOLO27: Inscreve-te na lista de espera.
Get Started
Ultralytics YOLO em produção·Calibrar e observar·Aula 8/9
Aulaintermediário

Observabilidade e deriva

Regista as métricas que detetam perdas de precisão silenciosas, testa a deriva das distribuições de confiança e gera alertas apenas para sinais que exigem ação.

Um serviço de visão pode estar disponível, ser rápido e estar errado. Uma câmera é deslocada, a iluminação muda, surge uma nova linha de produtos e o modelo continua a devolver caixas enquanto todos os painéis de infraestrutura permanecem verdes. Nesta lição, escurecer um clipe para simular o anoitecer alterou a confiança média em apenas 0,01 — algo impercetível num gráfico —, mas um teste KS de duas amostras assinalou a alteração com p = 0,007. Vais criar esse teste e o registo de dados que o alimenta.

Resultado

Emite métricas JSON por frame, executa um teste de deriva KS em relação a uma referência inicial, valida um conjunto de teste reservado e define alertas associados a ações concretas.

Via rápida
Se já sabes orientar-te, aqui está a versão resumida.
  1. Por frame: câmera, r.speed["inference"], quantidade de deteções, confiança média e valores de confiança brutos.

  2. Guarda as confianças do início como referência; compara cada dia com scipy.stats.ks_2samp.

  3. Valida semanalmente um conjunto de teste reservado e rotulado com yolo val; gera um alerta se houver uma queda superior a 1 ponto de mAP.

  4. Gera alertas apenas para sinais que tenham uma próxima ação documentada; tudo o resto deve ficar num painel.

Prático

Três camadas de sinais#

CamadaPerguntaSinais
InfraestruturaO serviço está disponível e acompanha o ritmo?Latência, débito, frames descartados, utilização de CPU e GPU
Comportamento do modeloO modelo está a comportar-se como na semana passada?Deteções por frame, confiança média, distribuição de classes, tamanhos das caixas
Precisão do modeloO modelo continua a acertar?mAP no conjunto de teste reservado (métricas de desempenho), revisão humana por amostragem, taxa de falsos alarmes

A maioria das equipas cobre a primeira camada com ferramentas padrão e fica por aí. A segunda e a terceira são onde os sistemas de visão falham silenciosamente; o guia de monitorização de modelos aborda todo o ciclo de manutenção.

Página de implementação da Ultralytics Platform no separador Logs, com os filtros Errors e All acima de linhas INFO de pedidos com data e hora, para monitorização e chamadas de exemplo

Se implementares através da Ultralytics Platform, a página de implementação fornece a camada de infraestrutura (pedidos, taxa de erros, latência P95) e registos de pedidos que podes filtrar por erros, como acima; a lição Monitorizar a integridade e a precisão aborda esses aspetos. As camadas de comportamento e precisão ficam a teu cargo, e o resto desta lição ensina a criá-las.

Emite métricas por frame#

Cada objeto Results inclui tempos e caixas. Escreve uma linha JSON por frame e envia-a para o sistema de métricas que utilizas:

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()],  # valores brutos para o teste de 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}

Para que serve cada campo:

  • inference_ms: gera um alerta quando p95 exceder o limite definido.
  • detections: uma queda repentina para perto de zero geralmente indica uma câmera bloqueada ou com defeito; um aumento indica uma mudança na cena ou falsos positivos.
  • mean_conf: uma linha de tendência rápida, mas demasiado grosseira para detectar deriva por si só.
  • confs: a distribuição completa, necessária para o teste de deriva abaixo.

Testar distribuições de confiança para detectar deriva#

A deriva de dados aparece nos níveis de confiança muito antes de alguém rotular dados novos. Recolhe os níveis de confiança no lançamento como linha de base, recolhe uma janela recente e compara as duas distribuições com um teste de Kolmogorov-Smirnov de duas amostras (pip install scipy). Este script simula o anoitecer escurecendo o mesmo clipe:

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

Lê linha a linha:

  • Mesma cena: distribuições idênticas produzem uma estatística KS de 0 e p = 1, o resultado de controlo.
  • Anoitecer: 39 deteções a menos e uma média apenas 0,011 inferior, algo que ninguém notaria num gráfico. A estatística KS (a maior diferença entre as duas distribuições cumulativas) é 0,064, e p = 0,0068 < 0,01 indica que a alteração é real.

Um alerta de deriva é um motivo para analisar fotogramas de amostra, não uma prova de falha. Quando a deriva for real, recolhe e rotula fotogramas das câmeras afetadas: o guia de recolha e anotação de dados explica o que recolher, e o guia de ajuste fino explica o retreino. Os tamanhos das caixas (largura × altura) são um segundo indicador simples de deriva: as novas montagens e óticas aparecem primeiro nesses dados.

Valida semanalmente um conjunto de validação reservado#

Os sinais comportamentais indicam que algo mudou; só os rótulos mostram se a precisão caiu. Mantém um conjunto de validação reservado com 200–500 imagens de produção rotuladas e valida cada versão do modelo, além de o fazer todas as semanas:

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

Regista mAP50-95 e AP por classe ao longo do tempo e gera um alerta quando mAP cair mais de 1 ponto de uma semana para a seguinte. A causa mais comum é uma troca de modelo que deveria ser neutra; a segunda é a deriva. Uma matriz de confusão sobre o mesmo conjunto de validação reservado torna evidentes as regressões por classe.

Qualidade do modelo ao longo do tempo: a qualidade mantém-se enquanto chegam novos dados rotulados e, depois, diminui após o ponto de queda esperado; a questão é se devemos retreinar agora ou esperar

O conjunto de validação reservado é o que responde à pergunta deste gráfico. Retreina quando mostrar que a qualidade começa a cair ou quando tiveres dados rotulados novos suficientes das condições com deriva, e não segundo um calendário fixo.

Gera alertas para ações, não para números#

SinalGerar alerta quandoAção
p95 inference_msAcima do limite por mais de 3 minutosEscala horizontalmente ou muda para a exportação otimizada
Deteções por fotogramaQueda de 50% ou mais durante 5 minutosVerifica o fluxo da câmera e, depois, a versão do modelo
Fotogramas perdidosAcima de 5% durante 10 minutosAumenta a capacidade ou reduz os FPS por fluxo
Teste KS de confiançap < 0,01 em janelas diáriasAnalisa os fotogramas e, depois, executa a validação reservada
mAP50-95 do conjunto de validação reservadoQueda de 1 ponto ou mais de uma semana para a seguinteRecolhe, rotula e ajusta o modelo

Armadilhas#

Comparar janelas diferentes

Sintoma: o teste KS dispara todas as noites e todas as segundas-feiras. Solução: ciclos diários e semanais são mudanças reais de distribuição. Compare situações equivalentes (mesmas câmeras, mesmos horários, mesmo dia da semana) e use janelas de milhares de detecções.

Um conjunto de teste desatualizado

Sintoma: a mAP do conjunto de teste parece boa, mas os usuários relatam objetos não detectados. Solução: o conjunto de teste precisa se parecer com a produção atual. Atualize-o a cada trimestre com novos quadros rotulados das câmeras importantes.

Se ninguém agiria com base no alerta, não o envie

Todo alerta precisa de uma próxima ação descrita por escrito. Um sinal que você só quer monitorar deve ficar em um painel, não no sistema de alertas.

Experimente

Adiciona o registo JSON ao teu pipeline e executa-o durante uma hora (ou num vídeo longo). Mantém a primeira janela como baseline.jsonl e, em seguida, executa a verificação KS da solução numa segunda janela: uma hora diferente do dia, uma câmera diferente ou uma cópia escurecida. Apresenta a estatística KS e o valor p, além da tua tabela de alertas com uma ação para cada linha.

Concluído quando
Você concluiu a aula quando todos estes critérios forem atendidos.
  • O teu pipeline escreve uma linha JSON por fotograma, com latência, número de deteções, confiança média e níveis de confiança brutos.

  • Executaste um teste KS entre uma janela de linha de base e uma janela recente e registaste a estatística e o valor p.

  • Cada alerta que definiste tem um limiar, uma duração e uma próxima ação documentada.

Mostrar solução

Guarda a primeira janela saudável da saída de monitor.py como baseline.jsonl e, depois, compara cada nova janela com ela:

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

Esse é o resultado esperado quando os dois ficheiros provêm das mesmas imagens. Executa o teste diariamente com um agendador, envia a estatística e o valor p para o mesmo sistema de métricas dos registos por fotograma e encaminha review frames para uma pessoa, não para um sistema de pager.

Próximos passos

Na última lição, vais aprender qual alavanca acionar primeiro quando os painéis indicarem que a latência ou o custo ultrapassam o limite.

Entre para salvar seu progresso