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
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).
| 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.
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
ycom atraso ≥ 28 dias, o tamanho do horizonte. Assim um único modelo prevê os 28 dias sem recursão.tests/test_features.pyprova 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.
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.
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.
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.
- 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.
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).
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.
