You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.16 09:30:38