PyTorch中CrossEntropyLoss计算疑问:为何结果为0.7437而非0?
PyTorch CrossEntropyLoss 计算结果与手动推导不符的原因分析
哈哈,这个问题我当初刚上手PyTorch的时候也踩过一模一样的坑!你手动计算的交叉熵是基于已经归一化完成的概率分布,但PyTorch的nn.CrossEntropyLoss()根本不是这么算的——它其实是把LogSoftmax和NLLLoss(负对数似然损失)打包在一起的组合函数,输入要求是未经过softmax的原始输出(也就是常说的logits),而不是直接输入概率值。
我们来一步步拆解你给出的例子,就能明白为什么结果是0.7437了:
1. CrossEntropyLoss的核心计算步骤
nn.CrossEntropyLoss()的完整计算逻辑是:
- 第一步:对输入的logits执行softmax操作,得到归一化的概率分布
- 第二步:对得到的概率值取自然对数(ln)
- 第三步:针对目标类别,取对应对数概率的负值作为最终损失
2. 代入你的例子计算
你的输入logits是[0,0,0,1],目标类别是3:
- 第一步:计算softmax
softmax的公式是每个元素的e^x除以所有元素e^x的总和:
sum = e^0 + e^0 + e^0 + e^1 = 1 + 1 + 1 + 2.71828 ≈ 5.71828
目标类别3对应的softmax值 = e^1 / sum ≈ 2.71828 / 5.71828 ≈ 0.4754 - 第二步:取自然对数
ln(0.4754) ≈ -0.7437 - 第三步:取负值得到损失
最终损失 = -(-0.7437) = 0.7437
3. 如何得到你预期的0损失?
如果你想得到手动推导的0损失,需要先把输出转换成概率分布,再配合对应的损失函数:
比如先对logits做softmax得到[0,0,0,1],然后取对数得到[-inf, -inf, -inf, 0],再用nn.NLLLoss()计算,此时损失就是0。对应的测试代码大概是这样:
import torch import torch.nn as nn from torch.autograd import Variable output = Variable(torch.FloatTensor([0,0,0,1])).view(1, -1) target = Variable(torch.LongTensor([3])) # 先做softmax+log log_probs = torch.log(torch.softmax(output, dim=1)) criterion = nn.NLLLoss() loss = criterion(log_probs, target) print(loss) # 输出0.0
内容的提问来源于stack exchange,提问作者MBT
相关产品推荐
相关产品推荐

