Este projeto visa resolver o problema de negócio da previsão do risco de defasagem educacional dos estudantes, utilizando dados demográficos e de desempenho para identificar alunos em risco de atraso escolar.
Construção de uma pipeline completa de Machine Learning, desde o pré-processamento dos dados até o deploy do modelo em produção via API REST. O sistema utiliza um modelo de regressão neural (MLPRegressor) para prever o nível de defasagem baseado em indicadores educacionais e demográficos.
- Linguagem: Python 3.13
- Frameworks de ML: scikit-learn, polars, numpy
- API: FastAPI
- Serialização: pickle
- Testes: pytest
- Empacotamento: Docker
- Gerenciamento de Dependências: uv
- Monitoramento: logging com decorator @log_exec_time + dashboard de drift (PSI)
datathon/
├── Dockerfile # Configuração do container Docker
├── pyproject.toml # Metadados e dependências do projeto
├── README.md # Esta documentação
├── data/
│ ├── datasets/
│ │ ├── in/ # Dados brutos (2022.csv, 2023.csv, 2024.csv)
│ │ └── out/ # Dados processados (dataset.csv)
│ ├── logs/ # Logs de execução e inferência
│ ├── models/ # Modelos serializados (.pkl): main.pkl, main_scaler.pkl
│ └── training_outputs/ # Métricas e baseline de drift (.json)
├── dev/
│ └── main.ipynb # Notebook para análise exploratória e pré-processamento
├── scripts/
│ ├── create_paths.py # Script para criar diretórios necessários
│ └── train.py # Script para executar o treinamento do modelo
├── src/
│ ├── constants.py # Constantes do projeto (caminhos)
│ ├── utils.py # Utilitários (dependência de logging de execução)
│ ├── contexts/
│ │ └── defasagem/ # Contexto de negócio da defasagem
│ │ ├── drift.py # Cálculo de PSI e relatório de drift
│ │ ├── entities.py # Modelos Pydantic (PredictionInput, enums)
│ │ ├── executors.py # Acesso a dados (métricas, tempos de execução)
│ │ ├── model.py # Definição do modelo MLPRegressor
│ │ ├── predict.py # Lógica de predição
│ │ ├── routes.py # Endpoints da API FastAPI
│ │ ├── templates/
│ │ │ └── drift_dashboard.html # Template HTML do painel de drift
│ │ └── train.py # Lógica de treinamento
│ ├── server/
│ │ └── config.py # Configuração do servidor FastAPI
│ └── tests/
│ └── test_defasagem.py # Testes unitários- Python 3.13
- Docker (opcional, para containerização)
- uv (gerenciador de dependências)
- Header obrigatório em todos os endpoints de negócio:
X-API-Key - Chave carregada via variável de ambiente
API_KEY(arquivo.envna raiz do projeto)
Exemplo de .env:
API_KEY=sua-chave-api-aqui# Instalar uv (se não tiver)
pip install uv
# Sincronizar dependências
uv sync
# Ativar ambiente virtual
source .venv/bin/activate # Linux/Mac
# ou
.venv\Scripts\activate # Windows# Criar diretórios necessários
uv run python scripts/create_paths.py
# Treinar o modelo
uv run python scripts/train.py
# Executar testes
uv run pytest
# Iniciar o servidor localmente
uv run uvicorn src.server.config:app --host 0.0.0.0 --port 8080# Construir imagem
docker build -t datathon-ml .
# Executar container
docker run --env-file .env -p 8080:8080 datathon-mlA API estará disponível em http://localhost:8080/docs (documentação interativa do FastAPI).
curl -X POST "http://localhost:8080/defasagem/predict" \
-H "X-API-Key: $API_KEY" \
-H "Content-Type: application/json" \
-d '{
"idade": 15,
"genero": 0,
"instituicao": 1,
"mat": 8.5,
"por": 7.2,
"ipv": 6.8,
"ian": 9.1,
"ing": 8.9,
"ips": 7.5,
"iaa": 8.0,
"ieg": 7.8,
"inde": 8.2,
"ida": 7.9
}'Resposta esperada: 2.34 (valor float representando o nível de defasagem previsto)
curl -X GET "http://localhost:8080/defasagem/get-metrics" \
-H "X-API-Key: $API_KEY"Resposta esperada:
{
"Mean Absolute Error (MAE)": 0.123,
"Mean Squared Error (MSE)": 0.045,
"Root Mean Squared Error (RMSE)": 0.212,
"R-squared (R²) Score": 0.876,
"Explained Variance Score": 0.889,
"Median Absolute Error": 0.098
}curl -X GET "http://localhost:8080/defasagem/get-exec-times" \
-H "X-API-Key: $API_KEY"Resposta esperada:
[
{
"start": "15/01/2024, 10:30:00",
"duration_in_seconds": 0.023,
"system_memory_percent_start": 45.6,
"system_memory_percent_end": 46.1
}
]curl -X GET "http://localhost:8080/defasagem/get-drift?window=500" \
-H "X-API-Key: $API_KEY"Resposta esperada:
{
"global_status": "ok",
"window_requested": 500,
"window_size": 500,
"features": {
"idade": {"psi": 0.031, "status": "ok"}
},
"prediction": {"psi": 0.044, "status": "ok"}
}curl -X GET "http://localhost:8080/defasagem/drift-dashboard?window=500" \
-H "X-API-Key: $API_KEY"Abra no navegador:
http://localhost:8080/defasagem/drift-dashboard?window=500
curl -X GET "http://localhost:8080/defasagem/get-drift-history?days=30" \
-H "X-API-Key: $API_KEY"Resposta esperada:
[
{
"date": "2026-03-01",
"global_status": "ok",
"window_size": 42,
"prediction": {"psi": 0.052, "status": "ok"},
"features": {
"idade": {"psi": 0.038, "status": "ok"}
}
}
]import httpx
url = "http://localhost:8080/defasagem/predict"
headers = {"X-API-Key": "<API_KEY_FROM_ENV>"}
data = {
"idade": 15,
"genero": 0,
"instituicao": 0,
"mat": 8.5,
"por": 7.2,
"ipv": 6.8,
"ian": 9.1,
"ing": 8.9,
"ips": 7.5,
"iaa": 8.0,
"ieg": 7.8,
"inde": 8.2,
"ida": 7.9
}
response = httpx.post(url, json=data, headers=headers)
print(f"Defasagem prevista: {response.json()}")- Carregamento dos dados brutos dos arquivos CSV (2022.csv, 2023.csv, 2024.csv)
- Mapeamento de variáveis categóricas: gênero (Masculino/Feminino → 0/1) e instituição de ensino (Privada/Pública/Outro → 0/1/2)
- Seleção e ordenação das features conforme definido no modelo PredictionInput
- Concatenação dos datasets em um único DataFrame
- Utilização direta das features numéricas (idades, notas) e categóricas mapeadas
- Não há criação de novas features derivadas no pipeline atual
- Divisão dos dados em treino (80%) e teste (20%) com
train_test_split - Aplicação de
StandardScalerpara normalização dos dados - Treinamento do modelo MLPRegressor (rede neural para regressão)
- Avaliação com métricas: MAE, MSE, RMSE, R², Explained Variance, Median AE
- Modelo fixo: MLPRegressor do scikit-learn com configuração padrão
- Persistência do modelo treinado via pickle (
main.pkl) e do scaler via pickle (main_scaler.pkl) - Salvamento das métricas em JSON (main.json)
- Features de entrada normalizadas via
StandardScaler(carregado demain_scaler.pkl) antes da inferência - Logging assíncrono de tempo de execução e uso de memória
- Logging de inferências (features + predição) em
data/logs/main_predictions.jsonl - Baseline de referência salvo em
data/training_outputs/main_drift_baseline.json - Monitoramento de drift via PSI por feature e por saída do modelo
- Retorno do valor previsto como float