Spaces:
Sleeping
Sleeping
Update app.py
Browse files
app.py
CHANGED
|
@@ -22,14 +22,13 @@ class HousePricePredictor:
|
|
| 22 |
self.scaler = None
|
| 23 |
self.df = None
|
| 24 |
self.is_trained = False
|
| 25 |
-
self.selected_features =
|
| 26 |
self._data_loaded = False
|
| 27 |
self.stats = {
|
| 28 |
'n_imoveis': 0,
|
| 29 |
'n_caracteristicas': 0,
|
| 30 |
'preco_medio': 0
|
| 31 |
}
|
| 32 |
-
self.feature_states = {} # Para armazenar estado das features
|
| 33 |
|
| 34 |
def load_data(self):
|
| 35 |
"""Carrega dados do arquivo kc_house_data.csv"""
|
|
@@ -43,9 +42,6 @@ class HousePricePredictor:
|
|
| 43 |
# Limpeza básica dos dados
|
| 44 |
self._clean_data()
|
| 45 |
|
| 46 |
-
# Inicializar estados das features
|
| 47 |
-
self._initialize_feature_states()
|
| 48 |
-
|
| 49 |
# Atualizar estatísticas
|
| 50 |
self.stats = {
|
| 51 |
'n_imoveis': self.df.shape[0],
|
|
@@ -82,21 +78,6 @@ class HousePricePredictor:
|
|
| 82 |
print(f"📊 Dados limpos: {self.df.shape[0]} imóveis")
|
| 83 |
print(f"💰 Preço médio: ${self.df['price'].mean():,.2f}")
|
| 84 |
|
| 85 |
-
def _initialize_feature_states(self):
|
| 86 |
-
"""Inicializa os estados das features baseado nas correlações"""
|
| 87 |
-
if self.df is not None:
|
| 88 |
-
correlations = self.df.corr()['price'].abs().sort_values(ascending=False)
|
| 89 |
-
|
| 90 |
-
# Selecionar automaticamente as 6 features mais correlacionadas
|
| 91 |
-
top_features = []
|
| 92 |
-
for feature in correlations.index:
|
| 93 |
-
if feature != 'price' and len(top_features) < 6:
|
| 94 |
-
top_features.append(feature)
|
| 95 |
-
|
| 96 |
-
# Inicializar estados
|
| 97 |
-
for feature in self.get_numeric_features():
|
| 98 |
-
self.feature_states[feature] = feature in top_features
|
| 99 |
-
|
| 100 |
def get_numeric_features(self):
|
| 101 |
"""Retorna lista de features numéricas (excluindo price)"""
|
| 102 |
if self.df is None:
|
|
@@ -106,19 +87,16 @@ class HousePricePredictor:
|
|
| 106 |
numeric_features.remove('price')
|
| 107 |
return numeric_features
|
| 108 |
|
| 109 |
-
def
|
| 110 |
-
"""Retorna
|
| 111 |
-
|
| 112 |
-
|
| 113 |
-
|
| 114 |
-
|
| 115 |
-
for feature
|
| 116 |
-
if feature
|
| 117 |
-
|
| 118 |
-
|
| 119 |
-
def get_selected_features(self):
|
| 120 |
-
"""Retorna lista de features selecionadas"""
|
| 121 |
-
return [feature for feature, selected in self.feature_states.items() if selected]
|
| 122 |
|
| 123 |
def get_dataset_stats(self):
|
| 124 |
"""Retorna estatísticas do dataset para display seguro"""
|
|
@@ -135,14 +113,12 @@ class HousePricePredictor:
|
|
| 135 |
'preco_medio': 0
|
| 136 |
}
|
| 137 |
|
| 138 |
-
def train_model(self):
|
| 139 |
"""Treina o modelo com as features selecionadas"""
|
| 140 |
try:
|
| 141 |
if self.df is None:
|
| 142 |
return False, "❌ Dados não carregados"
|
| 143 |
|
| 144 |
-
selected_features = self.get_selected_features()
|
| 145 |
-
|
| 146 |
if not selected_features:
|
| 147 |
return False, "❌ Selecione pelo menos uma feature"
|
| 148 |
|
|
@@ -234,21 +210,21 @@ print("🚀 Iniciando aplicação...")
|
|
| 234 |
initial_message = predictor.load_data()
|
| 235 |
initial_features = predictor.get_numeric_features()
|
| 236 |
dataset_stats = predictor.get_dataset_stats()
|
|
|
|
| 237 |
print(f"📊 Features disponíveis: {initial_features}")
|
| 238 |
|
| 239 |
# Funções para a interface Gradio
|
| 240 |
-
def create_feature_checkboxes():
|
| 241 |
-
"""Cria os checkboxes de features
|
| 242 |
features = predictor.get_numeric_features()
|
| 243 |
checkboxes = []
|
| 244 |
|
| 245 |
if features and predictor.df is not None:
|
| 246 |
correlations = predictor.df.corr()['price'].abs().sort_values(ascending=False)
|
| 247 |
-
feature_states = predictor.get_feature_states()
|
| 248 |
|
| 249 |
for feature in features:
|
| 250 |
corr_value = correlations.get(feature, 0)
|
| 251 |
-
is_selected =
|
| 252 |
|
| 253 |
checkboxes.append(
|
| 254 |
gr.Checkbox(
|
|
@@ -260,79 +236,67 @@ def create_feature_checkboxes():
|
|
| 260 |
|
| 261 |
return checkboxes
|
| 262 |
|
| 263 |
-
def
|
| 264 |
-
"""Atualiza
|
| 265 |
-
features = predictor.get_numeric_features()
|
| 266 |
-
feature_updates = {}
|
| 267 |
-
|
| 268 |
-
for i, is_checked in enumerate(checkbox_values):
|
| 269 |
-
if i < len(features):
|
| 270 |
-
feature_updates[features[i]] = is_checked
|
| 271 |
-
|
| 272 |
-
predictor.update_feature_states(feature_updates)
|
| 273 |
-
|
| 274 |
-
# Retorna o texto com as features selecionadas
|
| 275 |
-
selected_features = predictor.get_selected_features()
|
| 276 |
if selected_features:
|
| 277 |
features_text = "**Features selecionadas:**\n" + "\n".join([f"• {feat}" for feat in selected_features])
|
| 278 |
features_text += f"\n\n**Total:** {len(selected_features)} features"
|
|
|
|
| 279 |
else:
|
| 280 |
-
|
| 281 |
-
|
| 282 |
-
return features_text
|
| 283 |
|
| 284 |
-
def
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 285 |
"""Seleciona todas as features"""
|
| 286 |
features = predictor.get_numeric_features()
|
| 287 |
-
|
| 288 |
-
|
| 289 |
-
|
| 290 |
-
# Recriar checkboxes
|
| 291 |
-
checkboxes = create_feature_checkboxes()
|
| 292 |
-
features_text = "**Todas as features selecionadas**\n" + "\n".join([f"• {feat}" for feat in features])
|
| 293 |
-
features_text += f"\n\n**Total:** {len(features)} features"
|
| 294 |
-
|
| 295 |
-
return checkboxes, features_text
|
| 296 |
|
| 297 |
-
def deselect_all_features():
|
| 298 |
"""Desseleciona todas as features"""
|
| 299 |
-
|
| 300 |
-
for
|
| 301 |
-
|
| 302 |
-
|
| 303 |
-
# Recriar checkboxes
|
| 304 |
-
checkboxes = create_feature_checkboxes()
|
| 305 |
-
return checkboxes, "❌ Nenhuma feature selecionada"
|
| 306 |
|
| 307 |
-
def select_top_features():
|
| 308 |
"""Seleciona apenas as top 6 features por correlação"""
|
|
|
|
| 309 |
features = predictor.get_numeric_features()
|
| 310 |
-
if predictor.df is not None:
|
| 311 |
-
correlations = predictor.df.corr()['price'].abs().sort_values(ascending=False)
|
| 312 |
-
top_features = []
|
| 313 |
-
for feature in correlations.index:
|
| 314 |
-
if feature != 'price' and len(top_features) < 6:
|
| 315 |
-
top_features.append(feature)
|
| 316 |
-
|
| 317 |
-
# Resetar todos para False
|
| 318 |
-
for feature in features:
|
| 319 |
-
predictor.feature_states[feature] = False
|
| 320 |
-
|
| 321 |
-
# Selecionar apenas as top features
|
| 322 |
-
for feature in top_features:
|
| 323 |
-
if feature in predictor.feature_states:
|
| 324 |
-
predictor.feature_states[feature] = True
|
| 325 |
|
| 326 |
-
#
|
| 327 |
-
|
| 328 |
-
|
| 329 |
-
|
|
|
|
| 330 |
|
| 331 |
-
return
|
| 332 |
|
| 333 |
-
def train_model_action():
|
| 334 |
"""Treina o modelo com features selecionadas"""
|
| 335 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 336 |
|
| 337 |
if success:
|
| 338 |
metrics_text = f"""
|
|
@@ -355,6 +319,8 @@ def train_model_action():
|
|
| 355 |
else:
|
| 356 |
return result, None, gr.update(visible=False)
|
| 357 |
|
|
|
|
|
|
|
| 358 |
def create_correlation_plot():
|
| 359 |
"""Cria gráfico de correlação"""
|
| 360 |
if predictor.df is None:
|
|
@@ -567,24 +533,12 @@ def get_dataset_info():
|
|
| 567 |
- **Preço Médio**: ${stats['preco_medio']:,.2f}
|
| 568 |
"""
|
| 569 |
|
| 570 |
-
|
| 571 |
-
"""Retorna a seleção atual de features"""
|
| 572 |
-
selected = predictor.get_selected_features()
|
| 573 |
-
if selected:
|
| 574 |
-
return f"**Features selecionadas para treinamento:**\n" + "\n".join([f"• {feat}" for feat in selected]) + f"\n\n**Total:** {len(selected)} features"
|
| 575 |
-
else:
|
| 576 |
-
return "❌ Nenhuma feature selecionada. Volte para a aba '1. Selecionar Features'."
|
| 577 |
-
|
| 578 |
-
# Interface Gradio
|
| 579 |
with gr.Blocks(title="🏠 Análise e Previsão - King County Dataset Real") as demo:
|
| 580 |
gr.Markdown(
|
| 581 |
"""
|
| 582 |
# 🏠 Análise e Previsão de Preços de Imóveis
|
| 583 |
## 📊 Dataset Real - King County, Washington
|
| 584 |
-
|
| 585 |
-
### ℹ️ Sobre os Dados:
|
| 586 |
-
Este aplicativo utiliza o **dataset real** `kc_house_data.csv` do mercado imobiliário de King County.
|
| 587 |
-
Dados reais de vendas de imóveis com diversas características.
|
| 588 |
"""
|
| 589 |
)
|
| 590 |
|
|
@@ -592,94 +546,109 @@ with gr.Blocks(title="🏠 Análise e Previsão - King County Dataset Real") as
|
|
| 592 |
initial_status = gr.Markdown(f"**Status:** {initial_message}")
|
| 593 |
dataset_info = gr.Markdown(get_dataset_info())
|
| 594 |
|
|
|
|
|
|
|
|
|
|
| 595 |
with gr.Tab("🤖 1. Selecionar Features"):
|
| 596 |
gr.Markdown("### Selecione as Features para o Modelo")
|
| 597 |
|
| 598 |
-
gr.Markdown("""
|
| 599 |
-
**🎯 Como escolher:**
|
| 600 |
-
- **Features com alta correlação** (valores próximos de 1 ou -1) são melhores preditoras
|
| 601 |
-
- **Selecione múltiplas features** - quanto mais relevantes, melhor o modelo
|
| 602 |
-
- **Evite features muito correlacionadas** entre si
|
| 603 |
-
""")
|
| 604 |
-
|
| 605 |
with gr.Row():
|
| 606 |
with gr.Column(scale=2):
|
| 607 |
# Botões de seleção em massa
|
| 608 |
with gr.Row():
|
| 609 |
-
select_all_btn = gr.Button("✅ Selecionar Todas", variant="secondary"
|
| 610 |
-
deselect_all_btn = gr.Button("❌ Limpar Seleção", variant="secondary"
|
| 611 |
-
select_top_btn = gr.Button("🎯 Top 6 Features", variant="primary"
|
| 612 |
|
| 613 |
# Checkboxes das features
|
| 614 |
-
|
| 615 |
-
|
|
|
|
|
|
|
| 616 |
|
| 617 |
with gr.Column(scale=1):
|
| 618 |
gr.Markdown("### 📋 Features Selecionadas")
|
| 619 |
-
selected_features_display = gr.Markdown(
|
| 620 |
-
|
| 621 |
-
|
| 622 |
-
|
| 623 |
-
|
| 624 |
-
|
| 625 |
-
|
| 626 |
-
|
| 627 |
-
|
| 628 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 629 |
checkbox.change(
|
| 630 |
-
|
| 631 |
inputs=feature_checkboxes,
|
| 632 |
-
outputs=[selected_features_display]
|
| 633 |
)
|
| 634 |
|
| 635 |
# Botões de seleção em massa
|
| 636 |
select_all_btn.click(
|
| 637 |
-
select_all_features,
|
| 638 |
-
outputs=[
|
| 639 |
)
|
| 640 |
|
| 641 |
deselect_all_btn.click(
|
| 642 |
-
deselect_all_features,
|
| 643 |
-
outputs=[
|
| 644 |
)
|
| 645 |
|
| 646 |
select_top_btn.click(
|
| 647 |
-
select_top_features,
|
| 648 |
-
outputs=[
|
| 649 |
)
|
| 650 |
-
|
| 651 |
-
with gr.Tab("
|
| 652 |
-
gr.Markdown("###
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 653 |
|
| 654 |
with gr.Row():
|
| 655 |
with gr.Column():
|
| 656 |
-
gr.Markdown("#### 📈 Distribuição de Preços
|
| 657 |
-
price_plot_btn = gr.Button("🎨 Gerar Gráfico
|
| 658 |
price_plot = gr.Plot()
|
| 659 |
|
| 660 |
with gr.Column():
|
| 661 |
-
gr.Markdown("#### 🔗 Correlações
|
| 662 |
-
correlation_btn = gr.Button("🔄 Gerar Matriz
|
| 663 |
correlation_plot = gr.Plot()
|
| 664 |
|
| 665 |
-
gr.Markdown("
|
| 666 |
-
gr.Markdown("#### 🔍 Análise Detalhada por Feature")
|
| 667 |
|
| 668 |
with gr.Row():
|
| 669 |
with gr.Column():
|
| 670 |
feature_selector = gr.Dropdown(
|
| 671 |
-
label="Selecione uma
|
| 672 |
choices=initial_features,
|
| 673 |
value=initial_features[0] if initial_features else None
|
| 674 |
)
|
| 675 |
feature_stats = gr.Markdown()
|
| 676 |
|
| 677 |
with gr.Column():
|
| 678 |
-
feature_analysis_btn = gr.Button("📈 Analisar
|
| 679 |
|
| 680 |
with gr.Row():
|
| 681 |
-
feature_dist_plot = gr.Plot(
|
| 682 |
-
feature_price_plot = gr.Plot(
|
| 683 |
|
| 684 |
# Eventos
|
| 685 |
price_plot_btn.click(create_price_distribution_plot, outputs=[price_plot])
|
|
@@ -690,49 +659,26 @@ with gr.Blocks(title="🏠 Análise e Previsão - King County Dataset Real") as
|
|
| 690 |
outputs=[feature_dist_plot, feature_price_plot]
|
| 691 |
)
|
| 692 |
|
| 693 |
-
# Inicializar estatísticas
|
| 694 |
if initial_features:
|
| 695 |
feature_stats.value = get_feature_stats(initial_features[0])
|
| 696 |
|
| 697 |
-
# Atualizar estatísticas quando feature mudar
|
| 698 |
feature_selector.change(
|
| 699 |
get_feature_stats,
|
| 700 |
inputs=[feature_selector],
|
| 701 |
outputs=[feature_stats]
|
| 702 |
)
|
| 703 |
-
|
| 704 |
-
with gr.Tab("🎯 3. Treinar Modelo"):
|
| 705 |
-
gr.Markdown("### Treine o Modelo com as Features Selecionadas")
|
| 706 |
-
|
| 707 |
-
gr.Markdown("""
|
| 708 |
-
**📋 Features que serão usadas no modelo:**
|
| 709 |
-
(Selecione na aba "1. Selecionar Features")
|
| 710 |
-
""")
|
| 711 |
-
|
| 712 |
-
current_selection_display = gr.Markdown(get_current_selection())
|
| 713 |
-
|
| 714 |
-
train_output = gr.Markdown("Clique em 'Treinar Modelo' para iniciar o treinamento")
|
| 715 |
-
metrics_display = gr.JSON(label="Métricas Detalhadas", visible=False)
|
| 716 |
-
|
| 717 |
-
train_btn.click(
|
| 718 |
-
lambda: [get_current_selection(), train_model_action()],
|
| 719 |
-
outputs=[current_selection_display, train_output, metrics_display, metrics_display]
|
| 720 |
-
)
|
| 721 |
-
|
| 722 |
with gr.Tab("💰 4. Fazer Previsão"):
|
| 723 |
-
gr.Markdown("### Faça Previsões
|
| 724 |
|
| 725 |
prediction_inputs = gr.Column()
|
| 726 |
-
predict_btn = gr.Button("🎯 Calcular Preço
|
| 727 |
|
| 728 |
with gr.Row():
|
| 729 |
-
prediction_output = gr.Markdown("Treine o modelo primeiro
|
| 730 |
-
price_result = gr.Number(
|
| 731 |
-
label="💵 Preço Previsto",
|
| 732 |
-
visible=False
|
| 733 |
-
)
|
| 734 |
|
| 735 |
-
# Atualizar inputs quando modelo for treinado
|
| 736 |
metrics_display.change(
|
| 737 |
create_prediction_inputs,
|
| 738 |
inputs=[metrics_display],
|
|
@@ -747,46 +693,6 @@ with gr.Blocks(title="🏠 Análise e Previsão - King County Dataset Real") as
|
|
| 747 |
lambda: gr.update(visible=True),
|
| 748 |
outputs=[price_result]
|
| 749 |
)
|
| 750 |
-
|
| 751 |
-
with gr.Tab("📚 5. Explicações"):
|
| 752 |
-
gr.Markdown(
|
| 753 |
-
"""
|
| 754 |
-
## 📊 Guia do Dataset Real King County
|
| 755 |
-
|
| 756 |
-
### 🏠 Sobre os Dados Reais
|
| 757 |
-
**King County** inclui Seattle e áreas metropolitanas. O dataset contém:
|
| 758 |
-
- **Vendas reais** de imóveis
|
| 759 |
-
- **Período**: Maio 2014 - Maio 2015
|
| 760 |
-
- **Características**: 21 colunas incluindo localização, tamanho, qualidade
|
| 761 |
-
- **Preços**: Variam de dezenas de milhares a milhões de dólares
|
| 762 |
-
|
| 763 |
-
### 🎯 Como Selecionar Features:
|
| 764 |
-
1. **Selecione múltiplas features** - Quanto mais características relevantes, melhor
|
| 765 |
-
2. **Priorize alta correlação** - Features com corr > 0.3 são boas preditoras
|
| 766 |
-
3. **Use botões de seleção em massa** - "Selecionar Todas", "Top 6 Features"
|
| 767 |
-
4. **Evite multicolinearidade** - Não selecione features muito correlacionadas entre si
|
| 768 |
-
|
| 769 |
-
### 📈 Features Mais Importantes:
|
| 770 |
-
- **sqft_living**: Área habitável (alta correlação)
|
| 771 |
-
- **grade**: Grau de qualidade da construção
|
| 772 |
-
- **lat/long**: Localização geográfica
|
| 773 |
-
- **waterfront**: Vista para água
|
| 774 |
-
- **view**: Qualidade da vista
|
| 775 |
-
- **sqft_above**: Área acima do solo
|
| 776 |
-
|
| 777 |
-
### 🤖 Sobre o Modelo:
|
| 778 |
-
- **Regressão Linear Múltipla** com transformação logarítmica
|
| 779 |
-
- **Treinamento**: 80% dos dados
|
| 780 |
-
- **Teste**: 20% dos dados
|
| 781 |
-
- **Avaliação**: R², RMSE, MAE
|
| 782 |
-
|
| 783 |
-
### 💡 Dicas:
|
| 784 |
-
- Comece com **Top 6 Features** para um modelo balanceado
|
| 785 |
-
- Experimente diferentes combinações de features
|
| 786 |
-
- Verifique as métricas para avaliar performance
|
| 787 |
-
- Use a aba de análise para entender cada feature
|
| 788 |
-
"""
|
| 789 |
-
)
|
| 790 |
|
| 791 |
if __name__ == "__main__":
|
| 792 |
demo.launch()
|
|
|
|
| 22 |
self.scaler = None
|
| 23 |
self.df = None
|
| 24 |
self.is_trained = False
|
| 25 |
+
self.selected_features = []
|
| 26 |
self._data_loaded = False
|
| 27 |
self.stats = {
|
| 28 |
'n_imoveis': 0,
|
| 29 |
'n_caracteristicas': 0,
|
| 30 |
'preco_medio': 0
|
| 31 |
}
|
|
|
|
| 32 |
|
| 33 |
def load_data(self):
|
| 34 |
"""Carrega dados do arquivo kc_house_data.csv"""
|
|
|
|
| 42 |
# Limpeza básica dos dados
|
| 43 |
self._clean_data()
|
| 44 |
|
|
|
|
|
|
|
|
|
|
| 45 |
# Atualizar estatísticas
|
| 46 |
self.stats = {
|
| 47 |
'n_imoveis': self.df.shape[0],
|
|
|
|
| 78 |
print(f"📊 Dados limpos: {self.df.shape[0]} imóveis")
|
| 79 |
print(f"💰 Preço médio: ${self.df['price'].mean():,.2f}")
|
| 80 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 81 |
def get_numeric_features(self):
|
| 82 |
"""Retorna lista de features numéricas (excluindo price)"""
|
| 83 |
if self.df is None:
|
|
|
|
| 87 |
numeric_features.remove('price')
|
| 88 |
return numeric_features
|
| 89 |
|
| 90 |
+
def get_top_features_by_correlation(self, n=6):
|
| 91 |
+
"""Retorna as top n features por correlação com price"""
|
| 92 |
+
if self.df is None:
|
| 93 |
+
return []
|
| 94 |
+
correlations = self.df.corr()['price'].abs().sort_values(ascending=False)
|
| 95 |
+
top_features = []
|
| 96 |
+
for feature in correlations.index:
|
| 97 |
+
if feature != 'price' and len(top_features) < n:
|
| 98 |
+
top_features.append(feature)
|
| 99 |
+
return top_features
|
|
|
|
|
|
|
|
|
|
| 100 |
|
| 101 |
def get_dataset_stats(self):
|
| 102 |
"""Retorna estatísticas do dataset para display seguro"""
|
|
|
|
| 113 |
'preco_medio': 0
|
| 114 |
}
|
| 115 |
|
| 116 |
+
def train_model(self, selected_features):
|
| 117 |
"""Treina o modelo com as features selecionadas"""
|
| 118 |
try:
|
| 119 |
if self.df is None:
|
| 120 |
return False, "❌ Dados não carregados"
|
| 121 |
|
|
|
|
|
|
|
| 122 |
if not selected_features:
|
| 123 |
return False, "❌ Selecione pelo menos uma feature"
|
| 124 |
|
|
|
|
| 210 |
initial_message = predictor.load_data()
|
| 211 |
initial_features = predictor.get_numeric_features()
|
| 212 |
dataset_stats = predictor.get_dataset_stats()
|
| 213 |
+
top_features = predictor.get_top_features_by_correlation(6)
|
| 214 |
print(f"📊 Features disponíveis: {initial_features}")
|
| 215 |
|
| 216 |
# Funções para a interface Gradio
|
| 217 |
+
def create_feature_checkboxes(selected_features=None):
|
| 218 |
+
"""Cria os checkboxes de features"""
|
| 219 |
features = predictor.get_numeric_features()
|
| 220 |
checkboxes = []
|
| 221 |
|
| 222 |
if features and predictor.df is not None:
|
| 223 |
correlations = predictor.df.corr()['price'].abs().sort_values(ascending=False)
|
|
|
|
| 224 |
|
| 225 |
for feature in features:
|
| 226 |
corr_value = correlations.get(feature, 0)
|
| 227 |
+
is_selected = feature in (selected_features or [])
|
| 228 |
|
| 229 |
checkboxes.append(
|
| 230 |
gr.Checkbox(
|
|
|
|
| 236 |
|
| 237 |
return checkboxes
|
| 238 |
|
| 239 |
+
def update_selected_features_display(selected_features):
|
| 240 |
+
"""Atualiza o display das features selecionadas"""
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 241 |
if selected_features:
|
| 242 |
features_text = "**Features selecionadas:**\n" + "\n".join([f"• {feat}" for feat in selected_features])
|
| 243 |
features_text += f"\n\n**Total:** {len(selected_features)} features"
|
| 244 |
+
return features_text, gr.update(visible=bool(selected_features))
|
| 245 |
else:
|
| 246 |
+
return "❌ Nenhuma feature selecionada", gr.update(visible=False)
|
|
|
|
|
|
|
| 247 |
|
| 248 |
+
def get_selected_features_from_checkboxes(*checkbox_values):
|
| 249 |
+
"""Converte valores dos checkboxes para lista de features selecionadas"""
|
| 250 |
+
features = predictor.get_numeric_features()
|
| 251 |
+
selected = []
|
| 252 |
+
for i, is_checked in enumerate(checkbox_values):
|
| 253 |
+
if is_checked and i < len(features):
|
| 254 |
+
selected.append(features[i])
|
| 255 |
+
return selected
|
| 256 |
+
|
| 257 |
+
def select_all_features(feature_checkboxes):
|
| 258 |
"""Seleciona todas as features"""
|
| 259 |
features = predictor.get_numeric_features()
|
| 260 |
+
# Atualizar todos os checkboxes para True
|
| 261 |
+
updated_checkboxes = [gr.Checkbox(value=True) for _ in feature_checkboxes]
|
| 262 |
+
return updated_checkboxes, *update_selected_features_display(features)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 263 |
|
| 264 |
+
def deselect_all_features(feature_checkboxes):
|
| 265 |
"""Desseleciona todas as features"""
|
| 266 |
+
# Atualizar todos os checkboxes para False
|
| 267 |
+
updated_checkboxes = [gr.Checkbox(value=False) for _ in feature_checkboxes]
|
| 268 |
+
return updated_checkboxes, *update_selected_features_display([])
|
|
|
|
|
|
|
|
|
|
|
|
|
| 269 |
|
| 270 |
+
def select_top_features(feature_checkboxes):
|
| 271 |
"""Seleciona apenas as top 6 features por correlação"""
|
| 272 |
+
top_features = predictor.get_top_features_by_correlation(6)
|
| 273 |
features = predictor.get_numeric_features()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 274 |
|
| 275 |
+
# Atualizar checkboxes baseado nas top features
|
| 276 |
+
updated_checkboxes = []
|
| 277 |
+
for i, feature in enumerate(features):
|
| 278 |
+
is_selected = feature in top_features
|
| 279 |
+
updated_checkboxes.append(gr.Checkbox(value=is_selected))
|
| 280 |
|
| 281 |
+
return updated_checkboxes, *update_selected_features_display(top_features)
|
| 282 |
|
| 283 |
+
def train_model_action(selected_features_text):
|
| 284 |
"""Treina o modelo com features selecionadas"""
|
| 285 |
+
# Extrair features selecionadas do texto de display
|
| 286 |
+
if "❌" in selected_features_text:
|
| 287 |
+
return "❌ Nenhuma feature selecionada. Selecione features na aba anterior.", None, gr.update(visible=False)
|
| 288 |
+
|
| 289 |
+
# Obter features selecionadas dos checkboxes atuais
|
| 290 |
+
features = predictor.get_numeric_features()
|
| 291 |
+
selected_features = []
|
| 292 |
+
for feature in features:
|
| 293 |
+
if f"• {feature}" in selected_features_text:
|
| 294 |
+
selected_features.append(feature)
|
| 295 |
+
|
| 296 |
+
if not selected_features:
|
| 297 |
+
return "❌ Nenhuma feature selecionada. Selecione features na aba anterior.", None, gr.update(visible=False)
|
| 298 |
+
|
| 299 |
+
success, result = predictor.train_model(selected_features)
|
| 300 |
|
| 301 |
if success:
|
| 302 |
metrics_text = f"""
|
|
|
|
| 319 |
else:
|
| 320 |
return result, None, gr.update(visible=False)
|
| 321 |
|
| 322 |
+
# ... (mantenha as outras funções como create_correlation_plot, create_feature_analysis_plot, etc. inalteradas)
|
| 323 |
+
|
| 324 |
def create_correlation_plot():
|
| 325 |
"""Cria gráfico de correlação"""
|
| 326 |
if predictor.df is None:
|
|
|
|
| 533 |
- **Preço Médio**: ${stats['preco_medio']:,.2f}
|
| 534 |
"""
|
| 535 |
|
| 536 |
+
# Interface Gradio simplificada
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 537 |
with gr.Blocks(title="🏠 Análise e Previsão - King County Dataset Real") as demo:
|
| 538 |
gr.Markdown(
|
| 539 |
"""
|
| 540 |
# 🏠 Análise e Previsão de Preços de Imóveis
|
| 541 |
## 📊 Dataset Real - King County, Washington
|
|
|
|
|
|
|
|
|
|
|
|
|
| 542 |
"""
|
| 543 |
)
|
| 544 |
|
|
|
|
| 546 |
initial_status = gr.Markdown(f"**Status:** {initial_message}")
|
| 547 |
dataset_info = gr.Markdown(get_dataset_info())
|
| 548 |
|
| 549 |
+
# Estado para armazenar features selecionadas
|
| 550 |
+
selected_features_state = gr.State(value=[])
|
| 551 |
+
|
| 552 |
with gr.Tab("🤖 1. Selecionar Features"):
|
| 553 |
gr.Markdown("### Selecione as Features para o Modelo")
|
| 554 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 555 |
with gr.Row():
|
| 556 |
with gr.Column(scale=2):
|
| 557 |
# Botões de seleção em massa
|
| 558 |
with gr.Row():
|
| 559 |
+
select_all_btn = gr.Button("✅ Selecionar Todas", variant="secondary")
|
| 560 |
+
deselect_all_btn = gr.Button("❌ Limpar Seleção", variant="secondary")
|
| 561 |
+
select_top_btn = gr.Button("🎯 Top 6 Features", variant="primary")
|
| 562 |
|
| 563 |
# Checkboxes das features
|
| 564 |
+
initial_checkboxes = create_feature_checkboxes(top_features)
|
| 565 |
+
feature_checkboxes = []
|
| 566 |
+
for checkbox in initial_checkboxes:
|
| 567 |
+
feature_checkboxes.append(checkbox)
|
| 568 |
|
| 569 |
with gr.Column(scale=1):
|
| 570 |
gr.Markdown("### 📋 Features Selecionadas")
|
| 571 |
+
selected_features_display = gr.Markdown()
|
| 572 |
+
train_btn = gr.Button("🚀 Treinar Modelo", variant="primary", size="lg", visible=False)
|
| 573 |
+
|
| 574 |
+
# Inicializar display
|
| 575 |
+
selected_features_display.value = update_selected_features_display(top_features)[0]
|
| 576 |
+
train_btn.visible = True
|
| 577 |
+
|
| 578 |
+
# Função para atualizar quando checkboxes mudam
|
| 579 |
+
def on_checkbox_change(*checkbox_values):
|
| 580 |
+
selected = get_selected_features_from_checkboxes(*checkbox_values)
|
| 581 |
+
selected_features_state.value = selected
|
| 582 |
+
display_text, btn_visible = update_selected_features_display(selected)
|
| 583 |
+
return display_text, gr.update(visible=btn_visible)
|
| 584 |
+
|
| 585 |
+
# Conectar eventos dos checkboxes
|
| 586 |
+
for i, checkbox in enumerate(feature_checkboxes):
|
| 587 |
checkbox.change(
|
| 588 |
+
on_checkbox_change,
|
| 589 |
inputs=feature_checkboxes,
|
| 590 |
+
outputs=[selected_features_display, train_btn]
|
| 591 |
)
|
| 592 |
|
| 593 |
# Botões de seleção em massa
|
| 594 |
select_all_btn.click(
|
| 595 |
+
lambda: select_all_features(feature_checkboxes),
|
| 596 |
+
outputs=feature_checkboxes + [selected_features_display, train_btn]
|
| 597 |
)
|
| 598 |
|
| 599 |
deselect_all_btn.click(
|
| 600 |
+
lambda: deselect_all_features(feature_checkboxes),
|
| 601 |
+
outputs=feature_checkboxes + [selected_features_display, train_btn]
|
| 602 |
)
|
| 603 |
|
| 604 |
select_top_btn.click(
|
| 605 |
+
lambda: select_top_features(feature_checkboxes),
|
| 606 |
+
outputs=feature_checkboxes + [selected_features_display, train_btn]
|
| 607 |
)
|
| 608 |
+
|
| 609 |
+
with gr.Tab("🎯 2. Treinar Modelo"):
|
| 610 |
+
gr.Markdown("### Treine o Modelo")
|
| 611 |
+
|
| 612 |
+
train_output = gr.Markdown("Selecione features na aba anterior e clique em 'Treinar Modelo'")
|
| 613 |
+
metrics_display = gr.JSON(label="Métricas Detalhadas", visible=False)
|
| 614 |
+
|
| 615 |
+
train_btn.click(
|
| 616 |
+
lambda text: train_model_action(text),
|
| 617 |
+
inputs=[selected_features_display],
|
| 618 |
+
outputs=[train_output, metrics_display, metrics_display]
|
| 619 |
+
)
|
| 620 |
+
|
| 621 |
+
with gr.Tab("📊 3. Análise Exploratória"):
|
| 622 |
+
gr.Markdown("### Explore os Dados")
|
| 623 |
|
| 624 |
with gr.Row():
|
| 625 |
with gr.Column():
|
| 626 |
+
gr.Markdown("#### 📈 Distribuição de Preços")
|
| 627 |
+
price_plot_btn = gr.Button("🎨 Gerar Gráfico", variant="primary")
|
| 628 |
price_plot = gr.Plot()
|
| 629 |
|
| 630 |
with gr.Column():
|
| 631 |
+
gr.Markdown("#### 🔗 Correlações")
|
| 632 |
+
correlation_btn = gr.Button("🔄 Gerar Matriz", variant="primary")
|
| 633 |
correlation_plot = gr.Plot()
|
| 634 |
|
| 635 |
+
gr.Markdown("#### 🔍 Análise por Feature")
|
|
|
|
| 636 |
|
| 637 |
with gr.Row():
|
| 638 |
with gr.Column():
|
| 639 |
feature_selector = gr.Dropdown(
|
| 640 |
+
label="Selecione uma feature",
|
| 641 |
choices=initial_features,
|
| 642 |
value=initial_features[0] if initial_features else None
|
| 643 |
)
|
| 644 |
feature_stats = gr.Markdown()
|
| 645 |
|
| 646 |
with gr.Column():
|
| 647 |
+
feature_analysis_btn = gr.Button("📈 Analisar", variant="primary")
|
| 648 |
|
| 649 |
with gr.Row():
|
| 650 |
+
feature_dist_plot = gr.Plot()
|
| 651 |
+
feature_price_plot = gr.Plot()
|
| 652 |
|
| 653 |
# Eventos
|
| 654 |
price_plot_btn.click(create_price_distribution_plot, outputs=[price_plot])
|
|
|
|
| 659 |
outputs=[feature_dist_plot, feature_price_plot]
|
| 660 |
)
|
| 661 |
|
| 662 |
+
# Inicializar estatísticas
|
| 663 |
if initial_features:
|
| 664 |
feature_stats.value = get_feature_stats(initial_features[0])
|
| 665 |
|
|
|
|
| 666 |
feature_selector.change(
|
| 667 |
get_feature_stats,
|
| 668 |
inputs=[feature_selector],
|
| 669 |
outputs=[feature_stats]
|
| 670 |
)
|
| 671 |
+
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 672 |
with gr.Tab("💰 4. Fazer Previsão"):
|
| 673 |
+
gr.Markdown("### Faça Previsões")
|
| 674 |
|
| 675 |
prediction_inputs = gr.Column()
|
| 676 |
+
predict_btn = gr.Button("🎯 Calcular Preço", variant="primary")
|
| 677 |
|
| 678 |
with gr.Row():
|
| 679 |
+
prediction_output = gr.Markdown("Treine o modelo primeiro")
|
| 680 |
+
price_result = gr.Number(label="💵 Preço Previsto", visible=False)
|
|
|
|
|
|
|
|
|
|
| 681 |
|
|
|
|
| 682 |
metrics_display.change(
|
| 683 |
create_prediction_inputs,
|
| 684 |
inputs=[metrics_display],
|
|
|
|
| 693 |
lambda: gr.update(visible=True),
|
| 694 |
outputs=[price_result]
|
| 695 |
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 696 |
|
| 697 |
if __name__ == "__main__":
|
| 698 |
demo.launch()
|