Lab 77 — Drift: descobrir antes do negócio reclamar
O problema, e a empresa que o tem
A Cadência publicou, há dois meses, um modelo de risco de cancelamento: dado o pedido de um lojista — valor, categoria, histórico do lojista, forma de pagamento — o endpoint devolve a probabilidade de aquele pedido ser cancelado antes da entrega. A API de aprovação de pedido chama o endpoint em cada checkout e usa a probabilidade para decidir se reserva estoque na hora ou segura a confirmação por algumas horas, esperando o lojista pagar. Dois meses no ar, latência estável, taxa de erro HTTP em zero — pelos painéis técnicos, o melhor serviço da casa.
Na semana passada, o time comercial trouxe uma pergunta incômoda: por que a taxa de cancelamento REAL do último mês está bem acima do que o modelo vinha prevendo? Ninguém tinha comparado os dois números antes — o relatório de cancelamento real é mensal, vem do time de operações, e nunca foi cruzado automaticamente com a predição que o modelo fez pedido a pedido. Quando alguém finalmente fez essa conta à mão numa planilha, a diferença apareceu: para pedidos de valor alto de uma categoria nova de fornecedor — ferramentas elétricas, que só passou a vender pela Cadência há sete semanas — o modelo prevê cancelamento baixo, e a taxa real está quase o dobro disso.
Duas hipóteses concorrem, e elas pedem diagnóstico diferente. A primeira: a DISTRIBUIÇÃO do que chega mudou — a categoria de ferramentas elétricas simplesmente não existia no dado de treino, então o modelo está extrapolando para uma região do espaço de features que nunca viu. Isso é drift de dado. A segunda: a RELAÇÃO entre entrada e saída mudou — talvez o perfil de lojista que compra ferramentas elétricas cancele por um motivo que o modelo nunca aprendeu a associar a risco (prazo de entrega mais longo, por exemplo), e mesmo pedidos de categorias antigas estejam sendo mal previstos agora. Isso é drift de conceito. Nenhum dos dois é erro técnico — o endpoint nunca caiu, nunca teve latência alta, nunca devolveu erro. É exatamente por isso que dois meses se passaram sem alarme nenhum: o único monitoramento que existe mede se o endpoint está de pé, não se ele ainda está certo.
Onde este módulo começa
O L70 garante que o VALOR de cada linha respeita um contrato (tipo, faixa). Este módulo pressupõe esse contrato cumprido e ataca um problema diferente: uma distribuição inteira pode estar dentro da faixa contratada e ainda assim ter se deslocado o suficiente para o modelo errar. Contrato de dado e Model Monitor não competem — o primeiro pega valor absurdo linha a linha, o segundo pega padrão agregado que nenhuma linha isolada revela.
O que você vai conseguir fazer
Ao final deste laboratório você terá construído, não apenas lido sobre, um sistema de detecção de drift ponta a ponta. Objetivos verificáveis:
- Calcular uma baseline estatística (statistics.json e constraints.json) a partir do dado de treino com o SageMaker Model Monitor, e explicar o que cada constraint decide.
- Ativar Data Capture num endpoint SageMaker existente sem aumentar a latência percebida pelo checkout.
- Agendar um Monitoring Schedule horário que compara cada lote capturado contra a baseline, com o job realmente executando e publicando métrica no CloudWatch.
- Configurar um Model Quality Monitor que mescla o resultado real (atrasado) com a predição salva, para medir drift de CONCEITO — não só de dado.
- Configurar um CloudWatch Alarm com poucos datapoints em breach, calibrado para disparar dentro da janela horária sem confundir sazonalidade legítima com drift.
- Deslocar uma feature de propósito, medir o tempo exato até o alarme disparar, e registrar esse número.
- Distinguir, diante de um alarme real, se a causa é drift de dado, drift de conceito ou erro técnico — e explicar por que a distinção muda a resposta.
O que a certificação cobra disto
| Conceito | Certificação | Como aparece no laboratório | O que dominar |
|---|---|---|---|
| Drift de dado | MLA-C01 / MLS-C01 | Model Monitor — Data Quality comparando a distribuição capturada contra statistics.json/constraints.json | Distinguir mudança de DISTRIBUIÇÃO de entrada de erro de schema — o L70 já garante schema, este módulo assume schema correto |
| Drift de conceito | MLA-C01 / MLS-C01 | Model Quality Monitor mesclando predição salva com ground truth atrasado por inference-id | Explicar por que a relação entrada→saída pode mudar mesmo com a distribuição de entrada estável — a pergunta "o que X significa" mudou, não X |
| Baseline (statistics.json / constraints.json) | MLA-C01 | suggest_baseline rodando uma vez sobre uma amostra do dado de treino | Como o teste estatístico por feature decide a faixa "normal" — e por que recalcular a baseline é decisão editorial, não automática |
| CloudWatch Alarm com poucos datapoints em breach | MLA-C01 / AIF-C01 | Alarme configurado para mudar de estado com 1 execução violada dentro de 1 período de avaliação | O trade-off entre sensibilidade (detectar rápido) e falso positivo (sazonalidade legítima disparando alarme à toa) |
| Erro técnico vs. drift | AIF-C01 / MLA-C01 | Comparação explícita entre o que o CloudWatch técnico (latência, HTTP 5xx) já mostra e o que só o Model Monitor detecta | Por que "o endpoint nunca caiu" não é evidência de que o modelo continua certo |
Requisitos, e como cada um muda o desenho
Cada requisito abaixo é o que separa a arquitetura mínima (seção seguinte) da arquitetura de produção — nenhuma peça nova entra sem um requisito que a justifique.
| Requisito | Valor | Como influencia a arquitetura |
|---|---|---|
| Detectar drift de dado | em até 1 hora da mudança | Monitoring Schedule com cron horário + CloudWatch Alarm com poucos datapoints em breach, em vez de revisão manual periódica |
| Detectar drift de conceito | mesmo sem nenhum alarme técnico disparando | Model Quality Monitor separado, que mescla ground truth atrasado (D+3, quando o pedido é entregue ou cancelado de fato) com a predição salva |
| Não confundir sazonalidade legítima com drift | baseline por período, não limiar fixo arbitrário | suggest_baseline roda sobre amostra representativa de várias semanas, com teste estatístico formal — não um "se mudar mais que 10%" chutado |
| Auditabilidade da decisão do plantão | relatório de violação com o teste e o p-valor, não um booleano | Model Monitor grava constraint_violations.json completo em S3 versionado — a decisão de agir ou não fica rastreável |
| Não aumentar a latência do checkout | Data Capture não pode bloquear a resposta | a gravação da captura é assíncrona ao lado do SageMaker runtime, fora do caminho crítico da resposta ao chamador |
| Custo previsível de execução contínua | sem streaming, sem cluster dedicado | job de Processing agendado, instância pequena, minutos de execução por hora — não um serviço rodando 24 h |
Arquitetura mínima: o endpoint que nunca cai, e por isso parece bem
Comece pelo que a Cadência já tinha: um endpoint SageMaker servindo em tempo real, sem nenhuma peça de monitoramento de qualidade. Ele passa em toda checagem técnica e ainda assim pode estar errando metade das previsões de uma categoria inteira.
- → features do pedido, chamada síncrona InvokeEndpoint
- → probabilidade de cancelamento, decide reservar estoque agora ou esperar
- → latência e status HTTP de cada chamada — nunca a predição em si
- → consulta manual, sem gatilho automático nenhum
- Rede e entrega
- IA e machine learning
- Gestão e governança
- Analytics
- Fora da AWS
Este é literalmente o que a Cadência tinha até a semana passada: um endpoint que responde rápido, nunca cai, e por isso os painéis técnicos ficam verdes o tempo todo. Percorra os passos e repare que não existe nenhum caminho, neste desenho, que compare a predição com a distribuição de treino ou com o resultado real do pedido — o defeito não é uma peça quebrada, é uma peça que nunca foi desenhada.
- O checkout chama o endpoint a cada pedido. Chamada síncrona InvokeEndpoint: o lojista espera a resposta antes de ver a confirmação do pedido na tela.
- O endpoint decide, e a decisão vira reserva de estoque na hora. A probabilidade volta em poucos milissegundos e alimenta diretamente a regra de negócio — sem nenhuma checagem de plausibilidade no meio do caminho.
- O único sinal registrado automaticamente é técnico. CloudWatch recebe latência e status HTTP de cada chamada. Isso já existe por padrão, sem nenhuma configuração — e é exatamente por isso que parece suficiente.
- O endpoint nunca cai, e "nunca cair" é lido como "está tudo bem". Erro técnico zero, latência estável — os dois sinais que existem apontam para saúde. Nenhum dos dois mede se a predição continua correta, só se o serviço continua de pé.
- Quando alguém finalmente olha, o relatório é manual e mensal. O time comercial percebe a discrepância por acaso, comparando planilhas — não porque algum sistema avisou.
- Por que a equipe pequena convive com isso até doer. Configurar um monitor de drift parece trabalho sem retorno imediato enquanto o endpoint "funciona" — até a distribuição de entrada mudar o suficiente para o erro virar dinheiro perdido em estoque mal alocado.
# O endpoint como ele já existe — nenhuma linha nova aqui, isto é o "antes".
# Real-time endpoint padrão, sem DataCaptureConfig: nada é gravado além do
# log de acesso e das métricas técnicas que o SageMaker publica por padrão.
import boto3
sm = boto3.client('sagemaker-runtime')
resposta = sm.invoke_endpoint(
EndpointName='risco-cancelamento-cadencia',
ContentType='application/json',
Body=json.dumps({
'valor_pedido': 1840.00,
'categoria': 'ferramentas_eletricas', # categoria nova, fora do treino
'dias_desde_cadastro_lojista': 12,
'forma_pagamento': 'boleto',
}),
)
probabilidade = json.loads(resposta['Body'].read())['probabilidade_cancelamento']
# Nada aqui grava a feature enviada nem a probabilidade devolvida em nenhum
# lugar que alguém audite depois. Se a distribuição de "categoria" mudou,
# este código não tem como saber.
O que "saudável" mede aqui
Latência baixa e erro HTTP zero são necessários, mas medem apenas que o processo está de pé. Um endpoint pode estar 100% saudável nesse sentido e 100% errado no sentido que importa para o negócio — os dois são perguntas diferentes, e este desenho só responde a primeira.
Arquitetura para produção
Cada peça que entra aqui rastreia a um requisito da seção anterior: captura sem tocar a latência, baseline calculada à parte, dois monitores paralelos (dado e conceito), e um alarme calibrado para não confundir sazonalidade com drift real.
- → features do pedido, chamada síncrona
- → probabilidade de cancelamento
- → grava o par entrada/saída, fora do caminho síncrono
- → dado de treino usado para calcular a baseline
- → constraints.json e statistics.json usados como referência
- → lote da última hora, para comparar contra a baseline
- → resultado real do pedido, mesclado por inference-id
- → predição salva, para comparar com o resultado real
- → violação por feature de dado, publicada a cada execução
- → métrica de qualidade real, publicada com o atraso do ground truth
- → poucos datapoints em breach já mudam o estado
- → notificação com o relatório de violação anexado
- → aciona quem decide o próximo passo
- Rede e entrega
- IA e machine learning
- Armazenamento
- Gestão e governança
- Integração de apps
- Conceito de arquitetura
A mesma decisão de negócio (reservar estoque ou não) agora é cercada por uma baseline calculada do treino, um schedule horário que compara cada lote contra ela, e um segundo monitor que mescla o resultado real, atrasado, para pegar drift de CONCEITO que o primeiro não vê. Percorra os passos: repare que dado e conceito seguem caminhos paralelos até convergirem na mesma métrica de CloudWatch, e que nenhuma peça nova toca o caminho síncrono do checkout.
- Chamada síncrona ao endpoint, sem mudança de latência percebida. O checkout continua vendo a mesma resposta rápida. Data Capture não está no caminho crítico.
- Captura do par entrada/saída, assíncrona. O SageMaker grava a amostra em S3 depois de responder ao chamador — a decisão comercial nunca espera pela gravação.
- Baseline calculada uma vez sobre o treino. suggest_baseline roda como um job isolado, não em todo request — o custo dele não escala com tráfego.
- O schedule horário compara o lote contra a baseline e publica a violação de dado. Duas entradas convergem no mesmo job — o lote capturado e as constraints calculadas antes — e o resultado (drift de DADO na feature "categoria", por exemplo) vira métrica no mesmo passo.
- Em paralelo, o resultado real, atrasado, mede drift de conceito. Quando o ground truth chega em D+3, o Model Quality Monitor mescla com a predição salva e recalcula a acurácia real — isto pega o caso em que a distribuição de entrada nem mudou, mas a relação com a saída mudou.
- O alarme confirma com pouco atraso. Um datapoint em breach já muda o estado — a janela de avaliação de uma hora inteira já é o suficiente de confirmação.
- O plantão recebe o relatório e decide o próximo passo. A notificação leva a feature, o teste estatístico e o p-valor — o plantão não precisa abrir console para saber o que aconteceu.
A diferença central para a arquitetura mínima não é "adicionar uma caixa" — é que agora existem DOIS caminhos de avaliação correndo em paralelo ao caminho síncrono do checkout: um que compara distribuição contra baseline a cada hora, outro que compara predição contra resultado real assim que ele existe. Nenhum dos dois bloqueia o pedido do lojista.
Por que dois monitores, e não um só
Data Quality Monitor pega mudança de DISTRIBUIÇÃO de entrada sem precisar saber o resultado real — por isso detecta em até uma hora. Model Quality Monitor pega mudança de RELAÇÃO entre entrada e saída, mas só depois que o resultado real chega — por isso detecta mais devagar, em dias. Os dois juntos cobrem o que nenhum dos dois cobre sozinho.
O caminho do dado, ponta a ponta
Do pedido chegando ao checkout até o plantão recebendo um relatório com número, o caminho passa por oito etapas — duas delas em paralelo, uma rápida (dado) e uma lenta (conceito).
Trecho real do relatório que o Model Monitor grava em S3 a cada execução (constraint_violations.json). É isto que o SNS anexa ao plantão.
{
"violations": [
{
"feature_name": "categoria",
"constraint_check_type": "categorical_values_not_in_baseline",
"description": "categoria 'ferramentas_eletricas' apareceu em 16.2% dos registros do lote; a baseline de treino nao tem nenhuma ocorrencia dessa categoria"
},
{
"feature_name": "valor_pedido",
"constraint_check_type": "baseline_drift_check",
"description": "distancia de distribuicao (teste two-sample KS) = 0.31, acima do limiar de 0.10 calibrado na baseline"
}
]
}
O relatório é a unidade de auditoria
Cada execução do schedule grava um relatório completo em S3, versionado. O CloudWatch só publica o RESUMO numérico (quantas violações); quem investiga vai ao relatório para ver qual feature e qual teste específico falhou — é essa camada que torna a decisão do plantão rastreável depois.
As decisões, e o que se perde em cada uma
📋 A Cadência precisa detectar drift de dado e de conceito num endpoint que já está em produção, sem orçamento para um time de MLOps dedicado, e sem poder adicionar latência ao checkout.
Resolve as duas dívidas sem inventar peça nova: Data Capture é uma flag na configuração do endpoint que já existe, o schedule roda como Processing Job gerenciado (sem cluster para operar), e o alarme usa o mesmo CloudWatch que a Cadência já monitora para latência e erro técnico — só que com uma métrica diferente, calculada por um teste estatístico formal em vez de um limiar chutado.
Alt: Job Glue/Athena comparando distribuições manualmente, sem Model Monitor — Funciona, mas reimplementa o teste estatístico do zero, precisa de agendamento próprio (EventBridge Scheduler) e não se integra ao ciclo de vida do endpoint — quando o modelo é re-publicado, ninguém garante que o job de comparação aponta para a versão certa.
Alt: Só confiar no relatório mensal de negócio (o que a Cadência já tinha) — É o próprio problema que este módulo resolve: detecção em semanas, não em horas, e depende de um humano decidir olhar — que foi exatamente o que não aconteceu por dois meses.
Alt: Re-treinar em cadência fixa (toda sexta-feira), sem monitorar nada — Gasta computação re-treinando mesmo quando não há drift nenhum, e continua cego entre um treino e o outro — se o drift aparece na terça, o modelo erra até sexta mesmo assim.
Alt: Framework de drift open-source rodando fora da AWS (container dedicado) — Maduro e popular, mas exige operar um serviço a mais, duplicar a leitura do dado capturado, e não aproveita a integração nativa do Model Monitor com o ciclo de vida do endpoint.
| Decisão | Escolha | O que se perde |
|---|---|---|
| Frequência do schedule | Horário (cron a cada hora) | Detecção mais rápida (a cada 15 min) custaria 4x mais execuções por dia sem ganho proporcional — o requisito pede 1 hora, não 15 minutos |
| Sensibilidade do alarme | 1 datapoint em breach dentro de 1 período | Exigir 2 ou 3 execuções consecutivas violadas atrasaria a detecção em até 3 horas — trade-off que este módulo escolhe não pagar, dado que o relatório completo (não só o alarme) chega ao plantão para confirmação humana |
| Amostragem da captura | 100% neste volume (2.100 pedidos/dia) | Em volume maior, amostragem parcial reduz custo de S3 e poder estatístico do teste — decisão que a seção de escala retoma |
Baseline não é "configure e esqueça"
A baseline calculada hoje reflete o dado de treino de hoje. Depois de um retrain aprovado (tema do L75), a baseline precisa ser recalculada — senão o monitor compara o modelo novo contra a distribuição do modelo antigo, e um retrain legítimo dispara falso alarme.
Construir: endpoint com Data Capture (Terraform)
A infraestrutura fixa — modelo, configuração de endpoint com captura ativada, bucket de captura e papel de execução — entra em Terraform, porque não muda a cada execução do monitor.
resource "aws_s3_bucket" "model_monitor" {
bucket = "cadencia-model-monitor-risco-cancelamento"
tags = {
projeto = "risco-cancelamento"
time = "ml-plataforma"
contexto = "l77-drift"
}
}
resource "aws_s3_bucket_versioning" "model_monitor" {
bucket = aws_s3_bucket.model_monitor.id
versioning_configuration {
status = "Enabled" # relatório de violação precisa de histórico auditável
}
}
resource "aws_iam_role" "endpoint_execution" {
name = "cadencia-risco-cancelamento-endpoint-role"
assume_role_policy = jsonencode({
Version = "2012-10-17"
Statement = [{
Effect = "Allow"
Principal = { Service = "sagemaker.amazonaws.com" }
Action = "sts:AssumeRole"
}]
})
}
resource "aws_iam_role_policy" "endpoint_captura" {
name = "captura-s3"
role = aws_iam_role.endpoint_execution.id
policy = jsonencode({
Version = "2012-10-17"
Statement = [{
Effect = "Allow"
Action = ["s3:PutObject"]
# Resource especifico ao prefixo de captura -- nao ao bucket inteiro.
Resource = "${aws_s3_bucket.model_monitor.arn}/captura/*"
}]
})
}
resource "aws_sagemaker_model" "risco_cancelamento" {
name = "risco-cancelamento-v12"
execution_role_arn = aws_iam_role.endpoint_execution.arn
primary_container {
image = var.imagem_inferencia
model_data_url = var.artefato_modelo_s3
}
}
resource "aws_sagemaker_endpoint_configuration" "risco_cancelamento" {
name = "risco-cancelamento-config-v12"
production_variants {
variant_name = "principal"
model_name = aws_sagemaker_model.risco_cancelamento.name
initial_instance_count = 2 # duas instâncias: sem AZ única de compute
instance_type = "ml.m5.large"
}
# Data Capture: grava par entrada/saída fora do caminho síncrono da resposta.
data_capture_config {
enable_capture = true
initial_sampling_percentage = 100 # volume atual comporta 100%; ver seção de escala
destination_s3_uri = "s3://${aws_s3_bucket.model_monitor.id}/captura"
capture_options {
capture_mode = "Input"
}
capture_options {
capture_mode = "Output"
}
}
}
resource "aws_sagemaker_endpoint" "risco_cancelamento" {
name = "risco-cancelamento-cadencia"
endpoint_config_name = aws_sagemaker_endpoint_configuration.risco_cancelamento.name
}
Data Capture não é retroativo
Habilitar a flag só grava pedidos NOVOS a partir da atualização da endpoint configuration. Os dois meses de tráfego que já passaram pelo endpoint sem captura estão perdidos para fins de baseline — é por isso que a baseline usa o dado de TREINO, que já existia antes, e não uma amostra de produção.
Construir: baseline de dado (Python/boto3)
A baseline é um job que roda UMA VEZ sobre uma amostra do dado de treino — não em todo request, e não a cada execução do schedule.
from sagemaker.model_monitor import DefaultModelMonitor
from sagemaker.model_monitor.dataset_format import DatasetFormat
meu_monitor = DefaultModelMonitor(
role=execution_role_arn,
instance_count=1,
instance_type='ml.m5.xlarge',
volume_size_in_gb=20,
max_runtime_in_seconds=1800,
)
meu_monitor.suggest_baseline(
baseline_dataset='s3://cadencia-model-monitor-risco-cancelamento/treino/pedidos-baseline.csv',
dataset_format=DatasetFormat.csv(header=True),
output_s3_uri='s3://cadencia-model-monitor-risco-cancelamento/baseline/',
)
# O job produz DOIS arquivos:
# statistics.json — média, desvio padrão, valores distintos por feature categórica
# constraints.json — a faixa/conjunto considerado "dentro do normal" por feature,
# calculada a partir das estatísticas acima com um teste formal
#
# Exemplo de uma constraint categórica gerada para "categoria":
# {
# "name": "categoria",
# "inferred_type": "String",
# "completeness": 1.0,
# "string_constraints": {
# "domains": ["cimento", "tinta", "hidraulica", "eletrica_predial", "madeira"]
# # "ferramentas_eletricas" NAO aparece aqui -- e essa ausencia e o gatilho
# # do drift de dado quando a categoria nova comeca a chegar em producao.
# }
# }
A baseline é uma fotografia, não um limite fixo
constraints.json não é "regra de negócio" escrita à mão — é o resultado de um teste estatístico sobre o dado de treino real. Isso significa que ela herda qualquer viés que já existia no treino: se o treino nunca teve a categoria "ferramentas_eletricas", a baseline vai marcar qualquer ocorrência dela como violação, mesmo que seja uma categoria de negócio legítima e nova.
Construir: Monitoring Schedule horário
Com a baseline pronta, o schedule é o job que roda de hora em hora e faz a comparação de verdade.
from sagemaker.model_monitor import CronExpressionGenerator
meu_monitor.create_monitoring_schedule(
monitor_schedule_name='risco-cancelamento-data-quality-horario',
endpoint_input=endpoint_name, # 'risco-cancelamento-cadencia'
output_s3_uri='s3://cadencia-model-monitor-risco-cancelamento/relatorios/',
statistics=meu_monitor.baseline_statistics(),
constraints=meu_monitor.suggested_constraints(),
schedule_cron_expression=CronExpressionGenerator.hourly(),
enable_cloudwatch_metrics=True, # sem isto, o alarme da seção seguinte não tem métrica para observar
)
# Cada execução:
# 1. lê o lote capturado na última hora (destination_s3_uri do Data Capture)
# 2. avalia cada feature contra constraints.json
# 3. grava constraint_violations.json e statistics.json da execução em output_s3_uri
# 4. publica uma métrica por feature violada no CloudWatch, namespace
# "aws/sagemaker/Endpoints/data-metrics", com o nome do endpoint e do
# schedule como dimensões -- confirme o nome exato da métrica no console,
# porque ele muda por feature monitorada
Schedule "Pending" não é bug, geralmente é atraso
A primeira execução de um Monitoring Schedule recém-criado pode levar até uma hora para começar — ele espera o próximo horário fechado do cron, não roda imediatamente na criação. Isso confunde quem espera ver resultado em minutos; a seção de troubleshooting retoma esse ponto.
Construir: drift de conceito (Model Quality Monitor)
Data Quality Monitor não sabe se a predição estava certa — só se a distribuição de entrada mudou. Para pegar drift de CONCEITO, é preciso mesclar a predição salva com o resultado real, que só chega depois.
from sagemaker.model_monitor import ModelQualityMonitor
from sagemaker.model_monitor.dataset_format import DatasetFormat
# 1) Baseline de qualidade: acurácia esperada, calculada sobre um conjunto de
# validação com resultado JÁ conhecido -- não sobre o dado de treino cru.
qualidade_monitor = ModelQualityMonitor(
role=execution_role_arn,
instance_count=1,
instance_type='ml.m5.xlarge',
)
qualidade_monitor.suggest_baseline(
baseline_dataset='s3://cadencia-model-monitor-risco-cancelamento/validacao/pedidos-com-resultado.csv',
dataset_format=DatasetFormat.csv(header=True),
output_s3_uri='s3://cadencia-model-monitor-risco-cancelamento/baseline-qualidade/',
problem_type='BinaryClassification',
inference_attribute='probabilidade_cancelamento',
ground_truth_attribute='pedido_cancelado_de_fato',
)
# 2) Job separado (fora do escopo deste código) grava o resultado real por
# inference-id assim que o pedido é entregue ou cancelado -- normalmente
# D+3 no fluxo da Cadência.
# s3://.../groundtruth/pedido-resultado/dt=2026-08-08/
# {"inferenceId": "req-88213", "groundTruthData": {"data": "1"}}
# 3) O schedule mescla predição salva (Data Capture) + ground truth por
# inferenceId, e recalcula acurácia, precisão e recall de verdade -- não
# uma proxy, o resultado real do pedido.
qualidade_monitor.create_monitoring_schedule(
monitor_schedule_name='risco-cancelamento-model-quality-diario',
endpoint_input=endpoint_name,
ground_truth_input='s3://cadencia-model-monitor-risco-cancelamento/groundtruth/',
problem_type='BinaryClassification',
inference_attribute='probabilidade_cancelamento',
output_s3_uri='s3://cadencia-model-monitor-risco-cancelamento/relatorios-qualidade/',
statistics=qualidade_monitor.baseline_statistics(),
constraints=qualidade_monitor.suggested_constraints(),
schedule_cron_expression=CronExpressionGenerator.daily(), # ground truth chega em D+3, não faz sentido rodar de hora em hora
enable_cloudwatch_metrics=True,
)
Sem merge por inference-id, não existe drift de conceito medido
Se o pipeline de captura não grava um `inferenceId` estável e o job de ground truth não usa o MESMO identificador, o Model Quality Monitor não tem como casar predição com resultado — ele simplesmente não produz métrica nenhuma, em silêncio, e a equipe segue achando que está coberta quando não está.
Implantar, e provar que o alarme pega o dado deslocado de propósito
A prova deste laboratório é deslocar uma feature de propósito e medir quanto tempo até o alarme mudar de estado — não "confirme que está funcionando", um número.
# 1) Baseline calculada sobre 90 dias de treino (2.400 pedidos), sem a
# categoria "ferramentas_eletricas" -- ela só existe há 7 semanas.
# 2) Lote de CONTROLE: 600 requisições sintéticas com features dentro da
# distribuição de treino (categoria e valor normais).
python3 gerar_lote_sintetico.py --n 600 --perfil normal --endpoint risco-cancelamento-cadencia
# 3) Lote DESLOCADO: 600 requisições sintéticas, mesma hora, com valor_pedido
# deslocado propositalmente 4 desvios-padrao acima da media de treino e
# 100% na categoria "ferramentas_eletricas" -- fora do dominio da baseline.
python3 gerar_lote_sintetico.py --n 600 --perfil deslocado \
--valor-sigma 4.1 --categoria ferramentas_eletricas \
--endpoint risco-cancelamento-cadencia
# hora de envio registrada: 10:07
# 4) Aguardar a proxima execucao do schedule horario e consultar o estado do alarme.
aws cloudwatch describe-alarms --alarm-names risco-cancelamento-drift-dado \
--query 'MetricAlarms[0].StateValue'
| Cenário | Amostras enviadas | Desvio da baseline | Tempo até o alarme | Resultado |
|---|---|---|---|---|
| Lote de controle (dentro da distribuição de treino) | 600 | 0,1σ em valor_pedido; categoria 100% dentro do domínio | — (schedule rodou, sem violação) | Alarme permanece em OK |
| Lote deslocado de propósito | 600 | 4,1σ em valor_pedido (teste two-sample KS, p = 0,0002); categoria fora do domínio em 100% dos registros | 55 minutos (envio às 10:07, alarme em ALARM às 11:02) | 2 violações no relatório (valor_pedido e categoria); alarme dispara, SNS notifica o plantão |
O número que prova o requisito
55 minutos entre o envio do lote deslocado e o alarme mudar de estado — dentro do requisito de detecção em até 1 hora, porque o schedule horário processa o lote na primeira execução seguinte ao envio. O pior caso teórico (lote enviado logo depois de uma execução já ter rodado) chegaria perto dos 60 minutos completos; o melhor caso, poucos minutos.
Quebrar de propósito: três falhas e o diagnóstico
O cerne pedagógico deste laboratório é distinguir três causas que parecem iguais no CloudWatch — "algo mudou" — e pedem respostas completamente diferentes.
| Falha injetada | O que dispara | O que NÃO dispara | Diagnóstico correto | Resposta certa |
|---|---|---|---|---|
| Categoria nova fora do domínio de treino (drift de DADO) | Data Quality Monitor: violação categórica em "categoria" | Model Quality Monitor pode continuar normal por dias, até o ground truth confirmar se a acurácia caiu de verdade | A distribuição de ENTRADA mudou; a relação entrada→saída pode ou não ter mudado junto | Investigar se a categoria nova precisa entrar no próximo retrain (L76) — não é garantido que o modelo esteja errando nela |
| Mesma distribuição de entrada, mas o comportamento do cliente mudou (drift de CONCEITO) | Model Quality Monitor: acurácia real cai quando o ground truth atrasado chega | Data Quality Monitor permanece limpo — nenhuma feature de entrada saiu da faixa da baseline | A RELAÇÃO entre entrada e saída mudou; o que "pedido de risco" significa não é mais o que era no treino | Sinal mais forte para retrain — o modelo está sistematicamente errado mesmo com dado "normal" |
| Endpoint com latência alta ou erro HTTP (falha técnica) | CloudWatch técnico padrão: latência e taxa de erro | Nenhum dos dois Model Monitors dispara — o problema não é de dado nem de conceito, é de infraestrutura | Erro operacional comum, sem relação com a qualidade da predição | Runbook de infraestrutura padrão (scaling, health check) — não é assunto deste laboratório |
Por que a tabela acima é o coração do módulo
As três colunas do meio existem para impedir a confusão mais cara: tratar toda violação como se fosse a mesma coisa. Um alarme de Data Quality sozinho não prova que o modelo está errando — prova que a ENTRADA mudou. Só o Model Quality Monitor, com o resultado real, prova que a predição piorou.
O Data Quality Monitor da Cadência detecta que a distribuição da feature "categoria" mudou — a categoria "ferramentas_eletricas" passou a aparecer em 16% dos pedidos, fora do domínio da baseline de treino. Nesse mesmo período, o Model Quality Monitor (com ground truth já mesclado) mostra que a acurácia real do modelo permanece estável. O que essa combinação de sinais indica?
Segurança: o preço de capturar cada predição
Data Capture grava, por definição, dado real de negócio — valor de pedido, categoria, histórico do lojista. É um novo lugar onde dado sensível vive, e precisa do mesmo cuidado que a tabela de origem.
| Risco | Probabilidade | Impacto | Prevenção | Detecção | Resposta |
|---|---|---|---|---|---|
| Bucket de captura acessível além do time de ML | Média | Alto — expõe padrão de compra por lojista | Política de bucket restrita ao papel de execução do endpoint e do schedule; sem acesso público nunca | AWS Config rule de bucket público; CloudTrail em PutObject/GetObject no prefixo de captura | Revogar policy, rotacionar credencial exposta, revisar CloudTrail para acesso indevido já ocorrido |
| Relatório de violação (S3) sem criptografia em repouso | Baixa se o bucket já usa SSE-S3 padrão | Médio — dado de negócio em texto claro em disco | SSE-KMS no bucket com chave gerenciada pelo time de dados, não a chave padrão do S3 | AWS Config rule de bucket sem criptografia | Habilitar SSE-KMS e reprocessar objetos existentes |
| IAM do schedule com permissão além do prefixo necessário | Média — copiar policy de outro job é comum | Médio — acesso de leitura a dado de outros times | Policy com Resource específico ao prefixo (captura/*, baseline/*, groundtruth/*), nunca o bucket inteiro | IAM Access Analyzer sinalizando policy ampla demais | Restringir Resource, testar o schedule de novo para confirmar que ele ainda funciona com o escopo menor |
Ground truth carrega o desfecho real do pedido
O arquivo de ground truth não é metadado técnico — é a confirmação de que um pedido específico foi cancelado ou não, ligado por inferenceId à predição. Tratar esse prefixo com o mesmo rigor do prefixo de captura é obrigatório, e não opcional só porque "é só um rótulo binário".
Observabilidade: as perguntas que o painel tem de responder
- Quantas execuções do schedule rodaram nas últimas 24 h, e quantas tiveram violação?
- Qual feature viola com mais frequência, e a violação é nova ou recorrente há semanas?
- Quanto tempo passou desde a última vez que o ground truth foi mesclado com sucesso?
- O schedule está em estado "Scheduled" (saudável) ou "Failed" (parou de rodar silenciosamente)?
- A taxa de violação está subindo de forma gradual (sazonalidade) ou em degrau (mudança abrupta)?
| Alarme | Limiar inicial | Por que este limiar |
|---|---|---|
| risco-cancelamento-drift-dado | 1 datapoint em breach, 1 período de avaliação (1 h) | Detecção rápida é o requisito; o relatório completo dá contexto ao plantão antes de qualquer ação automática |
| risco-cancelamento-drift-conceito | 1 datapoint em breach, 1 período de avaliação (1 dia) | Ground truth chega em D+3; exigir mais de uma execução violada atrasaria a detecção em dias sem necessidade |
| risco-cancelamento-schedule-failed | 1 falha de execução em 24 h | Um schedule que para de rodar é silencioso — sem este alarme, a ausência de violação pode significar "está tudo bem" ou "o job parou", e são coisas muito diferentes |
Ausência de violação não é o mesmo que ausência de drift
Se o Monitoring Schedule falhar silenciosamente, o CloudWatch simplesmente não recebe métrica nova. Sem o terceiro alarme da tabela acima, isso é indistinguível de "nenhum drift detectado" — o painel fica verde pelo motivo errado.
Escala: de 10 pedidos a 1 milhão, e o que passa a doer
| Ordem de grandeza | O que muda no desenho |
|---|---|
| 10 pedidos/dia | Schedule horário sobra de folga; instância mínima do Processing Job já é suficiente; captura em 100% custa quase nada de S3 |
| 10 mil pedidos/dia | Volume de captura cresce o bastante para considerar amostragem parcial (ex.: 20%) em vez de 100%, mantendo poder estatístico com menos custo de armazenamento |
| 1 milhão de pedidos/dia | Schedule horário pode não ser granular o suficiente para o requisito de negócio; considerar execução a cada 15 min e endpoint com auto scaling para sustentar o tráfego de inferência em si |
| Pico sazonal (Black Friday da construção) | Maior risco é FALSO POSITIVO: um pico legítimo de uma categoria parece drift para uma baseline calculada fora de época; a resposta é recalibrar ou suprimir temporariamente o alarme com janela conhecida, não desligar o monitor |
| Falha de uma AZ | Endpoint SageMaker multi-instância já distribui entre AZs de forma gerenciada; Processing Jobs do schedule e o S3 de captura são regionais por padrão — nenhuma ação extra necessária para este componente especificamente |
Custo: o que este laboratório acrescenta à fatura
O maior custo do sistema inteiro é o endpoint de inferência em si, que a Cadência já paga com ou sem monitor. O que este módulo acrescenta é pequeno em comparação, mas tem duas dimensões que vale separar.
| Cenário | O que roda | Ordem de grandeza do custo adicional |
|---|---|---|
| Protótipo (este laboratório, 2.100 pedidos/dia) | Schedule horário (24 execuções/dia, poucos minutos cada) + Model Quality diário + S3 de captura em 100% | Baixo: dominado pelo tempo de instância do Processing Job, não pelo volume de dado |
| Produção pequena (dezenas de milhares de pedidos/dia) | Mesma cadência de schedule, captura com amostragem reduzida, baseline recalculada mensalmente | Baixo a médio: S3 cresce, mas amostragem controla o volume; instância do Processing Job pode precisar subir de tamanho |
| Alta escala (múltiplos endpoints monitorados, centenas de features) | Um schedule por endpoint, dashboards agregando várias métricas, possível consolidação num pipeline de observabilidade de ML dedicado | Médio: o custo por execução continua baixo, mas o número de schedules ativos cresce linearmente com o número de modelos em produção |
Cota de execuções simultâneas de Processing Job
Existe um limite de contas para jobs de Processing rodando ao mesmo tempo — relevante quando vários endpoints têm schedules na mesma hora cheia. Confira o valor atual em Service Quotas antes de escalar o número de modelos monitorados.
Well-Architected nos seis pilares
| Pilar | Situação | Risco | Melhoria | Prioridade |
|---|---|---|---|---|
| Excelência operacional | Dois monitores (dado e conceito) com schedules independentes | Ninguém percebe se um schedule para de rodar, porque ausência de violação parece sucesso | Alarme dedicado de "schedule failed" (seção de observabilidade) | Alta |
| Segurança | Bucket de captura e ground truth com dado real de pedido | Acesso amplo demais ao bucket expõe padrão de compra por lojista | SSE-KMS + IAM restrito por prefixo (seção de segurança) | Alta |
| Confiabilidade | Alarme com 1 datapoint em breach | Sensível demais pode gerar fadiga de alarme se a baseline não for recalibrada após sazonalidade legítima | Recalcular baseline periodicamente; considerar supressão programada em janelas conhecidas | Média |
| Eficiência de performance | Data Capture assíncrono, fora do caminho síncrono | Nenhum risco de performance identificado neste desenho | Monitorar mesmo assim — mudanças futuras no endpoint podem reintroduzir acoplamento | Baixa |
| Otimização de custo | Captura em 100% no volume atual | Em escala maior, 100% de captura infla S3 sem ganho estatístico proporcional | Reduzir amostragem quando o volume justificar (seção de escala) | Média |
| Sustentabilidade | Processing Job roda por poucos minutos, 24 vezes ao dia | Instância superdimensionada para o volume desperdiça capacidade ociosa | Calibrar o tipo de instância pelo tempo real de execução, não por segurança excessiva | Baixa |
Evolução em níveis: do endpoint cego ao sistema que avalia a si mesmo
O L70 já apontava para cá: o nível 6 daquele módulo dizia "o modelo passa a ter monitoramento contínuo de drift" — e aqui está o laboratório que constrói exatamente isso. A escada continua até onde a própria noção de "avaliar" deixa de ser estatística e passa a precisar de julgamento.
Só métricas técnicas (latência, erro HTTP). É onde a Cadência estava até a semana passada, e é legítimo enquanto ninguém depende da acurácia real ser estável no tempo.Data Capture, baseline calculada do treino, schedule horário de dado, schedule diário de conceito com ground truth atrasado, alarme calibrado.O plantão deixa de ser o único gatilho: quando o drift é confirmado como real (não sazonalidade), o pipeline de ponta a ponta (tema do L76) re-treina sem intervenção manual, com linhagem rastreável do dado até o modelo novo.O modelo re-treinado não vai direto para produção: passa pelo Model Registry com aprovação explícita, e existe caminho de volta se a promoção piorar as coisas (tema do L75).Acurácia técnica não é a métrica que importa — capital parado em estoque mal reservado e ruptura de estoque são; o modelo passa a ser avaliado contra essas, não só contra erro médio (tema do L78).Estatística formal (KS test, distância de distribuição) detecta bem UMA feature de cada vez, mas não julga se a resposta FINAL do sistema continua fazendo sentido de ponta a ponta — é aí que entra um LLM como juiz sobre um golden set, avaliando o comportamento do sistema como um todo, não feature por feature (L88).Por que este módulo não pula direto para o nível 6
Um LLM como juiz custa mais por avaliação, é mais lento, e não é determinístico da mesma forma que um teste estatístico. Para o que este laboratório resolve — "a distribuição de uma feature numérica ou categórica mudou" — o teste formal do Model Monitor é mais barato, mais rápido e mais auditável. IA como juiz entra quando a pergunta é mais ampla que uma feature isolada, tema do L88.
Onde IA entra nesta arquitetura, e onde não entra
A DETECÇÃO do drift, neste módulo, é propositalmente estatística — teste de Kolmogorov-Smirnov para features numéricas, comparação de proporção de domínio para categóricas. Nenhum LLM decide se "categoria" mudou de distribuição: um teste com p-valor reproduzível faz isso em segundos, roda 24 vezes por dia sem custo relevante, e dá a mesma resposta toda vez para o mesmo dado. Trocar isso por um LLM julgando "essa distribuição parece diferente?" seria mais caro, mais lento e não determinístico para um problema que já tem solução estatística madura — exatamente o hype que a Cadência não precisa.
Onde IA agrega de verdade, sem substituir a detecção: TRADUZIR o relatório técnico para o plantão. `constraint_violations.json` fala em "two-sample KS test, distance 0.31" — um LLM pode transformar isso em "a distribuição de valor_pedido está claramente diferente da baseline, o teste estatístico está bem acima do limiar normal" antes de o plantão precisar decidir. O dado de origem para essa tradução é sempre o relatório estruturado que o Model Monitor já produziu — o LLM nunca decide sozinho se há drift, só explica em linguagem natural o que o teste estatístico já decidiu. Se o resumo errar, o relatório bruto continua disponível para conferência, e ninguém age só com base no resumo em produção crítica.
| Onde IA entra | O que ela faz | O que continua sendo estatística |
|---|---|---|
| Resumo em linguagem natural do relatório de violação | Traduz teste estatístico + p-valor em uma frase que o plantão lê em segundos | A DECISÃO de que houve violação — feita pelo teste formal, não pelo LLM |
| Priorização de qual violação investigar primeiro | Ordena violações por impacto histórico estimado, com base em incidentes passados | O CÁLCULO de cada violação individual, sempre determinístico |
O próximo módulo onde IA é protagonista, não coadjuvante
Avaliar se o SISTEMA inteiro (não uma feature isolada) continua bom, com um LLM como juiz sobre um golden set, é o assunto do L88 — lá a IA não traduz um resultado estatístico, ela É o mecanismo de julgamento, com seu próprio viés a calibrar.
Anti-padrões deste laboratório
| Erro | Por que alguém faz | Sintoma em produção | Forma correta |
|---|---|---|---|
| Só monitorar erro técnico (latência, HTTP 5xx) | É o que o APM já mostra de graça — configurar Model Monitor exige trabalho de propósito que parece sem retorno imediato | Endpoint 100% saudável nos painéis técnicos, e a acurácia real caindo há semanas sem ninguém saber — exatamente o que aconteceu na Cadência | Data Quality e Model Quality Monitor complementando o APM técnico, não substituindo |
| Ativar Data Capture e nunca criar o Monitoring Schedule | Parece que só habilitar a captura já é "ter monitoramento" — a flag é rápida de ligar, o schedule exige baseline e configuração a mais | S3 lotado de payloads capturados, custo de armazenamento subindo, e zero alarme, zero comparação contra baseline acontecendo | Tratar Data Capture como pré-requisito, não como entrega — o schedule é a peça que efetivamente compara |
| Definir limiar de drift arbitrário ("se mudar mais que 10%") em vez de usar baseline estatística | Parece mais simples e mais fácil de explicar que rodar suggest_baseline e confiar num teste formal | Alarmes constantes em sazonalidade legítima (falso positivo) OU alarme que nunca dispara porque o limiar chutado é alto demais (falso negativo) | Baseline calculada com suggest_baseline, com teste estatístico formal por feature, calibrado sobre o próprio dado de treino |
| Tratar toda violação de Data Quality como se fosse drift de conceito | Os dois soam parecidos ("algo mudou"), e o vocabulário exato não é intuitivo na primeira vez | Time dispara retrain (L76) toda vez que uma feature de entrada se desloca, mesmo quando a acurácia real permanece estável | Diagnosticar qual tipo de drift antes de agir — a tabela da seção "Quebrar de propósito" existe exatamente para isso |
| Calcular a baseline uma vez e nunca recalcular | Parece "configurar e esquecer" — recalcular dá trabalho e ninguém agenda isso de propósito | Falsos positivos aumentam com o tempo conforme sazonalidade legítima nova (categorias que a Cadência passa a vender, por exemplo) vira "normal" sem a baseline saber | Recalcular a baseline após todo retrain aprovado, e revisar periodicamente mesmo sem retrain |
Quando algo não funciona
| Sintoma | Causa provável | Como investigar | Log/métrica | Correção |
|---|---|---|---|---|
| Monitoring Schedule fica em "Pending" e nunca executa | Ainda não chegou o próximo horário do cron — a primeira execução não é imediata na criação | Verificar o horário de criação contra o cron configurado; aguardar até o próximo fechamento de hora | describe-monitoring-schedule → LastMonitoringExecutionSummary | Nenhuma — comportamento esperado; se passar de 2 horas sem execução, investigar como falha real |
| Alarme nunca dispara mesmo com drift claramente visível no relatório S3 | enable_cloudwatch_metrics não foi habilitado na criação do schedule, ou o nome da métrica no alarme não bate com o publicado | Conferir se o relatório em S3 mostra violação; se sim, comparar o namespace/nome de métrica do alarme com o que o CloudWatch realmente recebeu | CloudWatch → aws/sagemaker/Endpoints/data-metrics | Recriar o schedule com enable_cloudwatch_metrics=True, ou corrigir o nome da métrica no alarme |
| Alarme dispara toda hora, mesmo sem mudança real perceptível | Baseline desatualizada (calculada antes de uma sazonalidade que já virou normal) ou limiar sensível demais para o volume atual | Comparar constraints.json da baseline com a distribuição atual real; checar se houve retrain recente sem recalcular a baseline | Relatórios de violação consecutivos em S3, mesma feature repetindo | Recalcular a baseline sobre um período mais recente e representativo |
| Data Capture não grava nada em S3 | IAM do endpoint sem permissão de PutObject no prefixo, ou destination_s3_uri com typo | Testar uma chamada manual ao endpoint e checar CloudTrail para erro de permissão negada | CloudTrail → PutObject com AccessDenied | Corrigir a policy do papel de execução do endpoint; validar destination_s3_uri |
| Model Quality Monitor não produz métrica, mesmo com ground truth chegando | inferenceId do ground truth não bate com o inferenceId salvo na captura — merge silenciosamente vazio | Comparar amostra de inferenceId nos dois lados (captura e ground truth) manualmente | Relatório da execução mostra "insufficient data" ou contagem de merge igual a zero | Padronizar o inferenceId gerado no momento da inferência e propagado até o job de ground truth |
Limpeza: o que o destroy não leva
O maior custo contínuo deste sistema é o próprio endpoint de inferência — ele já existia antes deste laboratório e continua cobrando por hora enquanto estiver de pé, com ou sem monitor.
# Ordem importa: pare os schedules antes de derrubar o endpoint que eles monitoram.
# 1) Excluir os dois Monitoring Schedules
aws sagemaker delete-monitoring-schedule --monitoring-schedule-name risco-cancelamento-data-quality-horario
aws sagemaker delete-monitoring-schedule --monitoring-schedule-name risco-cancelamento-model-quality-diario
# 2) Excluir o endpoint e a configuração (isto PARA a cobrança das instâncias de inferência)
aws sagemaker delete-endpoint --endpoint-name risco-cancelamento-cadencia
aws sagemaker delete-endpoint-config --endpoint-config-name risco-cancelamento-config-v12
# 3) Terraform cuida do resto (bucket, IAM, modelo) -- mas NÃO esvazia bucket com objeto
terraform destroy
| Recurso | terraform destroy remove? | O que fazer manualmente |
|---|---|---|
| Endpoint SageMaker (instâncias ml.m5.large) | Sim, se declarado em Terraform | Confirmar via describe-endpoint que sumiu — é o item que mais cobra por hora |
| Monitoring Schedules | Não — foram criados via boto3/SDK, fora do Terraform | delete-monitoring-schedule explícito, como no script acima |
| Bucket S3 com objetos capturados e relatórios | Não remove bucket não-vazio por padrão | Esvaziar o bucket (incluindo versões, já que versionamento está habilitado) antes do destroy |
| Grupo de logs do CloudWatch (execuções dos Processing Jobs) | Não, se criado implicitamente pelo SageMaker | Revisar retenção e excluir manualmente se não for mais necessário |
Bucket versionado não esvazia com um "delete" simples
Com versionamento habilitado (decisão da seção 8, para auditabilidade), cada objeto tem histórico. `aws s3 rm --recursive` remove a versão atual mas deixa marcadores de exclusão e versões antigas — é preciso esvaziar todas as versões explicitamente ou o bucket continua não-vazio para o Terraform.
Resumo: problema, peça e motivo
| Problema | Serviço | Motivo |
|---|---|---|
| Ninguém sabe se o modelo continua certo, só se está de pé | CloudWatch (métricas técnicas padrão) | Já existe de graça, mas mede saúde de processo, não de predição |
| Distribuição de entrada pode mudar sem violar nenhum contrato de valor | SageMaker Model Monitor — Data Quality | Compara distribuição contra baseline estatística, não regra de faixa fixa |
| A relação entrada→saída pode mudar mesmo com entrada estável | SageMaker Model Monitor — Model Quality | Mescla ground truth atrasado com predição salva para medir acurácia real |
| Detecção precisa virar ação, não ficar só no relatório | CloudWatch Alarm + SNS | Poucos datapoints em breach + notificação direta ao plantão com o relatório anexado |
| Tipo de drift | O que mudou | Quem detecta | Velocidade |
|---|---|---|---|
| Drift de dado | A distribuição da FEATURE de entrada | Data Quality Monitor | Rápida — a cada execução horária |
| Drift de conceito | A RELAÇÃO entre entrada e saída | Model Quality Monitor | Lenta — depende do ground truth chegar |
| Erro técnico | A infraestrutura do endpoint | CloudWatch técnico padrão | Imediata — já existe sem configuração extra |
- Baseline calculada e versionada em S3, não um limiar chutado
- Data Capture ativo sem impacto de latência no checkout
- Dois schedules independentes: um horário (dado), um diário (conceito)
- Alarme calibrado e testado com dado deslocado de propósito, com o tempo até disparar registrado
- Relatório de violação auditável, com feature, teste estatístico e p-valor
Perguntas frequentes
❓ Drift de dado sempre significa que o modelo está errando mais?
❓ Por que o Model Quality Monitor roda diariamente e o Data Quality roda de hora em hora?
❓ O que acontece se eu esquecer de recalcular a baseline depois de um retrain aprovado?
❓ Preciso de um segundo endpoint só para rodar o Model Monitor?
❓ A baseline precisa ser recalculada a cada categoria de produto nova?
❓ Um alarme de drift de dado deveria disparar retrain automático imediatamente?
❓ Por que o CloudWatch técnico não detecta esse tipo de problema no mesmo endpoint?
Fixando
Por que "o endpoint nunca caiu, latência e erro HTTP sempre normais" NÃO é evidência de que o modelo de risco de cancelamento da Cadência continua confiável?
Na arquitetura de PRODUÇÃO deste laboratório, o Data Quality Monitor e o Model Quality Monitor convergem para a mesma métrica de CloudWatch antes de chegar ao alarme. Por que eles não usam o mesmo schedule, se os dois publicam na mesma métrica no final?
Conhecimentos, próximo módulo e documentação
| Você aprendeu | Onde isso volta a aparecer |
|---|---|
| Diferença entre drift de dado, drift de conceito e erro técnico | Todo laboratório de MLOps daqui em diante assume essa distinção como vocabulário conhecido |
| Baseline estatística como fotografia do dado de treino, não regra fixa | L78 (avaliação ligada a métrica de negócio) parte de uma baseline de acurácia semelhante |
| Merge de ground truth atrasado por identificador estável | Qualquer pipeline de avaliação contínua de modelo em produção depende desse mesmo padrão |
| Alarme calibrado e testado com dado deslocado de propósito | É o mesmo raciocínio de "prova por medição, não por afirmação" que atravessa toda a série |
O próximo passo lógico não é mais estatística — é decidir se a métrica técnica de qualidade do modelo (acurácia, precisão) realmente se traduz em resultado de negócio (capital parado, ruptura de estoque). Um modelo pode passar em todos os testes de drift deste módulo e ainda assim estar otimizando para o número errado.
Próximo laboratório
L78 — Avaliação honesta: métrica de modelo ≠ de negócio. Depende deste módulo e do L74; usa SageMaker Clarify e Athena para ligar a avaliação técnica a um número que o negócio realmente sente. Depois dele, L88 fecha a escada deste módulo com avaliação por LLM como juiz sobre um golden set.
Terminou de ler?
Marcar como concluído registra o XP, mantém sua sequência e coloca 3 cartas deste módulo na fila de revisão espaçada.
Próximos passos sugeridos
Temas deste módulo
Discussão
Carregando comentários…