Analizando conversión de clientes con Machine Learning y árboles de decisión

Aquí ampliaremos sus conocimientos sobre el análisis explicativo y le mostraremos cómo utilizar los árboles de decisión para comprender los impulsores del comportamiento del consumidor. Comenzaremos comparando y explicando las diferencias entre los modelos de regresión logística y de árboles de decisión, y luego discutiremos cómo se construyen y entrenan los árboles de decisión.

Regresión logística frente a árboles de decisión

Un modelo de regresión logística aprende de los datos encontrando la combinación lineal de variables de características que mejor estima la probabilidad logística de que ocurra un evento. Los árboles de decisión, como su nombre indica, aprenden de los datos haciendo crecer un árbol.

Más adelante hablaremos de cómo crecen los modelos de árboles de decisión y cómo se construyen los árboles con más detalle, pero primero... La principal diferencia entre los modelos de regresión logística y de árbol de decisión es el hecho de que los algoritmos de regresión logística buscan un único y mejor límite lineal en el conjunto de características, mientras que el algoritmo de árbol de decisión divide los datos para encontrar los subgrupos de datos que tienen una alta probabilidad de que ocurra un evento. Será más fácil explicar esto con un ejemplo. Veamos el siguiente diagrama:

arbol-de-decision.png

Este es un ejemplo de modelo de árbol de decisión. Como puede ver en este diagrama, divide los datos con ciertos criterios. En este ejemplo, el nodo raíz se divide en nodos hijos mediante un criterio de < 0,5. Si esta condición se cumple y es verdadera, entonces se mueve al nodo hijo de la izquierda. Si no, se mueve al nodo hijo de la derecha.

El nodo hijo de la izquierda se divide entonces en sus nodos hijos por un criterio de edad de < 61. El árbol crece hasta que encuentra nodos puros (lo que significa que todos los puntos de datos de cada nodo pertenecen a una clase) o hasta que cumple ciertos criterios de parada, como la profundidad máxima del árbol. Como puede ver en este ejemplo, los datos se dividen en siete particiones

El nodo más a la izquierda o la partición más baja es para aquellos puntos de datos con valores inferiores a 0,5 para la variable previous y con valores inferiores a 61 para la variable age. Por otro lado, el nodo de la derecha, en la parte inferior, es para aquellos puntos de datos con valores superiores a 0,5 para la variable anterior y con valores diferentes para la variable vivienda.

Una cosa que se nota aquí es que hay muchas interacciones entre las diferentes variables. Ningún nodo de una sola hoja en este árbol de ejemplo está dividido con una condición. Cada partición de este árbol se forma con más de un criterio y con interacciones entre diferentes características. Esta es la principal diferencia con los modelos de regresión logística.

Cuando no hay una estructura lineal en los datos, los modelos de regresión logística no pueden funcionar bien, ya que intentan encontrar combinaciones lineales entre las variables de las características. Por otro lado, los modelos de árboles de decisión funcionarán mejor para conjuntos de datos no lineales, ya que sólo intentan dividir los datos en los niveles más puros que puedan.

Creciendo los árboles de decisión

Cuando los árboles de decisión crecen, los árboles necesitan tener una lógica para dividir un nodo en nodos hijos. Hay dos métodos principales que se utilizan habitualmente para dividir los datos: La impureza de Gini y la ganancia de información de la entropía. En pocas palabras, la impureza de Gini mide el grado de impureza de una partición, y la ganancia de información de la entropía mide la cantidad de información que gana al dividir los datos con los criterios que se están probando.

Echemos un vistazo a la ecuación para calcular la medida de impureza de Gini:

Screenshot%20from%202021-03-09%2007-53-24.png

Aquí, la c representa las etiquetas de clase, y Pi representa la probabilidad de que se elija la etiqueta de clase i. Al restar la suma de las probabilidades al cuadrado de uno, la medida de impureza de Gini llega a cero, es decir, cuando todos los registros de cada partición o nodo de un árbol son puros con una sola clase objetivo.

La ecuación para calcular la entropía es la siguiente

Screenshot%20from%202021-03-09%2007-55-02.png

Como antes, la c representa las etiquetas de clase, y Pi representa la probabilidad de que se elija la etiqueta de clase i. A medida que el árbol crece, la entropía de cada posible división debe calcularse y compararse con la entropía anterior a la división. A continuación, se elegirá la división que dé el mayor cambio en las medidas de entropía o la mayor ganancia de información para hacer crecer el árbol

Este proceso se repetirá hasta que todos los nodos sean puros, o hasta que se cumplan los criterios de parada

Interpretación de los árboles de decisión

Interpretaremos los resultados mediante visualizaciones utilizando el paquete Python graphviz. Comenzaremos analizando en profundidad el conjunto de datos de marketing bancario, utilizando los paquetes pandas y matplotlib, y luego discutiremos cómo construir e interpretar los modelos de árboles de decisión.

El dataset podrás encontrarlo aqui. Descargalo, móntalo en tu ambiente y estarás listo para iniciar

Primero importa Matplotlib y Pandas en la siguiente celda

Y ahora import el dataset con pandas y guardalo en una variable llamada df

Nota: debes usar el parámetro sep=";" de Pandas, ya que los datos estan separados por ;

Imprime ahora el .head() y el shape para entender un poco mejor los datos

Ingeniería de características

Antes de empezar a analizar los datos, primero codificaremos la variable de salida, y, que tiene información sobre si un cliente ha comprado o suscrito un depósito a plazo, con valores numéricos. Haz un "label encoding" de la variable de salida y, donde: no es igual a 0 y yes es igual a 1 y el resultado asignalo a una nueva columna llamada: conversion

Codificación de las variables categóricas

Hay ocho variables categóricas en este conjunto de datos: job, marital, education, default, housing, loan, contact, and month. Antes de empezar a construir árboles de decisión, tenemos que codificar estas variables categóricas con valores numéricos. Veremos cómo podemos codificar algunas de estas variables categóricas en esta sección.

Codificación de los meses

Todos sabemos que sólo puede haber 12 valores únicos para la variable mes. Como hay un orden natural en los valores del mes, podemos codificar cada uno de los valores con un número correspondiente. Cambie la columna month para el el mes jan sea igual a 1, feb sea igual a 2 y asi sucesivamente hasta dec sea igual a 12

Codificación de job

A continuación, vamos a ver cómo podemos codificar las diferentes categorías de la columna job. Primero revise los valores únicos de esta columna uando el metodo nunique de pandas

Como puede ver en esta salida, no hay un orden natural para esta variable. Una categoría de trabajo no precede a la otra, por lo que no podemos codificar esta variable como lo hicimos para el mes.

Vamos a crear variables ficticias (dummy variables) para cada una de las categorías de trabajo. Una variable ficticia es una variable que se codifica con 1 si un determinado registro pertenece a la categoría, y con 0 si no. Podemos hacerlo fácilmente utilizando get_dummies() de pandas. Cree una nueva variables con el nombre jobs_encoded_df y ejecute el get_dummies() sobre la columna job

Ahora que hemos creado variables ficticias para cada categoría de trabajo, tenemos que añadir estos datos al DataFrame original. Esto lo puedes hacer con el metodo concat de pandas. Concatena ahora entonces df y jobs_encoded_df. No olvides pasar el parametro axis=1 al concat para que se haga la concatenación entre columnas.

Usando la función concat del paquete pandas, se puede añadir fácilmente el DataFrame recién creado con variables ficticias, jobs_encoded_df, al DataFrame original, df. El argumento axis=1 indica a la función concat que concatene el segundo DataFrame con el primero como columnas, no como filas.

Como puede ver, las variables ficticias recién creadas se añaden al DataFrame original como nuevas columnas para cada registro.

Codificación de Marital.

De forma similar a como codificamos la variable categórica, job, crearemos variables ficticias para cada categoría de la variable marital. Asi que haz lo mismo que en el paso anterior, y esta vez asigna el resultado del dummy en una variable llamada marital_encoded_df. Recuerda también hacer el concat

Una vez que haya llegado hasta aquí, su DataFrame original, df, debería contener todas las columnas originales, más las variables ficticias recién creadas para las columnas de trabajo y matrimonio.

Codificación de las variables de vivienda y préstamo

Las dos últimas variables categóricas que codificaremos en esta sección son la vivienda y el préstamo. La variable vivienda tiene dos valores únicos, "yes" y "no", y contiene información sobre si un cliente tiene un préstamo para vivienda. La otra variable, préstamo, también tiene dos valores únicos, "yes" y "no", y nos dice si un cliente tiene un préstamo personal. Podemos codificar estas dos variables utilizando el mismo código que usaste para el encoding de la variable objetivo y y cuyo resultado fue asignado a la variable conversion. Asi que ahora hazlo sobre las columnas mencionadas

Construcción de los árboles de decisión

Ahora que hemos codificado todas las variables categóricas, podemos empezar a construir modelos de árboles de decisión. Utilizaremos las siguientes variables como características en nuestros modelos de árboles de decisión:

features = [
    'age',
    'balance',
    'campaign',
    'previous',
    'housing',
    'admin.',
    'blue-collar',
    'entrepreneur',
    'housemaid',
    'management',
    'retired',
    'self-employed',
    'services',
    'student',
    'technician',
    'unemployed',
    'unknown',
    'divorced',
    'married',
    'single'
]

Copia y pega este código en la siguiente celda

Para construir y entrenar un modelo de árbol de decisión con Python, utilizaremos el módulo tree del paquete scikit-learn. Puedes importar el módulo requerido en la siguiente celda

Bajo el módulo de árbol en el paquete sklearn, hay una clase llamada DecisionTreeClassifier, que podemos utilizar para entrenar un modelo de árbol de decisión. Hazlo de ls siguiente manera: tree.DecisionTreeClassifier y pasale como parámetro una profundidad mazima de 4: max_depth=4. Asigna el resultado a la variable llamada dt_model

Hay muchos argumentos para la clase DecisionTreeClassifier, aparte del que estamos utilizando aquí, max_depth. El argumento max_depth controla cuánto puede crecer un árbol, y aquí, lo limitamos a 4, lo que significa que la longitud máxima de la raíz a la hoja puede ser 4.

También puede utilizar el argumento criterion para elegir entre las medidas de impureza de Gini y de ganancia de información de la entropía para la calidad de una división.

Hay muchas otras formas de ajustar su modelo de árbol de decisión, y le recomendamos que eche un vistazo a la documentación en para más información.

Para entrenar este modelo de árbol de decisión, puedes utilizar el metodo fit, asi que ejecútalo pasandole los valores de X como la lista features que acabamos de crear e y como la columna conversion

Interpretación de los árboles de decisión

Ahora que hemos entrenado un modelo de árbol de decisión, necesitamos extraer el conocimiento del modelo. En esta sección, vamos a utilizar un paquete llamado graphviz. Puedes instalar este paquete usando el siguiente comando en tu notebook: !pip3 install python-graphviz o si tienes un error, con este otro codigo tambien lo puedes hacer !pip3 install graphviz

Ahora importa el paquete con el siguiente comando import graphviz

Ahora que hemos configurado nuestro entorno con el nuevo paquete, graphviz, ejecuta siguiente código para ver cómo podemos visualizar el árbol de decisión entrenado:

dot_data = tree.export_graphviz(
    dt_model, 
    feature_names=features, 
    class_names=['0', '1'], 
    filled=True, 
    rounded=True, 
    special_characters=True
) 

graph = graphviz.Source(dot_data)

Copia y pega este codigo en la siguiente celda

Ahora solo debes escribir el nombre de la variable graph en la siguiente celda. Hazlo!

Como puedes ver, primero exportamos el modelo de árbol de decisión entrenado, dt_model, usando la función export_graphviz en el módulo tree del paquete sklearn.

Podemos definir las variables de características que usamos para entrenar este modelo usando el argumento feature_names. A continuación, podemos definir las clases (conversión frente a no conversión) que este modelo está entrenado para clasificar.

La función export_graphviz exporta el modelo de árbol de decisión entrenado en formato DOT, que es un lenguaje de descripción gráfica. Entonces, puedes pasar dot_data a la clase Source de graphviz. La variable graphviz contiene ahora un gráfico renderizable.

Echemos un vistazo más de cerca a este diagrama. Cada nodo contiene cinco líneas que describen la información que tiene el nodo en cuestión. La línea superior nos indica el criterio de división. El nodo raíz, por ejemplo, se divide en sus nodos hijos en función del valor de la variable previous. Si el valor de esta variable anterior es menor o igual que 0,5, entonces pasa al hijo de la izquierda. En cambio, si el valor de esta variable anterior es mayor que 0,5, entonces va al hijo de la derecha.

La segunda línea nos indica el valor de la medida de calidad para la división. Aquí, seleccionamos la medida de impureza gini para el criterio, por lo que podemos ver los cambios en las medidas de impureza en cada nodo en la segunda línea. La tercera línea nos indica el número total de registros que pertenecen al nodo dado. Por ejemplo, hay 45.211 muestras en el nodo raíz, y hay 8.257 muestras en el hijo derecho del nodo raíz.

La cuarta línea de cada nodo nos indica la composición de los registros en dos clases diferentes. El primer elemento representa el número de registros en el grupo de no conversión, y el segundo elemento representa el número de registros en el grupo de conversión. Por ejemplo, en el nodo raíz, hay 39.922 registros en el grupo de no conversión y 5.289 registros en el grupo de conversión. Por último, la quinta línea de cada nodo nos indica cuál será la predicción o clasificación del nodo en cuestión. Por ejemplo, si una muestra pertenece a la hoja más a la izquierda, la clasificación de este modelo de árbol de decisión será 0, lo que significa que no habrá conversión. Por otro lado, si una muestra pertenece a la octava hoja desde la izquierda, la clasificación de este modelo de árbol de decisión será 1, lo que significa que habrá conversión.

Ahora que sabemos lo que significa cada línea de cada nodo, vamos a discutir cómo podemos obtener información de este gráfico de árbol. Para conocer los clientes que pertenecen a cada nodo hoja, tenemos que recorrer el árbol. Por ejemplo, los clientes que pertenecen al octavo nodo de hoja de la izquierda son los que tienen un valor de 0 para la variable anterior, una edad superior a 60,5, una variable divorciado_marital con un valor de 1, y una variable trabajador_autónomo con un valor de 1. Es decir, aquellos que no fueron contactados antes de esta campaña y que son mayores de 60,5, divorciados y autónomos pertenecen a este nodo, y tienen una alta probabilidad de conversión.

Veamos otro ejemplo. Los clientes que pertenecen al segundo nodo de la hoja de la derecha son los que tienen un valor de 1 para la variable anterior, un valor de 1 para la variable vivienda, una edad superior a 60,5 y un saldo inferior o igual a 4.660,5. Es decir, a este nodo pertenecen los clientes que fueron contactados antes de esta campaña y que tienen un crédito a la vivienda, son mayores de 60,5, y tienen un saldo bancario inferior a 4.660,5 y 20 de los 29 que pertenecen a este nodo han sido convertidos y suscritos a un depósito a plazo fijo.

Como habrá notado en estos dos ejemplos, se puede obtener un conocimiento útil sobre quién es más o menos probable que se convierta a partir de modelos de árboles de decisión entrenados, visualizando el árbol entrenado. Sólo tiene que seguir los nodos y comprender qué tipos de atributos están altamente correlacionados con su clase objetivo. Para este ejercicio, restringimos el árbol para que crezca sólo hasta una profundidad de 4, pero usted puede elegir crecer un árbol más grande o más pequeño que el que usamos en este ejercicio.

Esperamos le haya gustado y aprendido de este reto!