PyTorch中BCELoss与CrossEntropyLoss使用weight参数报错如何解决
报错原因
nn.BCELoss、nn.CrossEntropyLoss的weight参数属于类初始化阶段的传入参数,不是前向传播计算损失时的入参,所以你在调用CE_Loss(output, target, weight=batch_weights)时会触发forward() got an unexpected keyword argument 'weight'的报错。
补充说明:初始化时传入的weight是类别级全局权重,长度等于总类别数,会对对应类别的所有样本损失统一做加权缩放,如果你需要为每个样本单独设置不同的权重,需要搭配reduction参数实现。
正确实现方式
根据你的需求分为两类场景:
场景1:仅按类别做加权(适配你的类别不平衡需求,少数类占10%的情况下直接按类别占比反比设置权重即可,比如多数类权重为1,少数类权重为9)
CrossEntropyLoss 用法(适用于未经过softmax激活的原始logits输出,二分类场景下output维度为[batch_size, 2],target为类别索引0/1)
import torch import torch.nn as nn # 权重顺序对应类别索引0、1,根据你的少数类对应的索引调整数值,权重需要和模型在同一设备 class_weights = torch.tensor([1.0, 9.0], device='cuda' if torch.cuda.is_available() else 'cpu') # 初始化损失时传入类别权重 CE_loss = nn.CrossEntropyLoss(weight=class_weights) # 计算损失时直接传入输出和标签即可 loss = CE_loss(output, target)
BCELoss 用法(适用于已经过sigmoid激活的输出,output维度为[batch_size],取值范围0-1,target为0/1的浮点型张量)
import torch import torch.nn as nn class_weights = torch.tensor([1.0, 9.0], device='cuda' if torch.cuda.is_available() else 'cpu') CE_loss = nn.BCELoss(weight=class_weights) loss = CE_loss(output, target)
小提示:如果二分类模型输出是未经过sigmoid的原始logits,建议使用
nn.BCEWithLogitsLoss替代nn.BCELoss,数值稳定性更好,加权用法和上述BCELoss完全一致。
场景2:需要逐样本自定义权重(即你的batch_weights为每个样本单独设置的权重值,维度和batch_size一致)
需要先将损失的reduction参数设为none,得到每个样本的单独损失后,手动乘对应样本权重再做聚合:
CrossEntropyLoss 用法
import torch import torch.nn as nn CE_loss = nn.CrossEntropyLoss(reduction='none') # 先得到每个样本的损失,维度为[batch_size] sample_loss = CE_loss(output, target) # 乘对应样本的权重后取平均/求和 weighted_loss = (sample_loss * batch_weights).mean()
BCELoss 用法
import torch import torch.nn as nn CE_loss = nn.BCELoss(reduction='none') sample_loss = CE_loss(output, target) weighted_loss = (sample_loss * batch_weights).mean()
注意:需要确保
batch_weights和sample_loss的维度、设备完全匹配,避免广播报错。
内容的提问来源于stack exchange,提问作者clueless
相关产品推荐
相关产品推荐

