Función PyTorch torch.nn.CrossEntropyLoss
Manual de referencia de PyTorch torch.nn
torch.nn.CrossEntropyLossEs la función de pérdida utilizada para clasificación multiclase en PyTorch.
Combina nn.LogSoftmax y nn.NLLLoss, y se usa comúnmente en tareas como clasificación de imágenes y clasificación de texto.
Definición de la función
torch.nn.CrossEntropyLoss(weight=None, ignore_index=-100, reduction='mean', label_smoothing=0.0)
Descripción de parámetros:
weight(Tensor): Asigna un peso diferente a cada clase, para casos de desequilibrio de clases.ignore_index(int): Ignora el cálculo de pérdida del índice especificado. Por defecto es -100.reduction(str): Modo de agregación de pérdida. Opcional'mean'、'sum'、'none'. Por defecto es'mean'。label_smoothing(float): Parámetro de suavizado de etiquetas, con valores entre 0 y 1. Por defecto es 0.
Principio matemático
La fórmula de la pérdida de entropía cruzada:
Loss = -log(exp(y_true) / sum(exp(y_i)))
Es decir, cuanto mayor sea la probabilidad predicha para la clase correcta, menor será la pérdida.
Ejemplos de uso
Ejemplo 1: Uso básico
Crear y usar la pérdida de entropía cruzada:
Ejemplo
import torch.nn as nn
# Crear la función de pérdida
criterion = nn.CrossEntropyLoss()
# Logits de salida del modelo (sin normalizar)
# Forma: (batch_size, num_classes)
outputs = torch.randn(4, 10)
# Etiquetas reales
labels = torch.tensor([2, 5, 1, 7])
# Calcular la pérdida
loss = criterion(outputs, labels)
print("Salida del modelo (logits):", outputs[0].tolist())
print("Etiquetas reales:", labels[0].item())
print("Pérdida de entropía cruzada:", loss.item())
Ejemplo 2: Pesos de clase
Manejar el desequilibrio de clases:
Ejemplo
import torch.nn as nn
# Pesos de clase: dar mayor peso a las clases minoritarias
# Supongamos 10 clases, la clase 3 y la clase 7 son más importantes
weight = torch.ones(10)
weight[3] = 2.0
weight[7] = 2.0
criterion_weighted = nn.CrossEntropyLoss(weight=weight)
outputs = torch.randn(4, 10)
labels = torch.tensor([2, 3, 7, 5])
loss = criterion_weighted(outputs, labels)
print("Pérdida de entropía cruzada ponderada:", loss.item())
Ejemplo 3: Suavizado de etiquetas
Usar suavizado de etiquetas para prevenir el sobreajuste:
Ejemplo
import torch.nn as nn
# Suavizado de etiquetas: 0.1 significa distribuir uniformemente el 10% de la probabilidad a otras clases
criterion_smooth = nn.CrossEntropyLoss(label_smoothing=0.1)
outputs = torch.randn(4, 10)
labels = torch.tensor([2, 5, 1, 7])
loss = criterion_smooth(outputs, labels)
print("Pérdida con suavizado de etiquetas:", loss.item())
# Comparación: sin suavizado de etiquetas
criterion = nn.CrossEntropyLoss()
loss_no_smooth = criterion(outputs, labels)
print("Pérdida sin suavizado de etiquetas:", loss_no_smooth.item())
Ejemplo 4: Flujo completo de entrenamiento de clasificación
Ejemplo completo de entrenamiento de modelo:
Ejemplo
import torch.nn as nn
import torch.optim as optim
# Modelo de clasificación simple
class Classifier(nn.Module):
def __init__(self, input_dim=784, num_classes=10):
super(Classifier, self).__init__()
self.fc = nn.Sequential(
nn.Linear(input_dim, 256),
nn.ReLU(),
nn.Dropout(0.5),
nn.Linear(256, num_classes)
)
def forward(self, x):
return self.fc(x)
# Inicializar el modelo y la pérdida
model = Classifier()
criterion = nn.CrossEntropyLoss()
optimizer = optim.Adam(model.parameters(), lr=0.001)
# Simular datos de entrenamiento
batch_size = 32
x = torch.randn(batch_size, 784) # Entrada
y = torch.randint(0, 10, (batch_size,)) # Etiquetas
# Propagación hacia adelante
model.train()
outputs = model(x)
loss = criterion(outputs, y)
# Propagación hacia atrás
optimizer.zero_grad()
loss.backward()
optimizer.step()
print("Pérdida del lote:", loss.item())
# Predicción
model.eval()
with torch.no_grad():
outputs = model(x)
predictions = outputs.argmax(dim=1)
accuracy = (predictions == y).float().mean()
print("Precisión de la predicción:", accuracy.item())
Ejemplo 5: Uso de ignore_index
Ignorar etiquetas específicas:
Ejemplo
import torch.nn as nn
# Ignorar las muestras con label=-100
criterion = nn.CrossEntropyLoss(ignore_index=-100)
outputs = torch.randn(5, 10)
# Las etiquetas de algunas muestras son -100, lo que indica que se ignoran
labels = torch.tensor([2, -100, 5, -100, 7])
loss = criterion(outputs, labels)
print("Pérdida después de ignorar etiquetas especiales:", loss.item())
Ejemplo 6: Diferentes modos de reduction
Controlar el modo de agregación de pérdida:
Ejemplo
import torch.nn as nn
outputs = torch.randn(4, 10)
labels = torch.tensor([2, 5, 1, 7])
# mean: devuelve la pérdida promedio
loss_mean = nn.CrossEntropyLoss(reduction='mean')(outputs, labels)
print("mean:", loss_mean.item())
# sum: devuelve la suma total
loss_sum = nn.CrossEntropyLoss(reduction='sum')(outputs, labels)
print("sum:", loss_sum.item())
# none: devuelve la pérdida de cada muestra
loss_none = nn.CrossEntropyLoss(reduction='none')(outputs, labels)
print("none:", loss_none.tolist())
Preguntas frecuentes
Q1: ¿Cuál es la diferencia entre CrossEntropyLoss y NLLLoss?
CrossEntropyLoss = LogSoftmax + NLLLoss. Ya tiene softmax incorporado, no es necesario agregarlo manualmente.
Q2: ¿Por qué la salida del modelo no usa softmax?
CrossEntropyLoss calcula softmax automáticamente en su interior; usar logits directamente puede mejorar la estabilidad numérica.
Q3: ¿Para qué escenarios es adecuado el suavizado de etiquetas?
El suavizado de etiquetas es adecuado para casos con un gran número de clases y puede mejorar la capacidad de generalización del modelo.
Escenarios de uso
nn.CrossEntropyLossLos principales escenarios de aplicación incluyen:
- Clasificación de imágenes: como CIFAR-10, ImageNet
- Clasificación de texto: análisis de sentimientos, clasificación de temas
- Tareas de clasificación multiclase: cualquier tarea de clasificación con más de 2 clases
Nota: las etiquetas deben ser índices de clase (0 a num_classes-1), no codificación one-hot.
Otras extensiones