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

如何在BERT序列分类模型中对特定类别预测加重惩罚?

解决BERT二分类模型类别偏向问题的方法

首先纠正你当前代码里的关键错误:nn.CrossEntropyLoss()的输入应该是模型输出的logits,而非经过softmax后的结果。因为CrossEntropyLoss内部已经集成了log_softmax和NLLLoss的计算逻辑,提前做softmax会导致数值不稳定,还会损失梯度信息。所以第一步要把损失计算改成:

loss = loss_fun(out_logits, labels_tensor.long())  # 注意标签要转成整数类型,CrossEntropyLoss要求标签为int64

针对你遇到的类别不平衡(仅1个样本属于类别1)导致的模型偏向问题,最直接的解决方式是给类别1的样本设置更高的损失权重,具体实现有两种方式:

方法一:使用带权重的CrossEntropyLoss

初始化损失函数时传入类别权重参数,根据样本不平衡比例调整权重数值(比如这里类别0和1的样本数是3:1,可给类别1设3倍权重):

# 定义类别权重:类别0权重1,类别1权重3,需和模型同设备
class_weights = torch.tensor([1.0, 3.0], device='cuda:0')
loss_fun = nn.CrossEntropyLoss(weight=class_weights)

# 用logits计算损失
loss = loss_fun(out_logits, labels_tensor.long())

这样模型计算类别1样本的损失时会自动乘以设置的权重,相当于加重了对该类样本预测错误的惩罚。

方法二:手动计算样本级加权损失

如果需要更灵活的控制(比如针对单个样本单独调整权重),可以手动计算每个样本的损失权重:

# 给标签为1的样本设置3倍权重,其他样本权重为1
sample_weights = torch.where(labels_tensor == 1, 3.0, 1.0).to('cuda:0')

# 先计算每个样本的交叉熵损失(reduction设为none保留单样本损失)
per_sample_loss = nn.CrossEntropyLoss(reduction='none')(out_logits, labels_tensor.long())
# 乘以样本权重后取平均得到总损失
loss = (per_sample_loss * sample_weights).mean()

这种方式适合样本不平衡程度差异较大、需要精细化调整单样本权重的场景。

额外优化建议

  • 数据层面:如果条件允许,补充更多类别1的样本,从根源上解决不平衡问题,这是最有效的方式。
  • 模型训练技巧:可以尝试使用Focal Loss,它会自动降低易分类样本的权重,聚焦难分类的样本(比如你的类别1样本),核心逻辑是给错误预测的难样本赋予更高的损失权重,你可以基于PyTorch手动实现该损失函数。

内容的提问来源于stack exchange,提问作者Penguin

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.07 03:35:17