LECCIÓN 10

Red en PyTorch

El cierre. Todo lo que aprendiste a mano, ahora en su forma profesional: definir la red con nn.Module, elegir un optimizador y entrenar XOR en unas pocas líneas hasta resolverlo.

Recuerda de las lecciones anteriores: el ciclo de entrenamiento es: forward → pérdida → backward → actualizar pesos. PyTorch autograd calcula los gradientes automáticamente con loss.backward(). Hoy usamos las herramientas de alto nivel de PyTorch para hacer todo esto en pocas líneas.

1. Definir la red con nn.Module

nn.Module es la forma de PyTorch de definir una red. Piénsalo como una ficha técnica: describes los ingredientes en __init__ (qué capas tiene) y el proceso en forward (cómo fluyen los datos). Cada nn.Linear(entradas, salidas) es la operación x @ W + b de la lección 3 — PyTorch guarda los pesos y los inicializa al azar por ti.

import torch
import torch.nn as nn

class XORNet(nn.Module):
    def __init__(self):
        super().__init__()
        self.fc1 = nn.Linear(2, 2)   # capa oculta: 2 → 2
        self.fc2 = nn.Linear(2, 1)   # capa salida:  2 → 1

    def forward(self, x):
        h = torch.sigmoid(self.fc1(x))   # oculta + activación
        y = torch.sigmoid(self.fc2(h))   # salida + activación
        return y

net = XORNet()
Es la misma arquitectura 2-2-1 de todo el curso. nn.Linear(2,2) es literalmente la operación x @ W + b de la lección 3. Solo que ahora PyTorch guarda y actualiza los pesos por ti.

2. Los datos, la pérdida y el optimizador

# Las 4 filas de la tabla de verdad de XOR
X = torch.tensor([[0.,0.],[0.,1.],[1.,0.],[1.,1.]])
Y = torch.tensor([[0.],   [1.],   [1.],   [0.]])

loss_fn = nn.MSELoss()                              # pérdida (lección 5)
optim   = torch.optim.Adam(net.parameters(), lr=0.1) # el que da los pasos

El optimizador automatiza la regla w = w − lr·gradiente de la lección 6. Usamos Adam en vez del descenso simple. ¿Qué lo hace diferente? Adam recuerda cuánto se ha movido cada peso en los pasos anteriores y ajusta el tamaño del salto: si un peso ha cambiado mucho, Adam es más cauteloso; si apenas se ha movido, da un paso más grande. Resultado: converge mucho más rápido (sin la meseta lenta de la lección 8).

3. El bucle de entrenamiento (el ciclo de la lección 8, en código)

torch.manual_seed(1)   # PyTorch inicializa los pesos al azar; fijar la semilla hace reproducible el resultado

for epoca in range(2001):
    optim.zero_grad()         # 0. limpiar gradientes del paso anterior (PyTorch los acumula; si no los limpias, se suman y los números se distorsionan)
    pred = net(X)             # 1. forward  → predicciones
    loss = loss_fn(pred, Y)   # 2. pérdida
    loss.backward()           # 3. backward → gradientes (autograd)
    optim.step()              # 4. actualizar pesos

¿Reconoces los 4 pasos? Son exactamente el ciclo de la lección 8. Esto imprime:

época    0: loss=0.25477
época  100: loss=0.20232
época  250: loss=0.00071
época  500: loss=0.00023
época 1000: loss=0.00007
época 2000: loss=0.00002  ← resuelto ✅

4. El resultado: XOR resuelto

print(net(X))   # predicciones finales
x₁x₂XOR (target)predicción de la red
0000.006
0110.996
1010.996
1100.004
🎲 Honestidad sobre XOR: con una red tan pequeña (2 neuronas ocultas), el resultado depende de la inicialización aleatoria. Con algunas semillas la red queda atascada en un mínimo local (pérdida ≈ 0.167, no aprende). Por eso fijamos seed=1. En redes reales esto se mitiga con más neuronas y mejores inicializaciones — pero es bueno que sepas que el entrenamiento no siempre es mágico al primer intento.

5. Lo que aprendiste

Lo que aprendiste hoy: nn.Module permite definir la red describiendo ingredientes (__init__) y proceso (forward). nn.Linear(2,2) es exactamente la operación x·W+b de la lección 3. Adam mejora el descenso simple adaptando el paso de cada peso. Con 2001 épocas y Adam (lr=0.1), XOR se resuelve completamente: predicciones 0.006, 0.996, 0.996, 0.004.

6. 🎓 Lo que aprendiste en todo el curso

LecciónConcepto
1La neurona: suma ponderada (w·x + b)
2Activación: la chispa no-lineal (sigmoid)
3Capa = multiplicación de matrices
4Forward pass: el viaje completo del dato
5Pérdida: medir el error con un número
6Gradiente: la pendiente que indica por dónde bajar
7Backpropagation: la regla de la cadena hacia atrás
8Entrenamiento: repetir el ciclo miles de veces
9Autograd: PyTorch reproduce tu backprop, automático
10nn.Module: la red completa, lista para escalar
¡Completaste el curso! Empezaste con una sola neurona y terminaste entrenando una red que resuelve XOR en PyTorch — entendiendo cada número del camino, sin gaps. Y lo mejor: estas mismas piezas (sumas ponderadas, activaciones, backprop, autograd) son exactamente las que construyen un Transformer. Ahora tienes la base para entenderlo todo. 🚀

Continúa con PyTorch paso a paso para ver cómo escalar esto a proyectos reales, y termina con el Transformer.