Machine learning desde cero · Lección 5.2 · 27 de 33 lecciones listas · 10 min
Ensambles: por qué muchos árboles superan a uno
En pocas palabras
Un ensamble combina muchos modelos imperfectos cuyos errores se compensan en parte. Así un random forest gana exactitud y estabilidad al añadir árboles.
Calentamiento Dos preguntas de lecciones anteriores. Un minuto, y no bloquea la lección.
Pide a una persona que adivine cuántos caramelos hay en un frasco grande y puede equivocarse muchísimo. Pide lo mismo a unos cientos de personas, promedia sus estimaciones y el resultado suele quedar asombrosamente cerca. Nadie se volvió más listo. Sus errores simplemente apuntaban en direcciones distintas y se compensaron. ¿Podemos construir un modelo de la misma manera, a partir de muchos modelos mediocres? Pruébalo tú mismo antes de leer la explicación.
Elige una respuesta y tu grado de seguridad.
Responde para desbloquear el experimento.
Experimento interactivo
Este experimento interactivo funciona en un navegador con JavaScript activado. El texto que lo rodea describe lo que muestra.
Ver la respuesta
Respuesta correcta: El árbol normal
El bosque de un árbol acierta el 70,9 % de los pasajeros de prueba y el árbol normal el 73,9 %: un único árbol con sorteos es incluso más débil. Solo ayuda promediar muchos árboles: 10 árboles dan un 76,1 % y 100 árboles un 76,9 %.
Prueba esto
- Empieza con el control del número de árboles en uno y compara el bosque con el árbol único. Con un solo árbol, el «bosque» es solo un árbol aleatorizado.
- Sube poco a poco el número de árboles y observa la exactitud de prueba del bosque. Fíjate en dónde deja de mejorar de forma apreciable.
- Sigue aumentando el número de árboles. ¿La exactitud del bosque empieza a caer, como la del árbol profundo en la lección 9, o se estabiliza?
- Compara el árbol único con el bosque grande. ¿En cuál confiarías para un caso que nunca has visto?
La idea en pocas palabras
Un ensamble es un modelo formado por muchos modelos cuyas predicciones se combinan, por votación en el caso de categorías o por promedio en el caso de números. El ensamble más famoso es el bosque aleatorio (random forest), presentado por Leo Breiman en 2001: un gran número de árboles de decisión, cada uno crecido de forma un poco distinta, que votan juntos.
La lección 9 terminó con una debilidad de los árboles: un pequeño cambio en los datos puede producir un árbol completamente distinto. Un solo árbol profundo es como un adivino demasiado seguro de sí mismo: agudo, pero errático. Un bosque convierte ese comportamiento errático en una ventaja. Si cada árbol comete errores distintos, la votación por mayoría acierta más a menudo que un árbol típico.
Por qué funciona
La palabra clave es distintos. Promediar modelos idénticos no cambia nada; sus errores son los mismos. Un random forest hace que sus árboles difieran de dos maneras. Primero, cada árbol se entrena con una muestra bootstrap: filas extraídas al azar del conjunto de entrenamiento con reemplazo, así que cada árbol ve un conjunto de datos un poco distinto, con algunas filas repetidas y otras fuera. Esta idea se llama bagging. Segundo, en cada división un árbol solo puede elegir entre un subconjunto aleatorio de las características, para que no todos los árboles se apoyen en la misma característica más fuerte.
La estadística nos dice cuánto ayuda esto. Si el error de cada árbol tiene varianza σ² y los errores de dos árboles cualesquiera están correlacionados con correlación ρ, el promedio de n árboles tiene varianza
ρ·σ² + (1 − ρ)·σ² / n
El segundo término se reduce al añadir árboles y desaparece para n grande. El primero no: es la parte del error que comparten todos los árboles. Por eso importa la aleatoriedad. Cuanto menos se parecen los árboles entre sí (cuanto menor es ρ), más gana el bosque, y por eso añadir árboles más allá de cierto punto casi no aporta nada.
Una consecuencia agradable: añadir más árboles no hace que un bosque memorice más. Cada árbol nuevo simplemente se suma a la votación, y las predicciones del bosque se estabilizan en lugar de volverse más extremas. El costo de más árboles es tiempo de cálculo, no sobreajuste.
Hay una segunda gran familia de ensambles, el boosting, que funciona al revés: en lugar de árboles independientes que votan, construye árboles pequeños uno tras otro, y cada uno corrige los errores de los anteriores. Los árboles con gradient boosting ganan con frecuencia en datos tabulares, incluidas muchas competiciones de Kaggle.
Error frecuente
Un ensamble no puede crear información que no esté en las características. Si todos los árboles se dejan engañar de la misma manera —por ejemplo, por una característica que filtra la respuesta o por datos que no representan a las personas sobre las que vas a predecir—, la votación solo repite el mismo error con más seguridad. El término correlacionado de la fórmula es exactamente ese error compartido. Otro error es suponer que más árboles siempre ayudan: cuando las mejoras se aplanan, los árboles extra solo cuestan tiempo. Por último, un bosque es mucho más difícil de leer que un árbol único; cambias el diagrama de flujo por exactitud.
Los árboles y los bosques dividen el espacio de características en cajas. En la próxima lección conocemos un modelo que, en cambio, curva su frontera con suavidad: la red neuronal.
Test
Tres preguntas para comprobar lo aprendido. Elige una respuesta o despliega la solución bajo cada pregunta. Con el teclado: las flechas eligen, Enter o Espacio confirma.
Ideas clave
- Un ensamble combina muchos modelos; los errores que apuntan en direcciones distintas se compensan.
- Un random forest hace que los árboles difieran con muestras bootstrap y subconjuntos aleatorios de características.
- El error que comparten todos los árboles no se promedia, así que las mejoras se aplanan al añadir árboles.
- Más árboles cuestan tiempo, pero no hacen que un bosque se sobreajuste; el boosting es una segunda familia de ensambles, secuencial.
Más a fondo: fórmula, código, práctica
Las matemáticas
Un bosque promedia las predicciones de n árboles. Sea σ² la varianza del error de cada árbol y ρ la correlación entre los errores de dos árboles cualesquiera. Entonces el promedio tiene varianza:
Var = ρ·σ² + (1 − ρ)·σ² / n
- El segundo término,
(1 − ρ)·σ² / n, es la parte que se reduce al añadir árboles. - El primer término,
ρ·σ², es el suelo: el error que comparten todos los árboles. Ningún número de árboles lo elimina. - Con árboles independientes (
ρ = 0) la varianza baja comoσ² / n. Con árboles idénticos (ρ = 1) no baja en absoluto. - Las muestras bootstrap y los subconjuntos aleatorios de variables existen para reducir
ρ. - Promediar reduce solo la parte de varianza del error. El sesgo que comparten todos los árboles permanece, así que un bosque de árboles sesgados sigue estando sesgado.
En código (Python)
Un bosque aleatorio de verdad con los pasajeros del Titanic, probando 2 variables en cada división. Usa la misma partición que el código de la lección 9, no la del lab, así que los números difieren de los 73,9 % y 76,9 % del lab. El notebook enlazado bajo el resultado descarga los datos por sí solo.
import pandas as pd
from sklearn.ensemble import RandomForestClassifier
from sklearn.model_selection import train_test_split
from sklearn.tree import DecisionTreeClassifier
df = pd.read_csv("data/raw/titanic.csv")
X = pd.DataFrame({"female": (df["sex"] == "female").astype(int)}).join(df[["pclass", "age", "sibsp", "parch", "fare"]])
Xtr, Xte, ytr, yte = train_test_split(X, df["survived"], test_size=0.3, stratify=df["survived"], random_state=1)
Xtr, Xte = Xtr.fillna({"age": Xtr["age"].median()}), Xte.fillna({"age": Xtr["age"].median()}) # mediana del entrenamiento para ambos
tree = DecisionTreeClassifier(random_state=0).fit(Xtr, ytr)
print(f"one full tree: test {tree.score(Xte, yte):.3f}")
for n in (1, 10, 100, 500):
forest = RandomForestClassifier(n_estimators=n, max_features=2, random_state=0).fit(Xtr, ytr)
print(f"forest of {n:3d}: test {forest.score(Xte, yte):.3f}")
oob = RandomForestClassifier(n_estimators=500, max_features=2, oob_score=True, random_state=0).fit(Xtr, ytr)
print(f"out-of-bag estimate (500 trees, training rows only): {oob.oob_score_:.3f}")
Resultado
one full tree: test 0.780
forest of 1: test 0.754
forest of 10: test 0.806
forest of 100: test 0.802
forest of 500: test 0.802
out-of-bag estimate (500 trees, training rows only): 0.809
Un árbol aleatorizado (0,754) es peor que un árbol completo (0,780), pero la votación supera a ambos: 10 árboles dan 0,806, y 100 y 500 árboles dan 0,802. El bosque se estabiliza en vez de caer como lo hizo el árbol profundo en la lección 9. La estimación out-of-bag, 0,809, se calcula solo con las filas de entrenamiento.
Descargar el notebook (.ipynb). Ábrelo en Jupyter o súbelo a Google Colab; descarga por sí solo los datos que falten.
Para profesionales
- Empieza con los valores por defecto, por ejemplo de 100 a 500 árboles, y luego comprueba con datos de validación dónde se aplana la curva. Pasado ese punto, más árboles solo cuestan tiempo y memoria.
- Ajusta el número de variables probadas por división y la profundidad o el tamaño de las hojas antes que el número de árboles. Eso cambia cuán correlacionados están los árboles.
- Usa la puntuación out-of-bag (
oob_score=True) como estimación gratuita: cada fila de entrenamiento la predicen solo los árboles cuya muestra bootstrap la dejó fuera, y esas predicciones se evalúan. No ajustes con el conjunto de prueba. - Comprueba de dónde vienen los datos antes de confiar en la votación. Si una variable con fuga engaña a todos los árboles, el bosque repite el error con más confianza.
- Un bosque es difícil de leer. La importancia de las variables da un orden aproximado, pero favorece las variables con muchos valores distintos; la importancia por permutación con datos reservados es una comprobación más segura.
¿Te ha sido útil?
¡Gracias! Nos ayuda a mejorar.
Profundiza en el Atlas
Entradas de la enciclopedia sobre las ideas de esta lección: