¿Qué es un árbol de decisión?
- ¿Está soleado?
- Sí: ¿La humedad es alta?
- Sí: No jugar
- No: Sí jugar
- No: ¿Está lloviendo?
- Sí: ¿Hay viento fuerte?
- Sí: No jugar
- No: Sí jugar
- No: Sí jugar
- Sí: ¿Hay viento fuerte?
- Sí: ¿La humedad es alta?
Entropía: midiendo el desorden
p_i es la proporción de elementos de la clase i en el conjunto S.Calculemos con nuestro dataset
Nuestro dataset tiene 14 muestras: 9 "sí" y 5 "no".
- p(sí) = 9/14 = 0.643
- p(no) = 5/14 = 0.357
- H(S) = -(0.643 * log2(0.643) + 0.357 * log2(0.357))
- H(S) = -(0.643 * (-0.637) + 0.357 * (-1.486))
- H(S) = -(-0.410 + (-0.531))
- H(S) = 0.94
Un valor de 0.94 nos dice que el dataset tiene alta incertidumbre: no podemos predecir fácilmente la clase sin más información.
Information Gain: eligiendo la mejor pregunta
Sv es el subconjunto de S donde el atributo A tiene el valor v.Calculemos el Information Gain para 'Ambiente'
Dividimos el dataset por "Ambiente":
- Soleado (5 muestras): 2 sí, 3 no → H = 0.97
- Nublado (4 muestras): 4 sí, 0 no → H = 0.0
- Lluvioso (5 muestras): 3 sí, 2 no → H = 0.97
Entropía ponderada:
(5/14 * 0.97) + (4/14 * 0.0) + (5/14 * 0.97) = 0.347 + 0 + 0.347 = 0.694
IG(Ambiente) = 0.94 - 0.694 = 0.246
El árbol repite este cálculo para cada atributo y elige el que tenga el mayor information gain. En este caso, "Ambiente" gana.
Construyendo un árbol en Python
| # | Ambiente | Temperatura | Humedad | Viento | Clase |
|---|---|---|---|---|---|
| 1 | soleado | alta | alta | falso | no |
| 2 | soleado | alta | alta | verdadero | no |
| 3 | nublado | alta | alta | falso | sí |
| 4 | lluvioso | media | alta | falso | sí |
| 5 | lluvioso | baja | normal | falso | sí |
| 6 | lluvioso | baja | normal | verdadero | no |
| 7 | nublado | baja | normal | verdadero | sí |
| 8 | soleado | media | alta | falso | no |
| 9 | soleado | baja | normal | falso | sí |
| 10 | lluvioso | media | normal | falso | sí |
| 11 | soleado | media | normal | verdadero | no |
| 12 | nublado | media | alta | verdadero | sí |
| 13 | nublado | alta | normal | falso | sí |
| 14 | lluvioso | media | alta | verdadero | no |
import pandas as pd
data = {
'Ambiente': ['soleado', 'soleado', 'nublado', 'lluvioso', 'lluvioso', 'lluvioso', 'nublado', 'soleado', 'soleado', 'lluvioso', 'soleado', 'nublado', 'nublado', 'lluvioso'],
'Temperatura': ['alta', 'alta', 'alta', 'media', 'baja', 'baja', 'baja', 'media', 'baja', 'media', 'media', 'media', 'alta', 'media'],
'Humedad': ['alta', 'alta', 'alta', 'alta', 'normal', 'normal', 'normal', 'alta', 'normal', 'normal', 'normal', 'alta', 'normal', 'alta'],
'Viento': ['falso', 'verdadero', 'falso', 'falso', 'falso', 'verdadero', 'verdadero', 'falso', 'falso', 'falso', 'verdadero', 'verdadero', 'falso', 'verdadero'],
'Clase': ['no', 'no', 'si', 'si', 'si', 'no', 'si', 'no', 'si', 'si', 'no', 'si', 'si', 'no']
}
df = pd.DataFrame(data)from sklearn.preprocessing import LabelEncoder
le = LabelEncoder()
for column in df.columns:
df[column] = le.fit_transform(df[column])from sklearn.tree import DecisionTreeClassifier
X = df.drop('Clase', axis=1)
y = df['Clase']
modelo = DecisionTreeClassifier(criterion='entropy')
modelo.fit(X, y)from sklearn import tree
import matplotlib.pyplot as plt
plt.figure(figsize=(12,8))
tree.plot_tree(modelo, feature_names=X.columns, class_names=['no', 'si'], filled=True)
plt.show()Prueba el árbol de decisión
Selecciona las condiciones climáticas y observa cómo el árbol toma su decisión paso a paso:
Análisis del árbol generado
Al observar el árbol de decisión entrenado, notamos que:
- La raíz del árbol es el atributo
Ambiente. Esto confirma nuestro cálculo: Ambiente tiene el mayor information gain (0.246), por lo que es la variable que mejor separa los datos. - Si
Ambiente <= 1.5, el siguiente atributo evaluado esViento. Cuando no hay viento (Viento <= 0.5), se predice jugar con certeza (entropía 0.0 en 5 muestras). - Si hay viento, se vuelve a considerar el
Ambiente, donde la decisión ya no es tan clara (entropía 1.0 con 2 y 2 muestras). - Si
Ambiente > 1.5, se analizaHumedad, y si esta no es baja, se consulta laTemperaturapara resolver la clasificación.
En resumen, el modelo revela que Ambiente es la variable más influyente, mientras queViento y Humedad refinan las decisiones. La Temperatura aparece solo cuando las condiciones anteriores no son suficientes para una clasificación clara. Este tipo de interpretabilidad es una de las mayores ventajas de los árboles de decisión.
Overfitting y poda
max_depth: profundidad máxima del árbolmin_samples_leaf: mínimo de muestras que debe tener una hojamin_samples_split: mínimo de muestras para dividir un nodo
# Árbol con poda
modelo_podado = DecisionTreeClassifier(
criterion='entropy',
max_depth=3,
min_samples_leaf=2
)
modelo_podado.fit(X, y)
# Visualizar
plt.figure(figsize=(10, 6))
tree.plot_tree(modelo_podado, feature_names=X.columns, class_names=['no', 'si'], filled=True)
plt.title('Árbol de decisión con poda')
plt.show()¿Cuándo podar?
De un árbol a un bosque: intro a Random Forest
- Un subconjunto aleatorio de las muestras del dataset (con reemplazo)
- Un subconjunto aleatorio de los atributos en cada división