Los árboles de decisión son una técnica de aprendizaje automático supervisado muy utilizada en muchos negocios. Como su nombre indica, esta técnica de machine learning toma una serie de decisiones en forma de árbol. Los nodos intermedios (las ramas) representan soluciones. Los nodos finales (las hojas) nos dan la predicción que vamos buscando.

Los árboles de decisión pueden usarse para resolver problemas tanto de clasificación como de regresión. Veamos cómo se usan en cada caso con ejemplos.

Árboles de Decisión para Clasificación

Datos para clasificación – Iris

Para explicar cómo funcionan los árboles de decisión con problemas de clasificación vamos a usar el conjunto de datos Iris. El problema consiste en clasificar correctamente la variedad de la flor iris a partir del ancho y largo de los pétalos y sépalos. Hay tres variedades de flor irissetosa, versicolorvirginica.

Este conjunto de datos tiene 150 muestras:

  • 50 iris setosa
  • 50 iris versicolor
  • 50 iris virginica

conjunto de datos iris para clasificación

Teoría de los árboles de decisión para clasificación

Si le damos las 150 flores del conjunto de datos Iris a un árbol de decisión para que lo clasifique, nos quedaría un árbol como el que se muestra a continuación. Vamos a aprender a leerlo:

  • cada color representa a una clase. El marrón para setosa, el verde para versicolor y el lila para virginica.
  • el color es más intenso cuanto más seguros estamos que la clasificación es correcta
  • los nodos blancos, por tanto, evidencia la falta de certeza
  • Hay dos tipos de nodo:
    • Nodos de decisión: tienen una condición al principio y tienen más nodos debajo de ellos
    • Nodos de predicción: no tienen ninguna condición ni nodos debajo de ellos. También se denominan «nodos hijo»

La información de cada nodo es la siguiente:

  • condición: si es un nodo donde se toma alguna decisión
  • gini: es una medida de impureza. A continuación veremos cómo se calcula
  • samples: número de muestras que satisfacen las condiciones necesarias para llegar a este nodo
  • value: cuántas muestras de cada clase llegan a este nodo
  • class: qué clase se le asigna a las muestras que llegan a este nodo

Árbol de Decisión para el problema de clasificación Iris

Interpretación

La interpretación del árbol de este árbol de decisión sería: si la longitud del pétalo es menos de 2.45 centímetros, entonces la flor iris pertenece a la variedad setosa. Si por el contrario, la longitud del pétalo es mayor que 2.45 centímetros, habría que mirar al ancho del pétalo. Cuando el ancho del pétalo es menor o igual a 1.75 centímetros, pertenece a la variedad versicolor con un 91% de probabilidad. Si no, parece que sería virginica con un 98% de probabilidad.

Gini: medida de impureza

Gini es una medida de impureza. Cuando Gini vale 0, significa que ese nodo es totalmente puro. La impureza se refiere a cómo de mezcladas están las clases en cada nodo. Para calcular la impureza gini, usamos la siguiente fórmula:

$$gini = 1\ – \sum_{k=1}^{n}{p_c^2}$$

pc se refiere a la probabilidad de cada clase. Podemos calcularla dividiendo el número de muestras de cada clase en cada nodo por el número de muestras totales por nodo.

Por ejemplo, para el caso del nodo donde la clasificación es versicolor, el cálculo sería el siguiente:

$$gini_{versicolor} = 1\ – \sum_{k=1}^{n}{p_c^2} = 1\ – \left(\frac{0}{54}\right)^2 – \left(\frac{49}{54}\right)^2 – \left(\frac{5}{54}\right)^2=0.168$$

¿Cómo se construyen los árboles de decisión para problemas de clasificación?

Los árboles de decisión se construyen usando un algoritmo voraz que optimiza la siguiente función de coste:

$$J(a,l_a)=\frac{m_{izquierdo}}{m}Gini_{izquierdo} + \frac{m_{derecho}}{m}Gini_{derecho}$$

  • a es la abreviatura de atributo (también llamado característica o feature)
  • la significa el límite del atributo
  • m se refiere al número de muestras

Por ejemplo, al comprobar si la longitud del pétalo es menor o igual a 2.45 centímetros, tenemos:

  • a = longitud del pétalo
  • la = 2.45
  • = 150

El algoritmo voraz elige qué atributos y qué límites son los mejores para tomar las decisiones. Al usar un algoritmo voraz, no tenemos la garantía de que este sea el mejor árbol posible. Sin embargo, en la práctica, obtenemos un árbol bastante bueno mucho más rápidamente que si necesitáramos el «mejor árbol posible».

Código python para entrenar y predecir con árboles de decisión para clasificación

# importamos las librerías que necesitamos
from sklearn.datasets import load_iris # datos de iris
from sklearn.tree import DecisionTreeClassifier # árbol de decisión para clasificación

iris = load_iris()
print(iris.DESCR) # información sobre del conjunto de datos iris

# lo más relevante es:
#    :Number of Instances: 150 (50 in each of three classes)
#    :Number of Attributes: 4 numeric, predictive attributes and the class
#    :Attribute Information:
#        - sepal length in cm
#        - sepal width in cm
#        - petal length in cm
#        - petal width in cm
#        - class:
#                - Iris-Setosa
#                - Iris-Versicolour
#                - Iris-Virginica

# veamos 4 filas donde ocurre un cambio de clase
print(iris.data[48:52,:])

# da el resultado
# [[5.3 3.7 1.5 0.2]
#  [5.  3.3 1.4 0.2]
#  [7.  3.2 4.7 1.4]
#  [6.4 3.2 4.5 1.5]]

# para la variable a predecir también hacemos lo mismo
print(iris.target[48:52])

# La clase 0 es Iris-Setosa, la 1 es Iris-Versicolor y la 2 es Iris-Virginica
# [0 0 1 1]

# Vamos a crear y entrenar un árbol de decisión para clasificar los datos de Iris
tree = DecisionTreeClassifier(max_depth=2, random_state=42) # vamos a usar un árbol de profundidad 2
tree.fit(iris.data, iris.target) # entrenamiento del árbol

# podemos usar el método predict para obtener predicciones
print( tree.predict(iris.data[47:53]) )

# resulta en
# [0 0 0 1 1 1]

# si queremos saber las probabilidades podemos usar el método predict_proba
print( tree.predict_proba(iris.data[47:53]) )

# la primera clase (Setosa) es la primera columna, la segunda clase en la segunda, etc..
# este es el resultado:
# [[1.         0.         0.        ]
#  [1.         0.         0.        ]
#  [1.         0.         0.        ]
#  [0.         0.90740741 0.09259259]
#  [0.         0.90740741 0.09259259]
#  [0.         0.90740741 0.09259259]]

Árboles de Decisión para Regresión

Datos para regresión

Para explicar cómo funcionan los árboles de decisión para problemas de regresión vamos a usar los datos que se presentan en la siguiente gráfica. Para generarlos he usado la siguiente fórmula en el intervalo [-5, 5]:

$$ y = 0.1x^2 + 0.2 (Ruido\ Gaussiano)$$Datos para el árbol de decisión para regresión

Teoría de los árboles de decisión para regresión

En el caso de regresión, en lugar de usar Gini como medida de impureza, usamos MSE, el error cuadrático medio. Para este problema, si usamos un árbol de decisión de profundidad 2, obtenemos el siguiente árbol.

Árbol de Decisión para Regresión

Interpretación

La interpretación del árbol de este árbol de decisión sería: si el valor de x es menor que -4.25, predice 2.2777; si está en el intervalo (-4.25, -3.75] predict 1.5774); si está en el intervalo (-3.75, 3.05] predict 0.3566 y si es mayor que 3.05 predice 1.6273.

¿Cómo se construyen los árboles de decisión para problemas de regresión?

Los árboles de decisión para regresión también se construyen usando un algoritmo voraz. Para regresión, la función de coste es la siguiente:

$$J(a,l_a)=\frac{m_{izquierdo}}{m}MSE_{izquierdo} + \frac{m_{derecho}}{m}MSE_{derecho}$$

  • a es la abreviatura de atributo (también llamado característica o feature)
  • la significa el límite del atributo
  • m se refiere al número de muestras

MSE es el error cuadrático medio por sus siglas en inglés (Mean Squared Error)

Código python para entrenar y predecir con árboles de decisión para regresión

# importamos las librerías que necesitamos
import numpy as np # NumPy para manipulación numérica
np.random.seed(42) # para hacer el código reproducible
from sklearn.tree import DecisionTreeRegressor # árbol de decisión para regresión

#función y = 0.1x^2 + 0.2(Ruido Gaussiano)
def f(x):
    y = 0.1*np.square(x) + 0.2*np.random.randn(x.size)
    return y

# Generamos los datos x, y con la función f(x)
x = np.arange(-5,5,0.1) # x = [-5, -4.9, -4.8, ... 4.8, 4.9, 5]
y = f(x) 

# Vamos a crear y entrenar un árbol de decisión para regresión
tree = DecisionTreeRegressor(max_depth=2, random_state=42) # máxima profundidad 2
tree.fit(x.reshape(-1,1), y) # entrenamos el árbol de regresión

# Ahora predecimos qué valores de y tendríamos para x2 = [-0.7, 0.5, 2.3]
x2 = np.array([-0.7, 0.5, 2.3]).reshape(-1,1)
print( tree.predict(x2) )

# obtenemos el siguiente resultado:
# [0.35655791 0.35655791 0.35655791]

A tener en cuenta cuando usamos Árboles de Decisión

Regularización

Los árboles de decisión de scikit-learn no están regularizados por defecto. Esto significa que para obtener el menor error posible, pueden crear tantos nodos como necesiten. Esto puede resultar en un modelo muy complejo que funcione muy bien en el conjunto de entrenamiento pero muy mal con datos nuevos.

La regularización consiste en limitar de alguna forma las capacidades del modelo para obtener un modelo de aprendizaje automático que sea más simple y  generalice mejor.

En scikit-learn podemos usar varios hiper-parámetros para configurar cómo regularizamos los árboles de decisión. Veamos los más usados:

  • max_depth: la profundidad máxima del árbol. En los ejemplos anteriores hemos usado max_depth = 2
  • min_samples_split: número mínimo de muestras necesarias antes de dividir este nodo. También se puede expresar en porcentaje.
  • min_samples_leaf: número mínimo de muestras que debe haber en un nodo final (hoja). También se puede expresar en porcentaje.
  • max_leaf_nodes: número máximo de nodos finales

El siguiente gráfico muestra los datos (en azul) y la predicción (en rojo) de dos árboles. El de la izquierda no está regularizado. El de la derecha está regularizado. La regularización, en este caso, consiste en que los nodos finales (las hojas del árbol) deben cubrir al menos un 5% de las muestras. Como puedes comprobar visualmente, el árbol regularizado va a generalizar mejor y no sufre de sobreajuste.

Regresión con árbol no regularizado vs árbol regularizado

Generalización de los árboles de decisión

Los árboles de decisión son modelos no-paramétricos. Esto significa que no sabemos cuántos parámetros vamos a tener hasta que no veamos los datos y construyamos el árbol. La regresión lineal es un modelo paramétrico porque antes de ver los datos podemos decir con toda certeza cuántos parámetros vamos a necesitar.

Ventaja de los modelos no-paramétricos

La principal ventaja de los árboles de decisión, como modelo no-paramétrico, es que pueden aprender cualquier cosa. En el siguiente gráfico vemos cómo aprende sin problemas una parábola con ruido (a la izquierda) y una función sinusoidal con ruido (a la derecha).

Un árbol de decisión, al ser un modelo no-paramétrico, puede aprender cualquier función

Desventaja de los modelos no-paramétricos

Por otra parte, al ser un modelo no-paramétrico, no sabe qué es lo que se supone que debe pasar fuera del rango de entrenamiento. Al contrario que en el caso de lo modelos paramétricos, no «sabe» extrapolar. En el siguiente gráfico vemos que aunque parece que es capaz de modelar una función parabólica o una sinusoidal, en realidad, no «sabe» lo que está haciendo.

Los árboles de decisión, al ser modelos no-paramétricos, no saben extrapolar

En realidad este problema no es tan malo como pudiera parecer en este gráfico. Normalmente, los problemas para los que usamos aprendizaje automático, tienen muchos atributos y habrá muchos de ellos para los que sí tendremos datos en el rango de entrenamiento. En cualquier caso, siempre conviene asegurarnos que la distribución de los datos que queremos predecir es similar a la distribución de datos que usamos para entrenar el modelo.

Importancia de los atributos

Podemos obtener una estimación de cómo de importante es cada atributo para realizar la predicción. Esto nos va a permitir entender mejor el problema que estemos resolviendo. Por ejemplo, en el caso de la clasificación de las distintas variedades de las flores Iris, tenemos esta importancia estimada:

  • sepal length (cm): 0.0
  • sepal width (cm): 0.0
  • petal length (cm): 0.5619909502262443
  • petal width (cm): 0.4380090497737556

Según estos resultados, no necesitamos los datos de los sépalos. El ancho y el largo de los pétalos son suficientes para clasificar las flores Iris en su variedad correcta.

Código python para obtener la importancia de los atributos en un árbol de decisión

# tree.feature_importances_ es un vector con la importancia estimada de cada atributo
for name, importance in zip(iris.feature_names, tree.feature_importances_):
    print(name + ': ' + str(importance))

# resultado:
# sepal length (cm): 0.0
# sepal width (cm): 0.0
# petal length (cm): 0.5619909502262443
# petal width (cm): 0.4380090497737556

Resumen

Los árboles de decisión son una técnica de aprendizaje automático muy utilizada. Su ventajas principales son:

  • son fáciles de entender y explicar a personas que todavía no están familiarizadas con técnicas de Inteligencia Artificial
  • se adaptan a cualquier tipo de datos
  • descubren cuáles son los atributos relevantes

También tienen sus desventajas:

  • no extrapolan bien fuera del rango de entrenamiento
  • tienen la tendencia a sobre-ajustar, sobre todo si no se regularizan

Recursos

Suscríbete a IArtificial.net

Árboles de Decisión con ejemplos en Python

4
Deja un comentario

avatar
2 Hilos de comentario
2 Respuestas de hilo
1 Seguidores
 
Comentario más reaccionado
El hilo de comentarios más caliente
3 Autores de comentarios
santJose Martinez HerasAdrián Arroyo Autores de comentarios recientes
  Suscribir  
el más nuevo el más antiguo el más votado
Notificar de
Adrián Arroyo
Invitado

Mencionar que los árboles también se pueden usar sin usar el índice de Gini, sino el criterio de ganancia de información. Esta es usada por los algoritmos ID3 y C4.5 y siempre me ha parecido más elegante por estar basada en teoría de la información.

sant
Invitado
sant

Hola Jose, lo primero agradecerte y felicitarte por este blog. Para los que nos estamos iniciando en esto te puedo asegurar que nos ayuda mucho gracias a la claridad con que expones los temas. Dicho esto no entiendo muy bien el apartado «desventajas de los modelos No-Paramétricos». Con rango de entrenamiento de refieres al conjunto de entrenamiento? y cuando dices que «no sabe extrapolar» te refieres a que no sabe generalizar con el conjunto de test? por extensión me pierdo cuando dices «Normalmente, los problemas para los que usamos aprendizaje automático, tienen muchos atributos y habrá muchos de ellos para… Leer más »