deep-learning · temario
3.2tema 2 de 4

PyTorch Essentials — Tensors, Autograd & Training Loop

Tensores, gradientes automáticos y el ciclo de entrenamiento

Un tensor en PyTorch es un array multidimensional que vive en CPU o GPU y puede registrar operaciones para calcular gradientes automáticamente. Es el bloque fundamental de todo en deep learning: imágenes, texto, audio y pesos de modelos son tensores.

Autograd es el motor de diferenciación automática de PyTorch. Cuando creas un tensor con requires_grad=True, cada operación sobre él construye un grafo computacional. Llamar .backward() en el loss recorre ese grafo hacia atrás y deposita los gradientes en el atributo .grad de cada tensor hoja.

nn.Module es la clase base de todos los modelos en PyTorch. Define la arquitectura en __init__ (capas, pesos) y la lógica de forward en forward(). El framework se encarga del backward automáticamente. Piénsalo como un plano arquitectónico: __init__ describe qué materiales tienes, forward describe cómo ensamblarlos.

El ciclo de entrenamiento siempre sigue el mismo patrón: zero_grad → forward → loss → backward → step. Saltarse zero_grad es el bug más frecuente en PyTorch porque los gradientes se acumulan entre iteraciones y las actualizaciones de pesos se vuelven incorrectas.

Los dispositivos (CPU/CUDA/MPS) deben ser consistentes: modelo y datos deben vivir en el mismo device. Un mismatch produce un RuntimeError inmediato. La práctica estándar es definir device = torch.device('cuda' if torch.cuda.is_available() else 'cpu') y mover modelo y tensores con .to(device).

Los optimizadores (Adam, SGD, AdamW) consumen los gradientes calculados por autograd y actualizan los parámetros del modelo. Adam es el punto de partida habitual: adapta el learning rate por parámetro y converge rápido en la mayoría de arquitecturas.

structure.txt
TENSOR CREATION
  x = torch.tensor([1.0, 2.0], requires_grad=True)
  x = torch.zeros(3, 4)         # shape (3, 4), CPU
  x = torch.randn(8, 512).to(device)

NN.MODULE TEMPLATE
  class MyModel(nn.Module):
      def __init__(self):
          super().__init__()
          self.fc1 = nn.Linear(128, 64)
          self.fc2 = nn.Linear(64, 10)
      def forward(self, x):
          x = torch.relu(self.fc1(x))
          return self.fc2(x)   # raw logits

TRAINING LOOP
  model.train()
  for batch_x, batch_y in dataloader:
      batch_x, batch_y = batch_x.to(device), batch_y.to(device)
      optimizer.zero_grad()
      logits = model(batch_x)
      loss = criterion(logits, batch_y)
      loss.backward()
      optimizer.step()

INFERENCE
  model.eval()
  with torch.no_grad():
      preds = model(test_x.to(device))

Debugging lab

Detecta y corrige el error en el código.

0/5 tests passing0%
  1. 3.2.5.1

    for batch_x, batch_y in dataloader: logits = model(batch_x) loss = criterion(logits, batch_y) loss.backward() optimizer.step()

  2. 3.2.5.2

    loss = criterion(logits, batch_y) optimizer.step() loss.backward()

  3. 3.2.5.3

    model = MyModel() batch_x = batch_x.to('cuda') logits = model(batch_x)

  4. 3.2.5.4

    model.eval() preds = model(test_x)

  5. 3.2.5.5

    # saving model torch.save(model, 'model.pt') # loading model = torch.load('model.pt')