Calculus·Unidad 7

Calc-07 — Multivariable chain rule & backpropagation

Este es el módulo más importante de todo el pilar de cálculo. Backpropagation — el algoritmo con el que se entrena toda red neuronal — no es más que el chain rule multivariable aplicado con eficiencia sobre un grafo de cómputo. Cuando lo derives a mano una vez, el deep learning deja de ser una caja negra para siempre.

Why this matters for ML

Este es el módulo más importante de todo el pilar de cálculo. Backpropagation — el algoritmo con el que se entrena toda red neuronal — no es más que el chain rule multivariable aplicado con eficiencia sobre un grafo de cómputo. Cuando lo derives a mano una vez, el deep learning deja de ser una caja negra para siempre.

Concepts covered

  • Chain rule multivariable
  • Computational graphs
  • Forward pass y backward pass
  • Backpropagation derivada desde el chain rule
  • Reverse-mode automatic differentiation (idea)

Intuition first

🎬 3Blue1Brown Neural Networks cap. 3 ("What is backpropagation really doing?") y cap. 4 ("Backpropagation calculus"). Es, literalmente, este módulo en video. Míralo dos veces.

Theory & key results

Chain rule multivariable: si zz depende de variables intermedias u1,,uku_1,\dots,u_k que a su vez dependen de tt: dzdt=i=1kzuiduidt.\frac{dz}{dt} = \sum_{i=1}^{k}\frac{\partial z}{\partial u_i}\frac{du_i}{dt}. En forma matricial es producto de Jacobians (Calc-06): para z=f(y)\mathbf{z}=f(\mathbf{y}), y=g(x)\mathbf{y}=g(\mathbf{x}), Jz/x=Jz/y  Jy/x.J_{\mathbf{z}/\mathbf{x}} = J_{\mathbf{z}/\mathbf{y}}; J_{\mathbf{y}/\mathbf{x}}.

Computational graph: representa un cálculo como un grafo de operaciones. Ejemplo (una neurona con loss): x w a=wx +b z=a+b σ y^=σ(z) loss L=(y^y)2.x \xrightarrow{\ \cdot w\ } a=wx \xrightarrow{\ +b\ } z=a+b \xrightarrow{\ \sigma\ } \hat y=\sigma(z) \xrightarrow{\ \text{loss}\ } L=(\hat y - y)^2.

Forward pass: calcula los valores de izquierda a derecha (obtienes y^\hat y y LL).

Backward pass (backprop): calcula las derivadas de LL respecto a cada parámetro, de derecha a izquierda, multiplicando derivadas locales (chain rule). Para el grafo de arriba: Ly^=2(y^y),y^z=σ(z)(1σ(z)),za=1,aw=x.\frac{\partial L}{\partial \hat y}=2(\hat y - y),\quad \frac{\partial \hat y}{\partial z}=\sigma(z)(1-\sigma(z)),\quad \frac{\partial z}{\partial a}=1,\quad \frac{\partial a}{\partial w}=x. Encadenando: Lw=Ly^y^zzaaw=2(y^y)σ(z)(1σ(z))x.\frac{\partial L}{\partial w} = \frac{\partial L}{\partial \hat y}\cdot\frac{\partial \hat y}{\partial z}\cdot\frac{\partial z}{\partial a}\cdot\frac{\partial a}{\partial w} = 2(\hat y - y),\sigma(z)(1-\sigma(z)),x. Y Lb\frac{\partial L}{\partial b} es igual pero con ab=1\frac{\partial a}{\partial b}=1 en vez de xx.

Por qué "backward": compartir subresultados. Calcular de atrás hacia adelante reutiliza L(nodo)\frac{\partial L}{\partial (\text{nodo})} una sola vez por nodo → coste lineal en el tamaño del grafo. Eso es reverse-mode autodiff, lo que hacen PyTorch/TensorFlow por ti.

Worked example (numérico, una neurona)

x=1, w=0.5, b=0, y=1x=1,\ w=0.5,\ b=0,\ y=1.

  • Forward: a=0.5a=0.5, z=0.5z=0.5, y^=σ(0.5)0.622\hat y=\sigma(0.5)\approx0.622, L=(0.6221)20.143L=(0.622-1)^2\approx0.143.
  • Backward: Ly^=2(0.6221)=0.756\frac{\partial L}{\partial\hat y}=2(0.622-1)=-0.756; σ(z)=0.6220.3780.235\sigma'(z)=0.622\cdot0.378\approx0.235; entonces Lw=0.7560.2351x=0.178\frac{\partial L}{\partial w}=-0.756\cdot0.235\cdot1\cdot x=-0.178 y Lb=0.178\frac{\partial L}{\partial b}=-0.178 (con x=1x=1 coinciden).
  • Un paso de GD (η=0.1\eta=0.1): w0.50.1(0.178)=0.518w\leftarrow0.5-0.1(-0.178)=0.518 → la loss baja.

Notebook exercises (by hand)

  1. Dibuja el computational graph de L=(σ(wx+b)y)2L=(\sigma(wx+b)-y)^2 y marca cada derivada local.
  2. Deriva L/w\partial L/\partial w y L/b\partial L/\partial b del ejercicio 1 con el chain rule.
  3. Para z=f(u,v)z=f(u,v), u=x2u=x^2, v=xyv=xy: calcula z/x\partial z/\partial x con la versión de suma del chain rule.
  4. Extiende el ejemplo a dos neuronas en serie (xhy^x\to h\to \hat y) y encuentra L/w1\partial L/\partial w_1 (la primera capa) — verás aparecer el producto de factores.
  5. Explica por qué backprop es más eficiente que calcular cada derivada por separado.
  6. ¿Qué le pasa al gradient si muchos factores σ(z)\sigma'(z) (≤0.25) se multiplican en cadena? (Pista: vanishing gradients.)

Python lab

import numpy as np

def sigmoid(z): return 1/(1+np.exp(-z))

# forward + backward de una neurona, a mano
x, w, b, y = 1.0, 0.5, 0.0, 1.0
a = w*x + b; z = a; yhat = sigmoid(z); L = (yhat - y)**2
# backward
dL_dyhat = 2*(yhat - y)
dyhat_dz = yhat*(1 - yhat)
dL_dw = dL_dyhat * dyhat_dz * x
dL_db = dL_dyhat * dyhat_dz * 1
print("L:", L, " dL/dw:", dL_dw, " dL/db:", dL_db)

# verifica con gradiente numérico
def loss(w, b): return (sigmoid(w*x+b) - y)**2
h = 1e-6
num_w = (loss(w+h,b) - loss(w-h,b)) / (2*h)
print("dL/dw numérico:", num_w, " vs analítico:", dL_dw)   # coinciden

Reto (adelanto del capstone): implementa backprop para una red de 2 capas con varias neuronas usando Jacobians/matrices.

Examen final 📝

Intenta cada nivel antes de abrir las soluciones.

🟡 Medio

  1. Con z=u2z=u^2, u=3x+1u=3x+1: calcula dz/dxdz/dx con el chain rule y evalúa en x=1x=1.
  2. Con z=f(u,v)z=f(u,v), u=x2u=x^2, v=sinxv=\sin x: escribe dz/dxdz/dx en términos de z/u\partial z/\partial u, z/v\partial z/\partial v.

🟠 Medio-difícil

  1. Para L=(σ(wx+b)y)2L=(\sigma(wx+b)-y)^2 con x=2,w=0.5,b=0,y=0x=2, w=0.5, b=0, y=0: haz forward pass y backward pass y da L/w\partial L/\partial w numérico.
  2. Red de dos capas escalares: h=σ(w1x)h=\sigma(w_1 x), y^=w2h\hat y=w_2 h, L=(y^y)2L=(\hat y-y)^2. Deriva L/w1\partial L/\partial w_1 con el chain rule (verás factores multiplicándose capa a capa).

🔴 Difícil

  1. Deriva las ecuaciones de backprop para una capa vectorial z=Wx+b\mathbf z=W\mathbf x+\mathbf b, a=σ(z)\mathbf a=\sigma(\mathbf z): expresa LW\frac{\partial L}{\partial W}, Lb\frac{\partial L}{\partial \mathbf b} y Lx\frac{\partial L}{\partial \mathbf x} en términos de δ=Lz\boldsymbol\delta=\frac{\partial L}{\partial \mathbf z} (usa matrix calculus, Calc-09).
  2. Explica el problema de vanishing gradients: si una red profunda encadena nn capas sigmoid, ¿por qué L/(peso de la 1ª capa)\partial L/\partial(\text{peso de la 1ª capa}) tiende a 0? Estima el orden de magnitud si cada factor σ0.25\sigma'\le0.25 y hay 10 capas, y menciona cómo ReLU mitiga esto.
✅ Soluciones
  1. dz/dx=2u3=6(3x+1)dz/dx=2u\cdot3=6(3x+1); en x=1x=1: 64=246\cdot4=24.
  2. dzdx=zu2x+zvcosx\frac{dz}{dx}=\frac{\partial z}{\partial u}2x+\frac{\partial z}{\partial v}\cos x.
  3. Forward: z=1z=1, σ(1)0.731\sigma(1)\approx0.731, L=(0.731)20.535L=(0.731)^2\approx0.535. Backward: L/y^=2(0.731)=1.462\partial L/\partial\hat y=2(0.731)=1.462; σ(1)=0.7310.2690.197\sigma'(1)=0.731\cdot0.269\approx0.197; L/w=1.4620.197x=1.4620.19720.576\partial L/\partial w=1.462\cdot0.197\cdot x=1.462\cdot0.197\cdot2\approx0.576.
  4. Lw1=2(y^y)L/y^w2y^/hσ(w1x)h/z1xz1/w1\frac{\partial L}{\partial w_1}=\underbrace{2(\hat y-y)}{\partial L/\partial\hat y}\cdot\underbrace{w_2}{\partial\hat y/\partial h}\cdot\underbrace{\sigma'(w_1x)}{\partial h/\partial z_1}\cdot\underbrace{x}{\partial z_1/\partial w_1}.
  5. δ=Laσ(z)\boldsymbol\delta=\frac{\partial L}{\partial\mathbf a}\odot\sigma'(\mathbf z). Entonces LW=δx\frac{\partial L}{\partial W}=\boldsymbol\delta,\mathbf x^\top (outer product), Lb=δ\frac{\partial L}{\partial\mathbf b}=\boldsymbol\delta, Lx=Wδ\frac{\partial L}{\partial\mathbf x}=W^\top\boldsymbol\delta (esto propaga el gradiente a la capa anterior).
  6. L/w1\partial L/\partial w_1 incluye el producto de nn factores σ(zk)0.25\sigma'(z_k)\le0.25; con 10 capas, 0.2510106\lesssim0.25^{10}\approx10^{-6} → el gradiente casi desaparece y la 1ª capa apenas aprende. ReLU tiene derivada 1 en la región activa (no ≤0.25), así que no encoge el gradiente multiplicativamente.