LECCIÓN 9

PyTorch y autograd

Hiciste backprop a mano en la lección 7. Ahora deja que PyTorch lo haga por ti — y comprueba con tus propios ojos que calcula EXACTAMENTE los mismos números, automáticamente.

1. ¿Qué cambia con PyTorch?

Hasta ahora calculamos cada derivada a mano. En la práctica nadie hace eso: lo hace autograd, el motor de diferenciación automática de PyTorch. Tú escribes solo el forward; PyTorch construye un grafo de las operaciones y, al llamar loss.backward(), recorre ese grafo hacia atrás aplicando la regla de la cadena — exactamente lo que hiciste en la lección 7, pero solo.

Tensor + requires_grad=True le dice a PyTorch "vigila este valor, quiero su gradiente". Tras loss.backward(), cada tensor tendrá su gradiente en .grad. Cero cálculo manual.

2. Reproducimos el forward de XOR con tensores

Usamos los mismos pesos canónicos y la misma entrada x = (1, 0):

import torch

# Pesos canonicos, marcados como entrenables
W1 = torch.tensor([[0.20,-0.30],[0.40,0.10]], requires_grad=True)
b1 = torch.tensor([-0.10, 0.20],              requires_grad=True)
W2 = torch.tensor([[0.50],[-0.40]],           requires_grad=True)
b2 = torch.tensor([0.10],                     requires_grad=True)

x = torch.tensor([1., 0.])
t = torch.tensor([1.])

# Forward (idéntico a la lección 4)
a1 = torch.sigmoid(x @ W1 + b1)      # capa oculta
a2 = torch.sigmoid(a1 @ W2 + b2)     # salida
loss = 0.5 * (a2 - t)**2             # MSE ½
a2 = 0.543014   loss = 0.104418   ← idéntico a las lecciones 4 y 5 ✅

3. Una línea reemplaza toda la lección 7

loss.backward()   # autograd calcula TODOS los gradientes

print(W2.grad)    # gradiente de los pesos de salida
print(b2.grad)
print(W1.grad)    # gradiente de los pesos de entrada
print(b1.grad)

PyTorch imprime:

W2.grad = [-0.059533, -0.053868]
b2.grad = [-0.113401]
W1.grad = [[-0.014140, 0.011312], [-0.000000, 0.000000]]
b1.grad = [-0.014140, 0.011312]

4. La comprobación que lo demuestra todo

Comparemos, lado a lado, lo que calculaste a mano (lección 7) con lo que dio autograd:

GradienteA mano (lección 7)autograd (PyTorch)
dL/dW₂[−0.059533, −0.053868][−0.059533, −0.053868]
dL/db₂−0.113401−0.113401
dL/dW₁ (de x₁)[−0.014140, 0.011312][−0.014140, 0.011312]
dL/db₁[−0.014140, 0.011312][−0.014140, 0.011312]
# Verificación automática
assert torch.allclose(W2.grad.flatten(),
                      torch.tensor([-0.059533, -0.053868]), atol=1e-5)
# ✅ pasa — autograd == tu backprop a mano
Coinciden hasta el último decimal. Esto no es coincidencia: autograd es la regla de la cadena de la lección 7, aplicada por el computador. Entender backprop a mano te da la intuición; PyTorch te da la velocidad y la escala. Lo mejor de los dos mundos.

5. ¿Por qué importa tanto?

En la última lección daremos el paso final: construir la red con las herramientas de alto nivel de PyTorch (nn.Module, nn.Linear, un optimizador) y entrenar XOR hasta que lo resuelva de verdad — en pocas líneas.