PyTorch中nn.CrossEntropyLoss仅返回-0.0?训练损失始终为零的问题
CrossEntropyLoss返回0及训练损失恒为0的问题
问题1:torch.nn.CrossEntropyLoss()(torch.Tensor([0]), torch.Tensor([1]))返回tensor(-0.)的原因
PyTorch的CrossEntropyLoss有两个核心要求你没注意到:
- 输入规则:第一个参数(模型输出)需为
[batch_size, num_classes]形状,代表每个样本在不同类别上的预测得分;第二个参数(标签)必须是类别索引(整数类型),范围是0到num_classes-1,不能是浮点型或超出索引范围的值。 - 你传入的输出是单元素张量(相当于1个类别),标签
1超出了0到0的合法索引范围,属于非法输入,导致计算出现数值异常,最终返回了-0.0。
问题2:训练时损失始终为零的原因
结合代码和数据处理,核心问题是损失函数、模型输出、标签三者完全不匹配:
- 损失函数选型错误:
CrossEntropyLoss适用于多分类任务,要求模型输出通道数等于类别数(二分类需输出2个通道),但你设置S3=1,单通道输出完全不符合该损失函数的要求。 - 标签格式错误:你把标签处理成了
[[0], [1]]的浮点型二维张量,但CrossEntropyLoss需要的是一维整数张量(比如[0,1])。 - 模型输出激活错误:最后一层用
ReLU会截断负得分,而CrossEntropyLoss要求输入是未经过Softmax的原始得分(logits),ReLU的截断会导致损失计算异常。
修复方案
方案1:继续使用CrossEntropyLoss(标准二分类)
- 调整模型结构:将
S3设为2,去掉最后一层的ReLU:
def forward(self, x): x = F.relu(self.linear1(x)) x = self.linear2(x) # 输出原始logits,无需ReLU return x
- 修正标签格式:转为一维整数张量,无需嵌套列表:
y_train = torch.from_numpy(y_train).type(torch.LongTensor) y_val = torch.from_numpy(y_val).type(torch.LongTensor) y_test = torch.from_numpy(y_test).type(torch.LongTensor)
方案2:改用BCELoss(单输出二分类)
如果坚持用单通道输出,可切换为适合二分类的BCELoss:
- 调整模型结构:最后一层加
Sigmoid激活:
def forward(self, x): x = F.relu(self.linear1(x)) x = F.sigmoid(self.linear2(x)) return x
- 损失函数替换:
loss_fn = nn.BCELoss()
内容的提问来源于Stack Exchange,提问作者Selvi7
相关产品推荐
相关产品推荐

