En este módulo, aprenderemos sobre las funciones de pérdida y los algoritmos de optimización, que son componentes esenciales en el entrenamiento de redes neuronales. Las funciones de pérdida nos permiten cuantificar qué tan bien o mal está funcionando nuestro modelo, mientras que los algoritmos de optimización nos ayudan a ajustar los parámetros del modelo para minimizar la pérdida.

  1. Funciones de Pérdida

¿Qué es una Función de Pérdida?

Una función de pérdida (o función de costo) mide la discrepancia entre las predicciones del modelo y los valores reales. El objetivo del entrenamiento es minimizar esta pérdida.

Tipos Comunes de Funciones de Pérdida

  1. Error Cuadrático Medio (MSE)

    • Utilizado principalmente en problemas de regresión.
    • Fórmula: \( \text{MSE} = \frac{1}{n} \sum_{i=1}^{n} (y_i - \hat{y}_i)^2 \)
    • Donde \( y_i \) es el valor real y \( \hat{y}_i \) es la predicción del modelo.
  2. Entropía Cruzada (Cross-Entropy)

    • Utilizado principalmente en problemas de clasificación.
    • Fórmula: \( \text{Cross-Entropy} = -\frac{1}{n} \sum_{i=1}^{n} [y_i \log(\hat{y}_i) + (1 - y_i) \log(1 - \hat{y}_i)] \)
    • Donde \( y_i \) es la etiqueta real y \( \hat{y}_i \) es la probabilidad predicha.

Implementación en PyTorch

import torch
import torch.nn as nn

# Ejemplo de MSE Loss
mse_loss = nn.MSELoss()
input = torch.tensor([0.5, 0.8, 0.3], requires_grad=True)
target = torch.tensor([0.0, 1.0, 0.0])
loss = mse_loss(input, target)
print(f'MSE Loss: {loss.item()}')

# Ejemplo de Cross-Entropy Loss
cross_entropy_loss = nn.CrossEntropyLoss()
input = torch.tensor([[0.2, 0.8], [0.6, 0.4]], requires_grad=True)
target = torch.tensor([1, 0])
loss = cross_entropy_loss(input, target)
print(f'Cross-Entropy Loss: {loss.item()}')

  1. Algoritmos de Optimización

¿Qué es un Algoritmo de Optimización?

Un algoritmo de optimización ajusta los parámetros del modelo para minimizar la función de pérdida. Los optimizadores actualizan los pesos del modelo basándose en el gradiente de la pérdida con respecto a los pesos.

Tipos Comunes de Algoritmos de Optimización

  1. Gradiente Descendente Estocástico (SGD)

    • Actualiza los pesos usando un subconjunto aleatorio de datos.
    • Fórmula de actualización: \( w = w - \eta \nabla L(w) \)
    • Donde \( \eta \) es la tasa de aprendizaje y \( \nabla L(w) \) es el gradiente de la pérdida.
  2. Adam (Adaptive Moment Estimation)

    • Combina las ventajas de AdaGrad y RMSProp.
    • Fórmula de actualización: Utiliza momentos de primer y segundo orden de los gradientes.

Implementación en PyTorch

import torch.optim as optim

# Ejemplo de SGD
model = nn.Linear(2, 1)  # Modelo simple de una capa lineal
optimizer = optim.SGD(model.parameters(), lr=0.01)

# Ejemplo de Adam
optimizer = optim.Adam(model.parameters(), lr=0.001)

  1. Ejemplo Práctico: Entrenamiento de una Red Neuronal Simple

Definición del Modelo

import torch
import torch.nn as nn
import torch.optim as optim

# Definición de un modelo simple
class SimpleNN(nn.Module):
    def __init__(self):
        super(SimpleNN, self).__init__()
        self.fc1 = nn.Linear(2, 3)
        self.fc2 = nn.Linear(3, 1)

    def forward(self, x):
        x = torch.relu(self.fc1(x))
        x = torch.sigmoid(self.fc2(x))
        return x

model = SimpleNN()

Definición de la Función de Pérdida y el Optimizador

criterion = nn.MSELoss()
optimizer = optim.SGD(model.parameters(), lr=0.01)

Bucle de Entrenamiento

# Datos de ejemplo
inputs = torch.tensor([[0.5, 0.8], [0.3, 0.2], [0.9, 0.7]], requires_grad=True)
targets = torch.tensor([[1.0], [0.0], [1.0]])

# Entrenamiento
for epoch in range(100):
    optimizer.zero_grad()  # Limpiar los gradientes
    outputs = model(inputs)  # Forward pass
    loss = criterion(outputs, targets)  # Calcular la pérdida
    loss.backward()  # Backward pass
    optimizer.step()  # Actualizar los pesos

    if (epoch+1) % 10 == 0:
        print(f'Epoch [{epoch+1}/100], Loss: {loss.item():.4f}')

  1. Ejercicios Prácticos

Ejercicio 1: Implementar una Función de Pérdida Personalizada

Objetivo: Implementar una función de pérdida personalizada que combine MSE y Cross-Entropy.

class CustomLoss(nn.Module):
    def __init__(self):
        super(CustomLoss, self).__init__()
        self.mse = nn.MSELoss()
        self.cross_entropy = nn.CrossEntropyLoss()

    def forward(self, outputs, targets):
        mse_loss = self.mse(outputs, targets)
        cross_entropy_loss = self.cross_entropy(outputs, targets)
        return mse_loss + cross_entropy_loss

# Uso de la función de pérdida personalizada
criterion = CustomLoss()

Ejercicio 2: Comparar Diferentes Optimizadores

Objetivo: Entrenar el mismo modelo con diferentes optimizadores y comparar los resultados.

# Definir diferentes optimizadores
optimizers = {
    'SGD': optim.SGD(model.parameters(), lr=0.01),
    'Adam': optim.Adam(model.parameters(), lr=0.001),
    'RMSprop': optim.RMSprop(model.parameters(), lr=0.01)
}

# Entrenar y comparar
for opt_name, optimizer in optimizers.items():
    model = SimpleNN()  # Reiniciar el modelo
    for epoch in range(100):
        optimizer.zero_grad()
        outputs = model(inputs)
        loss = criterion(outputs, targets)
        loss.backward()
        optimizer.step()

    print(f'Optimizer: {opt_name}, Final Loss: {loss.item():.4f}')

Conclusión

En esta sección, hemos aprendido sobre las funciones de pérdida y los algoritmos de optimización, dos componentes cruciales en el entrenamiento de redes neuronales. Hemos visto cómo implementar y utilizar estas funciones en PyTorch, y hemos practicado con ejemplos y ejercicios prácticos. Con este conocimiento, estamos preparados para avanzar al siguiente módulo, donde exploraremos el entrenamiento de redes neuronales en mayor profundidad.

© Copyright 2024. Todos los derechos reservados