Pular para o conteúdo

A calibração na sua base

A calibração ajusta um cenário de adoção à sua série observada: quantas pessoas adotaram o seu produto, por período e município. Ela tem três passos:

  1. A busca: procura, numa janela de períodos, os parâmetros que melhor reproduzem a série.
  2. O teste: julga o cenário escolhido no holdout, os períodos depois da janela que a busca nunca simulou.
  3. O veredito: devolve o resultado do teste, o cenário escolhido e o que a série não conseguiu distinguir.

O cenário calibrado é uma versão feita só para o seu projeto, só com os seus dados. Ele não entra no catálogo nem serve a outro projeto ou organização. A série fica no armazenamento da sua organização e é apagada com o job.

O caminho mais curto é o chat: você guarda a base de clientes no projeto, e o assistente monta a série, propõe a calibração e cota. Você confirma cada passo e roda com o botão. A seção abaixo é o mesmo pedido pela API e pelo MCP.

Um pedido de calibração tem duas partes: pedido e serie.

{
"pedido": {
"versao_contrato": 3,
"cenario": { "versao_contrato": 3, "release": "v1.2.0", "familia": "adocao",
"geografia": { "ufs": ["SE"] },
"horizonte": { "data_inicio": "2025-01-01", "dias": 730 },
"replicas": 1, "grupo_comparacao": "meu-produto",
"kpis": ["adotantes"], "lancamento": { "dia": 1, "cenario_base": "pix" } },
"serie": { "declaracao": { "versao_contrato": 1, "granularidade": "mes",
"medida": "acumulado", "eixos": [] } },
"janela": { "inicio": 202501, "fim": 202512 },
"holdout": { "inicio": 202601, "fim": 202612 },
"parametros": { "beta0": { "min": -9.0, "max": -7.0, "passo": 0.1 },
"logit_lancamento": { "min": 2.0, "max": 3.0, "passo": 0.5 } },
"busca": { "metodo": "grade" }
},
"serie": [
{ "periodo": 202501, "municipio": "2800308", "contagem": 1520 }
]
}
  • cenario é um cenário de adoção. É o ponto de partida: os parâmetros que a calibração não move ficam como ele diz.
  • serie.declaracao descreve a série:
    • a granularidade: mes (períodos AAAAMM) ou dia (AAAAMMDD);
    • a medida: novos, as pessoas novas no período, ou acumulado, as pessoas até o período;
    • as quebras (eixos), além do município: faixa de idade, por exemplo.
    • a unidade (unidade): municipio, o padrão, ou area_ponderacao, a área de ponderação do IBGE (um conjunto de bairros; 10 dígitos, os 7 do município e mais 3). Pelo chat, a área vem do CEP de cada cliente da sua base; uma pessoa cujo CEP é ambíguo (cobre mais de uma área, como o CEP geral de uma cidade pequena) ou desconhecido fica fora da série, e o resumo diz quantas foram.
  • O hash da série não vai no pedido: a plataforma o calcula das linhas.
  • O JSON Schema do pedido (draft 2020-12) é público em GET /v1/schemas/pedido-calibracao, com o schema do cenário dentro, e tipa o pedido na referência e nas ferramentas de calibração do MCP. As regras que um JSON Schema não diz (entre campos, o calendário, o tamanho da grade) e a conferência contra a série e a release ficam com o servidor, com os mesmos códigos.
  • No lugar das linhas, serie_sha256 aponta uma série que o seu projeto montou a partir de uma base de clientes.
  • janela e holdout são intervalos de períodos. O holdout vem depois da janela. O horizonte do cenário precisa chegar ao último dia do holdout.
  • holdout_espacial (opcional) diz quem separa os municípios que a busca não vê. Sem o campo, a plataforma separa ({ "metodo": "plataforma" }). Para escolher você mesmo: { "metodo": "cliente", "municipios": ["2800308", ...] }, com pelo menos 10 municípios de cada lado. Para não separar nenhum: { "metodo": "nenhum" }. Um pedido na versão 2 continua aceito e é lido como versão 3 sem holdout espacial.

A série é um agregado, nunca um registro de pessoa. A plataforma recusa, com um código e a linha, a série que não segue estas regras:

  • Municípios da release: cada municipio é um código IBGE de 7 dígitos das UFs do cenário.
  • Contagens de pelo menos 5, ou zero: uma contagem de 1 a 4 é uma pessoa quase identificada.
  • Num acumulado:
    • a contagem nunca cai;
    • cada passo é 0 ou pelo menos 5, porque o passo é o número de pessoas novas no período. Um município em que o acumulado sobe de 1 a 4 num período precisa sair da série. Num município pequeno isso é comum;
    • a contagem começa no dia 1 do cenário. O acumulado precisa contar desde o início da campanha; se a sua base já tinha clientes antes, mande a série como novos.
  • Sem buracos: cada município e quebra tem todos os períodos da série, sem pular nenhum, e a série cobre a janela e o holdout inteiros.
  • Até 150.000 linhas por pedido.
  • Por enquanto: só a família adocao, e sem quebra por canal.

Você escolhe os parâmetros livres e a faixa de cada um em parametros:

Parâmetro O que move
beta0 O nível de adoção
logit_lancamento O impulso no lançamento
dia_lancamento O dia do lançamento (inteiro)
beta_expo Quanto a exposição pesa na decisão
amortecimento_saturacao Como a adoção desacelera perto da saturação (de 0 a 1)
pesos_canais O peso de cada canal de exposição (canais lista quais)
gamma_celulas A diferença entre grupos de pessoas (agrupamento: por exemplo, faixa de idade)
deslocamento_porte A diferença entre cidades grandes, médias e pequenas: um ajuste do nível por porte de município (três valores)

Antes da busca, uma análise mede o que a janela consegue distinguir. Um parâmetro que não muda a série, ou que só muda junto com outro, fica no ponto de partida, e o resultado diz qual e por quê.

Uma série de totais mensais costuma distinguir o nível e o impulso, mas não o peso de cada canal. Quanto mais parâmetros livres, mais rodadas e mais caro, e não necessariamente melhor.

Um nível só para o estado inteiro raramente serve à capital e às cidades pequenas ao mesmo tempo. deslocamento_porte dá à calibração um ajuste do nível por porte de município: um valor para a maior cidade do estado, um para as cidades grandes, um para as médias e um para as pequenas, somados ao nível. O porte de cada município vem da população sintética do estado, e não da sua série: a maior cidade fica sozinha no seu porte, porque ela adota diferente até das cidades grandes ao lado dela; entre as demais, as maiores até metade da população restante são as grandes, as seguintes até 90% as médias, e o resto as pequenas. Por isso o ajuste vale também para os municípios onde a sua base não tem ninguém, que é o que faz o padrão aprendido viajar.

A série precisa ter municípios de portes diferentes: com os municípios do ajuste num só porte, o pedido é recusado (strata_required). O valor escolhido de cada porte aparece em parametros como deslocamento_porte[maior_cidade], [grandes], [medios] e [pequenos]; um porte que a série não distinguiu, ou que não está na sua base (uma base sem a capital), fica em zero.

  • grade: todos os pontos da grade de cada parâmetro (o passo é obrigatório).
  • aleatoria: candidatos pontos sorteados nas faixas.
  • sequencial: uma busca local a partir do cenário de partida, com até candidatos pontos. É útil com muitos parâmetros livres, mas pode parar perto do ponto de partida.

O escolhido é o candidato com o menor erro médio na janela, lido por estrato de porte: os municípios da série são agrupados pelo porte que têm na população sintética do estado — a maior cidade, as grandes, as médias e as pequenas, os mesmos portes do ajuste por porte —, e o erro por bloco é medido em cada estrato e depois tirado em média, com peso igual para todos. Assim o erro nas cidades pequenas conta tanto quanto o da capital, e a busca pode aprender onde o padrão difere; com poucos municípios há um estrato só, e o critério é o erro do total. Os candidatos só rodam até o fim da janela. Só o escolhido roda até o fim do holdout. O resultado mostra o erro do escolhido por estrato também no holdout, e a razão entre o simulado e o observado de cada município no fim dele, para você ver onde ele erra; a aprovação segue sendo a do erro total.

O veredito julga o escolhido no holdout. Ele é aprovada quando todos os testes que se aplicam passam:

  • Erro por bloco (MAPE): os blocos são trimestres numa série mensal e semanas numa diária. Um bloco que mistura a janela e o holdout conta como holdout.
    • O limite é 20% nos blocos do primeiro ano depois da janela e 12% depois.
    • Um bloco com algum período zerado é medido pelo erro da soma do bloco.
  • Ordem entre municípios (τ de Kendall):
    • a ordem dos municípios em cada fim de ano do holdout e no último período dele não pode cair mais de 0,02 abaixo da ordem no fim da janela;
    • entre dois pontos seguidos, também não pode cair mais de 0,02;
    • vale com pelo menos 10 municípios.
  • Ordem por idade (τ ≥ 0,8): só quando a série tem a quebra por idade.

Uma calibração que passa no holdout do tempo pode ainda errar onde você não vende: o ensaio do Pix em Sergipe mostrou que o nível aprendido numa metade dos municípios erra a outra em 20% a 48%, enquanto a ordem entre os municípios se mantém. Por isso, com 31 municípios ou mais na série, a plataforma separa um terço deles antes da busca, e a busca nunca os vê:

  • Quem fica de fora: o maior município pelo total da janela fica sempre no ajuste (é a âncora); os outros são ordenados por esse total, tomados em trios, e um sorteio fixo pelo id do pedido separa um de cada trio. O mesmo pedido separa sempre os mesmos municípios.
  • Como são julgados: o escolhido roda neles e é medido em todos os períodos, janela e holdout, pelo mesmo erro por bloco (limite de 20%) e pela mesma ordem entre municípios, no conjunto e em dois estratos de porte.
  • O resultado vem no veredito, em espacial: transfere ou nao_transfere. Ele não muda a aprovação, que continua sendo a do holdout no tempo; ele diz se a calibração vale onde você ainda não tem clientes.
  • Você escolhe os municípios com holdout_espacial.metodo = "cliente", para responder “e nesta região?”. O veredito registra quem escolheu.

Cada série e holdout aceitam 3 tentativas: as calibrações na fila, rodando ou concluídas contra os mesmos dois. Uma que falhou ou foi cancelada não conta. Depois da terceira, escolha um holdout que nenhuma tentativa viu. Assim o holdout continua sendo um teste, e não vira parte do ajuste.

Quando o job conclui, GET /v1/calibracoes/{id} (ou get_calibration no MCP, ou a página do job no app) devolve:

  • veredito: o resultado, a tentativa e cada métrica, bloco a bloco.
  • identificabilidade: os parâmetros que a busca moveu, os que ficaram no ponto de partida e por quê.
  • busca: o método, quantos candidatos rodaram e o erro do escolhido na janela.
  • parametros: o valor escolhido de cada parâmetro livre, ao lado da faixa pedida.
    • na_borda diz que o valor ficou no limite da faixa: o melhor ponto que a busca alcançou estava na borda, e uma faixa maior pode ter um ponto melhor.

É tudo o que a calibração devolve: o veredito, a identificabilidade, a busca e os parâmetros escolhidos, em palavras e números. O cenário escolhido inteiro fica guardado na plataforma e é o que um cenário com cenario_base: "calibracao" usa ao simular; não há arquivo para baixar.

Um cenário de adoção do mesmo projeto pode partir do cenário que a calibração escolheu:

"lancamento": { "dia": 1, "cenario_base": "calibracao", "calibracao": "<id do job de calibração>" }
  • Só o mesmo projeto. O id de uma calibração de outro projeto ou de outra organização é recusado como se não existisse (calibration_not_found).
  • A calibração precisa ter concluído, com o resultado guardado (calibration_not_ready), na mesma release do cenário (calibration_release_mismatch) e com todas as UFs do cenário (calibration_uf_missing).
  • O que a simulação usa:
    • os parâmetros escolhidos, lançados no dia do pedido novo;
    • uma cópia do cenário escolhido e do veredito, que fica com o job. Apagar a calibração impede simulações novas a partir dela, e não mexe nas que já rodaram.
  • O rótulo: toda saída leva o veredito da calibração, cliente_aprovada ou cliente_reprovada. Uma calibração reprovada também serve de base, com o rótulo dizendo isso. A aba Validação do job mostra o teste do holdout.
  • O preço é o da simulação.

A calibração paga a tarifa da simulação por todas as rodadas que faz:

rodadas = candidatos + 2 × parâmetros livres + 1
pessoa_dias = população das UFs × dias até o fim do holdout × réplicas × rodadas
preço = máximo(5,50 ; 3,95 + 0,00172 × pessoa_dias / 1.000.000)
  • Candidatos: numa grade, o tamanho dela; nos outros métodos, candidatos.
  • Parâmetros livres: cada peso de canal ou grupo de gamma_celulas conta um; deslocamento_porte conta três.
  • As 2 rodadas por parâmetro são as da análise de identificabilidade.
  • A última rodada é a do escolhido até o fim do holdout.

Por exemplo, Roraima (619.519 pessoas), 730 dias, uma réplica, uma grade de 2 pontos e um parâmetro livre:

  • 5 rodadas;
  • 2.261.244.350 pessoa-dias;
  • R$ 7,839341.

POST /v1/calibracoes/estimate (ou estimate_calibration no MCP) confere o pedido e a série e dá o preço sem reservar nada.

Quanto tempo leva: a cotação traz minutos_estimados, o tempo aproximado de execução depois que a calibração começa. Ele cresce com a população das UFs, com os dias da janela e com o número de candidatos. Uma grade pequena num estado pequeno leva minutos. Um ano de São Paulo com uma grade de 63 pontos leva perto de um dia.