Projeto final do Módulo 1 — Fundamentos de Dados, Programação e Análise
Preditiva com Python [T2]. Pipeline de ciência de dados ponta a ponta que
trata, analisa e modela dados reais de vendas de imóveis em Nova York para
prever o preço de venda (sale_price) — um problema de regressão.
- 🎯 Problema de Negócio
- 🗂️ Estrutura do Repositório
- ⚙️ Tecnologias Utilizadas
- 🚀 Como Executar
- 🔄 Arquitetura do Pipeline
- 📈 Fases do Projeto
- 🧠 Decisões Técnicas Relevantes
- 📊 Visualizações
- 🏆 Resultados
- 💼 Veredito de Negócio
- 🗃️ Modelo Versionado (v1)
- 🌟 Boas Práticas
- 🔮 Próximos Passos
- 🎯 Entregáveis da Avaliação
- 👤 Autor
Opção escolhida: B (dataset livre — equivalente à Opção B do edital),
usando a base pública NYC Property Sales (Kaggle:
new-york-city/nyc-property-sales),
com ~84 mil registros de transações imobiliárias na cidade de Nova York.
- Variável-alvo:
sale_price(valor numérico contínuo, em dólares). - Por que importa para o negócio: uma estimativa consistente de preço apoia corretores, compradores e vendedores na comparação de imóveis, na identificação de preços fora da faixa esperada e na priorização de análises mais aprofundadas antes de uma negociação.
- Recorte analítico: o dataset bruto mistura transações residenciais,
comerciais e registros administrativos com preço zerado. O notebook filtra
isso logo na Fase 2, restringindo a análise a transações residenciais
válidas (
sale_price > 0, sem unidades comerciais, com área construída e ano de construção preenchidos).
projeto/
├── data/
│ ├── raw/ # cópia do CSV bruto baixado via kagglehub
│ ├── processed/ # base limpa (pós Fase 2/3)
│ └── final/ # recorte final usado na modelagem (Fase 4)
├── models/
│ └── v1/
│ ├── modelo_regressao_v1.pkl
│ └── metricas_v1.json
├── notebooks/
│ └── projeto_final_nyc_property_sales.ipynb
├── outputs/
│ └── figures/
│ ├── 01_histograma_sale_price.png
│ ├── 02_scatter_gross_square_feet_vs_price_log.png
│ ├── 03_heatmap_correlacao.png
│ ├── 04_boxplots_outliers_log.png
│ ├── 05_heatmap_features_numericas.png
│ ├── 06_real_vs_previsto.png
│ ├── 07_residuos.png
│ └── 08_hist_residuos.png
├── requirements.txt
├── .gitignore
├── LICENSE
└── README.md
A pasta
src/(modularização em.py) não foi usada nesta entrega — todo o pipeline está no notebook, conforme expressamente aceito pelo edital.
| Tecnologia | Finalidade |
|---|---|
| Python 3.10+ | Linguagem principal |
| kagglehub | Download programático do dataset |
| Pandas / NumPy | Manipulação, limpeza e vetorização dos dados |
| Matplotlib / Seaborn | Visualizações analíticas e diagnósticas |
| scikit-learn | Pipeline, pré-processamento, Regressão Linear, Árvore de Decisão, métricas |
| statsmodels | Cálculo do VIF (multicolinearidade) |
| joblib | Persistência do modelo treinado (.pkl) |
Clone o repositório:
git clone https://github.com/lwallauer/SCTEC-Projeto_Final_Mod01.git
cd SCTEC-Projeto_Final_Mod01Instale as dependências:
pip install -r requirements.txtAbra o notebook (recomendado: Google Colab, pela integração com kagglehub):
notebooks/projeto_final_nyc_property_sales.ipynb
Execute as células em ordem, de cima para baixo. A primeira célula de código
baixa o dataset via kagglehub — é necessário ter uma conta Kaggle e,
localmente, o arquivo kaggle.json configurado (no Colab, a autenticação é
feita automaticamente).
Ao final da execução, o notebook grava:
- a base tratada em
data/processed/edata/final/; - os gráficos em
outputs/figures/; - o modelo campeão e suas métricas em
models/v1/.
Dados Brutos (Kaggle)
↓
Fase 1 — Análise Exploratória de Dados (EDA)
↓
Fase 2 — Tratamento e Limpeza (duplicatas, ausentes, outliers)
↓
Fase 3 — Feature Engineering (colunas derivadas)
↓
Fase 4 — Preparação para Modelagem (encoding, VIF, split, scaling)
↓
Fase 5 — Modelagem, Validação e Diagnóstico de Overfitting
↓
Regressão Linear vs. Árvore de Decisão (diferencial)
↓
Seleção do modelo campeão (menor RMSE de teste)
↓
Fase 6 — Avaliação, Interpretação e Versionamento (models/v1)
- Shape, tipos primitivos e
describe()do dataset bruto. - 3 gráficos analíticos: histograma de
sale_price, dispersãogross_square_feet×sale_price(escala log-log, com linha de tendência ajustada em espaço logarítmico) e heatmap de correlação de Pearson. - Leitura crítica: forte assimetria à direita no preço e necessidade de tratamento cuidadoso antes da modelagem.
- Remoção de duplicatas exatas.
- Recorte para transações residenciais válidas (
sale_price > 0, sem unidades comerciais, área e ano de construção preenchidos). - Imputação de
land_square_feet/gross_square_feetpela mediana por borough (distribuições assimétricas e com outliers tornam a média pouco robusta). - Diagnóstico visual de outliers via boxplot (escala log) — o corte efetivo é propositalmente adiado para a Fase 4 (ver seção de decisões abaixo).
property_age_at_sale: idade do imóvel na data da venda.sale_month: mês da venda, para capturar possível sazonalidade.has_apartment_number: indica se o registro tem número de unidade.- Nenhuma coluna derivada usa
sale_pricecomo insumo (sem risco de vazamento do alvo).
- Agrupamento de categorias raras (bairro, categoria construtiva, zipcode)
em
"OUTROS", para conter a cardinalidade antes do one-hot encoding. - Verificação de multicolinearidade via matriz de correlação e VIF (todas as variáveis numéricas com VIF < 1,5 — sem problema relevante).
train_test_split80/20.- Tratamento de outliers das explicativas após o split, com limites de corte (IQR) calculados apenas no treino.
StandardScaler,SimpleImputereOneHotEncoderembutidos numPipeline/ColumnTransformer, comfitrestrito ao treino.
- Modelo-base exigido pelo edital: Regressão Linear, treinado sobre
log1p(sale_price). - Diferencial: segundo modelo, uma Árvore de Decisão para Regressão
regularizada (
max_depth=10,min_samples_leaf=25). - Diagnóstico de overfitting (gap treino/teste) separado do diagnóstico de poder preditivo absoluto (R²), evitando confundir "sem overfitting" com "modelo bom".
- Seleção do modelo campeão pelo menor RMSE de teste.
- Métricas MAE, MSE, RMSE e R² do modelo campeão.
- Gráficos de dispersão real × previsto e de resíduos (distribuição e resíduo × previsto).
- Veredito de negócio conectando o erro numérico à decisão prática.
- Modelo campeão retreinado com 100% dos dados e salvo em
models/v1/.
Por que adiar o tratamento de outliers para depois do split? Calcular os limites de corte (IQR) usando a base inteira — antes de saber quais linhas ficariam no teste — vazaria informação do conjunto de teste para o treino (data leakage). Os boxplots da Fase 2 servem só para diagnóstico visual; o corte real usa apenas quantis do treino (Fase 4) e é aplicado igualmente a treino e teste.
Por que
log1p(sale_price)em vez do preço bruto?sale_priceé fortemente assimétrico à direita (poucos imóveis extremamente caros puxam a cauda). Modelar o logaritmo estabiliza a variância e evita que esses poucos valores extremos dominem o ajuste da Regressão Linear. As métricas finais são sempre reportadas na escala original, viaexpm1.
Por que agrupar categorias raras em "OUTROS" antes do one-hot? Bairro, categoria construtiva e zipcode têm dezenas/centenas de valores únicos. Sem agrupamento, o one-hot geraria muitas colunas esparsas e pouco informativas. Uma checagem de cardinalidade no notebook confirma que, após o agrupamento, o one-hot final tem 91 colunas para 21.229 linhas de treino — cardinalidade baixa o suficiente para não ser, sozinha, uma fonte relevante de overfitting disfarçado.
Por que escolher o modelo pelo RMSE de teste, e não pelo R² de treino? RMSE de teste mede o erro em dados que o modelo não viu, no mesmo espaço monetário do problema de negócio — é o critério de desempate definido pelo próprio edital.
| Modelo | Conjunto | MAE (US$) | RMSE (US$) | R² |
|---|---|---|---|---|
| Regressão Linear | Treino | 472.421 | 1.837.085 | 0,249 |
| Regressão Linear | Teste | 478.317 | 2.025.959 | 0,259 |
| Árvore de Decisão | Treino | 450.590 | 1.712.572 | 0,35 |
| Árvore de Decisão 🏆 | Teste | 470.527 | 1.870.671 | 0,37 |
A Árvore de Decisão foi eleita modelo campeão (menor RMSE de teste), com ganho de ~40% relativo no R² frente à Regressão Linear, sem sinal de overfitting adicional (gap treino/teste comparável ao da linear).
Em média, o modelo campeão erra cerca de US$ 470.527 por imóvel no conjunto de teste — o equivalente a 78,4% da mediana do preço observada nessa amostra. O resultado é útil como estimativa inicial e apoio à análise comparativa, mas o erro relativo ainda é alto para substituir a avaliação humana em casos atípicos ou de alto valor. Isso indica viés (underfitting): as variáveis disponíveis no dataset (área, unidades, localização agregada, idade do imóvel) não são suficientes para capturar a dinâmica completa de preços do mercado imobiliário de Nova York, que também depende de fatores não presentes na base, como estado de conservação, vista e padrão de acabamento.
O modelo campeão é retreinado com 100% dos dados tratados e salvo em:
models/v1/modelo_regressao_v1.pkl— pipeline completo (pré-processamento + regressor), viajoblib.models/v1/metricas_v1.json— métricas de treino/teste, data do treinamento, modelo campeão e lista de variáveis explicativas.
- PEP 8: nomes de variáveis e funções em
snake_case, linhas respeitando o limite de comprimento recomendado, espaçamento consistente entre imports/funções/blocos lógicos. - Sem data leakage: encoding, escalonamento e tratamento de outliers ajustados apenas no treino; split feito antes de qualquer estatística derivada dos dados.
- Reprodutibilidade:
random_state=42em split e modelos;requirements.txtdocumentando as dependências. - Clean code: funções reutilizáveis (
evaluate_from_log,metrics_to_frame,group_top_categories,save_current_figure) e comentários curtos apenas nos pontos de decisão técnica. - Diagnóstico crítico: overfitting e poder preditivo avaliados como perguntas distintas, com verificação de cardinalidade baseada em evidência (não em suposição).
- Licenciamento: projeto sob MIT License (ver
LICENSE), permitindo reuso e adaptação do código com atribuição.
- Validação cruzada (k-fold) para estimar a variância das métricas, não só um único split.
- Busca de hiperparâmetros (
GridSearchCV/RandomizedSearchCV) para a Árvore de Decisão e testes com Random Forest/Gradient Boosting. - Enriquecer a base com variáveis que hoje faltam (estado de conservação, vista, padrão de acabamento), possivelmente via fontes externas.
- Modularizar o pipeline em
src/(dataset.py,features.py,modeling/train.py), como diferencial de organização. - Versão v2 do modelo, documentando o histórico de melhorias em
models/v2/.
| Entregável | Link |
|---|---|
| 📓 Notebook final | notebooks/projeto_final_nyc_property_sales.ipynb |
| 📁 Repositório GitHub | github.com/lwallauer/SCTEC-Projeto_Final_Mod01 |
| 🎬 Vídeo de apresentação | Assista no Google Drive (Precione CTRL + link para abrir em uma nova aba) |
Projeto desenvolvido para o Módulo 1 da trilha Desenvolvimento de IA para Análise Preditiva, consolidando conhecimentos em Data Prep, Feature Engineering, Análise Exploratória, Regressão e boas práticas de reprodutibilidade em Machine Learning.
Leandro Wallauer dos Santos







