La regresión logística se destaca como un algoritmo esencial para tareas de clasificación. A diferencia del enfoque de regresión lineal, donde el objetivo es predecir un valor continuo utilizando una función como \(\hat{y} = x \cdot \omega + b\) con una pérdida de suma de cuadrados, los problemas de clasificación requieren estimar a qué categoría pertenece una muestra. En lugar de comparar valores numéricos directos, buscamos extraer características abstractas y asignar una probabilidad a cada clase posible, eligiendo finalmente la de mayor probabilidad.
Conjuntos de Datos Integrados
PyTorch facilita la carga de conjuntos de datos clásicos a través del módulo torchvision.datasets. Podemos inicializar MNIST o CIFAR10 fácilmente para tareas de entrenamiento y evaluación.
from torchvision import datasets
# Cargar datos de entrenamiento y prueba
mnist_train_data = datasets.MNIST(root='./data', train=True, download=True)
mnist_test_data = datasets.MNIST(root='./data', train=False, download=True)
cifar_train_data = datasets.CIFAR10(root='./data', train=True, download=True)
cifar_test_data = datasets.CIFAR10(root='./data', train=False, download=True)
Clasificación Binaria y la Función Sigmoide
Consideremos un escenario clásico de clasificación binaria. Imaginemos que predecimos si un estudiante aprueba o reprueba un examen basándonos en sus horas de estudio. La salida ya no es una calificación continua, sino una etiqueta binaria: 1 (aprobado) o 0 (reprobado). Dado que la suma de probabilidades de ambas clases debe ser 1 (\(P(y=1) + P(y=0) = 1\)), basta con calcular la probabilidad de una de ellas.
La salida de un modelo lineal es un número real, pero las probabilidades deben estar en el intervalo \([0, 1]\). Para lograr esta transformación, empleamos la función sigmoide (o función logística): \[ S(z) = \frac{1}{1 + e^{-z}} \] Esta función tiene límites de 0 (cuando \(z \to -\infty\)) y 1 (cuando \(z \to +\infty\)), y es estrictamente creciante. Al aplicarla sobre la salida lineal \(z = W \cdot X + b\), obtenemos el modelo de regresión logística completo: \[ P = \sigma(W \cdot X + b) = \frac{1}{1 + e^{-(W \cdot X + b)}} \]
La función de pérdida también debe adaptarse. En lugar del Error Cuadrático Medio (MSE), se utiliza la Entropía Cruzada Binaria (BCE) para medir la divergencia entre la distribución real y la predicha: \[ \mathcal{L} = -(Y \log P + (1-Y) \log(1-P)) \] Donde \(Y\) es la etiqueta verdadera y \(P\) es la probabilidad estimada. Esta métrica evalúa qué tan diferentes son dos distribuciones de probabilidad, siendo óptimo cuando las distribuciones coinciden.
Implementación Práctica
Al construir el modelo en PyTorch, el flujo de trabajo presenta tres variaciones respecto a la regresión lineal estándar: se añade una activación sigmoide al final del modelo, la función de pérdida cambia a BCELoss, y los datos deben estructurarse con etiquetas categóricas flotantes.
import torch
import torch.nn as nn
class LogisticClassifier(nn.Module):
def __init__(self, num_features):
super().__init__()
self.linear_layer = nn.Linear(num_features, 1)
self.sigmoid = nn.Sigmoid()
def forward(self, x_input):
z = self.linear_layer(x_input)
return self.sigmoid(z)
# Datos de ejemplo
features = torch.randn(100, 10) # 100 muestras, 10 características
targets = torch.randint(0, 2, (100, 1)).float() # Etiquetas binarias 0 o 1
# Configuración del modelo, función de pérdida y optimizador
model = LogisticClassifier(num_features=10)
criterion = nn.BCELoss()
optimizer = torch.optim.SGD(model.parameters(), lr=0.01)
# Ciclo de entrenamiento
epochs = 100
for epoch in range(epochs):
predictions = model(features)
loss = criterion(predictions, targets)
optimizer.zero_grad()
loss.backward()
optimizer.step()
if epoch % 10 == 0:
print(f"Epoch {epoch} | Loss: {loss.item():.4f}")