Portfolio Portafolio

Greedy Split SearchBúsqueda voraz de divisiones

A step-by-step walkthrough of how a decision tree chooses where to split a node. Un recorrido paso a paso de cómo un árbol de decisión elige dónde dividir un nodo.

Before you startAntes de empezar

A tiny vocabulary, to make the rest of the page readable. Everything else is built from these.

  • Regression. Predicting a number y from one or more numbers x. Here we have one predictor x and one target y.
  • Feature. Another word for a predictor variable x. With several features we call them x1, x2, … On this page there is just one.
  • Observation (data point). One pair (x, y). We have five of them.
  • Response. The y we are trying to predict.
  • Decision tree. A rule of the form “ask a question about x, follow the yes-branch or the no-branch, then ask another question, … until a final prediction comes out.” Pictured below.
  • Node. One point in the tree where a question is asked, or (if there is no further question) where a prediction is returned. The top node is the root. Nodes that still split are internal. Leaves are at the bottom.
  • Parent and child. When a node splits in two, the splitter is the parent, and the two resulting nodes are its children.
  • Split (threshold). One question of the form “is xs?”. The number s is the threshold.

We will build everything else (RSS, greedy, the algorithm) from scratch in the panels below.

Un vocabulario breve, para que el resto de la página se lea con soltura. Todo lo demás se construye a partir de estas ideas.

  • Regresión. Predecir un número y a partir de uno o varios números x. Aquí tenemos una sola variable predictora x y una respuesta y.
  • Variable (feature). Otra forma de llamar a una variable predictora x. Cuando hay varias, las nombramos x1, x2, … En esta página solo aparece una.
  • Observación (punto de datos). Una pareja (x, y). Tenemos cinco.
  • Respuesta. El valor y que intentamos predecir.
  • Árbol de decisión. Una regla de la forma “haz una pregunta sobre x, sigue la rama del sí o la del no, haz otra pregunta, … hasta que salga una predicción final.” Se muestra abajo.
  • Nodo. Cada punto del árbol donde se hace una pregunta, o (si ya no hay más preguntas) donde se devuelve una predicción. El nodo de hasta arriba es la raíz. Los nodos que todavía se dividen son internos. Las hojas están al final.
  • Padre e hijo. Cuando un nodo se parte en dos, el que se dividió es el padre, y los dos nodos que resultan son sus hijos.
  • División (umbral). Una pregunta de la forma “¿es xs?”. Al número s se le llama umbral.

El resto (RSS, la idea de voraz, el algoritmo completo) lo iremos construyendo desde cero en los paneles siguientes.

Visualizing the treeVisualizando el árbol

Here is the full tree we will build on the 5-point dataset, for reference. Most of this page is about one choice: the threshold at the root (the “?”).

root: all 5 points is x ≤ s ? yes no left child points with x ≤ s right child points with x > s (may split further, same procedure) (may split further, same procedure)

The whole page is about choosing the value of s at one node, the root. After we pick it, each child runs the exact same procedure on its own data. That is how the tree grows.

Aquí está, para tenerlo a la vista, el árbol completo que construiremos sobre el conjunto de 5 puntos. Casi toda la página gira en torno a una sola elección: el umbral en la raíz (el “?”).

raíz: los 5 puntos ¿es x ≤ s ? no hijo izquierdo puntos con x ≤ s hijo derecho puntos con x > s (puede volver a dividirse, con el mismo procedimiento) (puede volver a dividirse, con el mismo procedimiento)

Toda la página trata de elegir el valor de s en un solo nodo, la raíz. Una vez elegido, cada hijo ejecuta exactamente el mismo procedimiento con sus propios datos. Así crece el árbol.

The QuestionLa pregunta

A decision tree predicts a number y from a number x. It does this by cutting the data into groups and assigning a single prediction to each group: the group's average y.

The cut is made one question at a time: “is xs?”. Observations that answer yes go into one group, the rest into the other. Each group can be cut again by the same kind of question, and again, until we stop.

Every cut needs a threshold, a specific number s. This page answers exactly one question: given 5 data points, which s is best, and why?

The plan is honest brute force. List every threshold worth trying. For each one, split the data and score how tightly the two resulting groups cluster around their own averages. Keep the threshold with the best score.

Un árbol de decisión predice un número y a partir de un número x. Lo hace cortando los datos en grupos y asignándole a cada grupo una sola predicción: el promedio de y dentro de ese grupo.

El corte se hace una pregunta a la vez: “¿es xs?”. Las observaciones que responden sí se van a un grupo, y el resto al otro. Cada grupo puede volver a cortarse con una pregunta del mismo tipo, y otra vez, hasta que nos detengamos.

Cada corte necesita un umbral, un número concreto s. Esta página contesta una única pregunta: dados 5 puntos, ¿cuál es la mejor s, y por qué?

El plan es fuerza bruta, sin disimulos. Enumerar todos los umbrales que valga la pena probar. Para cada uno, dividir los datos y medir qué tan apretados quedan los dos grupos alrededor de su propio promedio. Quedarse con el umbral de mejor puntaje.

The dataset (one feature, five observations)El conjunto de datos (una variable, cinco observaciones)
(x=1, y=4) (x=2, y=6) (x=3, y=8) (x=7, y=25) (x=8, y=27)

Five (x, y) observations, one feature. Notice that the x values themselves form two clumps, {1, 2, 3} and {7, 8}, with a wide gap in between, and the y values grow with x. You can see the clumps on the scatter plot further down the page.

Parent mean  ȳ = (4+6+8+25+27)/5 = 70/5 = 14
Parent RSS = (4−14)² + (6−14)² + (8−14)² + (25−14)² + (27−14)²
           = 100 + 64 + 36 + 121 + 169 = 490

Before any split, our best single prediction for the node is ȳ = 14. The Parent RSS (490) is the total squared error we pay for using that one number. Splitting should shrink this number.

(x=1, y=4) (x=2, y=6) (x=3, y=8) (x=7, y=25) (x=8, y=27)

Cinco observaciones (x, y), una sola variable. Fíjese en que los valores de x forman dos cúmulos, {1, 2, 3} y {7, 8}, con un hueco ancho entre ambos, y que los valores de y crecen con x. Los cúmulos se aprecian en el diagrama de dispersión que aparece más adelante.

Media del padre  ȳ = (4+6+8+25+27)/5 = 70/5 = 14
RSS del padre = (4−14)² + (6−14)² + (8−14)² + (25−14)² + (27−14)²
           = 100 + 64 + 36 + 121 + 169 = 490

Antes de cualquier división, la mejor predicción única para el nodo es ȳ = 14. El RSS del padre (490) es el error cuadrático total que pagamos por usar ese solo número. La división debería achicar esa cifra.

Why these four thresholds?¿Por qué justo estos cuatro umbrales?

A threshold is just a number. In principle we could try infinitely many. Why only four?

Because between any two consecutive x-values, the split is identical. Any s in the open interval (3, 7), whether 3.1, 5, or 6.999, puts {1, 2, 3} on the left and {7, 8} on the right. Same groups, same RSS. So we only need one threshold per gap.

The standard convention is the midpoint of the gap. Sorted unique x values are 1, 2, 3, 7, 8. Four gaps, four midpoints:

(1+2)/2 = 1.5    (2+3)/2 = 2.5    (3+7)/2 = 5    (7+8)/2 = 7.5

With n unique x values there are n − 1 candidate thresholds. The algorithm tries every one of them.

Un umbral no es más que un número. En principio podríamos probar una infinidad. ¿Por qué nada más cuatro?

Porque entre dos valores consecutivos de x, la división es siempre la misma. Cualquier s en el intervalo abierto (3, 7), ya sea 3.1, 5 o 6.999, deja {1, 2, 3} a la izquierda y {7, 8} a la derecha. Mismos grupos, mismo RSS. Basta, entonces, con un umbral por cada hueco.

La convención habitual es tomar el punto medio del hueco. Los valores únicos de x, ordenados, son 1, 2, 3, 7, 8. Cuatro huecos, cuatro puntos medios:

(1+2)/2 = 1.5    (2+3)/2 = 2.5    (3+7)/2 = 5    (7+8)/2 = 7.5

Con n valores únicos de x hay n − 1 umbrales candidatos. El algoritmo los prueba todos.

What does RSS mean?¿Qué significa RSS?

RSS stands for Residual Sum of Squares. For a group of y-values with mean ȳ:

RSS = Σ (yiȳ

In words: pick the mean as the group’s representative, measure how far each member is from that mean, square those distances, add them up.

  • RSS = 0. Every point in the group is identical. The mean describes them exactly. A “pure” group.
  • Small RSS. The group is tightly clustered around its mean. A good local prediction.
  • Large RSS. The group is spread out. The mean is a poor summary.

When we split, we want each child to be as pure as possible, which means both RSSL and RSSR should be small. So we minimize their sum: RSSL + RSSR.

Why squared, not absolute? Because squaring is the partner of the mean. If we pick a single number c to represent a group of y-values and score it by Σ (yic)², then setting the derivative to zero gives −2 Σ (yic) = 0, i.e. c = ȳ. So: minimize sum of squares → best summary is the mean. The two choices are locked together. (If we minimized Σ |yic| instead, the best c would be the median, and that would give a different kind of tree.)

RSS viene del inglés Residual Sum of Squares, la suma de cuadrados residuales. Para un grupo de valores de y con media ȳ:

RSS = Σ (yiȳ

En palabras: se toma la media como representante del grupo, se mide qué tan lejos queda cada miembro de esa media, se elevan esas distancias al cuadrado y se suman.

  • RSS = 0. Todos los puntos del grupo son idénticos. La media los describe con exactitud. Un grupo “puro”.
  • RSS pequeño. El grupo queda apretado alrededor de su media. Buena predicción local.
  • RSS grande. El grupo está disperso. La media resume mal al conjunto.

Al dividir queremos que cada hijo sea lo más puro posible, lo que equivale a que tanto RSSL como RSSR sean chicos. Por eso minimizamos su suma: RSSL + RSSR.

¿Por qué al cuadrado y no el valor absoluto? Porque elevar al cuadrado y la media van de la mano. Si elegimos un solo número c para representar al grupo y lo puntuamos con Σ (yic)², al derivar e igualar a cero queda −2 Σ (yic) = 0, es decir, c = ȳ. Así que: minimizar la suma de cuadrados → el mejor resumen es la media. Las dos decisiones están amarradas. (Si en cambio minimizáramos Σ |yic|, la mejor c sería la mediana, y eso daría un árbol distinto.)

The algorithm, in four linesEl algoritmo, en cuatro líneas

Now that we have the words (threshold, split, RSS) we can write the whole procedure down:

  1. List every candidate threshold s. These are the midpoints between consecutive sorted unique x values.
  2. For each s, split the node into Left (xs) and Right (x > s).
  3. Compute the post-split RSS = RSSL + RSSR, the total squared error we pay if we use each group's own mean as that group's prediction.
  4. Pick the s* that makes the post-split RSS smallest.

With p features instead of one, step 1 also loops over j = 1, …, p, and the winner is the pair (j*, s*). Here p = 1, so we can ignore j.

Con el vocabulario listo (umbral, división, RSS) podemos escribir todo el procedimiento:

  1. Enumerar los umbrales candidatos s. Son los puntos medios entre valores consecutivos de x (únicos y ordenados).
  2. Para cada s, dividir el nodo en izquierda (xs) y derecha (x > s).
  3. Calcular el RSS tras la división = RSSL + RSSR, el error cuadrático total que pagamos si usamos la media propia de cada grupo como predicción del grupo.
  4. Quedarse con el s* que deje ese RSS lo más chico posible.

Con p variables en lugar de una, el paso 1 también recorre j = 1, …, p, y el ganador es la pareja (j*, s*). Aquí p = 1, así que podemos olvidarnos de j.

Worked Computations: All Four CandidatesCálculos detallados: los cuatro candidatos

To see what the algorithm actually does, we compute every number by hand. For each threshold: form the two groups, take each group’s mean, compute each group’s RSS, add them.

Candidate 1  ·  s = 1.5split at midpoint of (1, 2)
Left  (x ≤ 1.5)
members: {4}
ȳL = 4 / 1 = 4
RSSL = (4−4)² = 0
Right  (x > 1.5)
members: {6, 8, 25, 27}
ȳR = (6+8+25+27)/4 = 66/4 = 16.5
RSSR = (6−16.5)² + (8−16.5)² + (25−16.5)² + (27−16.5)²
      = 110.25 + 72.25 + 72.25 + 110.25 = 365
Post-split RSS = 0 + 365 = 365 Only one point on the left → right child still carries most of the spread.

Move the threshold one gap to the right. Now the left group gains a point and the right loses one.

Candidate 2  ·  s = 2.5split at midpoint of (2, 3)
Left  (x ≤ 2.5)
members: {4, 6}
ȳL = (4+6)/2 = 10/2 = 5
RSSL = (4−5)² + (6−5)² = 1 + 1 = 2
Right  (x > 2.5)
members: {8, 25, 27}
ȳR = (8+25+27)/3 = 60/3 = 20
RSSR = (8−20)² + (25−20)² + (27−20)²
      = 144 + 25 + 49 = 218
Post-split RSS = 2 + 218 = 220 Left is now tight (RSS=2), but right mixes small and large y.

Jump across the big gap in x. Both groups are now tightly clustered.

Candidate 3  ·  s = 5Winner
Left  (x ≤ 5)
members: {4, 6, 8}
ȳL = (4+6+8)/3 = 18/3 = 6
RSSL = (4−6)² + (6−6)² + (8−6)²
      = 4 + 0 + 4 = 8
Right  (x > 5)
members: {25, 27}
ȳR = (25+27)/2 = 52/2 = 26
RSSR = (25−26)² + (27−26)² = 1 + 1 = 2
Post-split RSS = 8 + 2 = 10 Both children tight. This is the split that respects the natural gap in x.

Push the threshold too far right. The left group is forced to mix small and large y-values again.

Candidate 4  ·  s = 7.5split at midpoint of (7, 8)
Left  (x ≤ 7.5)
members: {4, 6, 8, 25}
ȳL = (4+6+8+25)/4 = 43/4 = 10.75
RSSL = (4−10.75)² + (6−10.75)² + (8−10.75)² + (25−10.75)²
      = 45.5625 + 22.5625 + 7.5625 + 203.0625 = 278.75
Right  (x > 7.5)
members: {27}
ȳR = 27 / 1 = 27
RSSR = (27−27)² = 0
Post-split RSS = 278.75 + 0 = 278.75 Right has one point, so its RSS is 0, but the left child is very spread out.

Para ver qué hace realmente el algoritmo, calculamos todo a mano. Para cada umbral: armamos los dos grupos, sacamos la media de cada uno, calculamos su RSS y los sumamos.

Candidato 1  ·  s = 1.5división en el punto medio de (1, 2)
Izquierda  (x ≤ 1.5)
miembros: {4}
ȳL = 4 / 1 = 4
RSSL = (4−4)² = 0
Derecha  (x > 1.5)
miembros: {6, 8, 25, 27}
ȳR = (6+8+25+27)/4 = 66/4 = 16.5
RSSR = (6−16.5)² + (8−16.5)² + (25−16.5)² + (27−16.5)²
      = 110.25 + 72.25 + 72.25 + 110.25 = 365
RSS tras la división = 0 + 365 = 365 Solo queda un punto a la izquierda, así que el hijo derecho se carga casi toda la dispersión.

Recorremos el umbral un hueco a la derecha. Ahora el grupo de la izquierda gana un punto y el de la derecha pierde uno.

Candidato 2  ·  s = 2.5división en el punto medio de (2, 3)
Izquierda  (x ≤ 2.5)
miembros: {4, 6}
ȳL = (4+6)/2 = 10/2 = 5
RSSL = (4−5)² + (6−5)² = 1 + 1 = 2
Derecha  (x > 2.5)
miembros: {8, 25, 27}
ȳR = (8+25+27)/3 = 60/3 = 20
RSSR = (8−20)² + (25−20)² + (27−20)²
      = 144 + 25 + 49 = 218
RSS tras la división = 2 + 218 = 220 La izquierda ya está apretada (RSS=2), pero la derecha mezcla valores chicos y grandes de y.

Saltamos el hueco grande en x. Los dos grupos quedan ahora bien apretados.

Candidato 3  ·  s = 5Ganador
Izquierda  (x ≤ 5)
miembros: {4, 6, 8}
ȳL = (4+6+8)/3 = 18/3 = 6
RSSL = (4−6)² + (6−6)² + (8−6)²
      = 4 + 0 + 4 = 8
Derecha  (x > 5)
miembros: {25, 27}
ȳR = (25+27)/2 = 52/2 = 26
RSSR = (25−26)² + (27−26)² = 1 + 1 = 2
RSS tras la división = 8 + 2 = 10 Los dos hijos quedan apretados. Esta es la división que respeta el hueco natural de los datos en x.

Empujamos el umbral demasiado a la derecha. El grupo de la izquierda se ve obligado a mezclar valores chicos y grandes de y otra vez.

Candidato 4  ·  s = 7.5división en el punto medio de (7, 8)
Izquierda  (x ≤ 7.5)
miembros: {4, 6, 8, 25}
ȳL = (4+6+8+25)/4 = 43/4 = 10.75
RSSL = (4−10.75)² + (6−10.75)² + (8−10.75)² + (25−10.75)²
      = 45.5625 + 22.5625 + 7.5625 + 203.0625 = 278.75
Derecha  (x > 7.5)
miembros: {27}
ȳR = 27 / 1 = 27
RSSR = (27−27)² = 0
RSS tras la división = 278.75 + 0 = 278.75 La derecha tiene un solo punto, así que su RSS es 0; pero el hijo izquierdo queda muy disperso.
Comparing the four candidatesComparando los cuatro candidatos

Stack the four post-split RSS values next to each other:

s = 1.5  →  RSS = 365
s = 2.5  →  RSS = 220
s = 5   →  RSS = 10     ← smallest
s = 7.5  →  RSS = 278.75

The winner is s* = 5. The total squared error drops from 490 at the parent down to 10 after the split, a reduction of about 98%. In plain language: nearly all of the spread that the single parent mean failed to capture is explained once we let each side of the split use its own mean.

The algorithm never “sees” the visible gap between x = 3 and x = 7. It only compares four numbers. But those four numbers tell the same story the eye does: the cleanest split is the one that respects where the data already clumps.

Pongamos los cuatro valores de RSS (tras la división) uno al lado del otro:

s = 1.5  →  RSS = 365
s = 2.5  →  RSS = 220
s = 5   →  RSS = 10     ← el más chico
s = 7.5  →  RSS = 278.75

El ganador es s* = 5. El error cuadrático total cae de 490 en el padre a 10 tras la división, una reducción cercana al 98%. Dicho en palabras llanas: casi toda la dispersión que la media única del padre no alcanzaba a explicar queda explicada en cuanto dejamos que cada lado de la división use su propia media.

El algoritmo nunca “ve” el hueco visible entre x = 3 y x = 7. Solo compara cuatro números. Y sin embargo, esos cuatro números cuentan la misma historia que cuenta el ojo: la división más limpia es la que respeta el lugar donde los datos ya se agrupan por su cuenta.

Try it yourselfPruébelo usted mismo

Press Play to watch the algorithm step through the four candidates in order. Or drag the slider to move the threshold freely. Points recolor into the left or right group, each group's mean redraws as a dashed line, and the numbers below update live.

Oprima Reproducir para ver cómo el algoritmo recorre los cuatro candidatos en orden. O arrastre el deslizador para mover el umbral libremente. Los puntos cambian de color según caigan en el grupo izquierdo o derecho, la media de cada grupo se redibuja como línea punteada, y los números de abajo se actualizan en vivo.

Split ViewVista de la división
Advanced mode swaps in a richer dataset with more candidate thresholds: more plateaus, more drama. The worked examples and narrative above stay tied to the basic dataset.El modo avanzado usa un conjunto de datos más rico y con más umbrales candidatos: más mesetas, más tensión. Los ejemplos detallados y la narrativa de arriba siguen amarrados al conjunto básico.
Left group (x ≤ s)Grupo izquierdo (x ≤ s) Right group (x > s)Grupo derecho (x > s) Threshold sUmbral s
drag:arrastrar:
Live ComputationCálculo en vivo
ThresholdUmbral s =
LeftIzquierda =
RightDerecha =
ȳL =     ȳR =
RSSL =
RSSR =
Post-split RSSRSS tras la división =
vs. parent RSS =contra el RSS del padre = 490. Reduction:Reducción:
Candidate Comparison (summary)Comparación de candidatos (resumen)
threshold sumbral s Left yy de la izquierda Right yy de la derecha RSSL RSSR Post-split RSSRSS tras la división
RSS LandscapePaisaje del RSS

Each horizontal step is one of the four candidate thresholds. The step is flat because any s inside a single gap between two x values produces the same split: the same two groups, and therefore the same RSS. The step drops and rises as the threshold crosses data points. The lowest step is the winner. Toggle to Advanced mode to see a denser version of the same picture, a V-shape whose trough points at where the data naturally separates.Cada escalón horizontal es uno de los cuatro umbrales candidatos. El escalón sale plano porque cualquier s dentro de un mismo hueco entre dos valores de x produce la misma división: los mismos dos grupos y, por lo tanto, el mismo RSS. El escalón baja o sube conforme el umbral cruza puntos. El escalón más bajo es el ganador. Cambie al modo avanzado para ver una versión más densa del mismo dibujo, una forma de V cuyo fondo apunta justo al lugar donde los datos se separan de manera natural.

After the split: what happens nextDespués de la división: qué sigue

We have picked s* = 5 at the root. The root is done. Each child now becomes a new node with its own data, and the same procedure runs on it from scratch:

  • The left child gets {(1,4), (2,6), (3,8)}. Its candidate thresholds are the midpoints of 1, 2, 3, namely 1.5 and 2.5. It will pick whichever gives the smaller post-split RSS on those three points.
  • The right child gets {(7,25), (8,27)}. Only one candidate threshold: 7.5.

Each child picks its own s*, splits, and its grand-children repeat the procedure. A stopping rule (typically a minimum node size or a maximum depth) decides when a node becomes a leaf instead of splitting again.

Nothing on this page changes for the children. The recipe (enumerate midpoints, compute RSS for each split, pick the smallest) is what the tree runs at every node.

Ya elegimos s* = 5 en la raíz. La raíz queda lista. Cada hijo se vuelve ahora un nodo nuevo con sus propios datos, y el mismo procedimiento corre sobre él desde cero:

  • El hijo izquierdo recibe {(1,4), (2,6), (3,8)}. Sus umbrales candidatos son los puntos medios de 1, 2, 3, es decir, 1.5 y 2.5. Elegirá el que dé un RSS tras la división más chico sobre esos tres puntos.
  • El hijo derecho recibe {(7,25), (8,27)}. Un único umbral candidato: 7.5.

Cada hijo elige su propia s*, se divide, y sus nietos repiten el procedimiento. Una regla de paro (por lo general un tamaño mínimo de nodo o una profundidad máxima) decide cuándo un nodo se convierte en hoja en lugar de volver a partirse.

Nada de lo que vimos en esta página cambia para los hijos. La receta (enumerar los puntos medios, calcular el RSS de cada división, quedarse con el más chico) es lo que el árbol ejecuta en cada nodo.

Where does “greedy” come in?¿De dónde viene lo de “voraz”?

We just ran the search for one node. Once we commit to s* = 5, the two children become new nodes: {4, 6, 8} on the left and {25, 27} on the right. Each child runs the same exhaustive search, using only its own data. The tree grows one node at a time.

The algorithm never looks ahead. It does not ask “would a slightly worse split now lead to cleaner splits later?”. It just picks the best s for the node in front of it. That is the meaning of greedy: locally optimal, globally unverified.

This is sometimes suboptimal. A root split that scores slightly worse could unlock much cleaner child splits later. But searching every possible whole tree is computationally intractable (the number of candidate trees explodes very quickly), so in practice we accept the greedy approximation, and empirically it performs well enough to be the standard recipe.

Acabamos de correr la búsqueda para un solo nodo. Una vez que nos comprometemos con s* = 5, los dos hijos se vuelven nodos nuevos: {4, 6, 8} a la izquierda y {25, 27} a la derecha. Cada hijo corre la misma búsqueda exhaustiva, usando solo sus propios datos. El árbol crece nodo a nodo.

El algoritmo nunca se asoma hacia adelante. No se pregunta “¿una división un poco peor ahora me daría divisiones más limpias después?”. Simplemente elige la mejor s para el nodo que tiene enfrente. En eso consiste ser voraz: óptimo en lo local, sin garantía de ser óptimo en lo global.

A veces esto sale subóptimo. Una división raíz que puntúe algo peor podría destrabar divisiones mucho más limpias después. Pero buscar entre todos los árboles completos posibles es computacionalmente inalcanzable (la cantidad de árboles candidatos explota rapidísimo), así que en la práctica aceptamos la aproximación voraz, y en los hechos rinde lo suficiente como para ser la receta estándar.

Sequel: many features, and Random ForestsContinuación: varias variables y los bosques aleatorios

Everything on this page used one feature. Real datasets have many. A mortality table carries age, sex, policy year, duration, smoker status, geography. A claims-severity model can easily have dozens of predictors. How does the algorithm change when p > 1?

Very little, in fact. With p features x1, x2, …, xp, the inner loop of step 1 now runs over both the feature index j and the threshold s:

  1. For each feature j = 1, …, p, list its candidate thresholds (the midpoints of its sorted unique values).
  2. For each pair (j, s), split the node using xjs, then compute post-split RSS.
  3. Pick the single pair (j*, s*) that minimizes post-split RSS across every feature and every threshold.

At each node the tree asks one question: “out of all possible splits on any feature, which one purifies the children most?” The winner might be age at the root, policy duration at the left child, smoker status four levels down. Every node picks its own feature-threshold pair from its own data.

From one tree to a forest

One tree is noisy. Small changes in the training data can swing the root split, which cascades into very different leaves. The fix, once computers got fast enough to afford it, is to build many trees and average them.

A Random Forest does two things to make the trees differ from each other:

  • Bagging. Each tree trains on a bootstrap sample of the rows (sample with replacement). Every tree sees a slightly different dataset.
  • Feature subsampling. At every node, the exhaustive search is restricted to a random subset of the features (typically of size √p). Same algorithm we just ran, but over fewer candidates.

Hundreds of such trees are built. A new observation gets a prediction from each one, and the forest's answer is the average (for regression) or the majority vote (for classification). The two layers of randomization make the trees weakly correlated, so averaging them shrinks variance without raising bias much.

Boosting is the other common extension. Trees are grown sequentially, each one fitting the residuals the previous trees missed. Gradient boosting (XGBoost, LightGBM) is what dominates on tabular data today.

All of these methods inherit the same split-search recipe we built on this page. The greedy choice at one node, with RSS as the score, is the building block every tree-based method is constructed from. Everything else is extra machinery on top.

Todo lo que vimos usó una sola variable. Los conjuntos de datos reales tienen muchas. Una tabla de mortalidad carga edad, sexo, año de póliza, duración, condición de fumador y región geográfica. Un modelo de severidad de siniestros puede fácilmente arrastrar decenas de variables predictoras. ¿Cómo cambia el algoritmo cuando p > 1?

Poco, en realidad. Con p variables x1, x2, …, xp, el ciclo interno del paso 1 ahora recorre tanto el índice de variable j como el umbral s:

  1. Para cada variable j = 1, …, p, enumere sus umbrales candidatos (los puntos medios de sus valores únicos, ordenados).
  2. Para cada pareja (j, s), divida el nodo con xjs y calcule el RSS tras la división.
  3. Quédese con la única pareja (j*, s*) que minimice el RSS tras la división entre todas las variables y todos los umbrales.

En cada nodo el árbol hace una sola pregunta: “entre todas las divisiones posibles, sobre cualquier variable, ¿cuál purifica más a los hijos?”. El ganador puede ser la edad en la raíz, la duración de la póliza en el hijo izquierdo, la condición de fumador cuatro niveles más abajo. Cada nodo elige su propia pareja variable-umbral a partir de sus propios datos.

De un árbol a un bosque

Un solo árbol es ruidoso. Cambios chicos en los datos de entrenamiento pueden mover la división de la raíz, y eso se propaga en cascada hasta producir hojas muy distintas. La solución, una vez que las computadoras fueron lo bastante rápidas como para permitírselo, es construir muchos árboles y promediarlos.

Un bosque aleatorio (Random Forest) hace dos cosas para que los árboles se diferencien entre sí:

  • Bagging. Cada árbol se entrena con una muestra bootstrap de los renglones (muestreo con reemplazo). Cada árbol ve un conjunto de datos ligeramente distinto.
  • Submuestreo de variables. En cada nodo, la búsqueda exhaustiva se restringe a un subconjunto aleatorio de las variables (por lo común de tamaño √p). El mismo algoritmo que acabamos de ver, solo que sobre menos candidatos.

Se construyen cientos de árboles así. Una observación nueva recibe una predicción de cada uno, y la respuesta del bosque es el promedio (en regresión) o el voto mayoritario (en clasificación). Las dos capas de aleatorización hacen que los árboles queden débilmente correlacionados, de modo que al promediarlos se reduce la varianza sin aumentar mucho el sesgo.

El boosting es la otra extensión común. Los árboles se construyen en secuencia: cada uno ajusta los residuales que dejaron los árboles anteriores. El gradient boosting (XGBoost, LightGBM) es hoy lo que domina sobre datos tabulares.

Todos estos métodos heredan la misma receta de búsqueda de divisiones que armamos en esta página. La elección voraz en un nodo, con el RSS como criterio, es la pieza básica con la que se construye cualquier método basado en árboles. El resto es maquinaria extra montada encima.