Creación de un árbol de decisiones

En esta unidad, usarás el entrenamiento de la biblioteca YDF (Yggdrasil Decision Forest) y, luego, interpretarás un árbol de decisión.

Esta unidad está inspirada en el instructivo 🧭 de primeros pasos de YDF.

Aspectos preliminares

Antes de estudiar el conjunto de datos, haz lo siguiente:

  1. Crea un notebook de Colab nuevo.
  2. Instala la biblioteca de YDF colocando y ejecutando la siguiente línea de código en tu nuevo notebook de Colab:
    !pip install ydf -U
    
  3. Importa las siguientes bibliotecas:
    import ydf
    import numpy as np
    import pandas as pd
    

El conjunto de datos de los pingüinos de Palmer

Este Colab usa el conjunto de datos Palmer Penguins, que contiene mediciones de tamaño de tres especies de pingüino:

  • Barbijo
  • Papúa
  • Adelia

Este es un problema de clasificación: el objetivo es predecir la especie de un pingüino según los datos del conjunto de datos de pingüinos de Palmer. Estos son los pingüinos:

Tres especies de pingüinos
diferentes.

Figura 16: Tres especies diferentes de pingüinos. Imagen de @allisonhorst

 

El siguiente código llama a una función Pandas para cargar el conjunto de datos de Palmer Penguins en la memoria:

path = "https://storage.googleapis.com/download.tensorflow.org/data/palmer_penguins/penguins.csv"
dataset = pd.read_csv(path)
label = "species"

# Display the first 3 examples.
dataset.head(3)

En la siguiente tabla, se da formato a los primeros 3 ejemplos del conjunto de datos de Palmer Penguins:

Tabla 3: Los primeros 3 ejemplos en Palmer Penguins

especie island bill_length_mm bill_depth_mm flipper_length_mm body_mass_g sexo year
0 Adelia Torgersen 39,1 18.7 181,0 3,750.0 male 2007
1 Adelia Torgersen 39,5 17,4 186,0 3,800.0 female 2007
2 Adelia Torgersen 40,3 18.0 195,0 3,250.0 female 2007

El conjunto de datos completo contiene una combinación de atributos numéricos (por ejemplo, bill_depth_mm), categóricos (por ejemplo, island) y faltantes. A diferencia de las redes neuronales, los bosques de decisión admiten todos estos tipos de atributos de forma nativa, por lo que no tienes que aplicar codificación one-hot, normalización o atributo adicional is_present.

La siguiente celda de código divide el conjunto de datos en un conjunto de entrenamiento y un conjunto de prueba:

# Use the ~20% of the examples as the testing set
# and the remaining ~80% of the examples as the training set.
np.random.seed(1)
is_test = np.random.rand(len(dataset)) < 0.2

train_dataset = dataset[~is_test]
test_dataset = dataset[is_test]

print("Training examples: ", len(train_dataset))
# >> Training examples: 272

print("Testing examples: ", len(test_dataset))
# >> Testing examples: 72

Entrena árboles de decisión con hiperparámetros predeterminados

Puedes entrenar tu primer árbol de decisión con el algoritmo de aprendizaje CART (árboles de clasificación y regresión) (también conocido como algoritmo de aprendizaje) sin especificar ningún hiperparámetro. Esto se debe a que el algoritmo de aprendizaje ydf.CartLearner proporciona buenos valores de hiperparámetros predeterminados. Más adelante en el curso aprenderás más sobre cómo funciona este tipo de modelo.

model = ydf.CartLearner(label=label).train(train_dataset)

La llamada anterior no especificó columnas para usar como atributos de entrada. Por lo tanto, se usa cada columna en el conjunto de entrenamiento. En la llamada, tampoco se especificó la semántica (por ejemplo, numérica, categórica o de texto) de los atributos de entrada. Por lo tanto, la semántica de los atributos se infiere automáticamente.

Llama a model.plot_tree() para mostrar el árbol de decisión resultante:

model.plot_tree()

En Colab, puedes usar el mouse para mostrar detalles sobre elementos específicos, como la distribución de clases en cada nodo.

un árbol de decisión entrenado con hiperparámetros predeterminados.

Figura 17: Un árbol de decisión entrenado con hiperparámetros predeterminados.

Colab muestra que la condición raíz contiene 243 ejemplos. Sin embargo, puedes recordar que el conjunto de datos de entrenamiento contenía 272 ejemplos. Los 29 ejemplos restantes se reservaron automáticamente para la validación y la reducción de árboles.

La primera condición prueba el valor de bill_depth_mm. Las tablas 4 y 5 muestran la probabilidad de diferentes especies según el resultado de la primera afección.

Tabla 4: Probabilidad de diferentes especies si bill_depth_mm ≥ 42.3

Especie Probabilidad
Adelia (rojo) 8%
Papúa (azul) 58%
Barbijo (verde) 36%

 

Tabla 5: Probabilidad de diferentes especies si bill_depth_mm < 42.3

Especie Probabilidad
Adelia (rojo) 97%
Papúa (azul) 2%
Barbijo (verde) 0%

bill_depth_mm es un atributo numérico. Por lo tanto, el valor 42.3 se encontró mediante el algoritmo de división exacta para la clasificación binaria con atributos numéricos.

Si bill_depth_mm ≥ 42.3 es verdadero, realiza más pruebas para determinar si flipper_length_mm ≥ 207.5 puede separar casi a la perfección a Gentoos y Adelia.

El siguiente código proporciona la precisión del entrenamiento y la prueba del modelo:

train_evaluation = model.evaluate(train_dataset)
print("train accuracy:", train_evaluation.accuracy)
# >> train accuracy:  0.9338

test_evaluation = model.evaluate(test_dataset)
print("test accuracy:", test_evaluation.accuracy)
# >> test accuracy:  0.9167

Es raro, pero posible, que la exactitud de la prueba sea mayor que la del entrenamiento. En ese caso, es posible que el conjunto de prueba difiera del conjunto de entrenamiento. Sin embargo, este no es el caso, ya que el entrenamiento y la prueba se dividieron al azar. Una explicación más probable es que el conjunto de datos de prueba es muy pequeño (solo 72 ejemplos), por lo que la estimación de exactitud es ruidosa.

En la práctica, para un conjunto de datos tan pequeño, sería preferible usar validación cruzada, ya que procesaría valores de métricas de evaluación más precisos. Sin embargo, en este ejemplo, continuamos con un entrenamiento y una prueba para que sea más simple.

Mejora los hiperparámetros del modelo

El modelo es un árbol de decisión único que se entrenó con valores de hiperparámetros predeterminados. Para obtener mejores predicciones, puedes hacer lo siguiente:

  1. Usa un algoritmo de aprendizaje más potente, como un modelo de bosque aleatorio o árboles con boosting del gradiente. Esos algoritmos de aprendizaje se explicarán en la página siguiente.

  2. Optimizar el hiperparámetro mediante la intuición y las observaciones. La guía de mejora del modelo puede ser útil.

  3. Usa el ajuste de hiperparámetros para probar de forma automática una gran cantidad de hiperparámetros posibles.

Dado que aún no hemos visto el algoritmo aleatorio de árboles con boosting del gradiente y de bosque y, dado que la cantidad de ejemplos es demasiado pequeña para realizar un ajuste automático de hiperparámetros, deberás mejorar el modelo de forma manual.

El árbol de decisión que se muestra arriba es pequeño, y la hoja con el ejemplo 61 contiene una combinación de etiquetas Adelia y Barbijo. ¿Por qué el algoritmo no dividió más esta hoja? Existen dos motivos posibles:

  • Es posible que se haya alcanzado la cantidad mínima de muestras por hoja (min_examples=5 de forma predeterminada).
  • Es posible que el árbol se haya dividido y reducido para evitar el sobreajuste.

Reduce la cantidad mínima de ejemplos a 1 y observa los resultados:

model = ydf.CartLearner(label=label, min_examples=1).train(train_dataset)
model.plot_tree()

Un árbol de decisión entrenado con min_examples=1.

Figura 18: Un árbol de decisión entrenado con min_examples=1.

 

El nodo de hoja que contiene 61 ejemplos se dividió varias veces.

Para ver si es valioso dividir aún más el nodo, evaluamos la calidad de este modelo nuevo en el conjunto de datos de prueba:

print(model.evaluate(test_dataset).accuracy)
# >> 0.97222

La calidad del modelo aumentó con una exactitud de la prueba que va de 0.9167 a 0.97222. Este cambio de hiperparámetros fue una buena idea.

Anterior a un bosque de decisión

Si continuamos mejorando los hiperparámetros, es probable que podamos alcanzar una exactitud perfecta. Sin embargo, en lugar de este proceso manual, podemos entrenar un modelo más potente, como un bosque aleatorio y ver si funciona mejor.

model = ydf.RandomForestLearner(label=label).train(pandas_train_dataset)
print("Test accuracy: ", model.evaluate(pandas_test_dataset).accuracy)
# >> Test accuracy: 0.986111

La exactitud del bosque aleatorio es mejor que la de nuestro árbol simple. En las siguientes páginas, aprenderás por qué.

Uso y limitación

Como se mencionó antes, un solo árbol de decisión suele ser de menor calidad que los métodos modernos de aprendizaje automático, como bosques aleatorios, árboles con aumento de gradiente y redes neuronales. Sin embargo, los árboles de decisiones siguen siendo útiles en los siguientes casos:

  • Como referencia simple y económica para evaluar enfoques más complejos.
  • Cuando existe una compensación entre la calidad del modelo y la interpretabilidad.
  • Como proxy para la interpretación del modelo de bosques de decisión, que el curso explorará más adelante.