FernandezUNB commited on
Commit
242e930
·
verified ·
1 Parent(s): a49b452

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +71 -292
app.py CHANGED
@@ -250,7 +250,7 @@ def train_model_action(*checkbox_values):
250
  selected_features.append(features[i])
251
 
252
  if not selected_features:
253
- return "❌ Nenhuma feature selecionada. Selecione pelo menos uma feature.", None, gr.update(visible=False)
254
 
255
  success, result = predictor.train_model(selected_features)
256
 
@@ -271,149 +271,17 @@ def train_model_action(*checkbox_values):
271
  direction = "📈 Aumenta preço" if feature['Coeficiente'] > 0 else "📉 Diminui preço"
272
  metrics_text += f"\n{i+1}. **{feature['Feature']}**: {feature['Coeficiente']:.4f} ({direction})"
273
 
274
- return metrics_text, result, gr.update(visible=True)
275
  else:
276
- return result, None, gr.update(visible=False)
277
 
278
- def create_correlation_plot():
279
- """Cria gráfico de correlação"""
280
- if predictor.df is None:
281
- return None
282
-
283
- try:
284
- # Selecionar features mais importantes
285
- numeric_cols = predictor.df.select_dtypes(include=[np.number]).columns.tolist()
286
- if len(numeric_cols) > 8:
287
- correlations = predictor.df.corr()['price'].abs().sort_values(ascending=False)
288
- top_features = correlations.index[:8].tolist()
289
- else:
290
- top_features = numeric_cols
291
-
292
- corr_matrix = predictor.df[top_features].corr()
293
-
294
- fig, ax = plt.subplots(figsize=(12, 10))
295
- sns.heatmap(corr_matrix, annot=True, fmt='.2f', cmap='RdYlBu', center=0,
296
- square=True, linewidths=0.5, cbar_kws={"shrink": 0.8}, ax=ax)
297
- ax.set_title('🔗 Matriz de Correlação - Dataset Real King County', fontsize=14, fontweight='bold')
298
- plt.tight_layout()
299
- return fig
300
- except Exception as e:
301
- print(f"Erro no gráfico de correlação: {e}")
302
- return None
303
-
304
- def create_feature_analysis_plot(selected_feature):
305
- """Cria gráfico de análise para uma feature específica"""
306
- if predictor.df is None or not selected_feature:
307
- return None, None
308
-
309
- try:
310
- # Gráfico 1: Distribuição
311
- fig1, ax1 = plt.subplots(figsize=(10, 5))
312
- ax1.hist(predictor.df[selected_feature], bins=30, edgecolor='black', alpha=0.7, color='skyblue')
313
- ax1.axvline(predictor.df[selected_feature].mean(), color='red', linestyle='--', linewidth=2,
314
- label=f'Média: {predictor.df[selected_feature].mean():.2f}')
315
- ax1.set_xlabel(selected_feature)
316
- ax1.set_ylabel('Frequência')
317
- ax1.set_title(f'📊 Distribuição de {selected_feature}')
318
- ax1.legend()
319
- ax1.grid(True, alpha=0.3)
320
- plt.tight_layout()
321
-
322
- # Gráfico 2: Relação com preço
323
- fig2, ax2 = plt.subplots(figsize=(10, 5))
324
-
325
- if predictor.df[selected_feature].nunique() < 10:
326
- # Boxplot para variáveis categóricas
327
- data_to_plot = []
328
- categories = sorted(predictor.df[selected_feature].unique())
329
- for cat in categories:
330
- data_to_plot.append(predictor.df[predictor.df[selected_feature] == cat]['price'])
331
-
332
- ax2.boxplot(data_to_plot, labels=categories)
333
- else:
334
- # Scatter plot para variáveis contínuas
335
- ax2.scatter(predictor.df[selected_feature], predictor.df['price'], alpha=0.3, s=20, color='steelblue')
336
- # Linha de tendência
337
- z = np.polyfit(predictor.df[selected_feature], predictor.df['price'], 1)
338
- p = np.poly1d(z)
339
- x_range = np.linspace(predictor.df[selected_feature].min(), predictor.df[selected_feature].max(), 100)
340
- ax2.plot(x_range, p(x_range), "r--", linewidth=2, alpha=0.8, label='Tendência linear')
341
- ax2.legend()
342
-
343
- ax2.set_xlabel(selected_feature)
344
- ax2.set_ylabel('Preço ($)')
345
- correlation = predictor.df[selected_feature].corr(predictor.df['price'])
346
- ax2.set_title(f'💰 Preço vs {selected_feature} (Corr: {correlation:.3f})')
347
- ax2.grid(True, alpha=0.3)
348
-
349
- # Formatar eixo y para dólares
350
- ax2.yaxis.set_major_formatter(plt.FuncFormatter(lambda x, p: f'${x:,.0f}'))
351
-
352
- plt.tight_layout()
353
- return fig1, fig2
354
-
355
- except Exception as e:
356
- print(f"Erro nos gráficos de análise: {e}")
357
- return None, None
358
-
359
- def create_price_distribution_plot():
360
- """Cria gráfico da distribuição de preços"""
361
- if predictor.df is None:
362
- return None
363
-
364
- fig, ax = plt.subplots(figsize=(12, 6))
365
- ax.hist(predictor.df['price'], bins=50, edgecolor='black', alpha=0.7, color='steelblue')
366
- ax.axvline(predictor.df['price'].mean(), color='red', linestyle='--', linewidth=2,
367
- label=f'Média: ${predictor.df["price"].mean():,.0f}')
368
- ax.axvline(predictor.df['price'].median(), color='green', linestyle='--', linewidth=2,
369
- label=f'Mediana: ${predictor.df["price"].median():,.0f}')
370
- ax.set_xlabel('Preço ($)')
371
- ax.set_ylabel('Número de Imóveis')
372
- ax.set_title('🏠 Distribuição dos Preços - Dataset Real King County')
373
- ax.legend()
374
- ax.grid(True, alpha=0.3)
375
-
376
- # Formatar eixo x para dólares
377
- ax.xaxis.set_major_formatter(plt.FuncFormatter(lambda x, p: f'${x:,.0f}'))
378
-
379
- plt.tight_layout()
380
- return fig
381
-
382
- def get_feature_stats(feature):
383
- """Retorna estatísticas de uma feature"""
384
- if predictor.df is None or feature not in predictor.df.columns:
385
- return "Selecione uma feature para ver estatísticas"
386
-
387
- stats = predictor.df[feature].describe()
388
- correlation = predictor.df[feature].corr(predictor.df['price'])
389
-
390
- return f"""
391
- ## 📈 Estatísticas de **{feature}**
392
-
393
- **Valores:**
394
- - Média: {stats['mean']:.2f}
395
- - Mediana: {stats['50%']:.2f}
396
- - Desvio Padrão: {stats['std']:.2f}
397
- - Mínimo: {stats['min']:.2f}
398
- - Máximo: {stats['max']:.2f}
399
-
400
- **Distribuição:**
401
- - 25º Percentil: {stats['25%']:.2f}
402
- - 75º Percentil: {stats['75%']:.2f}
403
- - Valores Únicos: {predictor.df[feature].nunique()}
404
-
405
- **Relação com Preço:**
406
- - Correlação: {correlation:.3f}
407
- - Interpretação: {'Forte' if abs(correlation) > 0.5 else 'Moderada' if abs(correlation) > 0.3 else 'Fraca'} relação
408
- """
409
-
410
- def create_prediction_inputs(selected_features):
411
  """Cria inputs para previsão baseado nas features selecionadas"""
412
- if not selected_features:
413
  return []
414
 
415
  inputs = []
416
- for feature in selected_features:
417
  if feature in predictor.df.columns:
418
  min_val = float(predictor.df[feature].min())
419
  max_val = float(predictor.df[feature].max())
@@ -438,16 +306,19 @@ def create_prediction_inputs(selected_features):
438
 
439
  return inputs
440
 
441
- def predict_price_action(*feature_values, selected_features):
442
  """Faz previsão de preço"""
443
  if not predictor.is_trained:
444
  return "❌ Modelo não treinado. Treine o modelo primeiro.", None
445
 
446
  try:
447
  input_features = {}
448
- for i, feature in enumerate(selected_features):
449
- if i < len(feature_values):
450
- input_features[feature] = feature_values[i]
 
 
 
451
 
452
  pred_price, error = predictor.predict_price(input_features)
453
 
@@ -473,174 +344,82 @@ def predict_price_action(*feature_values, selected_features):
473
  except Exception as e:
474
  return f"❌ Erro na previsão: {str(e)}", None
475
 
476
- def get_dataset_info():
477
- """Retorna informações do dataset para display seguro"""
478
- stats = predictor.get_dataset_stats()
479
- return f"""
480
- **📊 Dataset Carregado:**
481
- - **Arquivo**: kc_house_data.csv
482
- - **Imóveis**: {stats['n_imoveis']:,}
483
- - **Características**: {stats['n_caracteristicas']}
484
- - **Preço Médio**: ${stats['preco_medio']:,.2f}
485
- """
486
-
487
- # Interface Gradio simplificada
488
- with gr.Blocks(title="🏠 Análise e Previsão - King County Dataset Real") as demo:
489
  gr.Markdown(
490
  """
491
- # 🏠 Análise e Previsão de Preços de Imóveis
492
- ## 📊 Dataset Real - King County, Washington
493
  """
494
  )
495
 
496
  # Status inicial
497
  initial_status = gr.Markdown(f"**Status:** {initial_message}")
498
- dataset_info = gr.Markdown(get_dataset_info())
499
 
500
- with gr.Tab("🤖 1. Treinar Modelo"):
501
- gr.Markdown("### Selecione as Features e Treine o Modelo")
502
-
503
- with gr.Row():
504
- with gr.Column(scale=2):
505
- gr.Markdown("#### 📋 Selecione as Features:")
506
-
507
- # Criar checkboxes
508
- feature_checkboxes = create_feature_checkboxes()
509
-
510
- with gr.Column(scale=1):
511
- gr.Markdown("#### 📊 Features Selecionadas:")
512
- selected_features_display = gr.Markdown()
513
- train_btn = gr.Button("🚀 Treinar Modelo", variant="primary", size="lg")
514
-
515
- # Atualizar display quando checkboxes mudam
516
- for checkbox in feature_checkboxes:
517
- checkbox.change(
518
- update_selected_features_display,
519
- inputs=feature_checkboxes,
520
- outputs=[selected_features_display, train_btn]
521
- )
522
-
523
- # Resultados do treinamento
524
- train_output = gr.Markdown()
525
- metrics_display = gr.JSON(label="Métricas Detalhadas", visible=False)
526
-
527
- train_btn.click(
528
- train_model_action,
529
- inputs=feature_checkboxes,
530
- outputs=[train_output, metrics_display, metrics_display]
531
- )
532
-
533
- with gr.Tab("💰 2. Fazer Previsão"):
534
- gr.Markdown("### Faça Previsões com o Modelo")
535
-
536
- gr.Markdown("#### 📋 Selecione as Features para Previsão:")
537
-
538
- # Checkboxes separadas para previsão
539
- prediction_feature_checkboxes = create_feature_checkboxes()
540
-
541
- # Display das features selecionadas para previsão
542
- prediction_selected_display = gr.Markdown()
543
-
544
- # Inputs dinâmicos para previsão
545
- prediction_inputs = gr.Column()
546
-
547
- # Botão de previsão
548
- predict_btn = gr.Button("🎯 Calcular Preço", variant="primary")
549
-
550
- # Resultado da previsão
551
- with gr.Row():
552
- prediction_output = gr.Markdown("Selecione as features e ajuste os valores")
553
- price_result = gr.Number(label="💵 Preço Previsto", visible=False)
554
-
555
- # Função para atualizar inputs quando features mudam
556
- def update_prediction_inputs(*checkbox_values):
557
- features = predictor.get_numeric_features()
558
- selected = []
559
-
560
- for i, is_checked in enumerate(checkbox_values):
561
- if is_checked and i < len(features):
562
- selected.append(features[i])
563
 
564
- # Atualizar display
565
- if selected:
566
- display_text = "**Features selecionadas para previsão:**\n" + "\n".join([f"• {feat}" for feat in selected])
567
- display_text += f"\n\n**Total:** {len(selected)} features"
568
- else:
569
- display_text = "❌ Nenhuma feature selecionada"
570
 
571
- # Criar inputs
572
- inputs = create_prediction_inputs(selected)
573
-
574
- return display_text, inputs
575
-
576
- # Conectar checkboxes de previsão
577
- for checkbox in prediction_feature_checkboxes:
578
- checkbox.change(
579
- update_prediction_inputs,
580
- inputs=prediction_feature_checkboxes,
581
- outputs=[prediction_selected_display, prediction_inputs]
582
- )
583
-
584
- # Fazer previsão
585
- predict_btn.click(
586
- lambda *vals: predict_price_action(*vals, selected_features=[f for i, f in enumerate(predictor.get_numeric_features()) if i < len(prediction_feature_checkboxes) and prediction_feature_checkboxes[i].value]),
587
- inputs=[prediction_inputs],
588
- outputs=[prediction_output, price_result]
589
- ).then(
590
- lambda: gr.update(visible=True),
591
- outputs=[price_result]
592
  )
593
 
594
- with gr.Tab("📊 3. Análise Exploratória"):
595
- gr.Markdown("### Explore os Dados")
 
 
 
 
 
596
 
597
  with gr.Row():
598
  with gr.Column():
599
- gr.Markdown("#### 📈 Distribuição de Preços")
600
- price_plot_btn = gr.Button("🎨 Gerar Gráfico", variant="primary")
601
- price_plot = gr.Plot()
602
 
603
  with gr.Column():
604
- gr.Markdown("#### 🔗 Correlações")
605
- correlation_btn = gr.Button("🔄 Gerar Matriz", variant="primary")
606
- correlation_plot = gr.Plot()
607
-
608
- gr.Markdown("#### 🔍 Análise por Feature")
609
-
610
- with gr.Row():
611
- with gr.Column():
612
- feature_selector = gr.Dropdown(
613
- label="Selecione uma feature",
614
- choices=initial_features,
615
- value=initial_features[0] if initial_features else None
616
  )
617
- feature_stats = gr.Markdown()
618
-
619
- with gr.Column():
620
- feature_analysis_btn = gr.Button("📈 Analisar", variant="primary")
621
-
622
- with gr.Row():
623
- feature_dist_plot = gr.Plot()
624
- feature_price_plot = gr.Plot()
625
-
626
- # Eventos
627
- price_plot_btn.click(create_price_distribution_plot, outputs=[price_plot])
628
- correlation_btn.click(create_correlation_plot, outputs=[correlation_plot])
629
- feature_analysis_btn.click(
630
- create_feature_analysis_plot,
631
- inputs=[feature_selector],
632
- outputs=[feature_dist_plot, feature_price_plot]
633
- )
634
-
635
- # Inicializar estatísticas
636
- if initial_features:
637
- feature_stats.value = get_feature_stats(initial_features[0])
638
-
639
- feature_selector.change(
640
- get_feature_stats,
641
- inputs=[feature_selector],
642
- outputs=[feature_stats]
643
- )
644
 
645
  if __name__ == "__main__":
646
  demo.launch()
 
250
  selected_features.append(features[i])
251
 
252
  if not selected_features:
253
+ return "❌ Nenhuma feature selecionada. Selecione pelo menos uma feature.", None, gr.update(visible=False), gr.update(visible=False)
254
 
255
  success, result = predictor.train_model(selected_features)
256
 
 
271
  direction = "📈 Aumenta preço" if feature['Coeficiente'] > 0 else "📉 Diminui preço"
272
  metrics_text += f"\n{i+1}. **{feature['Feature']}**: {feature['Coeficiente']:.4f} ({direction})"
273
 
274
+ return metrics_text, result, gr.update(visible=True), gr.update(visible=True)
275
  else:
276
+ return result, None, gr.update(visible=False), gr.update(visible=False)
277
 
278
+ def create_prediction_inputs(metrics_result):
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
279
  """Cria inputs para previsão baseado nas features selecionadas"""
280
+ if metrics_result is None or 'selected_features' not in metrics_result:
281
  return []
282
 
283
  inputs = []
284
+ for feature in metrics_result['selected_features']:
285
  if feature in predictor.df.columns:
286
  min_val = float(predictor.df[feature].min())
287
  max_val = float(predictor.df[feature].max())
 
306
 
307
  return inputs
308
 
309
+ def predict_price_action(*feature_values):
310
  """Faz previsão de preço"""
311
  if not predictor.is_trained:
312
  return "❌ Modelo não treinado. Treine o modelo primeiro.", None
313
 
314
  try:
315
  input_features = {}
316
+ if hasattr(predictor, 'selected_features') and predictor.selected_features:
317
+ for i, feature in enumerate(predictor.selected_features):
318
+ if i < len(feature_values):
319
+ input_features[feature] = feature_values[i]
320
+ else:
321
+ return "❌ Nenhuma feature selecionada", None
322
 
323
  pred_price, error = predictor.predict_price(input_features)
324
 
 
344
  except Exception as e:
345
  return f"❌ Erro na previsão: {str(e)}", None
346
 
347
+ # Interface Gradio simplificada com tudo em uma aba
348
+ with gr.Blocks(title="🏠 Cálculo de Preço - King County Dataset Real") as demo:
 
 
 
 
 
 
 
 
 
 
 
349
  gr.Markdown(
350
  """
351
+ # 🏠 Cálculo de Preços de Imóveis - King County
352
+ ## 📊 Selecione Features, Treine Modelo e Faça Previsões
353
  """
354
  )
355
 
356
  # Status inicial
357
  initial_status = gr.Markdown(f"**Status:** {initial_message}")
 
358
 
359
+ with gr.Row():
360
+ with gr.Column(scale=2):
361
+ gr.Markdown("### 📋 1. Selecione as Features para o Modelo")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
362
 
363
+ # Criar checkboxes
364
+ feature_checkboxes = create_feature_checkboxes()
 
 
 
 
365
 
366
+ with gr.Column(scale=1):
367
+ gr.Markdown("### 📊 Features Selecionadas:")
368
+ selected_features_display = gr.Markdown()
369
+ train_btn = gr.Button("🚀 Treinar Modelo", variant="primary", size="lg")
370
+
371
+ # Atualizar display quando checkboxes mudam
372
+ for checkbox in feature_checkboxes:
373
+ checkbox.change(
374
+ update_selected_features_display,
375
+ inputs=feature_checkboxes,
376
+ outputs=[selected_features_display, train_btn]
 
 
 
 
 
 
 
 
 
 
377
  )
378
 
379
+ # Resultados do treinamento
380
+ train_output = gr.Markdown()
381
+ metrics_display = gr.JSON(label="Métricas Detalhadas", visible=False)
382
+
383
+ # Seção de previsão (inicialmente oculta)
384
+ with gr.Column(visible=False) as prediction_section:
385
+ gr.Markdown("### 💰 2. Faça Previsões de Preço")
386
 
387
  with gr.Row():
388
  with gr.Column():
389
+ gr.Markdown("#### 🎯 Configure as Características do Imóvel")
390
+ prediction_inputs = gr.Column()
391
+ predict_btn = gr.Button("🎯 Calcular Preço", variant="primary", size="lg")
392
 
393
  with gr.Column():
394
+ gr.Markdown("#### 📊 Resultado da Previsão")
395
+ prediction_output = gr.Markdown("Preencha os valores e clique em 'Calcular Preço'")
396
+ price_result = gr.Number(
397
+ label="💵 Preço Previsto",
398
+ visible=False,
399
+ elem_classes="price-display"
 
 
 
 
 
 
400
  )
401
+
402
+ # Eventos
403
+ train_btn.click(
404
+ train_model_action,
405
+ inputs=feature_checkboxes,
406
+ outputs=[train_output, metrics_display, metrics_display, prediction_section]
407
+ )
408
+
409
+ metrics_display.change(
410
+ create_prediction_inputs,
411
+ inputs=[metrics_display],
412
+ outputs=[prediction_inputs]
413
+ )
414
+
415
+ predict_btn.click(
416
+ predict_price_action,
417
+ inputs=[prediction_inputs],
418
+ outputs=[prediction_output, price_result]
419
+ ).then(
420
+ lambda: gr.update(visible=True),
421
+ outputs=[price_result]
422
+ )
 
 
 
 
 
423
 
424
  if __name__ == "__main__":
425
  demo.launch()