Skip to content

Repository files navigation

📈 PrevDemanda — previsão de demanda diária com pipeline de dados e MLOps

CI Python 3.11+ Licença MIT

Previsão de pedidos por dia para as próximas 4 semanas de um e-commerce. O foco é a engenharia: contrato de dados, features sem vazamento, backtesting temporal, experimentos rastreados no MLflow, testes e CI.

Projeto desenvolvido por Rodrigo Gandarela Soares de Farias Duca (Engenharia de Computação — Universidade SENAI CIMATEC), set/2026. Temáticas: Séries Temporais, Engenharia de Dados e MLOps. Especificação completa (Spec-Driven Development) em specs/.

📖 Documentação técnica detalhada, passo a passo: DOCUMENTACAO.md

Resultado

Backtest com origem móvel: 4 dobras de 28 dias (mai–ago/2018), treino sempre anterior ao teste.

Modelo MAE ↓ RMSE sMAPE (%)
Naive sazonal (t−7), baseline 61,8 71,4 31,6
Média móvel 28 dias 58,0 68,6 27,2
Holt-Winters aditivo amortecido 64,3 73,0 32,6
LightGBM (alvo relativo) 48,9 58,2 23,1

O LightGBM reduz o MAE em 21% em relação ao baseline (≈ 49 pedidos/dia de erro médio, com média de ~218 pedidos/dia no período).

O que cada componente contribui (ablação)

Variante do LightGBM MAE Leitura
Modelo completo 48,9 —
sem feriados/Black Friday 51,8 eventos ajudam
sem médias/desvios móveis 57,7 o nível recente é a informação mais importante
alvo absoluto (prevendo y direto) 54,0 normalizar pelo nível recente ajuda as árvores
+ feature de tendência (dias_desde_inicio) 53,0 árvores não extrapolam tendência, e a feature atrapalha

Tabela completa, MAE por dobra e importância de features: reports/resultados.md.

Última dobra do backtest

Como funciona

config.yaml
    │
ingestão ─► qualidade ─► features ─► backtest (4 dobras) ─► treino final ─► previsão 28 dias
 (CSV)     (contrato)   (lags ≥ 28)  naive · MM28 · HW ·     melhor modelo     + intervalo 80%
                                      LightGBM + ablações
                                            │
                                   MLflow: parâmetros, métricas por dobra, gráficos, modelo

Decisões técnicas principais:

  • Previsão direta sem vazamento. Toda feature usa y com atraso ≥ 28 dias, o tamanho do horizonte. Assim um único modelo prevê os 28 dias sem recursão. tests/test_features.py prova isso: alterar os últimos 28 valores não muda nenhuma feature.
  • Alvo relativo. O LightGBM prevê y / média_móvel_28(deslocada). A média carrega o nível e a tendência, e as árvores aprendem o padrão (dia da semana, dia do mês, feriados, Black Friday).
  • Contrato de dados (src/qualidade.py). O pipeline para se houver datas duplicadas, dias faltando, valores negativos ou mais de 3 dias seguidos sem pedidos. Foi essa checagem que detectou o ramp-up de jan/2017 e a queda artificial no fim da coleta (ago/2018), que agora são recortados.
  • Intervalo de previsão empírico. Os modelos quantílicos do LightGBM cobriram só ~41% dos valores reais no backtest (o esperado era 80%). A previsão final usa os quantis dos resíduos do backtest.

Como rodar

python -m venv .venv && .venv\Scripts\activate      # Linux/Mac: source .venv/bin/activate
pip install -r requirements.txt
make dados        # baixa o dataset Olist via kagglehub → data/raw/
make pipeline     # python -m src.pipeline   (~1–2 min em CPU)
make app          # streamlit run app/app.py
make mlflow       # UI do MLflow em http://127.0.0.1:5000
make test         # pytest (dados sintéticos, sem precisar do Kaggle)

Sem make (Windows): rode os comandos equivalentes que estão no Makefile.

Estrutura

src/ingestao.py    CSV → série diária, recorte das pontas
src/qualidade.py   contrato de dados
src/features.py    calendário, feriados BR, Black Friday, lags e janelas deslocadas
src/modelos.py     Naive7, MediaMovel28, HoltWinters, LGBM (interface fit/predict comum)
src/backtest.py    dobras de origem móvel + métricas
src/pipeline.py    orquestração + MLflow
app/app.py         dashboard Streamlit
tests/             15 testes (qualidade, features/vazamento, backtest, métricas)
config.yaml        todos os parâmetros do experimento
DOCUMENTACAO.md    guia técnico completo, passo a passo

Qualidade: 15 testes (pytest) e lint (ruff) rodam a cada push pelo CI, com dados sintéticos — sem precisar do Kaggle.

Dados

Brazilian E-Commerce Public Dataset by Olist, licença CC BY-NC-SA 4.0. Arquivo olist_orders_dataset.csv, agregado em pedidos por dia (sem cancelados e indisponíveis). Série usada: 2017-02-01 → 2018-08-23 (569 dias). Dados anonimizados pela Olist. Aqui só são usadas contagens agregadas.

Limitações

  • Uma empresa, um período (2017–2018). Não generaliza para outros negócios sem retreino.
  • Viés de seleção leve. As variantes do LightGBM (alvo relativo, sem tendência) foram comparadas no mesmo backtest que reporta o resultado. Com mais histórico, o certo seria reservar um holdout final separado.
  • Surtos de demanda (ex.: ago/2018) são subestimados. O nível vem da média móvel com 28 dias de atraso.
  • Os intervalos quantílicos do LightGBM ficaram mal calibrados. O intervalo empírico corrige o nível médio de cobertura, mas não se adapta ao dia.

Licença

Código sob MIT. Os dados não são redistribuídos e mantêm a licença de origem (Olist, CC BY-NC-SA 4.0).

Próximos passos (produção)

Agendamento semanal (Airflow/cron) → retreino → registro no MLflow Model Registry. Monitoramento: comparar o MAE semanal real com o MAE de referência do backtest e alertar se passar de 1,5×. Previsão hierárquica por categoria de produto.

About

Previsão de pedidos por dia para as próximas 4 semanas de um e-commerce. O foco é a engenharia: contrato de dados, features sem vazamento, backtesting temporal, experimentos rastreados no MLflow, testes e CI.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Used by

Contributors

Languages