← Todo el material
Curso Intermedio 23 de agosto de 2026

Machine Learning — Módulo 5: árboles de decisión

Quinto módulo del Curso de Machine Learning: qué es un árbol de decisión, cómo elige sus cortes con la impureza (Gini y entropía en simple), por qué un árbol solo se sobreajusta y cómo controlarlo con max_depth y poda, con código real de scikit-learn.

☰ Índice del contenido

En el Módulo 4 aprendimos a mirar un modelo con lupa: accuracy, precision, recall, la matriz de confusión. Ya sabemos juzgar modelos. Pero hasta ahora los que hemos entrenado — regresión lineal y logística — comparten una limitación: trazan fronteras rectas. Le piden al mundo que sea lineal, y el mundo rara vez lo es. Este módulo presenta un modelo que piensa distinto, más parecido a cómo decidimos las personas: a punta de preguntas. El árbol de decisión, además, tiene una virtud que ningún otro modelo de este curso iguala: se puede dibujar y leer entero. Es el primer modelo verdaderamente interpretable que vas a entrenar.

La tesis del módulo

Un árbol de decisión es un juego de “veinte preguntas”: parte los datos con preguntas sí/no hasta acorralar una respuesta. Es transparente y no exige que los datos sean lineales, pero un árbol solo, si lo dejas crecer, memoriza en vez de aprender. Todo el oficio con árboles es saber cuándo pararlo.

Qué es un árbol de decisión

Un árbol de decisión (glosamos: una serie de preguntas sí/no encadenadas que van partiendo los datos hasta llegar a una predicción) funciona como un diagrama de flujo. Cada pregunta mira una sola variable y la compara con un umbral: “¿la edad es menor que 30?”, “¿el ingreso supera los 800 mil?”. Según la respuesta, bajas por una rama u otra, y llegas a la siguiente pregunta. Cuando ya no hay más preguntas, aterrizas en una hoja: ahí está la predicción.

Tres nombres que usaremos todo el módulo:

  • Nodo raíz: la primera pregunta, arriba de todo. Ve todos los datos.
  • Nodo interno: cualquier pregunta intermedia. Recibe un subconjunto de datos y lo vuelve a partir.
  • Hoja: el final de una rama. No pregunta nada; entrega la respuesta (una clase, si clasificas; un número, si haces regresión).

Lo bonito es que no hay caja negra: puedes seguir el camino de cualquier dato con el dedo, desde la raíz hasta su hoja, y entender exactamente por qué el modelo predijo lo que predijo.

                   START
                     │
                     ▼
         ┌───────────────────────┐
         │ ¿ingreso < 800.000 ?  │
         └───────────┬───────────┘
           sí        │        no
        ┌────────────┴────────────┐
        ▼                         ▼
┌──────────────────┐     ┌─────────────────┐
│   ¿edad < 25 ?   │     │  HOJA: aprueba  │
└────────┬─────────┘     └─────────────────┘
    sí   │   no
  ┌──────┴──────┐
  ▼             ▼
┌─────────┐ ┌─────────┐
│  HOJA:  │ │  HOJA:  │
│ rechaza │ │ aprueba │
└─────────┘ └─────────┘

Cómo elige el árbol sus cortes

La pregunta clave es: de todas las variables y todos los umbrales posibles, ¿cuál pone el árbol primero? El algoritmo prueba cortes y se queda con el que deja los grupos más puros. Un grupo puro es uno donde casi todos los ejemplos son de la misma clase.

Para medir “pureza” hay dos métricas clásicas:

  • Impureza de Gini: la probabilidad de equivocarte si etiquetaras un ejemplo al azar según la mezcla de clases del grupo. Grupo todo de una clase → Gini 0 (perfecto). Grupo mitad y mitad → Gini alto. Es la que usa scikit-learn por defecto.
  • Entropía: mide el “desorden” o la incertidumbre del grupo. Mismo espíritu: 0 cuando el grupo es puro, máxima cuando está más revuelto. La ganancia al partir se llama information gain (ganancia de información).

En la práctica ambas dan árboles muy parecidos; Gini es un poco más rápido de calcular. Lo que importa entender es el mecanismo: el árbol es codicioso — en cada nodo elige el mejor corte de ese momento, sin mirar más adelante. No busca el árbol óptimo global; busca partir bien, paso a paso.

 Grupo antes del corte (revuelto, impuro):
   ● ● ○ ● ○ ○ ● ○   → Gini alto

 El árbol busca la pregunta que mejor separe:

      ¿variable X < umbral?
                 │
        ┌────────┴────────┐
        ▼                 ▼
  ● ● ● ● (puro)   ○ ○ ○ ○ (puro)
    Gini ≈ 0         Gini ≈ 0

El problema: un árbol solo se sobreajusta

Aquí está el talón de Aquiles. Si dejas que el árbol crezca sin límite, seguirá partiendo hasta que cada hoja tenga un solo ejemplo. En ese punto tiene accuracy perfecto en train… porque literalmente memorizó los datos. Eso es overfitting (sobreajuste): el modelo se aprende el ruido y los casos particulares del conjunto de entrenamiento en vez de la regla general, y colapsa con datos nuevos. Si quieres el tratamiento a fondo de este fenómeno, está en Redes — Módulo 7: overfitting y regularización; aquí lo vemos en su versión “árbol”.

Un árbol sin frenos es el ejemplo más puro de overfitting que existe: un árbol profundo dibuja una frontera con escalones absurdos que rodean cada punto individual.

Ojo: un árbol que da 100% de accuracy en train casi nunca es una buena noticia. Es la señal clásica de que memorizó. Lo que importa es el accuracy en el conjunto de test — el que nunca vio.

Para controlarlo tienes dos familias de frenos:

  1. Pre-poda (parar antes): limitas el crecimiento con hiperparámetros. Los principales:
    • max_depth: la profundidad máxima (cuántas preguntas en cadena como mucho). El freno más importante.
    • min_samples_leaf: mínimo de ejemplos que debe tener una hoja. Impide hojas de un solo dato.
    • min_samples_split: mínimo de ejemplos para que un nodo se atreva a partir.
  2. Post-poda (podar después): dejas crecer el árbol y luego cortas ramas que no aportan. En scikit-learn se hace con ccp_alpha (cost-complexity pruning).

Un árbol en código

Usamos DecisionTreeClassifier de scikit-learn. La API es la misma de siempre: fit para entrenar, predict para predecir.

from sklearn.tree import DecisionTreeClassifier, export_text
from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split
from sklearn.metrics import accuracy_score

# datos de ejemplo (clásico dataset de flores iris)
X, y = load_iris(return_X_y=True)
X_train, X_test, y_train, y_test = train_test_split(
    X, y, test_size=0.2, random_state=42
)

# árbol SIN límite: lo dejamos memorizar
arbol_libre = DecisionTreeClassifier(random_state=42)
arbol_libre.fit(X_train, y_train)
print("train:", accuracy_score(y_train, arbol_libre.predict(X_train)))  # ~1.0
print("test :", accuracy_score(y_test,  arbol_libre.predict(X_test)))   # más bajo

# árbol CON freno: max_depth limita la profundidad
arbol = DecisionTreeClassifier(
    max_depth=3,           # como mucho 3 preguntas en cadena
    min_samples_leaf=5,    # cada hoja con al menos 5 ejemplos
    random_state=42,       # reproducibilidad
)
arbol.fit(X_train, y_train)
print("test podado:", accuracy_score(y_test, arbol.predict(X_test)))

# la joya del árbol: leerlo en texto plano
print(export_text(arbol, feature_names=load_iris().feature_names))

Ese export_text (o plot_tree si prefieres un dibujo) es el superpoder del árbol: te imprime el modelo completo, pregunta por pregunta. Ningún otro modelo del curso te deja auditar así su lógica.

Ojo: random_state no es un capricho. El árbol tiene pasos con desempate aleatorio; fijar la semilla hace que tu resultado sea reproducible. Sin ella, dos corridas pueden dar árboles distintos.

Ventajas y desventajas del árbol

VentajaDesventaja
Interpretable: se dibuja y se lee enteroSe sobreajusta con facilidad si no lo frenas
No exige fronteras linealesInestable: cambiar pocos datos cambia el árbol
No necesita escalar las variablesUn árbol solo suele ser poco preciso (“débil”)
Mezcla variables numéricas y categóricasFronteras a escalones, no diagonales suaves
Rápido de entrenar y de predecirSesgo hacia variables con muchos valores

Fíjate en un detalle práctico muy cómodo: los árboles no necesitan que escales las variables (StandardScaler y compañía). Como cada corte mira una variable a la vez con un umbral, da lo mismo que el ingreso esté en pesos y la edad en años. Esto los distingue de la regresión y las redes neuronales, y lo aprovecharemos en el módulo de pipelines.

Errores comunes

  • Dejar el árbol crecer sin límite y celebrar el 100% en train. Es overfitting garantizado. Siempre pon un max_depth o mira el test.
  • Confundir Gini con entropía como si una fuera “la correcta”. Son dos formas de medir lo mismo; en la práctica dan árboles casi idénticos. No pierdas tiempo eligiendo.
  • Escalar las variables antes de un árbol. No hace daño, pero es trabajo inútil: al árbol le da igual la escala.
  • Fiarse de un solo árbol para producción. Es inestable: reentrenar con datos un poco distintos puede darte un árbol muy diferente. Esa fragilidad es justo lo que arreglan los ensembles.
  • Creer que un árbol interpretable es siempre un árbol preciso. La interpretabilidad se paga con precisión. A veces vale la pena; a veces no.

La frase para llevarse

“Un árbol de decisión es transparente y no le teme a lo no-lineal, pero si lo dejas crecer, memoriza. El truco no es dejarlo pensar más: es enseñarle a parar.”

Qué viene

Un árbol solo es un modelo débil: interpretable, sí, pero frágil y poco preciso. La idea que cambió el juego fue no confiar en un árbol, sino en muchos y dejar que voten. En el Módulo 6: Random Forest veremos cómo juntar cientos de árboles distintos convierte un modelo mediocre en uno de los más robustos y confiables del machine learning tabular — a cambio de perder un poco de la transparencia que tanto nos gustó aquí.

Material relacionado

Machine Learningscikit-learnÁrboles de decisiónOverfitting

Preguntas sobre este curso

Regístrate gratis para hacer preguntas y guardar tu progreso.

✉ Entérate de lo nuevo

Recibe un aviso cuando publique nuevos cursos, workshops o investigaciones. Sin spam.