En este módulo, aprenderemos cómo implementar el bucle de entrenamiento en PyTorch, que es el núcleo de cualquier proceso de aprendizaje profundo. El bucle de entrenamiento es donde se realiza la optimización del modelo, ajustando los pesos y sesgos para minimizar la función de pérdida.

Conceptos Clave

  1. Forward Pass: Propagación de los datos de entrada a través de la red para obtener la predicción.
  2. Cálculo de la Pérdida: Comparación de la predicción con el valor real para calcular la pérdida.
  3. Backward Pass (Backpropagation): Propagación de la pérdida hacia atrás a través de la red para calcular los gradientes.
  4. Actualización de Pesos: Uso de un optimizador para ajustar los pesos de la red en función de los gradientes calculados.

Estructura del Bucle de Entrenamiento

El bucle de entrenamiento en PyTorch generalmente sigue estos pasos:

  1. Inicialización del Modelo, Pérdida y Optimizador:

    • Definir el modelo.
    • Definir la función de pérdida.
    • Definir el optimizador.
  2. Iteración sobre el Dataset:

    • Dividir el dataset en lotes (batches).
    • Para cada lote:
      • Realizar el forward pass.
      • Calcular la pérdida.
      • Realizar el backward pass.
      • Actualizar los pesos.
  3. Evaluación del Modelo (opcional):

    • Evaluar el modelo en un conjunto de validación para monitorear el rendimiento.

Ejemplo Práctico

A continuación, se presenta un ejemplo práctico de un bucle de entrenamiento en PyTorch.

Paso 1: Inicialización

import torch
import torch.nn as nn
import torch.optim as optim
from torch.utils.data import DataLoader, TensorDataset

# Definir un modelo simple
class SimpleNN(nn.Module):
    def __init__(self):
        super(SimpleNN, self).__init__()
        self.fc1 = nn.Linear(10, 50)
        self.fc2 = nn.Linear(50, 1)
    
    def forward(self, x):
        x = torch.relu(self.fc1(x))
        x = self.fc2(x)
        return x

# Crear el modelo
model = SimpleNN()

# Definir la función de pérdida y el optimizador
criterion = nn.MSELoss()
optimizer = optim.SGD(model.parameters(), lr=0.01)

Paso 2: Preparación de los Datos

# Datos de ejemplo
X = torch.randn(100, 10)
y = torch.randn(100, 1)

# Crear DataLoader
dataset = TensorDataset(X, y)
dataloader = DataLoader(dataset, batch_size=10, shuffle=True)

Paso 3: Bucle de Entrenamiento

# Número de épocas
num_epochs = 20

for epoch in range(num_epochs):
    for inputs, targets in dataloader:
        # Forward pass
        outputs = model(inputs)
        loss = criterion(outputs, targets)
        
        # Backward pass
        optimizer.zero_grad()
        loss.backward()
        
        # Actualización de los pesos
        optimizer.step()
    
    print(f'Epoch [{epoch+1}/{num_epochs}], Loss: {loss.item():.4f}')

Explicación del Código

  1. Inicialización del Modelo, Pérdida y Optimizador:

    • SimpleNN es una red neuronal simple con dos capas lineales.
    • criterion es la función de pérdida de error cuadrático medio (MSE).
    • optimizer es el optimizador SGD (descenso de gradiente estocástico) con una tasa de aprendizaje de 0.01.
  2. Preparación de los Datos:

    • X y y son datos de entrada y salida generados aleatoriamente.
    • DataLoader se utiliza para manejar el dataset y dividirlo en lotes.
  3. Bucle de Entrenamiento:

    • Para cada época, iteramos sobre los lotes de datos.
    • Realizamos el forward pass para obtener las predicciones.
    • Calculamos la pérdida comparando las predicciones con los valores reales.
    • Realizamos el backward pass para calcular los gradientes.
    • Actualizamos los pesos del modelo utilizando el optimizador.

Ejercicio Práctico

Ejercicio

Implementa un bucle de entrenamiento para una red neuronal que clasifique imágenes del dataset MNIST. Utiliza una red neuronal con una capa oculta y la función de pérdida de entropía cruzada.

Solución

import torch
import torch.nn as nn
import torch.optim as optim
from torchvision import datasets, transforms
from torch.utils.data import DataLoader

# Definir el modelo
class MNISTNN(nn.Module):
    def __init__(self):
        super(MNISTNN, self).__init__()
        self.fc1 = nn.Linear(28*28, 128)
        self.fc2 = nn.Linear(128, 10)
    
    def forward(self, x):
        x = x.view(-1, 28*28)
        x = torch.relu(self.fc1(x))
        x = self.fc2(x)
        return x

# Preparar los datos
transform = transforms.Compose([transforms.ToTensor(), transforms.Normalize((0.5,), (0.5,))])
train_dataset = datasets.MNIST(root='./data', train=True, transform=transform, download=True)
train_loader = DataLoader(train_dataset, batch_size=64, shuffle=True)

# Inicializar el modelo, la función de pérdida y el optimizador
model = MNISTNN()
criterion = nn.CrossEntropyLoss()
optimizer = optim.Adam(model.parameters(), lr=0.001)

# Bucle de entrenamiento
num_epochs = 5

for epoch in range(num_epochs):
    for inputs, targets in train_loader:
        # Forward pass
        outputs = model(inputs)
        loss = criterion(outputs, targets)
        
        # Backward pass
        optimizer.zero_grad()
        loss.backward()
        
        # Actualización de los pesos
        optimizer.step()
    
    print(f'Epoch [{epoch+1}/{num_epochs}], Loss: {loss.item():.4f}')

Explicación del Código

  1. Modelo:

    • MNISTNN es una red neuronal con una capa oculta de 128 neuronas y una capa de salida de 10 neuronas (una para cada dígito del 0 al 9).
  2. Datos:

    • Utilizamos el dataset MNIST, que contiene imágenes de dígitos escritos a mano.
    • transforms.Compose se utiliza para convertir las imágenes a tensores y normalizarlas.
  3. Bucle de Entrenamiento:

    • Similar al ejemplo anterior, pero utilizando la función de pérdida de entropía cruzada (CrossEntropyLoss) y el optimizador Adam (optim.Adam).

Conclusión

En esta sección, hemos aprendido cómo implementar un bucle de entrenamiento en PyTorch. Este proceso es fundamental para entrenar cualquier modelo de aprendizaje profundo. Hemos cubierto los pasos esenciales, desde la inicialización del modelo hasta la actualización de los pesos, y hemos proporcionado ejemplos prácticos para reforzar los conceptos.

En el siguiente módulo, exploraremos cómo validar y probar nuestros modelos para asegurarnos de que están generalizando bien a datos no vistos.

© Copyright 2024. Todos los derechos reservados