import pandas as pd import numpy as np import joblib import seaborn as sns import matplotlib.pyplot as plt import xgboost as xgb import warnings import gradio as gr from reportlab.lib.pagesizes import A4 from reportlab.platypus import Spacer, Frame, PageTemplate, BaseDocTemplate, Paragraph from reportlab.lib.styles import getSampleStyleSheet inf_scaler_in = joblib.load("dados/apartamentos/input_scaler_ape_DEZ2024.save") inf_scaler_out = joblib.load("dados/apartamentos/output_scaler_ape_DEZ2024.save") inf_model_v1 = xgb.Booster(); inf_model_v1.load_model("dados/apartamentos/APARTAMENTO_2020_a_2025.model") inf_model_v2 = xgb.Booster(); inf_model_v2.load_model("dados/apartamentos/APARTAMENTOS_RESIDUAL_2026.model") # Função para gerar PDF def gerar_pdf(dados_imovel, valor_unit, valor_total): filename = 'relatorio.pdf' doc = BaseDocTemplate(filename, pagesize=A4) styles = getSampleStyleSheet() story = [ Paragraph("Relatório - Modelo Híbrido 2026", styles['Title']), Spacer(1, 12), Paragraph(f"Ano Base: {dados_imovel['ano_ref']}", styles['Normal']), Paragraph(f"Características: {dados_imovel['area']} m², Padrão {dados_imovel['padrao']}, Ano Const. {dados_imovel['ano_c']}", styles['Normal']), Paragraph(f"Localização (UTM): X={dados_imovel['x']}, Y={dados_imovel['y']}", styles['Normal']), Spacer(1, 20), Paragraph(f"Valor Unitário Calculado: R$ {valor_unit:,.2f}/m²", styles['Heading2']), Paragraph(f"Valor Total Estimado: R$ {valor_total:,.2f}", styles['Heading2']), ] frame = Frame(doc.leftMargin, doc.bottomMargin, doc.width, doc.height, id='normal') template = PageTemplate(id='base', frames=frame) doc.addPageTemplates([template]) doc.build(story) return filename # FUNÇÃO PRINCIPAL DA INTERFACE def avaliar_imovel(fon_str, x, y, rh, ano_c, atotal, andar, padrao, ano_ref): # 1. Mapeamento de Features (Feature Engineering em Tempo Real) is_oferta = 1 if fon_str == "Oferta" else 0 # Padrão (One Hot Encoding manual) # Se for A ou B, C/D/E permanecem 0 dummies_padrao = {'C': 0, 'D': 0, 'E': 0} if padrao in dummies_padrao: dummies_padrao[padrao] = 1 # Dummies de Ano V1 (2019-2024) anos_v1 = {f'ANO_{a}': (1 if str(ano_ref) == str(a) else 0) for a in range(2019, 2025)} # Dummy de Ano V2 (2025) is_2025 = 1 if str(ano_ref) == '2025' else 0 # Montagem do DataFrame Input (Single Row) # Atenção aos Logs! input_dict = { 'FON': [is_oferta], 'ANO_CONST': [float(ano_c)], 'ANDAR': [float(andar)], 'X': [float(x)], 'Y': [float(y)], 'ATOTAL': [np.log(float(atotal))], # Log Transform 'RH': [np.log(float(rh))], # Log Transform **dummies_padrao, **anos_v1 } # Lista de colunas na ordem correta do V1 cols_v1 = [ 'FON', 'ANO_CONST', 'ANDAR', 'X', 'Y', 'ATOTAL', 'RH', 'ANO_2019', 'ANO_2020', 'ANO_2021', 'ANO_2022', 'ANO_2023', 'ANO_2024', 'C', 'D', 'E' ] df_inferencia = pd.DataFrame(input_dict) # Garante ordem e preenche ausentes se houver for c in cols_v1: if c not in df_inferencia.columns: df_inferencia[c] = 0 df_inferencia = df_inferencia[cols_v1] try: # 2. Escalonamento V1 array_scaled = inf_scaler_in.transform(df_inferencia) # 3. Predição Baseline (V1) dmatrix_base = xgb.DMatrix(array_scaled, feature_names=cols_v1) pred_base = inf_model_v1.predict(dmatrix_base) # 4. Lógica de Decisão Temporal (Compatibilidade Reversa) # Se o ano for anterior a 2025, não usamos o modelo residual para manter consistência histórica. final_pred_scaled = pred_base if int(ano_ref) >= 2025: # Prepara entrada V2 (V1 Scaled + Coluna ANO_2025) # Adiciona a coluna 2025 (que é 1 neste caso) input_v2 = np.hstack([array_scaled, [[is_2025]]]) dmatrix_v2 = xgb.DMatrix(input_v2) dmatrix_v2.set_base_margin(pred_base) # Predição Híbrida final_pred_scaled = inf_model_v2.predict(dmatrix_v2) # 5. Pós-Processamento (Inverse Transform) # Inverte Scaler de Output pred_log = inf_scaler_out.inverse_transform(np.array(final_pred_scaled).reshape(-1,1)) # Inverte Log (Exp) val_unit_real = np.exp(pred_log).flatten()[0] # Cálculos Finais total_val = val_unit_real * float(atotal) # Gera PDF dados_contexto = { 'ano_ref': ano_ref, 'area': atotal, 'padrao': padrao, 'ano_c': ano_c, 'x': x, 'y': y } path_pdf = gerar_pdf(dados_contexto, val_unit_real, total_val) msg = f"Valor Unitário: R$ {val_unit_real:,.2f}/m²\nValor Total: R$ {total_val:,.2f}" return msg, path_pdf except Exception as e: return f"Erro Crítico: {str(e)}", None def load_inputs(): in_fon = gr.Radio(["Transação", "Oferta"], label="Fonte de Dados", value="Transação") in_x = gr.Number(label="Coord X (UTM)", value=281554) in_y = gr.Number(label="Coord Y (UTM)", value=1675418) in_rh = gr.Number(label="Região Homogênea", value=120) in_area = gr.Number(label="Área Total (m²)", value=60) in_andar = gr.Number(label="Andar", value=4) in_ano_c = gr.Number(label="Ano Construção", value=2020) in_padrao = gr.Dropdown(["C", "D", "E"], label="Padrão", value="C") in_ano_ref = gr.Dropdown([str(i) for i in range(2019, 2026)], label="Ano Base", value="2025") return [in_fon, in_x, in_y, in_rh, in_ano_c, in_area, in_andar, in_padrao, in_ano_ref] title = 'Apartamentos - XGBoost Regressor - 2026' description = f""" #
Modelo para Apartamentos - XGBoost Regressor - 2026
Dados referentes aos anos 2019 a 2025.