NumPy与PyTorch计算交叉熵损失结果不一致问题问询
问题原因及解决方法
两者结果不一致的核心原因是PyTorch的nn.CrossEntropyLoss计算逻辑和你用NumPy实现的公式完全不匹配,具体差异点有两个:
1. 输入数据的含义不同
你的NumPy代码里,y_hat是经过Softmax归一化后的概率值,公式直接计算标准交叉熵:-np.sum(target*np.log(y_hat))。
但PyTorch的nn.CrossEntropyLoss默认要求输入的output是模型的原始输出(logits,未经过Softmax),它会自动先对output做Softmax,再取对数,最后计算损失。你现在把已经Softmax后的概率值传给它,等于重复做了一次Softmax,结果自然偏差。
2. 标签格式要求不同
你的NumPy代码用的是one-hot编码的目标标签,但nn.CrossEntropyLoss要求标签是类别索引(单个整数),而非one-hot向量。你传入的[1,0,0,0,0]这种one-hot格式,会被PyTorch错误解析,进一步导致结果异常。
修正方法(两种可选)
方法一:已有Softmax概率值时,用nn.NLLLoss
既然已经有了Softmax后的概率,只需先取对数,再用NLLLoss(负对数似然损失),同时标签用类别索引:
import torch import torch.nn as nn import numpy as np y_hat = [0.57,0.05,0.14,0.10,0.14] # 对概率取对数,需保留batch维度(加一层中括号) log_y_hat = torch.FloatTensor([np.log(y_hat)]) # 目标是第0类,标签用索引0,类型为LongTensor label = torch.LongTensor([0]) loss = nn.NLLLoss() loss_value = loss(log_y_hat, label) print(loss_value) # 输出:tensor(0.5621),与NumPy结果一致
方法二:用nn.CrossEntropyLoss,输入原始logits
如果你的模型输出的是未经过Softmax的logits,直接传入CrossEntropyLoss,标签用类别索引即可。以下是从y_hat反推logits的示例(实际使用时直接传入模型原始输出即可):
import torch import torch.nn as nn y_hat = [0.57,0.05,0.14,0.10,0.14] # 从概率反推logits(仅作示例) logits = torch.log(torch.FloatTensor(y_hat)) loss = nn.CrossEntropyLoss() label = torch.LongTensor([0]) loss_value = loss(logits.unsqueeze(0), label) print(loss_value) # 输出:tensor(0.5621),与NumPy结果一致
内容的提问来源于stack exchange,提问作者hello m
相关产品推荐
相关产品推荐

