Previsão agora é uma chamada de biblioteca: anotações de quem rodou o TimesFM 2.5
O TimesFM 2.5 do Google encolheu para 200M de parâmetros, liderou o GIFT-Eval em zero-shot no lançamento e agora está por trás do AI.FORECAST do BigQuery — então rodei o modelo eu mesmo em séries com formato de telemetria. Em zero-shot, ele superou o seasonal-naive em 15% com 0,6s por previsão em CPU. Depois adicionei um salto de nível de 60% uma semana antes da previsão e a baseline de uma linha venceu por 1,5x — enquanto a banda de quantis do modelo silenciosamente alargava 2,6x. Estas são minhas anotações sobre o que chamou atenção, o que observar antes de confiar nele e os casos de uso em que eu realmente o colocaria em produção.
Entreguei a um modelo de 200 milhões de parâmetros cinco semanas de telemetria falsa que ele nunca tinha visto — contagens horárias de requisições com ciclo diário, queda no fim de semana e uma leve tendência de alta — e pedi a próxima semana. Sem treinamento, sem tuning, sem nenhuma pista sobre a frequência dos dados. Ele superou uma baseline seasonal-naive em 15% e produziu cada previsão em 0,6 segundo na CPU da máquina em que rodei. Depois desloquei a série para um novo patamar uma semana antes da previsão, do jeito que um lançamento ou uma migração desloca tráfego real, e o ranking se inverteu: a baseline mais burra que conheço venceu por um fator de 1,5.
Os dois resultados são o ponto destas anotações. O TimesFM 2.5 é o argumento mais forte até agora de que previsão está virando uma chamada de biblioteca em vez de um projeto de modelagem — e o formato da falha que ele me mostrou é exatamente o que checar antes de plugá-lo em qualquer coisa que importe.
O que chamou a atenção de todo mundo
O TimesFM começou como uma aposta de pesquisa de que a receita dos LLMs se transfere para séries temporais. O post original do Google Research (fevereiro de 2024, com o paper no ICML 2024) descreve um transformer decoder-only que lê uma série em patches — 32 pontos temporais de entrada, 128 de saída por passo — pré-treinado em cerca de 100 bilhões de pontos temporais do mundo real, boa parte deles Google Trends e pageviews da Wikipédia. A afirmação que fez as pessoas prestarem atenção: em zero-shot, ele se aproxima de modelos como DeepAR e PatchTST que foram treinados no dataset alvo. Treine uma vez em tudo, preveja qualquer coisa — a mesma inversão que os modelos de linguagem provocaram no NLP, onde o treinamento por tarefa colapsou em pré-treinar-e-depois-promptar.
A versão 2.5, lançada em 15 de setembro de 2025, é o motivo de eu finalmente ter rodado o modelo. Três mudanças se destacam nas notas de release. O modelo encolheu dos 500M de parâmetros da 2.0 para 200M e ficou mais preciso. O contexto máximo cresceu de 2.048 pontos para 16.384 — o suficiente para entregar dois anos de dados horários. E as partes desconfortáveis da API antiga sumiram: acabou o indicador de frequência que era preciso adivinhar, e entrou uma cabeça opcional de quantis de 30M de parâmetros que emite quantis contínuos até um horizonte de 1.000 passos. No GIFT-Eval, o benchmark comunitário para previsão geral, o Google reportou a 2.5 liderando os foundation models zero-shot tanto em MASE quanto em CRPS no lançamento — precisão pontual e probabilística ao mesmo tempo. Essa liderança não durou. O Chronos-2, publicado um mês depois, em outubro de 2025, reporta resultados de estado da arte no GIFT-Eval à frente do TimesFM 2.5 nas duas métricas, e recebe covariáveis nativamente por in-context learning em vez de por um canal separado. Leia o topo desse leaderboard como alvo móvel, não como propriedade de um modelo. A licença é Apache-2.0.
O sinal mais forte de que isso deixou de ser um artefato de pesquisa: em novembro de 2025, o Google plugou o TimesFM 2.5 no BigQuery e no AlloyDB como funções SQL — AI.FORECAST está GA no BigQuery, detecção de anomalias está em preview, e o modelo por trás deles agora é treinado em mais de 400 bilhões de pontos temporais. Prever uma tabela virou uma chamada de função que mora onde os dados já estão. Quando uma capacidade cruza de "clone o repositório" para "é uma função SQL", engenheiros de backend a herdam tenham pedido ou não.
Cinco semanas de telemetria falsa e uma baseline com amnésia
Papers fazem benchmark em varejo, tráfego e clima. Eu me importo com séries no formato daquelas que o trabalho de backend realmente produz, então meu harness de teste gera telemetria horária — carga base em torno de 1.000 requisições por hora, ciclo diário senoidal, queda de 25% no fim de semana, tendência lenta de alta e ruído. Dois cenários: um estável e outro em que o nível salta 60% uma semana antes do início da previsão e permanece lá, do jeito que o tráfego se move depois de um lançamento.
A baseline é seasonal-naive: repita a última semana, sem mudar uma vírgula. É o adversário honesto de qualquer sistema de previsão, porque custa uma linha e nenhum modelo que perde para ela merece a palavra "modelo" em produção.
"""Experimento zero-shot com TimesFM 2.5: séries com formato de telemetria vs seasonal-naive."""
import time
import numpy as np
RNG = np.random.default_rng(42)
HOURS_PER_WEEK = 168
CONTEXT = 5 * HOURS_PER_WEEK # 5 semanas de histórico horário
HORIZON = HOURS_PER_WEEK # prever 1 semana à frente
def telemetry(n, base=1000.0, trend_per_hour=0.05, break_at=None, break_factor=1.0):
"""Série horária: sazonalidade diária + semanal, leve tendência, ruído, salto de nível opcional."""
t = np.arange(n)
daily = 0.35 * np.sin(2 * np.pi * (t % 24) / 24 - 1.2)
weekly = np.where((t // 24) % 7 >= 5, -0.25, 0.0) # queda de fim de semana
level = base + trend_per_hour * t
series = level * (1.0 + daily + weekly)
if break_at is not None:
series[break_at:] *= break_factor
return series + RNG.normal(0, 0.03 * base, n)
def seasonal_naive(context, horizon, season=HOURS_PER_WEEK):
reps = int(np.ceil(horizon / season))
return np.tile(context[-season:], reps)[:horizon]
def mae(a, b):
return float(np.mean(np.abs(a - b)))
def main():
import timesfm
model = timesfm.TimesFM_2p5_200M_torch.from_pretrained(
"google/timesfm-2.5-200m-pytorch")
model.compile(
timesfm.ForecastConfig(
max_context=CONTEXT, max_horizon=HORIZON,
normalize_inputs=True, use_continuous_quantile_head=True,
fix_quantile_crossing=True,
)
)
scenarios = {
"steady": telemetry(CONTEXT + HORIZON),
"regime-break": telemetry(CONTEXT + HORIZON, break_at=CONTEXT - HOURS_PER_WEEK,
break_factor=1.6),
}
for name, series in scenarios.items():
context, actual = series[:CONTEXT], series[CONTEXT:]
start = time.monotonic()
point, quantiles = model.forecast(horizon=HORIZON, inputs=[context])
elapsed = time.monotonic() - start
tfm_mae = mae(point[0], actual)
naive_mae = mae(seasonal_naive(context, HORIZON), actual)
q = quantiles[0] # (horizonte, 10): média + decis q10..q90
spread = float(np.mean(q[:, 9] - q[:, 1])) # largura média da banda q90-q10
print(f"[{name}] TimesFM MAE={tfm_mae:.1f} seasonal-naive MAE={naive_mae:.1f} "
f"ratio={tfm_mae / naive_mae:.2f} q10-q90 width={spread:.1f} "
f"forecast time={elapsed:.1f}s")
if __name__ == "__main__":
main()Rode com python timesfm_experiment.py depois de pip install "timesfm[torch]" — a primeira execução baixa o checkpoint do Hugging Face. Duas linhas merecem comentário. O ForecastConfig é onde a ergonomia da 2.5 aparece: normalize_inputs cuida da escala, a cabeça contínua de quantis é uma flag e não sobrou nenhum parâmetro de frequência para você chutar errado. E a saída de quantis tem shape (horizonte, 10) — a média mais os decis q10 até q90 — o que acaba sendo a coisa mais valiosa que o modelo emite.
Na minha máquina (Python 3.11, torch 2.11, apenas CPU) a saída foi:
[steady] TimesFM MAE=27.8 seasonal-naive MAE=32.7 ratio=0.85 q10-q90 width=102.0 forecast time=0.6s
[regime-break] TimesFM MAE=56.2 seasonal-naive MAE=37.6 ratio=1.49 q10-q90 width=268.2 forecast time=0.6s
O cenário estável é a manchete que os papers prometeram, reproduzida na minha mesa: 15% melhor que o seasonal-naive, em zero-shot, numa série que o modelo nunca viu, com uma banda q10–q90 de cerca de ±5% do nível, em 0,6 segundo na CPU. Sem pipeline de treinamento, sem hiperparâmetros, sem GPU.
A quebra de regime é onde a coisa fica instrutiva, e o detalhamento diário mostra um quadro mais nítido que o agregado. O modelo não erra o novo patamar — seu pior dia é o primeiro, em que prevê uma média diária de 1.594 contra 1.675 reais, ainda hedgeando em direção às cinco semanas de histórico mais baixo que recebeu. Depois ele se adapta, acompanha o novo nível dos dias úteis com erro de aproximadamente 1–2% e fica 2–6% acima na queda do fim de semana. O seasonal-naive, que lembra exatamente uma semana — toda ela pós-quebra —, fica mais perto da realidade em quase todos os dias. Amnésia, nesta situação específica, é uma feature: a baseline não pode ser distraída pelo regime antigo porque nunca o viu.
O comportamento que redime o modelo é que ele sinaliza a própria confusão. A banda q10–q90 que ficou em média em 102 requisições por hora no cenário estável foi para 268 em média depois da quebra, e cresceu de 225 no primeiro dia para 377 no sétimo. A previsão pontual perdeu para uma linha de código; a estimativa de incerteza me disse para não confiar na previsão pontual. A figura abaixo mostra os dois painéis — a previsão horária acompanhando o novo regime e as médias diárias expondo o hedge.
O que observar antes de confiar nele
Minha execução trouxe à tona a primeira ressalva diretamente: o modelo extrapola padrões, não causas. Um salto de nível que ele só viu por uma semana é ponderado contra tudo que veio antes. Em termos de produção, a semana seguinte a cada lançamento, migração ou mudança de preço é exatamente quando a previsão é menos confiável — e é também quando todo mundo mais quer uma previsão.
A segunda decorre dela: trate a banda de quantis como a saída principal, não como enfeite. Uma previsão pontual plugada num autoscaler é uma decisão sem barras de erro; a mesma previsão condicionada à largura da banda é uma decisão que sabe quando se abster. Na minha execução com quebra de regime, a banda alargou 2,6x antes de o erro pontual se materializar como problema — esse sinal é de graça, e a flag fix_quantile_crossing garante que os decis chegam já ordenados.
Terceiro, o modelo é univariado por série. Ele lê um fluxo de números; não pode saber que um deploy subiu, que uma campanha de marketing começou ou que um feriado está chegando, a menos que essa informação já esteja visível como histórico na própria série. Suporte a covariáveis existe como um add-on XReg restaurado em outubro de 2025, mas o caminho mágico do zero-shot é histórico-entra, previsão-sai. Qualquer série cujo futuro seja dirigido por eventos fora do próprio passado vai punir essa cegueira.
Quarto, segure os números de benchmark com leveza. Um paper de outubro de 2025 sobre avaliação de foundation models de séries temporais argumenta que, à medida que os corpora de pré-treino engolem a maior parte dos dados públicos de séries temporais, sobreposição entre treino e teste e correlação temporal tornam os leaderboards zero-shot propensos a "estimativas de desempenho excessivamente otimistas que não generalizam para cenários do mundo real". Não leio isso como acusação contra nenhum modelo específico — é um problema estrutural da categoria, o mesmo debate de contaminação pelo qual os benchmarks de LLM passaram. A consequência prática é o padrão que usei acima: seu próprio holdout, contra o seasonal-naive, nas suas próprias séries, é o único benchmark que resolve alguma coisa. O harness tem menos de 80 linhas; não há desculpa para pular.
Onde eu realmente usaria
Os casos de uso pelos quais eu começaria compartilham um formato: séries sazonais, com tendência lenta, em que uma estimativa de nível para a próxima semana ou o próximo dia muda uma decisão, e em que errar é recuperável.
Planejamento de capacidade e pré-escala é o óbvio. Preveja o pico horário de amanhã a partir de seis semanas de histórico e aqueça capacidade à frente da curva em vez de reagir a ela; um autoscaler reativo continua como rede de segurança, então uma previsão ruim custa dinheiro, não disponibilidade. Planejamento de fila e backlog é a mesma matemática que trabalhei nas minhas anotações anteriores sobre aritmética de recuperação de backlog: o tempo de drenagem depende da curva de chegadas que você espera, e uma previsão de chegadas transforma "esse backlog vai zerar antes do pico da noite?" de palpite em inequação. Pré-aquecimento de cache antes de uma rampa de tráfego prevista compra o mesmo ganho de latência que pré-aquecer por cron, menos a ignorância do cron sobre tendência. E projeção de error budget — prever uma série de burn rate para ver se o orçamento sobrevive ao mês — é uma decisão que tolera imprecisão e se beneficia diretamente da banda de quantis.
Se os dados já vivem no BigQuery, o cálculo pende ainda mais: AI.FORECAST transforma o experimento em uma única query sem nenhuma infraestrutura, que é a forma mais barata possível de descobrir se um foundation model se paga nas suas séries. O mesmo release de GA trouxe o AI.EVALUATE, que pontua uma previsão contra os valores reais separados como holdout — a comparação que defendi acima, em uma segunda query. Passe model => 'TimesFM 2.5' explicitamente; o padrão não é a 2.5.
Onde eu não usaria: qualquer coisa com contrato de reação sub-segundo (esse é o trabalho da detecção de anomalias, não da previsão); séries dominadas por eventos externos que o modelo não enxerga — promoções, deploys, tráfego de incidente; a primeira semana após qualquer mudança conhecida de regime, conforme meus próprios resultados acima; e qualquer série em que a razão contra o seasonal-naive volte perto de 1,0, porque um modelo que empata com uma linha de código é puro overhead operacional.
Pontos que levo daqui
- Em zero-shot, sobre telemetria estável, o TimesFM 2.5 superou o seasonal-naive em 15% em 0,6 segundo na CPU — sem pipeline de treinamento, sem GPU, sem precisar informar a frequência.
- Uma semana depois de um salto de nível de 60%, o mesmo modelo perdeu para o seasonal-naive por 1,5x. A semana seguinte a um lançamento ou migração é quando a previsão é menos confiável e mais desejada.
- Trate a banda q10–q90 como a saída principal. Ela alargou 2,6x no regime quebrado antes de o erro pontual importar — um sinal gratuito de abstenção para qualquer coisa que leia a previsão.
- O modelo é univariado: deploys, promoções e feriados são invisíveis, a menos que já apareçam como histórico na série.
- Posição em leaderboard é temporária — o Chronos-2 assumiu a liderança do GIFT-Eval um mês depois da 2.5. Rode o harness no seu próprio holdout; uma razão contra o seasonal-naive perto de 1,0 significa que o modelo é puro overhead operacional.
A regra de decisão que estou guardando disto: rode o harness contra o seasonal-naive no seu próprio holdout — a razão decide se o modelo merece um lugar no loop, e a banda de quantis decide, hora a hora, se acreditar nele. O experimento que já deixei na fila é o caminho das covariáveis: se o XReg com uma série marcadora de deploys fecha a lacuna da quebra de regime, ou se aquela primeira semana depois de um lançamento simplesmente pertence aos humanos. O Chronos-2 transforma isso numa pergunta de dois modelos, já que ele recebe covariáveis in-context em vez de por um add-on separado.
Curtindo? Talvez goste disso aqui.
Nada parecido — quer tentar outro ângulo?
Posts Relacionados
Pré-registrando o Experimento #1: Quão Frágeis São os Prompts de Extração de JSON em Produção?
O primeiro experimento concreto da linha de pesquisa de precisão — comprometido em público antes da coleta dos dados. Cinco classes de perturbação, quinze variantes, quatro métricas, quatro hipóteses falsificáveis e um repositório companion executável com testes.
Transformando Engenharia de Contexto de LLM em um Loop de Avaliação com DSPy
Notas de dois fins de semana cavando o DSPy. Parei de tratar prompts como a fonte da verdade e comecei a tratá-los como saída compilada de uma assinatura tipada, uma métrica e um otimizador. Aqui está o menor programa end-to-end que mantive, como o MIPROv2 de fato busca, e onde a abordagem cai por terra na prática.
Avaliação de Memória: Medindo Como a Memória de IA se Degrada ao Longo da Vida de um Projeto
A maioria dos benchmarks de memória de IA avalia recall e para por aí. Isso esconde o modo de falha real: fatos desatualizados envenenando silenciosamente a janela de contexto. Aqui está um framework de avaliação baseado em ciclo de vida que testa recall, revisão e esquecimento controlado em todos os pontos de mudança pelos quais um projeto de longa duração passa.