Trabajo Práctico 2: Análisis con Regresión logística - Organización de Datos

Alumnos y Padrón

  • Grassano, Bruno - 103855
  • Romero, Adrián - 103371

https://github.com/brunograssano/TP-Organizacion-de-datos

Configuraciones iniciales

Importamos las bibiliotecas que utilizaremos a lo largo del notebook

In [1]:
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
In [2]:
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
In [3]:
from sklearn.linear_model import LogisticRegression
In [4]:
from preprocessing import prepararSetDeDatos
from preprocessing import prepararSetDeHoldout
from preprocessing import prepararSetDeValidacion
from preprocessing import expansionDelDataset
from preprocessing import conversionAVariablesNormalizadas
In [5]:
from funcionesAuxiliares import mostrarAUCScore
from funcionesAuxiliares import mostrarROCCurve
from funcionesAuxiliares import mostrarMatrizDeConfusion
from funcionesAuxiliares import escribirPrediccionesAArchivo
from funcionesAuxiliares import obtenerDatasets
from funcionesAuxiliares import obtenerHoldout

Importamos los datos y los procesamos

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.

In [6]:
X, y = obtenerDatasets()

X = prepararSetDeDatos(X)
y = prepararSetDeValidacion(y)

Funciones Auxiliares

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.

In [7]:
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

Regresión logística

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.

In [8]:
X_rl = conversionAVariablesNormalizadas(X)

Buscamos los mejores hiperparámetros

En la búsqueda de los hiperparámetros consideramos que los más importantes eran los siguientes:

  • Penalidad
  • C

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.

In [9]:
mejor_valor, mejor_regularizacion, mejor_c = obtenerMejoresHiperparametros(X_rl)
In [10]:
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}")
El mejor valor fue de AUC fue: 0.856
La regularizacion encontrada que maximiza el AUC fue: none
El valor de C que maximiza el AUC fue: 5

Vemos ahora con la expansion.

In [11]:
X = expansionDelDataset(X)
In [12]:
X.head()
Out[12]:
sufijo tipo_de_sala genero edad amigos parientes precio_ticket fila nombre_sede autocompletamos_edad 2_clusters 4_clusters 10_clusters cantidad_total_invitados total_pagado pago_categorizado edades_estratificadas categoria_invitados
0 Señor 4d hombre 73.0 0 0 1 No responde fiumark_quilmes False 1 1 4 0 1 Pago poco mayor Fue solo
1 Señora 4d mujer 35.0 1 1 2 No responde fiumark_quilmes False 0 2 0 2 6 Pago normal adulto Fue en grupo
2 Señor normal hombre 32.0 0 0 3 No responde fiumark_chacarita True 0 2 0 0 3 Pago normal adulto Fue solo
3 Señor 4d hombre 32.0 0 0 1 No responde fiumark_palermo True 0 2 0 0 1 Pago poco adulto Fue solo
4 Señorita 4d mujer 4.0 1 1 2 No responde fiumark_palermo False 0 3 3 2 6 Pago normal ninio Fue en grupo
In [13]:
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)
In [14]:
mejor_valor_exp, mejor_regularizacion_exp, mejor_c_exp = obtenerMejoresHiperparametros(X_rl_exp)
In [15]:
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}")
El mejor valor fue de AUC fue: 0.857
La regularizacion encontrada que maximiza el AUC fue: none
El valor de C que maximiza el AUC fue: 0.1

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.

In [16]:
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)
In [17]:
mejor_valor_exp2, mejor_regularizacion_exp2, mejor_c_exp2 = obtenerMejoresHiperparametros(X_rl_exp2)
In [18]:
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}")
El mejor valor fue de AUC fue: 0.858
La regularizacion encontrada que maximiza el AUC fue: none
El valor de C que maximiza el AUC fue: 5

Vemos que mejoro un poco mas. Probamos de armar un modelo nuevo de Regresion Logistica con los hiperparametros encontrados.

Evaluamos las métricas

Dividimos el set de datos en sets de training y test. Luego creamos el modelo con los hiperparámetros obtenidos.

In [19]:
X_train, X_test, y_train, y_test = train_test_split(X_rl_exp2, y, test_size=0.25, random_state=0)
In [20]:
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)
In [21]:
rl.fit(X_train, y_train)
Out[21]:
LogisticRegression(max_iter=5000, penalty='none', solver='saga')
In [22]:
y_pred = rl.predict(X_test)

Vemos los resultados ahora con las diferentes métricas.

In [23]:
print(classification_report(y_test, y_pred, target_names=['No vuelve','Vuelve']))
              precision    recall  f1-score   support

   No vuelve       0.83      0.87      0.85       121
      Vuelve       0.79      0.74      0.76        80

    accuracy                           0.82       201
   macro avg       0.81      0.80      0.81       201
weighted avg       0.81      0.82      0.81       201

In [24]:
mostrarMatrizDeConfusion(y_pred,y_test)

Graficamos la curva ROC

In [25]:
mostrarROCCurve(rl,"Regresion Logistica",X_test, X_train, y_test, y_train)
In [26]:
mostrarAUCScore(rl,"Regresion Logistica",X_test,y_test)
AUC para Regresion Logistica: 0.871

Observamos que se obtuvo un rendimiento bastante bueno con este modelo.

Predicciones sobre el nuevo archivo

Obtenemos y preparamos el nuevo archivo realizando el mismo preprocesamiento realizado anteriormente.

In [27]:
holdout = obtenerHoldout()
ids_usuarios = np.array(holdout['id_usuario'])
holdout = prepararSetDeHoldout(holdout)
holdout = expansionDelDataset(holdout)
In [28]:
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.

In [29]:
predicciones_holdout = rl.predict(holdout_rl)
In [30]:
escribirPrediccionesAArchivo(predicciones_holdout,"RegresionLogistica",ids_usuarios)