调用loss.backward()触发CUDA device-side assert报错,BCELoss无法使用如何解决
报错原因
- 核心触发点是
BCELoss对输入的取值范围有硬性要求:预测输入必须落在[0,1]区间内,你的代码直接传入了模型输出的原始logits(值域为(-∞,+∞)),计算损失时出现log(负数)、log(0)等非法运算,在CUDA设备上运行就会触发device-side assert报错。 - 额外需检查的潜在问题:你的代码存在变量名书写不统一的问题,定义损失函数时用的变量名是小写
loss,计算损失时调用的是大写Loss,如果没有全局定义大写的损失函数变量,也会触发运行错误。 - 标签维度本身没问题:你传入的z和y都是(128,2)形状,符合BCELoss要求的「输入和标签形状一致」的规则,你用CrossEntropyLoss时把y改成(128,)是因为CrossEntropyLoss默认接收类别索引标签,和BCELoss的标签规则不同。
修复方案
根据你的使用场景可以二选一:
方案1:继续使用BCELoss
- 给模型输出的z加一层Sigmoid激活,把数值压缩到[0,1]区间,计算损失的代码改为
loss = loss(torch.sigmoid(z), y) - 确保标签y的所有取值仅为0或1,不要出现其他数值
- 统一损失函数的变量名,避免大小写错误
方案2(更推荐):替换为BCEWithLogitsLoss
直接把损失函数定义改为loss = nn.BCEWithLogitsLoss(),不需要手动加Sigmoid激活,直接传入原始logits和同形状的onehot标签即可,这个损失函数内置了Sigmoid运算,数值稳定性比手动加激活再算BCELoss更好。
内容的提问来源于stack exchange,提问作者user3668129
相关产品推荐
相关产品推荐

