File size: 14,986 Bytes
a8ba5a3
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3522641
a8ba5a3
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3522641
 
 
 
a8ba5a3
 
 
 
 
 
 
3522641
 
 
a8ba5a3
 
 
 
 
 
 
 
 
3522641
 
a8ba5a3
3522641
 
a8ba5a3
3522641
a8ba5a3
 
 
 
 
 
 
 
7854b44
a8ba5a3
7854b44
a8ba5a3
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3522641
 
a8ba5a3
 
 
 
 
3522641
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
# 1. CARGA DE LIBRER脥AS ------------------------------------
import pandas as pd
import numpy as np
import seaborn as sns
import matplotlib.pyplot as plt
import plotly.express as px
import plotly.graph_objects as go
import statsmodels.formula.api as smf
import itertools
import io
import gradio as gr
import warnings
warnings.filterwarnings("ignore")


# 2. CARGA Y PREPARACI脫N DE LOS DATOS ---------------------
try:
    # Use the raw URL to the CSV file
    # Para Hugging Face Spaces, la ruta es local al repositorio
    seguros = pd.read_csv('Costo_Seguro.csv')
    # print("Dataset 'Costo_Seguro' cargado correctamente.")
except Exception as e:
    print(f"Fallo al cargar el archivo: {e}.")

modelo_RLM = None # Objeto para guardar el modelo de Regresi贸n Lineal M煤ltiple
modelo_RLM_log = None # Objeto para guardar el modelo de Regresi贸n Lineal M煤ltiple Logar铆tmico

# Modelo Regresi贸n Lineal M煤ltiple
formula = 'seguro ~ edad + imc + C(genero) + C(hijos) + C(fumador) + C(region)'
modelo_RLM = smf.ols(formula, data = seguros).fit()

# Modelo Regresi贸n Lineal M煤ltiple logar铆tmico
formula = 'np.log(seguro) ~ edad + imc + C(genero) + C(hijos) + C(fumador) + C(region)'
modelo_RLM_log = smf.ols(formula, data = seguros).fit()

# Mostrar la forma (filas, columnas) del dataset original
# print(f"\nForma del dataset original: {seguros.shape}")

# Mostrar las primeras filas deL dataset
# print("\nPrimetras 20 filas del dataset:")
# print(seguros.head(20))

### FUNCIONES PARA PRESENTAR DATOS / GR脕FICOS EN LA INTERFAZ GRADIO

def obtener_info_dataset():

    # Convertimos la tupla shape a Markdown
    filas, columnas = seguros.shape
    info_shape = f"**{filas}** filas, **{columnas}** columnas"

    # Convertimos el DataFrame.head() a Markdown
    info_head = seguros.head(10).to_markdown(index=False)

    # Convertimos el DataFrame.describe() a Markdown
    info_describe = seguros.describe().to_markdown()

    return info_shape, info_head, info_describe


def generar_graficos():

    plt1 = px.histogram(seguros, x='seguro', nbins=50,
                   title="Histograma del Costo del Seguro",
                   labels={'seguro': 'Costo del Seguro'})
    #plt1.show()

    plt2 = px.box(seguros, x='genero', y='seguro',
             title="Distribuci贸n del Costo del Seguro por G茅nero",
             labels={'genero': 'G茅nero del Asegurado', 'seguro': 'Costo del Seguro'})
    # plt2.show()

    plt3 = px.box(seguros, x='fumador', y='seguro',
             title="Distribuci贸n del Costo del Seguro por Condici贸n de Fumador",
             labels={'fumador': 'Condici贸n de Fumador del Asegurado', 'seguro': 'Costo del Seguro'})
    # plt3.show()

    plt4 = px.box(seguros, x='region', y='seguro',
             title="Distribuci贸n del Costo del Seguro por Regiones",
             labels={'region': 'Regi贸n de Origen del Asegurado', 'seguro': 'Costo del Seguro'})
    # plt4.show()

    plt5 = px.scatter(seguros, x='edad', y='seguro',
                 title="Edad vs. Costo del Seguro",
                 labels={'edad': 'Edad del Asegurado', 'seguro': 'Costo del Seguro'})
    # plt5.show()

    plt6 = px.scatter(seguros, x='imc', y='seguro',
                 title="IMC vs. Costo del Seguro",
                 labels={'imc': '脥ndice de Masa Corporal del Asegurado', 'seguro': 'Costo del Seguro'})
    # plt6.show()

    return plt1, plt2, plt3, plt4, plt5, plt6


def calcular_RLS():

    # Costo del Seguro vs. Edad
    RLS_1 = smf.ols('seguro ~ edad', data=seguros).fit()
    summary_text_1 = RLS_1.summary().as_text()
    data1_1 = f"```\n{summary_text_1}\n```" # Envuelve el texto en un bloque de c贸digo Markdown
    # M茅tricas
    r2  = RLS_1.rsquared
    adj = RLS_1.rsquared_adj
    rmse = np.sqrt(np.mean(RLS_1.resid**2))
    data1_2 = f"<b>M茅tricas:</b><br><b>R虏 = {r2:.4f}</b><br><b>R虏 Ajustado = {adj:.4f}</b><br><b>RMSE = {rmse:.2f}</b>"
    # Ecuaci贸n de la recta
    b0, b1 = RLS_1.params
    data1_3 = f"<b>Ecuaci贸n de la Recta:</b><br><b>Costo del Seguro = {b0:.2f} + {b1:.2f} * Edad</b>"
    # Gr谩fico de la recta de regresi贸n
    grid1 = np.linspace(seguros['edad'].min(), seguros['edad'].max(), 100)
    preds1 = RLS_1.predict(pd.DataFrame({'edad': grid1}))
    fig1 = go.Figure([
        go.Scatter(x=seguros['edad'], y=seguros['seguro'], mode='markers', name='Datos'),
        go.Scatter(x=grid1, y=preds1, mode='lines', name='Recta')
    ])
    fig1.update_layout(# title="Regresi贸n Lineal Simple: Costo del Seguro vs. Edad",
                  xaxis_title='Edad', yaxis_title='Costo del Seguro')
    # fig1.show()

    # Costo del Sefuro vs. IMC
    RLS_2 = smf.ols('seguro ~ imc', data=seguros).fit()
    summary_text_2 = RLS_1.summary().as_text()
    data2_1 = f"```\n{summary_text_2}\n```" # Envuelve el texto en un bloque de c贸digo Markdown
    # M茅tricas
    r2  = RLS_2.rsquared
    adj = RLS_2.rsquared_adj
    rmse = np.sqrt(np.mean(RLS_2.resid**2))
    data2_2 = f"<b>M茅tricas:</b><br><b>R虏 = {r2:.4f}</b><br><b>R虏 Ajustado = {adj:.4f}</b><br><b>RMSE = {rmse:.2f}</b>"
    # Ecuaci贸n de la recta
    b0, b1 = RLS_2.params
    data2_3 = f"<b>Ecuaci贸n de la Recta:</b><br><b>Costo del Seguro = {b0:.2f} + {b1:.2f} * IMC</b>"
    # Gr谩fico de la recta de regresi贸n
    grid2 = np.linspace(seguros['imc'].min(), seguros['imc'].max(), 100)
    preds2 = RLS_2.predict(pd.DataFrame({'imc': grid2}))
    fig2 = go.Figure([
        go.Scatter(x=seguros['imc'], y=seguros['seguro'], mode='markers', name='Datos'),
        go.Scatter(x=grid2, y=preds2, mode='lines', name='Recta')
    ])
    fig2.update_layout(# title="Regresi贸n Lineal Simple: Costo del Seguro vs. IMC",
                  xaxis_title='IMC', yaxis_title='Costo del Seguro')
    # fig2.show()

    return data1_1, data1_2, data1_3, data2_1, data2_2, data2_3, fig1, fig2


def calcular_RLM():
    summary_text = modelo_RLM.summary().as_text()
    data1 = f"```\n{summary_text}\n```"
    # M茅tricas
    r2  = modelo_RLM.rsquared
    adj = modelo_RLM.rsquared_adj
    rmse = np.sqrt(np.mean(modelo_RLM.resid**2))
    data2 = f"<b>M茅tricas:</b><br><b>R虏 = {r2:.4f}</b><br><b>R虏 Ajustado = {adj:.4f}</b><br><b>RMSE = {rmse:.2f}</b>"

    # Coeficientes de la Regresi贸n Lineal M煤ltiple
    coef_orig = modelo_RLM.params
    terms = [f"{coef_orig['Intercept']:.2f}"]
    for name, coef in coef_orig.items():
        if name == 'Intercept': continue
        terms.append(f"{coef:+.2f}*{name}")
    data3 = "Costo del Seguro = " + " ".join(terms)
    data3 = f"<b>{data3}</b>"

    return data1, data2, data3


def graficar_residuos():

    fig, axes = plt.subplots(1, 2, figsize=(12,5))
    # Gr谩fico de Residuos vs Costo del Seguro Ajustado
    axes[0].scatter(modelo_RLM.fittedvalues, modelo_RLM.resid, alpha=0.5)
    axes[0].axhline(0, color='red')
    axes[0].set(title='Residuos vs Costo del Seguro Ajustado', xlabel = 'Costo Ajustado', ylabel = 'Residuos')

    # Gr谩fico de Residuos vs Log(Costo del Seguro Ajustado)
    axes[1].scatter(modelo_RLM_log.fittedvalues, modelo_RLM_log.resid, color='darkgreen', alpha=0.5)
    axes[1].axhline(0, color='red')
    axes[1].set(title='Residuos vs Logaritmo del Costo del Seguro Ajustado', xlabel = 'Logaritmo del Costo Ajustado', ylabel = 'Residuos')
    plt.tight_layout()
    
    # IMPORTANTE: Para Gradio en Hugging Face, se retorna el objeto `plt`
    # o se usa `gr.Plot(plt.gcf())`. Aqu铆 devolveremos el objeto `plt`.
    # Alternativamente, podr铆as guardar la imagen y devolver la ruta, pero devolver `plt` es m谩s directo con `gr.Plot`.
    return plt


def predecir_costo(edad, genero, imc, hijos, fumador, region):
    global modelo_RLM

    if modelo_RLM is None:
        # Esto no deber铆a ocurrir si el modelo se entrena al inicio,
        # pero es una buena pr谩ctica de manejo de errores.
        return 0, 0, "ERROR: El Modelo de RLM no est谩 disponible."

    nuevo = pd.DataFrame({
        'edad':    [edad],
        'genero':  [genero],
        'imc':     [imc],
        'hijos':   [hijos],
        'fumador': [fumador],
        'region':  [region]
    })
    
    # Predicci贸n con el modelo RLM original (variable dependiente 'seguro')
    prediccion1 = modelo_RLM.predict(nuevo)[0]
    
    # Predicci贸n con el modelo RLM logar铆tmico (variable dependiente 'np.log(seguro)')
    prediccion_log = modelo_RLM_log.predict(nuevo)[0]
    # Se revierte el logaritmo con np.exp() para obtener la predicci贸n original
    prediccion2 = np.exp(prediccion_log)

    return prediccion1, prediccion2

### INTERFAZ GRADIO CON ESTRUCTURA DE PESTA脩AS

with gr.Blocks() as appweb: # Contenedor principal
    with gr.Row():
        gr.Image('encabezado.png', container = False)
        # T铆tulo de la aplicaci贸n
        # gr.Markdown("# COSTO DE SEGUROS PERSONALES")

    # Contenedor de pesta帽as
    with gr.Tabs():

        # Pesta帽a 1: Inicio
        with gr.TabItem("Inicio") as tab_inicio:
            gr.Markdown("## DATASET DE COSTOS DE SEGUROS PERSONALES")
            gr.Markdown("### Estructura:")
            data1_output = gr.Markdown()
            gr.Markdown("### Primeras 10 filas:")
            data2_output = gr.Markdown()
            gr.Markdown("### Estad铆sticas Generales:")
            data3_output = gr.Markdown()

            # Se cargan los datos al iniciar la aplicaci贸n
            appweb.load(fn = obtener_info_dataset, inputs = None,
                       outputs=[data1_output, data2_output, data3_output])

            # Se cargan los datos al seleccionar la pesta帽a "Inicio"
            # tab_inicio.select(fn = obtener_info_dataset, inputs = None,
            #           outputs=[data1_output, data2_output, data3_output])

        # Pesta帽a 2: Gr谩ficos Exploratorios
        with gr.TabItem("Gr谩ficos") as tab_graficos:
            gr.Markdown("## VISUALIZACI脫N EXPLORATORIA DE DATOS")

            with gr.Row():
                plot1_output = gr.Plot(label=None, show_label=False)
                plot2_output = gr.Plot(label=None, show_label=False)
            with gr.Row():
                plot3_output = gr.Plot(label=None, show_label=False)
                plot4_output = gr.Plot(label=None, show_label=False)
            with gr.Row():
                plot5_output = gr.Plot(label=None, show_label=False)
                plot6_output = gr.Plot(label=None, show_label=False)

            # Alternativa 1: al presionar un bot贸n se llama a la funci贸n generar_graficos()
            # btn_graficos = gr.Button("Gr谩ficos")
            # btn_graficos.click(fn = generar_graficos, inputs = None,
            #                  outputs = [plot1_output, plot2_output, plot3_output,
            #                             plot4_output, plot5_output, plot6_output])

            # Alternativa 2: al seleccionar la pesta帽a "Gr谩ficos" se llama a la funci贸n generar_graficos()
            # tab_graficos.select(fn = generar_graficos, inputs = None,
            #                     outputs = [plot1_output, plot2_output, plot3_output,
            #                               plot4_output, plot5_output, plot6_output])

            # Alternativa 3: al iniciar la aplicaci贸n se llama a la funci贸n generar_graficos()
            appweb.load(fn = generar_graficos, inputs = None,
                                outputs = [plot1_output, plot2_output, plot3_output,
                                           plot4_output, plot5_output, plot6_output])


        # Pesta帽a 3: Regresiones Lineales Simples
        with gr.TabItem("Regresi贸n Simple") as tab_reg_simple:
            gr.Markdown("# REGRESIONES LINEALES SIMPLES")

            gr.Markdown("## Costo del Seguro vs. Edad")
            reg11_output = gr.Markdown()
            with gr.Row():
                reg12_output = gr.Markdown()
                reg13_output = gr.Markdown()
            plotreg1_output = gr.Plot(label=None, show_label=False)

            gr.Markdown("## Costo del Seguro vs. IMC")
            reg21_output = gr.Markdown()
            with gr.Row():
                reg22_output = gr.Markdown()
                reg23_output = gr.Markdown()
            plotreg2_output = gr.Plot(label=None, show_label=False)

            tab_reg_simple.select(fn = calcular_RLS, inputs = None,
                                  outputs = [reg11_output, reg12_output, reg13_output,
                                            reg21_output, reg22_output, reg23_output,
                                            plotreg1_output, plotreg2_output])


        # Pesta帽a 4: Regresi贸n Lineal M煤ltiple
        with gr.TabItem("Regresi贸n M煤ltiple") as tab_reg_multiple:
            gr.Markdown("# REGRESI脫N LINEAL M脷LTIPLE")

            regm1_output = gr.Markdown()
            regm2_output = gr.Markdown()
            gr.Markdown("### Ecuaci贸n de la Regresi贸n")
            regm3_output = gr.Markdown()

            tab_reg_multiple.select(fn = calcular_RLM, inputs = None,
                                  outputs = [regm1_output, regm2_output, regm3_output])


        # Pesta帽a 5: Comparaci贸n de Residuos
        with gr.TabItem("Residuos") as tab_residuos:
            gr.Markdown("## COMPARACI脫N DE RESIDUOS ENTRE COSTO DEL SEGURO Y LOG(COSTO DEL SEGURO)")
            plotres_output = gr.Plot(label=None, show_label=False)

            tab_residuos.select(fn = graficar_residuos, inputs = None, outputs = plotres_output)


        # Pesta帽a 6: Predicci贸n de Costos - Modelo RLM
        with gr.TabItem("Predicci贸n de Costos"):
            gr.Markdown("## PREDICCI脫N DE COSTOS DE SEGURO PERSONAL")

            with gr.Row():
                input_edad = gr.Slider(minimum=18, maximum=80, step=1, value=30, label="Edad")
                input_genero = gr.Radio(choices=["femenino", "masculino"], label="G茅nero", value="femenino")
            with gr.Row():
                input_imc = gr.Slider(minimum=15, maximum=60, step=0.5, value=30.0, label="脥ndice de Masa Corporal")
                input_fumador = gr.Radio(choices=["si", "no"], label="Fumador", value="no")
            with gr.Row():
                input_hijos = gr.Slider(minimum=0, maximum=5, step=1, value=0, label="Cantidad de Hijos")
                input_region = gr.Radio(choices=["NO", "NE", "SO", "SE"], label="Regi贸n", value="NO")

            gr.Markdown("---")

            with gr.Row():
                btn_predecir = gr.Button("Predecir Costo")
                output_costo = gr.Number(label="Costo del Seguro (Modelo Lineal)", precision=2, value=0.00)
                output_costo_log = gr.Number(label="Costo del Seguro (Modelo Logar铆tmico)", precision=2, value=0.00)

            btn_predecir.click(fn = predecir_costo, inputs = [input_edad, input_genero, input_imc, input_hijos,
                        input_fumador, input_region], outputs = [output_costo, output_costo_log])

# Ejecuci贸n de la aplicaci贸n
# **MODIFICACI脫N CRUCIAL PARA HUGGING FACE SPACES**
# Usar server_name="0.0.0.0" y server_port=7860
appweb.launch(server_name="0.0.0.0", server_port=7860)