LECCIÓN 7

Backpropagation

La joya de la corona. Cómo calcular el gradiente de CADA peso de la red de forma eficiente, usando la regla de la cadena hacia atrás. Lo haremos número por número, sin un solo gap, sobre nuestra red XOR.

Recuerda de la lección anterior: para entrenar, necesitamos dL/dw para cada peso — cómo cambia la pérdida cuando movemos ese peso un poquito. La regla de actualización es: w_nuevo = w_viejo − lr × (dL/dw). Hoy calculamos esas derivadas para todos los pesos de XOR.
🤔 Esta es la lección más densa del curso. Backpropagation puede costar en la primera lectura — es completamente normal. Si te pierdes en algún paso, respira y relee solo ese paso. Lo importante no es memorizar los números sino ver el patrón: cada gradiente es "lo que llega de la derecha × la derivada local".

1. El problema y la idea

En la lección 6 vimos que necesitamos dL/dw para cada peso. Pero la pérdida está al final de una cadena: el peso afecta a z, que afecta a a, que afecta a la siguiente capa, que afecta a la pérdida. ¿Cómo calculamos el efecto de un peso enterrado en la primera capa sobre la pérdida final?

La solución es la regla de la cadena — la misma idea de los engranajes: si A mueve a B, y B mueve a C, el efecto de A sobre C es el producto de los dos efectos. Aquí: el efecto del peso sobre la pérdida = (efecto del peso sobre z) × (efecto de z sobre a) × (efecto de a sobre L).

Regla de la cadena en fórmula: dL/dw = (dL/da)·(da/dz)·(dz/dw). Backpropagation aplica esta regla hacia atrás, capa por capa, reutilizando lo ya calculado. De ahí el nombre: propagar el error hacia atrás.
forward → x→ z₁ → a₁→ z₂ → ŷ L ← backward (gradientes)

2. Punto de partida (el forward de la lección 4)

Trabajamos con x = (1, 0), target = 1. Recordemos lo que ya calculamos:

a₁ = [0.524979, 0.475021]   (salida capa oculta)
ŷ = a₂ = 0.543014            (predicción)
L  = 0.104418               (MSE ½)

W₂ = [0.50, -0.40]   W₁ = [[0.20, -0.30], [0.40, 0.10]]

Dato útil de la sigmoid: su derivada es σ'(z) = a·(1 − a), donde a = σ(z). Súper cómoda: solo necesitamos la activación que ya tenemos.

3. Backward, paso a paso (de derecha a izquierda)

1 Gradiente en la salida: dL/da₂

Con MSE L = ½(a₂ − t)², la derivada es directa (por eso el ½):

dL/da₂ = (a₂ - t) = 0.543014 - 1 = -0.456986

2 Atravesar la sigmoid de salida: dL/dz₂

Multiplicamos por la derivada de la sigmoid a₂(1−a₂):

dL/dz₂ = dL/da₂ · a₂·(1-a₂)
       = -0.456986 · (0.543014 · 0.456986)
       = -0.456986 · 0.248151
       = -0.113401

3 Gradiente de los pesos de salida: dL/dW₂ y dL/db₂

Como z₂ = a₁·W₂ + b₂, la derivada respecto a cada peso es la activación que lo multiplicaba. ¿Por qué? Por la misma razón que la derivada de 3x respecto a x es 3: si vendes a unidades a precio p, tu ingreso es a·p — subir p en 1 sube el ingreso en a. Aquí: z₂ = a₁·W₂, así que subir W₂ en 1 sube z₂ en a₁ — eso es la derivada.

dL/dW₂ = a₁ · dL/dz₂
   peso de a₁:  0.524979 · -0.113401 = -0.059533
   peso de a₂:  0.475021 · -0.113401 = -0.053868

dL/db₂ = dL/dz₂ = -0.113401   (el bias multiplica por 1)
✅ ¡Ya tenemos los gradientes de la capa de salida! Ahora seguimos hacia atrás, a la capa oculta.

4 Propagar a la capa oculta: dL/da₁

El error de z₂ se reparte hacia atrás según los pesos W₂ que lo trajeron:

dL/da₁ = dL/dz₂ · W₂
   hacia a₁:  -0.113401 · 0.50  = -0.056701
   hacia a₂:  -0.113401 · -0.40 = 0.045360

5 Atravesar la sigmoid oculta: dL/dz₁

Otra vez por a(1−a), ahora con las activaciones ocultas:

a₁·(1-a₁): [0.524979·0.475021, 0.475021·0.524979] = [0.249377, 0.249377]

dL/dz₁ = dL/da₁ · a₁·(1-a₁)
   z₁ de h₁:  -0.056701 · 0.249377 = -0.014140
   z₁ de h₂:  0.045360 · 0.249377 = 0.011312

6 Gradiente de los pesos de entrada: dL/dW₁ y dL/db₁

Igual que en el paso 3, pero la entrada ahora es x = (1, 0):

dL/dW₁ = x · dL/dz₁   (cada componente de x multiplica cada componente de dL/dz₁)

           h₁              h₂
  x₁=1:  1·-0.014140=-0.0141400.011312=0.011312
  x₂=0:  0·-0.014140=00.011312=0

dL/db₁ = dL/dz₁ = [-0.014140, 0.011312]
👀 Fíjate: los gradientes de los pesos que salen de x₂ son 0, porque x₂ = 0 en este ejemplo. Una entrada apagada no recibe corrección. Tiene todo el sentido.

4. El resultado: el gradiente completo

Acabamos de calcular, sin saltarnos nada, las derivadas de la pérdida respecto a los 9 valores entrenables:

Capa de salida:
  dL/dW₂ = [-0.059533, -0.053868]
  dL/db₂ = -0.113401

Capa oculta:
  dL/dW₁ = [[-0.014140, 0.011312], [0, 0]]
  dL/db₁ = [-0.014140, 0.011312]
Lo que aprendiste hoy: backpropagation calcula el gradiente de cada peso aplicando la regla de la cadena hacia atrás — de la pérdida hacia los pesos, capa por capa. Cada gradiente = "lo que llega de la derecha" × "la derivada local". Los 9 gradientes de XOR para x=(1,0): dL/dW₂ = [−0.0595, −0.0539], dL/db₂ = −0.1134, dL/dW₁ = [[−0.0141, 0.0113], [0, 0]], dL/db₁ = [−0.0141, 0.0113].

En la lección 8 usamos estos números en la regla w = w − lr·gradiente para mejorar la red de verdad. Y en la lección 9, PyTorch calculará exactamente estos mismos números automáticamente.