El motor que hace posible el aprendizaje. Autograd calcula gradientes automáticamente — es el backpropagation de tu curso, pero gratis y para cualquier cálculo que escribas.
@ para multiplicar matrices). Hoy añadimos el superpoder que hace posible el entrenamiento: que PyTorch calcule derivadas por ti.
Para entrenar una red necesitas la derivada de la pérdida respecto a cada peso (dL/dw).
Calcularla a mano para millones de pesos es imposible. Autograd lo hace por ti:
escribes solo el cálculo "hacia adelante" y PyTorch deriva el "hacia atrás" automáticamente.
requires_grad=True graba las operaciones
que se le hacen, formando un "grafo computacional". Cuando llamas .backward(), PyTorch
recorre ese grafo al revés aplicando la regla de la cadena.
El ciclo completo en 3 pasos. Derivemos y = x³ + 2x en x = 2:
x = torch.tensor(2.0, requires_grad=True) # 1. marcar como derivable
y = x**3 + 2*x # 2. operar (se graba el grafo)
y.backward() # 3. calcular gradientes
print(x.grad) # el resultado queda en .grad
Valor de y en x=2: y = x³ + 2x = 2³ + 2·2 = 8 + 4 = 12 ✓ Derivada término a término: d(x³)/dx = 3x² (regla de la potencia) d(2x)/dx = 2 ⇒ dy/dx = 3x² + 2 Evaluada en x=2: 3·(2²) + 2 = 3·4 + 2 = 12 + 2 = 14 ✓ = x.grad
Una red tiene muchos parámetros. backward() calcula la derivada respecto a
todos los tensores derivables de un golpe. Sea L = a² + 3b:
a = torch.tensor(1.0, requires_grad=True)
b = torch.tensor(2.0, requires_grad=True)
L = a**2 + 3*b
L.backward()
print(a.grad, b.grad)
Valor de L: L = a² + 3b = 1² + 3·2 = 1 + 6 = 7 ✓ Cuando hay varias variables, se deriva cada una por separado tratando las demás como si fueran números fijos. Eso se llama "derivada parcial" y se escribe con el símbolo ∂ (se llama "del" y se lee "dee parcial de"): Derivada parcial respecto a 'a' (b se trata como constante): ∂L/∂a (se lee "dee parcial de L respecto de a") = 2a + 0 = 2·1 = 2 ✓ Derivada parcial respecto a 'b' (a se trata como constante): ∂L/∂b = 0 + 3 = 3 ✓
Cada variable recibe su propia derivada parcial, en paralelo. Esto escala a millones de pesos sin cambiar nada del código.
Grabar el grafo cuesta memoria y tiempo. Cuando no vas a entrenar (por ejemplo, al hacer predicciones), conviene apagarlo:
w = torch.tensor(5.0, requires_grad=True)
(w * 2).requires_grad # normal: graba
with torch.no_grad(): # bloque sin grabación
(w * 2).requires_grad
(w * 2).detach().requires_grad # desconecta un tensor del grafo
with torch.no_grad(): al evaluar o predecir — ahorra memoria y va más rápido porque no construye el grafo. .detach() te da una copia de un tensor "desconectada" del grafo. Ejemplo concreto: loss.detach().item() extrae el número de la pérdida para imprimirlo sin arrastrar el historial de cálculos.
Un detalle que sorprende a todos: si llamas backward() dos veces, los gradientes
se suman en vez de reemplazarse:
x = torch.tensor(1.0, requires_grad=True)
(x * 3).backward()
print(x.grad) # 1er backward
(x * 3).backward()
print(x.grad) # 2do backward... ¡acumuló!
optimizer.zero_grad()
(lo verás en la lección 7): hay que poner los gradientes a cero antes de cada paso, o se irían
sumando los de pasos anteriores y el entrenamiento se rompería. Es el error olvidado más típico.
requires_grad=True marcas los tensores a derivar. Con .backward() PyTorch calcula todas las derivadas parciales (∂L/∂a, ∂L/∂b…) de golpe usando la regla de la cadena. Los gradientes se acumulan — por eso el bucle de entrenamiento siempre empieza con optimizer.zero_grad(). Usa with torch.no_grad(): cuando no necesitas entrenar. Autograd no es magia: es el backprop de tu curso de redes, automatizado.
Tienes los 3 fundamentos: tensores, operaciones y autograd. En la lección 5 construimos redes de verdad con nn.Module.