import streamlit as st from pickle import load import numpy as np models = load(open('lr_models.pkl', 'rb')) # ------------- FUNCTION DEFINITIONS ------------------ def calculate_bmi(height_cm: int, weight_kg: int) -> None: height_m = height_cm/100 return weight_kg / height_m**2 def overwrite_prediction(container_ref, raw_pred: float) -> None: eur_pred = usd_to_euro(raw_pred) with st.empty(): container_ref.write(f"""

{eur_pred:.2f}

{raw_pred:.2f}$

""", unsafe_allow_html=True) def usd_to_euro(amount: float) -> float: return amount*0.92 def format_entry(age: int, height_cm: int, weight_kg: int, raw_sex: str, raw_smoker: str, children: int) -> np.array: sex = 1 if raw_sex == 'Hombre' else 0 smoker = 1 if raw_smoker == 'Sí' else 0 bmi = calculate_bmi(height_cm, weight_kg) entry = np.array([age, bmi, sex, smoker, children]) \ .reshape(1, -1) return entry # ------------ WEB PAGE STRUCTURE ----------------- charge_container = st.empty() charge_container.write("""

0.00

0.00$

""", unsafe_allow_html=True) model_selection = st.selectbox(label='Versión del modelo', options=models.keys()) age_col, bmi_col, sex_col, smoker_col, children_col = st.columns(5) with age_col: age_ref = st.number_input(label='Edad', min_value=1, max_value=100) with bmi_col: height_ref = st.number_input(label='Altura (cm)', min_value=1, max_value=250) weight_ref = st.number_input(label='Peso (kg)', min_value=1.0, max_value=300.0) with sex_col: sex_ref = st.radio(label='Sexo', options=['Hombre', 'Mujer']) with smoker_col: smoker_ref = st.radio(label='¿Fumador?', options=['Sí', 'No']) with children_col: children_ref = st.number_input(label='Nº hijos', min_value=0) with st.container(): ref_button = st.button(label='¡Predecir 🔮!', use_container_width=True) warning_container = st.container(border=True) warning_container.markdown(""" ⚠️ :orange[**Aviso**]: *La información que insertes dentro de los elementos de entrada no será recolectada por la aplicación. Sólo será utilizada como entrada temporal para los modelos de **Regresión Lineal***. """) st.title('Predicción del importe de un seguro') st.markdown(""" ## Introducción Esta web proporciona una interfaz interactiva con la que puedes probar distintos modelos de **Regresión Lineal** para predecir el importe del seguro de una persona con las características siguientes: - **Su edad** - **Su IMC** (*calculado a través de la altura y peso*) - **Su sexo** - **Si es fumador o no** - **El número de hijos que tenga** """) st.markdown(""" ## Características de los modelos He entrenado un total de **3 modelos de Regersión Lineal**. Cada uno es ligeramente diferente por la forma en la que calcula la **ecuación de la regresión**. Los 3 han sido entrenados a través de una base de datos de una **aseguradora estadounidense**. Más específicamente, se han entrenado a través de una muestra de **200 registros**. En lo que a rendimiento respecta, los 3 son **bastante similares**. Para este caso se entiende **rendimiento** como el **porcentaje de las predicciones del modelo** que se ajustan a los valores reales de la muestra tomada. Aún así, se podrían clasificar los modelos en orden decreciente de rendmiento de la siguiente forma: 1. :green[LR Ridge] -> :green[~74.94%] 2. :orange[LR Lasso] -> :orange[~74.72%] 3. :red[LR Base] -> :red[~74.72%] Pese a que los dos últimos parecen tener rendimiento idéntico, el segundo tiene un **ajuste ligeramente mejor** de los coeficientes de la regresión. """) # --------------- FUNCTIONALITY ---------------- selected_model = models[model_selection] if ref_button: entry = format_entry( age_ref, height_ref, weight_ref, sex_ref, smoker_ref, children_ref) raw_charge = selected_model.predict(entry.reshape(1, -1)) charge_usd = raw_charge.ravel()[0] overwrite_prediction(charge_container, charge_usd)