Caderno operacional — calcular, simular e interpretar
Laboratório reproduzível em Python para conferir estatística descritiva, percentil, produto escalar, taxa-base, matriz de confusão e descida do gradiente. O leitor prevê cada resultado, calcula um caso à mão, executa uma solução sem dependências externas, provoca entradas inválidas e documenta o diagnóstico. Cada experimento explicita hipótese, comando, saída esperada, limite da interpretação e evidência que outra pessoa consegue revisar. O fechamento transfere os números para decisões de manutenção e integração com ERP sem converter escore em autorização automática, confundindo correlação com causa ou escondendo incerteza atrás de uma métrica isolada.
Caderno operacional — calcular, simular e interpretar
Introdução: transformar entendimento em evidência
Neste laboratório, “entendi” significa conseguir prever, calcular, executar, provocar uma falha e explicar o diagnóstico. Você trabalhará com números pequenos para enxergar cada etapa. O objetivo não é construir um modelo de produção; é impedir que uma biblioteca esconda um erro conceitual.
O fio condutor continua sendo manutenção integrada ao sistema de gestão empresarial (ERP, Enterprise Resource Planning). Tempos de atendimento mostram o efeito de um extremo; sensores formam vetores; um detector de ordem crítica mostra a taxa-base; uma parábola simples torna visível o efeito da taxa de aprendizado. OS significa ordem de serviço.
Vocabulário operacional
- caminho feliz é a execução com entradas válidas e resultado esperado;
- caso negativo usa uma entrada inválida ou condição de falha para verificar a proteção;
- saída determinística é aquela que se repete com as mesmas entradas e ambiente;
- evidência de execução é o comando, a saída e a interpretação que outra pessoa consegue conferir;
- falha provocada é um erro intencional e controlado; não é deixar código quebrado em produção;
- diagnóstico liga sintoma, hipótese, verificação e correção;
- asserção é uma verificação escrita com
assert: se a condição for falsa, o programa para e revela a divergência.
Contrato do laboratório
Objetivo: confirmar à mão e em Python estatística, vetores, métricas de classificação e otimização.
Hipótese: se a fórmula e a implementação representam a mesma pergunta, os resultados coincidem; se uma premissa é violada, o programa falha com mensagem específica em vez de produzir número enganoso.
Pré-requisitos: ter lido o capítulo anterior; saber salvar um arquivo de texto; ter Python 3.11 ou superior disponível. O código usa apenas a biblioteca padrão e não precisa de internet, conta, pacote ou segredo.
Duração estimada: 120 minutos — 25 para cálculos manuais, 35 para execução, 25 para falhas, 20 para interpretação e 15 para revisão.
Arquivo de trabalho: crie uma pasta descartável e salve o bloco completo da solução como caderno_matematica.py.
Comando:
python caderno_matematica.pyEm alguns ambientes Windows, o comando pode ser py caderno_matematica.py. Use o interpretador aprovado pelo seu projeto; não instale pacotes para este exercício.
Etapa 0 — faça previsões antes de executar
Copie e complete a tabela. Não procure precisão decimal ainda; preveja direção e ordem de grandeza.
| Experimento | Sua previsão | Por quê? |
|---|---|---|
média de [1, 2, 2, 3, 42] |
maior, igual ou menor que a mediana? | |
| escore do equipamento | entre 0 e 1? | |
| detector com evento raro | precisão maior ou menor que recall? | |
taxa de aprendizado 0,1 |
perda cai ou cresce? | |
taxa 1,0 |
converge, oscila ou diverge? | |
taxa 1,1 |
converge, oscila ou diverge? |
Essa previsão impede que você aceite qualquer número apenas porque apareceu no terminal.
Etapa 1 — estatística manual: qual é o “tempo típico”?
Use os tempos de atendimento em horas:
[1, 2, 2, 3, 42]- Some os valores e divida por cinco: a média é
10 h. - Ordene e escolha o valor central: a mediana é
2 h. - Calcule os desvios em relação a 10, eleve ao quadrado e some:
1.282 h². - Se os cinco registros forem a população, divida por
5:256,4 h². - Se forem amostra de uma população maior, a função
variancedo Python divide porn-1:320,5 h².
O ponto de 42 horas puxa a média, mas não a mediana. Isso não autoriza apagar o valor. Primeiro investigue se ele é erro de medição, indisponibilidade real de peça, parada de ERP ou atendimento legítimo extremo.
Percentil exige método declarado
Este laboratório usa posto mais próximo: para o percentil p, ordene n valores e escolha a posição ceil(p×n), começando a contar em 1. Para cinco valores, o percentil 90 ocupa ceil(0,90×5)=5, portanto vale 42. Outros softwares podem interpolar e retornar outro número; divergência de método não é automaticamente bug.
Etapa 2 — vetor e matriz: unidades antes de pesos
O equipamento já foi transformado para atributos normalizados:
x = [0,80; 0,50; 0,40]Use duas linhas de pesos:
risco = [0,60; 0,30; 0,10]
custo = [0,10; 0,20; 0,70]Calcule:
risco · x = 0,67
custo · x = 0,46Esses são escores sem unidade. O rótulo “custo” não os transforma em reais, e “risco” não os transforma em probabilidade. Para usar temperatura bruta, vibração e horas seria necessário documentar a transformação e calcular seus parâmetros apenas no conjunto de treino.
Etapa 3 — taxa-base e matriz de confusão
Calcule uma simulação determinística de 10.000 ordens:
- prevalência crítica:
1%; - recall do detector:
90%; - taxa de falso positivo entre normais:
5%.
As contagens esperadas são:
verdadeiros positivos = 90
falsos negativos = 10
falsos positivos = 495
verdadeiros negativos = 9.405Aqui “simulação” significa converter proporções esperadas em contagens inteiras com arredondamento; não estamos sorteando uma amostra aleatória. Em um experimento estocástico, seria necessário registrar a semente e analisar a variação entre execuções.
Antes de continuar, confira os dois totais: 90+10=100 ordens críticas e 495+9.405=9.900 normais. Depois calcule:
precisão = 90 / 585 ≈ 15,38%
recall = 90 / 100 = 90%
acurácia = 9.495 / 10.000 = 94,95%A documentação do scikit-learn apresenta definições e convenções de métricas (Metrics and scoring). Aqui fazemos as contas diretamente para enxergar os denominadores.
Etapa 4 — descida do gradiente como trajetória
A perda é L(θ)=(θ-3)²; sua derivada é 2(θ-3). Em cada passo:
θ_novo = θ_atual - taxa × 2(θ_atual-3)Parta de θ=0 e registre parâmetro e perda. Use quatro taxas para separar comportamentos:
0,1: convergência gradual;0,5: chega ao mínimo em um passo neste exemplo;1,0: alterna entre 0 e 6, sempre com perda 9;1,1: alterna e aumenta a distância, portanto diverge.
O desenho textual será uma tabela, não um gráfico decorativo. O que importa é observar se a perda cai, fica constante ou cresce. O exemplo é convexo, unidimensional e sem ruído; redes neurais não herdam automaticamente estes limites.
Solução executável comentada
O bloco abaixo é um programa completo para Python 3.11+. Ele não usa aleatoriedade; portanto não precisa de seed (semente). Todas as asserções são determinísticas. No dicionário da matriz, vp, fn, fp e vn abreviam verdadeiro positivo, falso negativo, falso positivo e verdadeiro negativo. lambda cria uma pequena função sem nome usada apenas para disparar cada caso inválido; a compreensão entre chaves constrói um dicionário percorrendo os pesos.
from math import ceil
from statistics import mean, median, pvariance, variance
def percentil_posto_mais_proximo(valores, proporcao):
"""Retorna percentil por nearest rank; proporcao deve estar em (0, 1]."""
if not valores:
raise ValueError("percentil exige ao menos um valor")
if not 0 < proporcao <= 1:
raise ValueError("proporção deve estar no intervalo (0, 1]")
ordenados = sorted(valores)
indice = ceil(proporcao * len(ordenados)) - 1
return ordenados[indice]
def produto_escalar(a, b):
if len(a) != len(b):
raise ValueError("vetores precisam ter a mesma dimensão")
return sum(x * y for x, y in zip(a, b))
def matriz_confusao(total, prevalencia, recall, taxa_falso_positivo):
for nome, valor in {
"prevalência": prevalencia,
"recall": recall,
"taxa de falso positivo": taxa_falso_positivo,
}.items():
if not 0 <= valor <= 1:
raise ValueError(f"{nome} deve estar entre 0 e 1")
positivos = round(total * prevalencia)
negativos = total - positivos
vp = round(positivos * recall)
fn = positivos - vp
fp = round(negativos * taxa_falso_positivo)
vn = negativos - fp
return {"vp": vp, "fn": fn, "fp": fp, "vn": vn}
def metricas(matriz):
vp, fn, fp, vn = (matriz[chave] for chave in ("vp", "fn", "fp", "vn"))
if vp + fp == 0:
raise ValueError("precisão indefinida: nenhum alerta positivo")
if vp + fn == 0:
raise ValueError("recall indefinido: nenhum caso positivo")
total = vp + fn + fp + vn
return {
"precisao": vp / (vp + fp),
"recall": vp / (vp + fn),
"acuracia": (vp + vn) / total,
}
def perda(theta):
return (theta - 3) ** 2
def trajetoria(taxa, passos=5, theta_inicial=0.0):
if taxa <= 0:
raise ValueError("taxa de aprendizado deve ser positiva")
theta = theta_inicial
historico = []
for passo in range(passos + 1):
historico.append((passo, theta, perda(theta)))
gradiente = 2 * (theta - 3)
theta = theta - taxa * gradiente
return historico
# 1. Estatística descritiva
tempos_horas = [1, 2, 2, 3, 42]
print("ESTATÍSTICA")
print(f"média={mean(tempos_horas):.1f} h")
print(f"mediana={median(tempos_horas):.1f} h")
print(f"variância populacional={pvariance(tempos_horas):.1f} h²")
print(f"variância amostral={variance(tempos_horas):.1f} h²")
print(f"p90 nearest-rank={percentil_posto_mais_proximo(tempos_horas, 0.90)} h")
assert mean(tempos_horas) == 10
assert median(tempos_horas) == 2
assert pvariance(tempos_horas) == 256.4
assert variance(tempos_horas) == 320.5
# 2. Dois escores produzidos por uma matriz 2x3
equipamento = [0.80, 0.50, 0.40]
pesos = {
"risco": [0.60, 0.30, 0.10],
"custo": [0.10, 0.20, 0.70],
}
escores = {nome: produto_escalar(linha, equipamento) for nome, linha in pesos.items()}
print("\nESCORES")
print({nome: round(valor, 2) for nome, valor in escores.items()})
assert round(escores["risco"], 2) == 0.67
assert round(escores["custo"], 2) == 0.46
# 3. Evento raro e métricas
matriz = matriz_confusao(10_000, 0.01, 0.90, 0.05)
resultado = metricas(matriz)
print("\nCLASSIFICAÇÃO")
print(matriz)
print({nome: f"{valor:.2%}" for nome, valor in resultado.items()})
assert matriz == {"vp": 90, "fn": 10, "fp": 495, "vn": 9405}
assert round(resultado["precisao"], 4) == 0.1538
assert resultado["recall"] == 0.90
assert round(resultado["acuracia"], 4) == 0.9495
# 4. Otimização: tabela compacta por taxa
print("\nOTIMIZAÇÃO (perda inicial -> perda após 5 passos)")
for taxa in (0.1, 0.5, 1.0, 1.1):
historico = trajetoria(taxa)
inicio = historico[0]
fim = historico[-1]
print(
f"taxa={taxa:.1f}: θ {inicio[1]:.3f}->{fim[1]:.3f}; "
f"perda {inicio[2]:.3f}->{fim[2]:.3f}"
)
assert trajetoria(0.1)[-1][2] < trajetoria(0.1)[0][2]
assert trajetoria(0.5)[1][2] == 0
assert trajetoria(1.0)[-1][2] == 9
assert trajetoria(1.1)[-1][2] > trajetoria(1.1)[0][2]
# 5. Casos negativos: as falhas são capturadas e verificadas
falhas_esperadas = []
for acao in (
lambda: produto_escalar([1, 2], [1]),
lambda: percentil_posto_mais_proximo([], 0.90),
lambda: matriz_confusao(100, 1.20, 0.90, 0.05),
lambda: trajetoria(0),
):
try:
acao()
except ValueError as erro:
falhas_esperadas.append(str(erro))
print("\nFALHAS ESPERADAS")
for mensagem in falhas_esperadas:
print(f"- {mensagem}")
assert len(falhas_esperadas) == 4
print("\nTODAS AS VERIFICAÇÕES PASSARAM")Resultado esperado e como lê-lo
Os valores centrais devem incluir:
média=10.0 h
mediana=2.0 h
variância populacional=256.4 h²
variância amostral=320.5 h²
p90 nearest-rank=42 h
{'risco': 0.67, 'custo': 0.46}
{'vp': 90, 'fn': 10, 'fp': 495, 'vn': 9405}
{'precisao': '15.38%', 'recall': '90.00%', 'acuracia': '94.95%'}
TODAS AS VERIFICAÇÕES PASSARAMA trajetória exata de 0,1 termina após cinco atualizações em θ≈2,017, com perda menor que a inicial. A taxa 0,5 chega a zero; 1,0 mantém perda 9; 1,1 aumenta a perda. Pequenas diferenças apenas na última casa impressa podem vir da representação de ponto flutuante, mas as asserções documentam a tolerância usada.
Etapa 5 — provoque, observe e diagnostique
O programa já captura quatro falhas. Agora execute uma mutação de cada vez e depois desfaça:
- Remova a verificação de dimensão em
produto_escalare chame[1, 2]com[1]. A funçãozip, que forma pares de posições, trunca silenciosamente e retorna1. Diagnóstico: o número parece válido, mas um atributo desapareceu. - Troque
vp / (vp + fp)porvp / (vp + fn)na precisão. O resultado vira 90%, igual ao recall. Diagnóstico: o denominador passou a responder outra pergunta. - Troque a taxa
0,1por1,1. Diagnóstico: parâmetro alterna e a perda cresce; não é “mais rápido”. - Remova o ponto de 42 horas. Diagnóstico: média e variância despencam; antes de excluir, investigue se era erro ou evento real.
Uma falha provocada passa quando você registra:
mutação -> sintoma observado -> hipótese -> cálculo de conferência -> correçãoNão preserve as mutações no arquivo final. Rode o programa novamente e exija a mensagem TODAS AS VERIFICAÇÕES PASSARAM.
Etapa 6 — aplicação no sistema de manutenção/ERP
Produza uma nota de decisão de no máximo uma página com estas respostas:
- Qual é a ordem, unidade e faixa de cada atributo do vetor?
- Os parâmetros de normalização vieram somente do treino?
- O escore
0,67é regra, ranking ou probabilidade calibrada? - Qual custo operacional tem um falso negativo? E um falso positivo?
- Como o sistema reage quando sensor, identidade ou ERP está indisponível?
- Que pessoa ou política determinística autoriza a ação final?
- Quais métricas serão acompanhadas por unidade e tipo de equipamento?
Uma resposta aceitável não diz apenas “a IA decide prioridade”. Ela separa recomendação de execução. Por exemplo: o modelo sugere prioridade e razões; o backend valida identidade, estado e unidade; o supervisor confirma ações de alto impacto; a integração registra tentativa e falha do ERP sem inventar sucesso.
Segurança, privacidade e custo
- use dados sintéticos neste laboratório; nenhum dado pessoal ou segredo é necessário;
- em produção, limite retenção e acesso a medições e identificadores;
- não publique métricas de grupos tão pequenos que revelem indivíduos ou equipes;
- registre versão de dados, transformação, modelo e política;
- meça custo de inspeções adicionais, atraso e falhas perdidas, não apenas custo computacional;
- não use o conjunto de teste para ajustar o limiar depois de ver o resultado.
Troubleshooting
| Sintoma | Verificação rápida | Correção provável |
|---|---|---|
python não encontrado |
python --version ou py --version |
usar o interpretador aprovado; não baixar executável desconhecido |
AssertionError na estatística |
imprimir lista e denominador | restaurar dados e distinguir pvariance de variance |
| precisão aparece como 90% | conferir denominador | usar VP/(VP+FP), não VP/(VP+FN) |
| escore incorreto | imprimir pares de zip |
conferir ordem e dimensão |
| percentil diverge de planilha | identificar método da ferramenta | registrar método; não forçar igualdade entre convenções |
| perda vira número enorme | imprimir taxa, gradiente e θ por passo |
reduzir taxa e conferir sinal da atualização |
| resultado muda sem aleatoriedade | comparar arquivo e versão do Python | remover estado oculto e registrar ambiente |
Evidências e critérios de aceite
Entregue:
caderno_matematica.pysem as mutações;- saída completa do comando;
- tabela de previsões preenchida antes da execução;
- quatro cálculos manuais fotografados ou transcritos;
- um registro de falha no formato mutação → sintoma → hipótese → conferência → correção;
- nota de decisão do sistema de manutenção/ERP.
O laboratório está aprovado quando:
- o programa termina com código de saída zero e todas as asserções passam;
- média, mediana, variâncias, escores e matriz coincidem com o cálculo manual;
- denominadores, unidades e método de percentil estão declarados;
- taxa
0,1reduz,1,0oscila e1,1aumenta a perda neste exemplo; - entradas inválidas geram quatro falhas esperadas, não números silenciosos;
- a interpretação distingue escore, probabilidade, recomendação e autorização;
- a nota explica ao menos uma limitação de dados e uma consequência de erro.
Recuperação ativa, repetição e transferência
Sem consultar, explique amanhã:
- por que média 10 e mediana 2 podem estar simultaneamente corretas;
- por que 90% de recall pode coexistir com 15,38% de precisão;
- por que taxa maior não significa treino melhor;
- por que produto escalar correto pode continuar semanticamente errado;
- por que reduzir perda de treino não prova benefício operacional.
Repita após 24 horas e sete dias. Na segunda repetição, troque “OS crítica” por fraude rara; na terceira, por defeito de fabricação. A aritmética da matriz permanece, mas prevalência, custo, limiar, revisão humana e impacto mudam.
Intercale com representação de dados: mostre como arredondamento, campo ausente ou unidade incorreta altera pelo menos um resultado deste caderno.
Limpeza
Apague somente a pasta descartável criada para o laboratório, depois de copiar as evidências para o local definido pelo curso. Não execute exclusão recursiva em diretório amplo. Nenhuma credencial, pacote global ou serviço precisa ser removido porque o exercício não os cria.
Conclusão
Você percorreu o ciclo completo: previu, calculou, implementou, executou, provocou falhas, diagnosticou e transferiu a conclusão para um sistema real. O valor do caderno não é a mensagem verde final; é conseguir explicar por que cada asserção existe, que pergunta cada denominador responde e onde a matemática termina e começa a política de negócio.
Fontes
Comprove o que você aprendeu
Responda todas as questões. O gabarito comentado só aparece depois do envio.