Después de seguir este tutorial tendrás dominados los árboles de decisión en Python 😎.
Vamos a aprender cómo implementar árboles de decisión en Python paso a paso, desde cero y utilizando únicamente la librería Numpy y lo haremos con un ejemplo sencillo.
De esta manera entenderás el funcionamiento interno de estos modelos a la perfección y cuando pasemos a utilizar la implementación de árboles de decisión de la librería Scikit-learn no habrá nada que se te escape.
Un árbol de decisión es un algoritmo de aprendizaje supervisado utilizado para resolver problemas de clasificación y regresión.
Están basados en una serie de decisiones derivadas de las características de los datos con los que se entrena.
Su estructura se asemeja a un árbol invertido, donde las decisiones fluyen desde la raíz hasta las hojas, llevando a un resultado final.
En este episodio del podcast sobre árboles de decisión te explico todo sobre los árboles de decisión en Machine Learning 🌳
En esta primera parte del tutorial construiremos un árbol de decisión desde cero, sólo utilizaremos la librería de Numpy.
Para entrenar un árbol de decisión en Python desde cero vamos a utilizar un problema de clasificación con famoso dataset del hundimiento del Titanic.
Es un clásico.
Es dataset del hundimiento del Titanic contiene información sobre los pasajeros del famoso barco que naufragó en 1912, incluyendo una variedad de características sobre los pasajeros, como su edad, sexo, clase en la que viajaban, número de hermanos o cónyuge a bordo, y el precio del billete, entre otros.
El objetivo típico al trabajar con este dataset es predecir si un pasajero sobrevivió o no al desastre, basándonos en estos atributos.
Como ves, es un ejemplo brutal para aprender sobre clasificación binaria y explorar el uso de los árboles de decisión.
Como vamos a implementar el entrenamiento del árbol de decisión desde cero vamos a utilizar un dataset muy simplificado para poder visualizar el proceso.
Nos quedaremos con estas características y las vamos a simplificar un poquito para que sean binarias:
Age
: Edad del pasajero. En nuestro caso si era menor de 18 años (Age=1
) o no (0
).Sex
: Género del pasajero. Si era mujer (1
) o no (0
).Pclass
: Si la persona viajaba en primera clase (1
) o no (0
).Para la primera parte del tutorial sólo utilizaremos los datos de 10 pasajeros (recuerda que queremos poder visualizar el árbol 🌳).
Por tanto, sólo necesitarás un Notebook de Google Colab. No es necesario que te instales nada, solo te hace falta una cuenta en Google 🙂.
Estos son los 10 pasajeros que utilizaremos en esta demo:
import numpy as np import pandas as pd # Etiquetas label = np.array([1, 1, 0, 0, 1, 0, 0, 1, 1, 0], dtype=object) etiquetas = ['RIP','Sobrevive'] # Características data = np.array([ [1, 1, 1, '👧🏻🥇'], [1, 0, 1, '👧🏻'], [1, 0, 0, '👩🏻🦱'], [1, 0, 0, '👩🏻🦱'], [1, 1, 1, '👧🏻🥇'], [0, 0, 1, '👦🏻'], [0, 0, 0, '👨🏻'], [1, 0, 1, '👧🏻'], [0, 1, 0, '🧔🏻♂️🥇'], [1, 0, 0, '👩🏻🦱'] ], dtype=object) caracteristica = ['Sex','Pclass','Age']
Para entrenar nuestro árbol de decisión, el objetivo será encontrar las características óptimas para dividir los datos de manera que consigamos la máxima pureza en los nuevos nodos en cada iteración.
Utilizaremos el criterio de mínima entropía para medir la pureza de los nodos. Cuanto menos mezcla de clases en los nodos, menor será la entropía.
Para cada característica del dataset haremos lo siguiente:
Después seleccionamos la característica con una mayor ganancia de información de todas las que hemos probado y seguimos dividiendo los nuevos nodos usando el mismo método.
Dejamos de dividir en nuevos nodos cuando hayamos llegado a la profundidad máxima del árbol (que es un hiperparámetro del modelo) o cuando todas las observaciones en un nodo pertenezcan a la misma clase.
El objetivo es que cada división en el árbol agrupe los datos de manera que las observaciones sean lo más homogéneas posible dentro de cada rama.
Para ello utilizaremos la entropía.
H(p_1) = -p_1 \text{log}_2(p_1) - (1- p_1) \text{log}_2(1- p_1)
La entropía mide el nivel de incertidumbre en un nodo. Cuanto más mezcladas estén las clases, mayor será la entropía.
Así que queremos conseguir que en nuestros nodos hojas la entropía sea lo menor posible. Eso significará que la mayoría de las observaciones en ese nodo pertenecen a la misma clase.
Como te decía antes, el objetivo del entrenamiento de un árbol de decisión es que las ramas que obtengamos al dividir el dataset de entrenamiento según la característica seleccionada sean lo más homogéneas posible.
Para ello calcularemos la ganancia de información de cada división que hagamos y nos quedaremos con la característica que nos devuelva la máxima ganancia de información.
La ganancia de información se calcula así:
\text{Ganancia de información} = H(p_1^\text{nodo})- (w^{\text{izq}}H(p_1^\text{izq}) + w^{\text{der}}H(p_1^\text{der}))
Así que vamos a crear una función que calcule la ganacia de información en un nodo.
Una vez que hemos entrenado nuestro árbol de decisión, una manera brutal de entender mejor cómo va a clasificar el desenlance de la travesía de nuevos pasajeros abordo del Titanic es visualizándolo.
Vamos a escribir una función muy sencilla para poder visualizar nuestro árbol de decisión a partir de los índices de las observaciones que hemos obtenido en cada división de las ramas.
Así podremos ver la estructura del árbol, las divisiones en cada nodo y las reglas que se han aprendido durante el entrenamiento.
Al ver el árbol, podemos observar qué características se han seleccionado en cada nodo y cómo se han realizado las divisiones, lo que facilita mucho la comprensión del modelo y nos ayudará a detectar posibles errores.
Nodo raíz: 👧🏻🥇 👧🏻 👩🏻🦱 👩🏻🦱 👧🏻🥇 👦🏻 👨🏻 👧🏻 🧔🏻♂️🥇 👩🏻🦱 Dividimos según la característica: Pclass ├─ Pclass = 1: 👧🏻🥇 👧🏻🥇 🧔🏻♂️🥇 Nodo hoja 🍃: Sobrevive └─ Pclass = 0: 👧🏻 👩🏻🦱 👩🏻🦱 👦🏻 👨🏻 👧🏻 👩🏻🦱 Dividimos según la característica: Age ├─ Age = 1: 👧🏻 👦🏻 👧🏻 Nodo hoja 🍃: Sobrevive └─ Age = 0: 👩🏻🦱 👩🏻🦱 👨🏻 👩🏻🦱 Nodo hoja 🍃: RIP
Según nuestro árbol de decisión podemos ver que las personas que viajaban en primera clase (Pclass=1
) sobreviven y de las que no viajaban en primera clase, los niños sobreviven y los adultos no.
Ya has construido un árbol de decisión muy sencillito pero desde cero.
Enhorabuena.
Ahora verás que entrenar un árbol de decisión utilizando la librería Scikit-learn es mucho más sencillo.
La librería Scikit-learn también proporciona un método de visualización del árbol de decisión menos rudimentario que el que hemos hecho nosotros antes 😅.
Si quieres saber más puedes echarle un vistazo a este resumen en español del capítulo del libro Hands-on Machine Learning with Scikit-learn Keras and Tensorflow.