Alumnos y Padrón
Importamos las bibiliotecas que utilizaremos a lo largo del notebook
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
from sklearn.model_selection import train_test_split
from sklearn.metrics import classification_report
from sklearn.metrics import confusion_matrix
from sklearn.metrics import roc_auc_score
from sklearn.metrics import roc_curve
from sklearn.model_selection import KFold, StratifiedKFold
from sklearn.linear_model import LogisticRegression
from preprocessing import prepararSetDeDatos
from preprocessing import prepararSetDeHoldout
from preprocessing import prepararSetDeValidacion
from preprocessing import expansionDelDataset
from preprocessing import conversionAVariablesNormalizadas
from funcionesAuxiliares import mostrarAUCScore
from funcionesAuxiliares import mostrarROCCurve
from funcionesAuxiliares import mostrarMatrizDeConfusion
from funcionesAuxiliares import escribirPrediccionesAArchivo
from funcionesAuxiliares import obtenerDatasets
from funcionesAuxiliares import obtenerHoldout
Leemos los datos que tenemos y llamamos a las funciones que se encargarán de dejar listos los datasets con la investigación del TP1.
X, y = obtenerDatasets()
X = prepararSetDeDatos(X)
y = prepararSetDeValidacion(y)
Creamos una función que obtiene mediante grid search y K-Fold cross validation el tipo de regularización que maximiza la métrica de AUC ROC para el modelo de regresión logística.
def obtenerMejoresHiperparametros(datosPreprocesados):
mejor_c = 0
mejor_valor = 0
mejor_regularizacion = None
y_array=np.array(y)
for regularizacion in ["l2","none", "l1", "elasticnet"]:
for valor_c in [0.001,0.01,0.1,0.2,0.5,0.7,1.0,1.5,2,2.5,3,3.5,4,5]:
if(regularizacion == "elasticnet"):
l1_ratio = 0.5
else:
l1_ratio = None
kf = StratifiedKFold(n_splits=5)
metricas = []
for fold_idx, (train_index, test_index) in enumerate(kf.split(datosPreprocesados, y_array)):
rl = None
if regularizacion == "none": # Para evitar los warnings que surgen al mandar None con l1_ratio y C
rl = LogisticRegression(penalty = regularizacion, max_iter = 5000, solver = "saga")
else:
rl = LogisticRegression(penalty = regularizacion, max_iter = 5000, solver = "saga", l1_ratio = l1_ratio, C=valor_c)
rl.fit(datosPreprocesados[train_index], y_array[train_index].ravel())
predicciones = rl.predict_proba(datosPreprocesados[test_index])[:, 1]
score_obtenida = roc_auc_score(y_array[test_index],predicciones)
metricas.append(score_obtenida)
if np.mean(metricas) >= mejor_valor:
mejor_valor = np.mean(metricas)
mejor_regularizacion = regularizacion
mejor_c = valor_c
return mejor_valor, mejor_regularizacion, mejor_c
La regresión logística es un método de aprendizaje supervisado sencillo el cual consiste en obtener una curva logística que sirva para predecir la clase de una instancia.
Para el procesamiento de los datos aplicamos el mismo tipo de procesamiento que en otros modelos (ej. KNN). Este consiste en convertir las variables categóricas a numéricas mediante OneHotEncoding y normalizar los datos que correspondan para evitar que ocurra un desvío no deseado al momento de realizar los cálculos. Primero probamos usando el dataframe inicial, sin expandirlo.
X_rl = conversionAVariablesNormalizadas(X)
En la búsqueda de los hiperparámetros consideramos que los más importantes eran los siguientes:
Penalidad: Especifica la penalización del modelo. Probamos con las siguientes regularizaciones 'l1','l2,'elasticnet, y sin regularización.
C: Es un parámetro que indica qué tan fuerte es la regularización. Similar a SVM.
mejor_valor, mejor_regularizacion, mejor_c = obtenerMejoresHiperparametros(X_rl)
print(f"El mejor valor fue de AUC fue: {round(mejor_valor,3)}")
print(f"La regularizacion encontrada que maximiza el AUC fue: {mejor_regularizacion}")
print(f"El valor de C que maximiza el AUC fue: {mejor_c}")
Vemos ahora con la expansion.
X = expansionDelDataset(X)
X.head()
columnas_codificables_extra = ['pago_categorizado','edades_estratificadas','categoria_invitados']
columnas_numericas_extra = ['2_clusters','4_clusters','10_clusters','cantidad_total_invitados','total_pagado']
X_rl_exp = conversionAVariablesNormalizadas(X,columnas_codificables_extra,columnas_numericas_extra)
mejor_valor_exp, mejor_regularizacion_exp, mejor_c_exp = obtenerMejoresHiperparametros(X_rl_exp)
print(f"El mejor valor fue de AUC fue: {round(mejor_valor_exp,3)}")
print(f"La regularizacion encontrada que maximiza el AUC fue: {mejor_regularizacion_exp}")
print(f"El valor de C que maximiza el AUC fue: {mejor_c_exp}")
Obtuvimos una muy ligera mejora. Probamos si se puede agrandar sacandole algunas de las columanas nuevas. Estas son algunas que pueden llegar a ser reduntantes en este modelo. Por ejemplo la cantidad total de invitados.
columnas_codificables_extra = ['pago_categorizado','edades_estratificadas','categoria_invitados']
columnas_numericas_extra = ['4_clusters','10_clusters','total_pagado']
X_rl_exp2 = conversionAVariablesNormalizadas(X,columnas_codificables_extra,columnas_numericas_extra)
mejor_valor_exp2, mejor_regularizacion_exp2, mejor_c_exp2 = obtenerMejoresHiperparametros(X_rl_exp2)
print(f"El mejor valor fue de AUC fue: {round(mejor_valor_exp2,3)}")
print(f"La regularizacion encontrada que maximiza el AUC fue: {mejor_regularizacion_exp2}")
print(f"El valor de C que maximiza el AUC fue: {mejor_c_exp2}")
Vemos que mejoro un poco mas. Probamos de armar un modelo nuevo de Regresion Logistica con los hiperparametros encontrados.
Dividimos el set de datos en sets de training y test. Luego creamos el modelo con los hiperparámetros obtenidos.
X_train, X_test, y_train, y_test = train_test_split(X_rl_exp2, y, test_size=0.25, random_state=0)
rl = None
if mejor_regularizacion_exp2 == "none":
rl = LogisticRegression(penalty = mejor_regularizacion_exp2,solver = "saga",max_iter = 5000)
else:
rl = LogisticRegression(penalty = mejor_regularizacion_exp2,l1_ratio = None, solver = "saga", C = mejor_c_exp2,max_iter = 5000)
rl.fit(X_train, y_train)
y_pred = rl.predict(X_test)
Vemos los resultados ahora con las diferentes métricas.
print(classification_report(y_test, y_pred, target_names=['No vuelve','Vuelve']))
mostrarMatrizDeConfusion(y_pred,y_test)
Graficamos la curva ROC
mostrarROCCurve(rl,"Regresion Logistica",X_test, X_train, y_test, y_train)
mostrarAUCScore(rl,"Regresion Logistica",X_test,y_test)
Observamos que se obtuvo un rendimiento bastante bueno con este modelo.
Obtenemos y preparamos el nuevo archivo realizando el mismo preprocesamiento realizado anteriormente.
holdout = obtenerHoldout()
ids_usuarios = np.array(holdout['id_usuario'])
holdout = prepararSetDeHoldout(holdout)
holdout = expansionDelDataset(holdout)
columnas_codificables_extra = ['pago_categorizado','edades_estratificadas','categoria_invitados']
columnas_numericas_extra = ['4_clusters','10_clusters','total_pagado']
holdout_rl = conversionAVariablesNormalizadas(holdout,columnas_codificables_extra,columnas_numericas_extra)
Realizamos las predicciones y escribimos al archivo CSV.
predicciones_holdout = rl.predict(holdout_rl)
escribirPrediccionesAArchivo(predicciones_holdout,"RegresionLogistica",ids_usuarios)