<jupyter_start><jupyter_text>Reporte reto regresion ML1

In this notebook we report insurance cost<jupyter_code># Ejecutar esta celda solo desde google colab
!git clone https://github.com/andres-soto-h/reto-regresion-ML1.git "/reto_ml_regresion"

%cd /reto_ml_regresion<jupyter_output><empty_output><jupyter_text>Información de cada integrante del grupo de trabajo

**Nombre Completo:** <NAME> 
**Cédula:** 1152209579 
**Correo Institucional:** <EMAIL> 

**Nombre Completo:** <NAME> 
**Cédula:** 1152438081 
**Correo Institucional:** <EMAIL>


**Nombre Completo:** <NAME> 
**Cédula:** 1214734406 
**Correo Institucional:** <EMAIL> 


**Nombre Completo:** <NAME>
**Cédula:** 1035428708
**Correo Institucional:** <EMAIL><jupyter_code>from sklearn.model_selection import train_test_split
from sklearn.ensemble import RandomForestRegressor
from sklearn.preprocessing import PolynomialFeatures
from sklearn.pipeline import make_pipeline
from sklearn.ensemble import VotingRegressor
from sklearn.preprocessing import StandardScaler
from sklearn.ensemble import GradientBoostingRegressor
import os
from functools import partial
import joblib
import pandas as pd
import data
import metrics
%load_ext autoreload
%autoreload 2<jupyter_output><empty_output><jupyter_text>Exploratory analysis<jupyter_code>df_data= pd.read_csv('train_regression.csv', sep=',')
df_data.head(5)
df_data.describe()
df_data.info()<jupyter_output><class 'pandas.core.frame.DataFrame'>
RangeIndex: 896 entries, 0 to 895
Data columns (total 7 columns):
 #   Column    Non-Null Count  Dtype  
---  ------    --------------  -----  
 0   age       896 non-null    int64  
 1   sex       896 non-null    object 
 2   bmi       896 non-null    float64
 3   children  896 non-null    int64  
 4   smoker    896 non-null    object 
 5   region    896 non-null    object 
 6   y         896 non-null    float64
dtypes: float64(2), int64(2), object(3)
memory usage: 49.1+ KB<jupyter_text>Haciendo una revisión inicial de los datos se identifica que no hay valores nulos en el dataset.La edad promedio para las personas incluidas en la base es de 39 años y el indice de masa corporal promedio es de 30 (por encima de lo normal y cercano a sobrepeso). El promedio de personas de la base tienen 1 hijo y el 75% de ellos tienen 2 o menos hijos.<jupyter_code>df_data.age.quantile(q=[0.25, 0.50, 0.75], interpolation='midpoint')
def transform_age(age):
    if age <=32:
        return "[18 to 32]"
    elif age<=48:
        return "[33 to 48]"
    else:
        return "[older than 48]"

df_data['age_range'] = df_data['age'].apply(transform_age)
def transform_bmi(bmi):
    if bmi <=18.5:
        return "Underweight"
    elif bmi<=24.9:
        return "Healthy weight"
    elif bmi<=29.9:
        return "Overweight"
    else:
        return "Obesity"

df_data['bmi_range'] = df_data['bmi'].apply(transform_bmi)
dict_data = df_data[["age_range","bmi_range","y"]].groupby(["age_range","bmi_range"]).mean().to_dict()['y']
import matplotlib.pyplot as plt
import seaborn as sns
import numpy as np
sns.set()

df_data.y.hist()
plt.title("Histograma de los costos de seguro médico");
sns.pairplot(df_data.drop("children", axis=1), hue="sex");<jupyter_output><empty_output><jupyter_text>Del anterior barplot comparativo, se puede determinar dos conclusiones principales: 1) La primera de ellas, es que la característica sexo, no es un factor distintivo que permita segementar grupos poblacionales con relación al comportamiento de las demás variables, dado que las curvas de densidad describen curvas de densidad similares tanto para hombres como para mujeres. Sólo cabe resaltar, que los puntos de frecuencia más alta en los histogramas, sí tienen asociados puntos más altos para la población masculina.2) De las variables analizadas, la edad parece tener una relación evidentemente lineal positiva con el valor del seguro. Adicionalmente, se observa una particularidad en esta relación, y es una separación de los datos en tres grupos.<jupyter_code>plt.figure(figsize=(15,5))

data_corr = pd.get_dummies(df_data, columns=["sex", "smoker"], prefix=["sex", "smoker"])

pearsonCorr = data_corr.corr(method='pearson')
spearmanCorr = data_corr.corr(method='spearman')

plt.subplot(1, 2, 1)
sns.heatmap(pearsonCorr, vmin=-1,vmax=1, cmap = "Greens", annot=True, linewidth=0.1)
plt.title("Pearson Correlation");

plt.subplot(1, 2, 2)
sns.heatmap(spearmanCorr, vmin=-1,vmax=1, cmap = "Blues", annot=True, linewidth=0.1)
plt.title("Spearman Correlation");<jupyter_output><empty_output><jupyter_text>Al realizar un análisis de la correlación de variables se evidencia que las vaiables con mayor correlación en el dataset vs los costos de atención médica son si la persona fuma o no, el índice de masa corporal y la edad. Ambas presentan una correlación positiva, por lo cual a mayor edad y mayor bmi, los costos de atención serán mayores.<jupyter_code>sns.scatterplot(df_data['age'], np.log(df_data['y']));
sns.histplot(np.log(df_data['y']));<jupyter_output><empty_output><jupyter_text>Realizando una normalización logarítima de los valores del costo de los seguros, se evidencia nuevamente las  3 agrupaciones de los datos al comparar la variable respuesta con la edad. La tendencia creciente en el valor del seguro se hace más evidente para los valores en escala logarítima de 7.0 a 9.5<jupyter_code>sns.scatterplot(df_data['bmi'], df_data['y']);
grid = sns.lmplot(x = "age", y = "y", col = "bmi_range", sharex=False, col_wrap = 4, data = df_data, height=4)
sns.boxplot(data=df_data, x= "bmi_range", y="y");sns.boxplot(data=df_data, x= "bmi_range", y="y")
plt.axhline(y=15000, c='red', linestyle = '--')
plt.axhline(y=30000, c='red', linestyle = '--');<jupyter_output><empty_output><jupyter_text>Al analizar los valores del seguro por la característica de clasificación según el índice de masa corporal, la cual segmenta al individuo en:- "Underweight" con bmi menores o iguales a 18.5- "Healthy weight" para valores bmi entre (18.5,24.9]- "Overweight" para valores bmi entre (24.9, 29.9]- "Obesity con bmi mayores a 29.9Se observa que al realizar la segmentación del índice de masa corporal se obtienen relaciones lineales mucho más marcadas que con el análsis de sólo el valor del índice. Adicional, no existe una diferencia significativa entre la distribución de los datos por tipo del rango del bmi, dado que el valor central de las cajas está al rededor de 10.000 y el q3 se mueve por debajo de los 15.000, excepto para el factor obesidad donde se tiene una mayor dispersión de los datos, con sesgo hacia la derecha y datos atípicos a partir del 45.000 aproximadamente.<jupyter_code>data1=df_data[df_data['y']<=15000]
data2=df_data[(df_data['y']>15000) & (df_data['y']<=30000)]
data3=df_data[df_data['y']>30000]

data1.bmi = data1.bmi.apply(lambda x : int(round(x)))
data2.bmi = data2.bmi.apply(lambda x : int(round(x)))
data3.bmi = data3.bmi.apply(lambda x : int(round(x)))

posible_outliers1 = df_data[(df_data['y']>50000) & (df_data['age']>20) & (df_data['age']<=30)]
posible_outliers2 = df_data[(df_data['y']>50000) & (df_data['age']>30) & (df_data['age']<60)]
posible_outliers = pd.concat([posible_outliers1, posible_outliers2])
posible_outliers.bmi = posible_outliers.bmi.apply(lambda x : int(round(x)))

plt.figure(figsize=(12,6))
sns.scatterplot(data=data1, x='age', y='y', size='bmi');
sns.scatterplot(data=data2, x='age', y='y', size='bmi');
sns.scatterplot(data=data3, x='age', y='y', size='bmi');
sns.scatterplot(data=posible_outliers, x='age', y='y', size='bmi');
plt.legend(loc='upper right');
#Eliminar posibles outliers del dataset 
data_so = df_data.drop(labels=list(posible_outliers.index), axis=0)
data_so.drop(columns=["bmi_range","age_range"], inplace=True)
data_so.to_csv("train_regression_so.csv",index=False)
df_data['sex'].value_counts()<jupyter_output><empty_output><jupyter_text>El dataset parece estar balanceado en términos del género de las personas<jupyter_code>df_data['smoker'].value_counts()
df_data['bmi_range'].value_counts()<jupyter_output><empty_output><jupyter_text>Se tiene que del total de personas, 188 son fumadores, habrá que revisar si esta caracteristica se encuentra asociada con un mayor BMI y posiblemente mayores costos de atención.<jupyter_code>df_data['region'].value_counts()<jupyter_output><empty_output><jupyter_text>El dataset también se encuentra balanceado respecto a las regiones<jupyter_code>df_data[['sex','y']].groupby('sex').mean()<jupyter_output><empty_output><jupyter_text>El costo promedio de atención para los hombres es un poco mas alto que para las mujeres<jupyter_code>sns.boxplot(data=df_data, x= "age_range", y="y", order=['[18 to 32]','[33 to 48]','[older than 48]']);
plt.axhline(y=15000, c='red', linestyle = '--')
plt.axhline(y=30000, c='red', linestyle = '--');
df_data[['age_range','y']].groupby('age_range').aggregate(["mean", "std"])<jupyter_output><empty_output><jupyter_text>como ya era evidente de análisis posteriores, ocurre un desplazamiento hacia arriba del valor promedio de los datos a medida que aumenta la edad. Pese a ello no es una característica enteramente discretizante puesto que los valores en cada grupo de edad se mueven en todo el rango de y.<jupyter_code>sns.boxplot(data=df_data, x= "children", y="y");
plt.axhline(y=15000, c='red', linestyle = '--')
plt.axhline(y=30000, c='red', linestyle = '--');
df_data.children.value_counts()<jupyter_output><empty_output><jupyter_text>la cantidad de hijos no tiene un factor totalmente discretizante en la relación con el valor del seguro. Inclusive se evidencia una concentración de los datos en torno a la media para los valores de 4 y 5 hijos asociados a la poca cantidad de datos que caen en esta característica.<jupyter_code>sns.boxplot(data=df_data, x= "region", y="y");
plt.axhline(y=15000, c='red', linestyle = '--')
plt.axhline(y=30000, c='red', linestyle = '--');
df_data[['region','y']].groupby('region').aggregate(["mean","median","std"])<jupyter_output><empty_output><jupyter_text>Los valores promedio para el costo del seguro por región son similares entre sí, con una leve diferencia para la región de southeast.<jupyter_code>sns.boxplot(data=df_data, x= "smoker", y="y");
plt.axhline(y=15000, c='red', linestyle = '--')
plt.axhline(y=30000, c='red', linestyle = '--');
df_data[['smoker','y']].groupby('smoker').aggregate(["mean","median","std"])<jupyter_output><empty_output><jupyter_text>Esta característica, parece tener íncidencia en la distribución de los valores de los seguros. Donde los no fumadores tienen una distribución asímetrica entre los cuartiles q1 y q3, con media y mediana cercanas entre sí, pero con un leve sesgo hacia la derecha en la franja de valores de seguro de 1.500 y 3.000. Se da un desplazamiento en los valores del seguro para las personas fumadoras, con datos no asímetricos en el 50% de sus valores con mediana de 34.036 y media de 31.716 aproximadamente.<jupyter_code>data_smoker = df_data[df_data.smoker == 'yes']
sns.boxplot(data=data_smoker, x= "bmi_range", y="y", order=["Underweight", 'Healthy weight','Overweight','Obesity'])
plt.axhline(y=15000, c='red', linestyle = '--')
plt.axhline(y=30000, c='red', linestyle = '--')
plt.title('Valor Seguro fumadores para cada grupo bmi');
data_smoker_obesity = data_smoker[data_smoker.bmi_range == 'Obesity']
fig, axes = plt.subplots(1, 2, figsize=(15, 5), sharey=True)
fig.suptitle('Análisis Obesisdad fumadores')

sns.boxplot(ax=axes[0],data=data_smoker_obesity, x= "age_range", y="y",order=['[18 to 32]','[33 to 48]','[older than 48]'])
axes[0].set_title('Valor seguro obesos fumadores por grupo bmi')
axes[0].axhline(y=15000, c='red', linestyle = '--')
axes[0].axhline(y=30000, c='red', linestyle = '--')

sns.boxplot(ax=axes[1],data=data_smoker_obesity, x= "sex", y="y")
axes[1].set_title('Valor seguro obesos fumadores por sexo')
axes[1].axhline(y=15000, c='red', linestyle = '--')
axes[1].axhline(y=30000, c='red', linestyle = '--');
data_not_smoker = df_data[df_data.smoker == 'no']
sns.boxplot(data=data_not_smoker, x= "bmi_range", y="y", order=["Underweight", 'Healthy weight','Overweight','Obesity']);
plt.axhline(y=15000, c='red', linestyle = '--')
plt.axhline(y=30000, c='red', linestyle = '--')
plt.title('Valor Seguro no fumadores para cada grupo bmi')
data_notsmoker_obesity = data_not_smoker[data_not_smoker.bmi_range == 'Obesity']
fig, axes = plt.subplots(1, 2, figsize=(15, 5), sharey=True)
fig.suptitle('Análisis Obesisdad no fumadores')

sns.boxplot(ax=axes[0],data=data_not_smoker, x= "age_range", y="y",order=['[18 to 32]','[33 to 48]','[older than 48]'])
axes[0].set_title('Valor seguro obesos fumadores por grupo bmi')
axes[0].axhline(y=15000, c='red', linestyle = '--')
axes[0].axhline(y=30000, c='red', linestyle = '--')

sns.boxplot(ax=axes[1],data=data_not_smoker, x= "sex", y="y")
axes[1].set_title('Valor seguro obesos fumadores por sexo')
axes[1].axhline(y=15000, c='red', linestyle = '--')
axes[1].axhline(y=30000, c='red', linestyle = '--');<jupyter_output><empty_output><jupyter_text>MODEL<jupyter_code>def evaluate_model(*, model, metric, X_train, y_train, X_test, y_test):
    train_predictions = model.predict(X_train)
    test_predictions = model.predict(X_test)
    train_error = metric(y_train, train_predictions)
    test_error = metric(y_test, test_predictions)
    return {
        "train_predictions": train_predictions,
        "test_predictions": test_predictions,
        "train_error": train_error,
        "test_error": test_error
    }

def print_report(*, model, evaluation):
    print(f"Model used:\n\t{reg}")
    print(f"Error:\n\ttrain set {evaluation['train_error']}\n\ttest error: {evaluation['test_error']}")
models_dir = "models"
dataset_path = "train_regression.csv"
dataset = data.get_dataset(
    partial(pd.read_csv, filepath_or_buffer=dataset_path),
    splits=("train", "test")
)
dataset<jupyter_output><empty_output><jupyter_text>Baseline<jupyter_code>model_path = os.path.join("models", "2021-06-10 16-20", "model.joblib")
reg = joblib.load(model_path)
evaluation = evaluate_model(
    model=reg,
    metric=metrics.custom_error,
    X_train=dataset["train"][0],
    y_train=dataset["train"][1],
    X_test=dataset["test"][0],
    y_test=dataset["test"][1]
)
print_report(model=reg, evaluation=evaluation)<jupyter_output>Model used:
	Pipeline(steps=[('average-price-per-bmi-regressor',
                 AveragePricePerBMIRegressor())])
Error:
	train set 8757.69126149081
	test error: 9692.9846746485<jupyter_text>Linear Regression Model<jupyter_code>model_path = os.path.join("models", "2021-06-10 20-18", "model.joblib")
reg = joblib.load(model_path)
evaluation = evaluate_model(
    model=reg,
    metric=metrics.custom_error,
    X_train=dataset["train"][0],
    y_train=dataset["train"][1],
    X_test=dataset["test"][0],
    y_test=dataset["test"][1]
)
print_report(model=reg, evaluation=evaluation)<jupyter_output>Model used:
	Pipeline(steps=[('categorical-encoder',
                 CategoricalEncoder(force_dense_array=True)),
                ('standard-scaler', StandardScaler()),
                ('linear-regressor', LinearRegression())])
Error:
	train set 4241.133955127506
	test error: 4331.7453896886955<jupyter_text>Linear regression with Feature Engineering<jupyter_code>model_path = os.path.join("models", "2021-06-12 20-54", "model.joblib")
reg = joblib.load(model_path)
evaluation = evaluate_model(
    model=reg,
    metric=metrics.custom_error,
    X_train=dataset["train"][0],
    y_train=dataset["train"][1],
    X_test=dataset["test"][0],
    y_test=dataset["test"][1]
)
print_report(model=reg, evaluation=evaluation)
model_path = os.path.join("models", "2021-06-12 20-54", "model.joblib")
reg = joblib.load(model_path)
evaluation = evaluate_model(
    model=reg,
    metric=metrics.r2_score,
    X_train=dataset["train"][0],
    y_train=dataset["train"][1],
    X_test=dataset["test"][0],
    y_test=dataset["test"][1]
)
print_report(model=reg, evaluation=evaluation)<jupyter_output>Model used:
	Pipeline(steps=[('categorical-encoder',
                 CategoricalEncoder(force_dense_array=True)),
                ('crosser', PolynomialFeatures(interaction_only=True)),
                ('standard-scaler', StandardScaler()),
                ('linear-regressor', LinearRegression())])
Error:
	train set 0.8317587737718674
	test error: 0.8438556548658451<jupyter_text>Random Forest<jupyter_code>model_path = os.path.join("models", "2021-06-10 21-00", "model.joblib")
reg = joblib.load(model_path)
evaluation = evaluate_model(
    model=reg,
    metric=metrics.custom_error,
    X_train=dataset["train"][0],
    y_train=dataset["train"][1],
    X_test=dataset["test"][0],
    y_test=dataset["test"][1]
)
print_report(model=reg, evaluation=evaluation)
evaluation = evaluate_model(
    model=reg,
    metric=metrics.r2_score,
    X_train=dataset["train"][0],
    y_train=dataset["train"][1],
    X_test=dataset["test"][0],
    y_test=dataset["test"][1]
)
print_report(model=reg, evaluation=evaluation)<jupyter_output>Model used:
	Pipeline(steps=[('categorical-encoder',
                 CategoricalEncoder(force_dense_array=True)),
                ('standard-scaler', StandardScaler()),
                ('random-forest-regressor',
                 RandomForestRegressor(max_depth=3, min_samples_split=6,
                                       n_estimators=150))])
Error:
	train set 0.8584824990235743
	test error: 0.8678502250420668<jupyter_text>Gradient Boosting<jupyter_code>model_path = os.path.join("models", "2021-06-10 20-54", "model.joblib")

reg = joblib.load(model_path)
evaluation = evaluate_model(
    model=reg,
    metric=metrics.custom_error,
    X_train=dataset["train"][0],
    y_train=dataset["train"][1],
    X_test=dataset["test"][0],
    y_test=dataset["test"][1]
)
print_report(model=reg, evaluation=evaluation)
evaluation = evaluate_model(
    model=reg,
    metric=metrics.r2_score,
    X_train=dataset["train"][0],
    y_train=dataset["train"][1],
    X_test=dataset["test"][0],
    y_test=dataset["test"][1]
)
print_report(model=reg, evaluation=evaluation)<jupyter_output>Model used:
	Pipeline(steps=[('categorical-encoder',
                 CategoricalEncoder(force_dense_array=True)),
                ('standard-scaler', StandardScaler()),
                ('gradient-boosting-regressor',
                 GradientBoostingRegressor(learning_rate=0.05, n_estimators=130,
                                           subsample=1))])
Error:
	train set 0.8913710207701334
	test error: 0.8882011923633542<jupyter_text>Stacking<jupyter_code>model_path = os.path.join("models", "2021-06-10 22-46", "model.joblib")
reg = joblib.load(model_path)
evaluation = evaluate_model(
    model=reg,
    metric=metrics.custom_error,
    X_train=dataset["train"][0],
    y_train=dataset["train"][1],
    X_test=dataset["test"][0],
    y_test=dataset["test"][1]
)
print_report(model=reg, evaluation=evaluation)
evaluation = evaluate_model(
    model=reg,
    metric=metrics.r2_score,
    X_train=dataset["train"][0],
    y_train=dataset["train"][1],
    X_test=dataset["test"][0],
    y_test=dataset["test"][1]
)
print_report(model=reg, evaluation=evaluation)<jupyter_output>Model used:
	Pipeline(steps=[('categorical-encoder',
                 CategoricalEncoder(force_dense_array=True)),
                ('standard-scaler', StandardScaler()),
                ('stacking-regressor',
                 StackingRegressor(estimators=[('lr', Ridge()),
                                               ('dt', DecisionTreeRegressor())],
                                   final_estimator=RandomForestRegressor(max_depth=3,
                                                                         min_samples_split=6,
                                                                         n_estimators=150)))])
Error:
	train set 0.8577023207063226
	test error: 0.8743546910094405<jupyter_text>Gradient Boosting with feature Engineering<jupyter_code>model_path = os.path.join("models", "2021-06-14 03-35", "model.joblib")
reg = joblib.load(model_path)
evaluation = evaluate_model(
    model=reg,
    metric=metrics.custom_error,
    X_train=dataset["train"][0],
    y_train=dataset["train"][1],
    X_test=dataset["test"][0],
    y_test=dataset["test"][1]
)
print_report(model=reg, evaluation=evaluation)
X_test_reto = pd.read_csv("test_regression_students.csv", sep=",")
X_test_reto["y"]=0
X_test_reto.to_csv("test_regression_students_y.csv",index=False)
dataset_path = "test_regression_students_y.csv"

dataset_reto = data.get_dataset_mod(
    partial(pd.read_csv, filepath_or_buffer=dataset_path),
    splits=("train", "test")
)
model = joblib.load(model_path)

X_test_reto=dataset_reto["test"][0]
test_predictions = model.predict(X_test_reto)
test_predictions.shape
import requests
import json
URL = "https://qzbbjszmjk.execute-api.us-east-1.amazonaws.com/dev"

results = {"id": "<NAME>; <NAME>; <NAME>; <NAME>","email": "<EMAIL>", "task_type": "Regression" ,"predictions": list(test_predictions)}
headers = {'Content-type': 'application/json', 'Accept': 'text/plain'}

#Quitar comentaro para enviar modelo
#r = requests.post(url= URL+"/benchmarkin/", data = json.dumps(results) , headers=headers)

#r.text<jupyter_output><empty_output><jupyter_text>Error analysis A partir del análisis exploratorio previo donde se evidencia una mayor concentración de datos por debajo de costos de seguro de 40.000, ver figura posterior, se espera que el modelo hallado presente errores más grandes a partir de estos costos, los cuales incluyen datos atípicos.Se plantean las siguientes hipótesis:1) $H_{02}$: Los errores más altos están asociados a las personas con obesidad.2) $H_{01}$: Los errores  más altos están asociados a los fumadores.3) $H_{03}$: Los errores más altos están asociados a personas con menos hijos que aquellos que tienen más hijos.3) $H_{04}$: Los errores mas altos están asociados a tarifas que estan por fuera del promedio de costo<jupyter_code>X_test = dataset["test"][0].reset_index()
y_true = dataset["test"][1].reset_index()["y"]
y_pred = pd.Series(evaluation["test_predictions"], name="Prediction")
pred_data=X_test.join([y_true , y_pred])
pred_data["error"]=np.abs(pred_data["y"]-pred_data["Prediction"])
error_data = pred_data.sort_values(by=["error"], ascending=False).head(30)

error_data.sort_values(by=["smoker","bmi_range","age_range"], ascending=False)
error_data.sort_values(by=["children","bmi_range","age_range"], ascending=False)
sns.scatterplot(data=error_data, x="age", y="Prediction", label="Predicción");
sns.scatterplot(data=error_data, x="age", y="y", label="Y true");<jupyter_output><empty_output><jupyter_text>Validación hipótesis 1<jupyter_code>sns.boxplot(data=error_data, x= "bmi_range", y="y");
error_data["bmi_range"].value_counts()<jupyter_output><empty_output><jupyter_text>Al revisar los datos se evidencia que las personas con obesidad y sobrepeso hacen parte de los 30 datos con mayor error en los pronósticos del dataset, para solucionar esto, se propone crear un nuevo modelo solamente con las variables de bmi_range, age y smoker sin hacer estandarización de las variables, con el objetivo de validar si este modelo da una mayor importancia a las viariables que tienen mayor correlación con el costo de atención (Especialmente el bmi) que es dónde se evidencia una oportunidad de mejora<jupyter_code>X_h1 = pd.get_dummies(df_data.drop(columns=["y","sex","children","region","age_range","bmi_range"]), columns=["smoker"], prefix=["smoker"])

y_h1 = df_data["y"]

X_train, X_test, y_train, y_test = train_test_split(X_h1, y_h1, test_size=0.2, random_state=42)

regr_h1=make_pipeline(PolynomialFeatures(3),RandomForestRegressor(max_depth=5))
regr_h1.fit(X_train, y_train)

score_train = regr_h1.score(X_train, y_train)
score_test = regr_h1.score(X_test, y_test)

print(f"Train score: {score_train}")
print(f"Test score: {score_test}")<jupyter_output>Train score: 0.8906912812443235
Test score: 0.8494444460426563<jupyter_text>No se evidencia que alimiar otras variables del modelo, para tratar de mejorar la importancia del BMI, los resultados del ajuste mejoren  Validación hipótesis 2Al revisar los datos, se descarta la hipótesis 1 ya que los errores mas altos están asociados a los no fumadores, así mismo dentro de los 30 datos con mayor error de pronóstico, solo 8 están asociados con personas que si fuman<jupyter_code>error_data["smoker"].value_counts()<jupyter_output><empty_output><jupyter_text>Validación hipótesis 3<jupyter_code>error_data["children"].value_counts()<jupyter_output><empty_output><jupyter_text>Al revisar los datos tampoco se corrobora la hipótesis 3 dado que a pesar de tener 18 personas con cero hijos en el dataset con mayores errores.También se tienen errores muy altos para personas con 1 o 2 hijos  Validación de hipótesis 4 Modelo de votación agrupando los datos por rango de costo y edad Se propone realizar 3 modelos de regresión separando el conjunto de datos en partes diferentes de acuerdo al "nivel" del costo de seguro, inicialmente, se realiza un modelo con kmeans para validar si se identifica algún subconjunto en los datos de manera automática, luego de esto se separan los datos en 3 grupos diferentes con el objetivo de ahcer un ajuste para cada uno.<jupyter_code>from sklearn.cluster import KMeans

data_cluster=df_data.copy()
data_cluster.drop(["y", "age_range", "bmi_range"], axis=1, inplace=True)


data_cluster = pd.get_dummies(data_cluster, columns=["sex", "smoker", "region"], prefix=["sex", "smoker", "region"])

model = KMeans(n_clusters=3)
model.fit(data_cluster)

# Prediction on the entire data
all_predictions = pd.Series(model.predict(data_cluster), name="class")
data_cluster2 = data_cluster.join([all_predictions,df_data["y"]])


sns.scatterplot(data=data_cluster2, x='age', y='y', hue="class");

data1=df_data[(df_data['y']<=9000) & (df_data['age']<=32)]
data2=df_data[(df_data['y']>9000) & (df_data['y'] <= 30000) & (df_data['age']<=32)]
data3=df_data[(df_data['y']>30000) &  (df_data['y']<50000)  & (df_data['age']<=32)]

data4=df_data[(df_data['y']<=12000) & (df_data['age'] > 32) & (df_data['age']<=48)]
data5=df_data[(df_data['y']>12000) & (df_data['y'] <= 30000) & (df_data['age'] > 32) & (df_data['age']<=48)]
data6=df_data[(df_data['y']>30000) & (df_data['y']<50000)  & (df_data['age'] > 32) & (df_data['age']<=48)]

data7=df_data[(df_data['y']<=19000) & (df_data['age']> 48)]
data8=df_data[(df_data['y']>19000) & (df_data['y'] <= 35000) & (df_data['age']>48)]
data9=df_data[(df_data['y']>35000) & (df_data['y']<50000)  & (df_data['age']>48)]

data_m1 = pd.concat([data1, data4, data7])
data_m2 = pd.concat([data2, data5, data8])
data_m3 = pd.concat([data3, data6, data9])
sns.scatterplot(data=data_m1, x='age', y='y');
sns.scatterplot(data=data_m2, x='age', y='y');
sns.scatterplot(data=data_m3, x='age', y='y');
X_m1 = pd.get_dummies(data_m1.drop(columns=["y"]), columns=["sex", "smoker", "region", "age_range", "bmi_range"], prefix=["sex", "smoker", "region","age_range", "bmi_range"])

X_m2 = pd.get_dummies(data_m2.drop(columns=["y"]), columns=["sex", "smoker", "region", "age_range", "bmi_range"], prefix=["sex", "smoker", "region","age_range", "bmi_range"])

X_m3 = pd.get_dummies(data_m3.drop(columns=["y"]), columns=["sex", "smoker", "region", "age_range", "bmi_range"], prefix=["sex", "smoker", "region","age_range", "bmi_range"])
y_m1=data_m1["y"]
y_m2=data_m2["y"]
y_m3=data_m3["y"]
# MODELO 1 
X_train, X_test, y_train, y_test = train_test_split(X_m1, y_m1, test_size=0.2, random_state=42)

regr1 = RandomForestRegressor(max_depth=4)
regr1.fit(X_train, y_train)

score_train = regr1.score(X_train, y_train)
score_test = regr1.score(X_test, y_test)

print(f"Train score: {score_train}")
print(f"Test score: {score_test}")
# MODELO 2
X_train, X_test, y_train, y_test = train_test_split(X_m2, y_m2, test_size=0.2, random_state=42)

regr = RandomForestRegressor()
regr.fit(X_train, y_train)

score_train = regr.score(X_train, y_train)
score_test = regr.score(X_test, y_test)

print(f"Train score: {score_train}")
print(f"Test score: {score_test}")
# MODELO 2.1

regr2=make_pipeline(PolynomialFeatures(5),RandomForestRegressor())
regr2.fit(X_train, y_train)

score_train = regr2.score(X_train, y_train)
score_test = regr2.score(X_test, y_test)

print(f"Train score: {score_train}")
print(f"Test score: {score_test}")
# MODELO 3
X_train, X_test, y_train, y_test = train_test_split(X_m3, y_m3, test_size=0.2, random_state=42)

regr3=make_pipeline(PolynomialFeatures(4),RandomForestRegressor(max_depth=5))
regr3.fit(X_train, y_train)

score_train = regr3.score(X_train, y_train)
score_test = regr3.score(X_test, y_test)

print(f"Train score: {score_train}")
print(f"Test score: {score_test}")
X_ = pd.get_dummies(df_data.drop(columns=["y"]), columns=["sex", "smoker", "region", "age_range", "bmi_range"], prefix=["sex", "smoker", "region","age_range", "bmi_range"])
y_ = df_data["y"]

X_train, X_test, y_train, y_test = train_test_split(X_, y_, test_size=0.2, random_state=42)

er = VotingRegressor([('m1', regr1), ('m2', regr2), ('m3', regr3)])
er.fit(X_train, y_train)

score_train = er.score(X_train, y_train)
score_test = er.score(X_test, y_test)

print(f"Train score: {score_train}")
print(f"Test score: {score_test}")<jupyter_output>Train score: 0.9330901279284052
Test score: 0.8492988576438845<jupyter_text>Al revisar los resultados del modelo de votación, se tiene que en test tiene un resultado peor al obtenido usando GradientBoostingRegressor<jupyter_code>X_test_reto2 = pd.get_dummies(X_test_reto, columns=["sex", "smoker", "region", "age_range", "bmi_range"], prefix=["sex", "smoker", "region","age_range", "bmi_range"])
test_predictions2 = er.predict(X_test_reto2)
test_predictions2.shape
results = {"id": "<NAME>; <NAME>; <NAME>; <NAME>","email": "<EMAIL>", "task_type": "Regression" ,"predictions": list(test_predictions2)}
headers = {'Content-type': 'application/json', 'Accept': 'text/plain'}

#r = requests.post(url= URL+"/benchmarkin/", data = json.dumps(results) , headers=headers)
#r.text<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.14492078285181734, 'fraction_numerical': 0.03737851151644255, 'mean_word_length': 5.814470401451576, 'pattern_counts': {'":': 12, '<': 159, '<?xml version=': 0, '>': 153, 'https://': 2, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 13, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '31', 'dir': 'jupyter-structured-clean-dedup', 'id': '560764', 'license': 'MIT', 'n_tokens_mistral': 11770, 'n_tokens_neox': 11029, 'n_words': 2406, 'path': 'report.ipynb', 'repo_name': 'andres-soto-h/reto-regresion-ML1', 'size': '30391'}