Predictor de infidelidad (III): Ejemplo de regresión logística en Python

Wednesday, February 27, 2019

Predictor de infidelidad (III): Ejemplo de regresión logística en Python

Ya estamos llegando al final del nuestro experimento. Tras introducir el problema y explorar el dataset en el primer post, y aprender cómo funciona el algoritmo de regresión logística, en el segundo, ya estamos listos para crear nuestro modelo a partir de los datos y... aplicarlo.  ¿Te animas a llegar hasta el final?

Imagen de un escenario para boda


En este tercer y último  post aprenderemos lo siguiente:

  • Como crear un predictor usando el modelo de regresión logística de scikit-learn
  • Cómo valorar sus métricas 
  • Cómo hacer una predicción
  • Qué conclusiones podemos extraer

Retomamos pues, nuestro Python notebook, donde, ya habíamos realizado la carga y exploración de los datos y creado la variable objetivo, a la que llamamos "infidelity". 
(Como hemos hecho en los post anteriores, primero, explicaremos paso a paso con imágenes cómo hacerlo, y al final del proceso, incorporamos la versión final editable de la que podéis copiar directamente el código para pegarlo en vuestro notebook )

3. Aplicación del modelo.


Para aplicar el modelo de regresión logística, vamos a usar una librería de Python, Patsy, que permite generar de forma muy cómoda el formato de matrices con el que funciona este modelo. Vamos a recordar un poco cómo era la notación matemática, para entender cuál debe ser el formato de entrada al modelo. La regresión logística era una transformación lineal (con salida no lineal) que se podía expresar de la siguiente manera:

Fórmula de una transformación lineal.
Figura 1: Fórmula de una transformación lineal.

Donde Y es la variable dependiente u objetivo que queremos estimar (“infidelity”), y X son las variables dependientes o predictoras, que “condicionan” el valor de la Y (“age”, “religious”, “children” etc). Los valores de los coeficientes βi son los que el modelo va a aprender” entrenándose con valores conocidos del dataset. Una vez entrenado el modelo, será capaz de predecir qué valor tendrá Y para un caso no recogido en los datos de entrenamiento. La fórmula  también puede expresarse de esta forma, como producto escalar:

Transformación lineal expresada como producto escalar.
Figura 2: Transformación lineal expresada como producto escalar.

Si  generalizamos para más de una observación Xi, necesitamos generar una matriz como esta:

Transformación lineal expresada de forma matricial.
Figura 3: Transformación lineal expresada de forma matricial.

3.1 Formateamos los datos con Patsy


La librería Patsy permite, precisamente, generar estas matrices de forma muy ágil gracias a la función dmatrices   y a su notación de fórmula. Además, dmatrices añade de forma automática la columna de “1” necesaria para obtener los términos de corte (εi), conocidos como “intercept terms”.

Otra de las ventajas de Patsy es que permite trabajar con datos categóricos de forma muy flexible, gracias a la función C(), que indica que los datos entre los paréntesis deben tratarse como etiquetas y no como números. En nuestro ejemplo, vamos a usarlo para que no considere como números los códigos de ocupación. Esta operación es lo que se llama, convertir datos en “dummy”.

Por tanto, al aplicar la función dmatrices con esta sintaxis, obtenemos como resultado dos matrices. La primera, con los resultados o valores de la variable objetivo “y”, y la segunda, con los valores de las variables independientes X o datos predictores:

Sintaxis de de función dmatrices de Patsy.
Figura 4: Sintaxis de de función dmatrices de Patsy.




Para nuestro ejemplo:
y, X = dmatrices('infidelity ~ rate_marriage + age +  yrs_married + children + religious+ educ + C(occupation) + C(occupation_husb) ', dta, return_type = 'dataframe')

Con esta sentencia obtenemos las dos matrices que hemos mencionado antes, en las que los valores de  “infidelity”(y) son iguales al producto de los valores de la matriz que representa las variables independientes (X) por unos coeficientes, más un término de corte. Al mismo tiempo indicamos que no use los valores de códigos de ocupación como numéricos sino como categóricos.

Código para convertir la matriz de datos en el formato necesario para aplicar el modelo.
Figura 5: Código para convertir la matriz de datos en el formato necesario para aplicar el modelo.











Comprobamos las dimensiones de las matrices de salida, y sus índices:

Código para comprobar las dimensiones de las matrices.
Figura 6: Código para comprobar las dimensiones de las matrices.

3.2 Aplicamos el modelo


Ya sólo nos queda un último paso para poder aplicar el modelo de regresión logística de scikit-learn, y es convertir el vector columna y en matriz 1D.  A continuación, ya podemos aplicar directamente el modelo LogisticRegression. Como resultado del entrenamiento del modelo, obtenemos la matriz de coeficientes:

Aplicación del modelo.
Figura 7: Aplicación del modelo.







Podemos ver que la precisión del modelo es de un 73%:

Estimación de la precisión.
Figura 8: Estimación de la precisión.





También, podemos estimar también qué porcentaje de individuos tienen alguna aventura, obteniendo un resultado de un 32%


Porcentaje de individuos infieles.
Figura 9: Porcentaje de individuos infieles.





La matriz de coeficientes obtenida muestra qué peso tiene cada uno de los coeficientes. Para visualizarlo, podemos usar List(zip), que crea una matriz a partir de dos listas, la que contiene el nombre de los índices, en la primera columna, y los valores en la segunda.

Código para obtener la matriz de coeficientes.
Figura 10: Código para obtener la matriz de coeficientes.



Por ejemplo, podemos ver cómo los incrementos en rate_marrige y religiousnes disminuyen la probabilidad de infidelidad. Lo cual es consistente con el análisis de correlación de variables que hicimos en el primer post.

Coeficientes.
Figura 11: Coeficientes.

3.3 Evaluamos el modelo


Para evaluar el modelo, dividimos el dataset en dos partes. Dejamos un 75% de los datos como datos de entrenamiento (train), y reservamos el 25% restando como datos de prueba (test). A continuación, entrenamos el modelo de nuevo, pero ahora sólo con los datos de entrenamiento. 


Dividimos el dataset en train y test.
Figura 12: Dividimos el dataset en train y test.













Una vez entrenado el modelo, lo aplicamos a los datos reservados como "test", y calculamos las  métricas precisión (Accurary) y exactitud (Precision). Cuidado con los "false friends"-


Hemos obtenido unos valores de un 73% para la precisión, que no es que sea muy alto, pero tampoco es un mal resultado. Indica que la dispersión de los valores es baja. Sin embargo, la exactitud, es sólo de un 62%. No es un dato muy bueno, ya que se refiere a lo cerca que está un resultado del valor verdadero.


Los valores de la diagonal principal de la matriz de confusión (993, 176) indican las predicciones correctas, tanto para verdaderos positivos, como verdaderos negativos. La otra diagonal (con valores 316, 117) recoge las predicciones erróneas.

 Calculamos precisión, exactitud y matriz de confusión.
Figura 13: Calculamos precisión, exactitud y matriz de confusión.

Para ver la matriz de confusión de forma mucho más "visual", podemos hacerlo en forma de mapa de calor:


Vemos la matriz de confusión como mapa de calor usando seaborn.
Figura 14: Código para ver la matriz de confusión como mapa de calor usando seaborn.

Matriz de confusión en forma de mapa de calor.
Figura 15: Matriz de confusión en forma de mapa de calor.

3.4 Hacemos una predicción

  
Por último, ya sólo nos queda hacer una predicción usando el modelo que acabamos de crear.  Para que nos resulta más fácil "escribir" los datos de entrada, usaremos el indexador iloc para extraer ,como ejemplo, uno de los registros de la matriz de datos. En particular hemos elegido el registro número 4.




Extraemos un registro del dataset como ejemplo.
Figura 16: Extraemos un registro del dataset como ejemplo.

Como resultado, podemos ver el aspecto que tiene este registro en concreto, lo reconvertimos en el formato necesario para poder aplicar el modelo y, ya que estamos, lo probamos. En este caso, la probabilidad de infidelidad es de un 30%.


Visualización de ese registro concreto.
Figura 17: Visualización de ese registro concreto.

A continuación, lo usaremos de base para introducir en el modelo los datos concretos para los que queremos obtener una predicción mediante el método keys(). Por ejemplo: mujer de 35 años, con 3 hijos, no religiosa,nivel educativo alto, con ocupaciones (ambos) técnicos especializados y una buena valoración de su matrimonio.

F.keys();F['age']=35; F['children']=3; F['yrs_married']=10; F['religious']=1; F['religious']=1; F['C(occupation_husb)[T.3.0]']=1

Cambiamos con F.keys() los valores de cada variable para introducir los que queramos
Figura 18: Cambiamos con F.keys() los valores de cada variable para introducir los que queramos






Al aplicar el modelo a este caso en particular, obtenemos como resultado una probabilidad de infidelidad del 29%. Prueba con los datos que quieras, ¿qué resultados obtienes?

esultado obtenido al aplicar el modelo al nuevo caso.
Figura 19: Resultado obtenido al aplicar el modelo al nuevo caso.

¿Te animas a probarlo? A continuación, tienes el código completo del experimento, que puedes cortar y pegar en tu Jupyter notebook. Te recomendamos que lo vayas haciendo paso a paso, como lo hemos explicado, para poder entender qué se hace en cada momento. Incluso, puedes ir introduciendo pequeñas modificaciones para probar cosas nuevas. 
Código


Código


4. Conclusiones

Llegado el momento de sacar conclusiones, tenemos que pararnos a reflexionar. ¿Cuál ha sido el objetivo del experimento?. Hemos aprendido a crear un modelo de predicción basado en regresión logística. Hemos conocido y aprendido a cargar los datasets de Statsmodels. Hemos recordado un poco de álgebra de matrices para comprender mejor el modelo. Y sí, hemos aplicado el modelo a nuestros datos (¿a que no te has resistido?), pero ¿tiene algún tipo de validez el resultado?.

A pesar de haber hecho un análisis serio, que, por supuesto se podría haber hecho siguiendo otros enfoques, por ejemplo, reduciendo por ejemplo el número de variables a considerar tras el análisis de correlación, o aplicando el modelo de staatsmodel en lugar del del scikit learn, o incluso eligiendo otro algoritmo de clasificación; nunca debemos olvidar sobre qué estamos construyendo nuestro modelo. Nos referimos, por supuesto, a los datos. Y un dataset cuyo origen es una encuesta realizada en los años 70 por una revista femenina en EEUU no parece que pueda ser extrapolable al momento actual, ni a latitudes tan distantes como la nuestra. Si embargo, en la era de las apps "para ligar" o encontrar tu media naranja, hay que ser conscientes de lo que una buena analítica de datos podría obtener a partir de sus bases de datos que, por supuesto, están protegidas por leyes de privacidad. Pero...ahí están.

Para mantenerte al día con LUCA visita nuestra página web,  suscríbete a LUCA Data Speaks o síguenos en TwitterLinkedIn YouTube.

No comments:

Post a Comment