共计 1750 个字符,预计需要花费 5 分钟才能阅读完成。
在机器学习分类任务中,处理类别不平衡数据是一个常见且棘手的问题。作为一名从业者,我深刻体会到标准 BCE(Binary Cross-Entropy)损失函数在这种场景下的局限性。本文将分享我在实践中总结的几种有效优化策略,希望能帮助遇到同样问题的同行们。

背景痛点:为什么标准 BCE 会失效
在二分类问题中,当两类样本数量差异显著时(比如正负样本比例为 1:10),标准 BCE 损失函数会让模型更倾向于预测多数类。这是因为损失函数对所有样本 ” 一视同仁 ”,导致少数类的错误分类对总体损失影响很小。
这种现象在实际业务中很常见,比如:
- 医疗诊断中的罕见病例检测
- 金融风控中的欺诈交易识别
- 工业质检中的缺陷产品分类
技术方案对比:三种改进方法
1. 加权 BCE(Weighted BCE)
这是最直接的改进方式,通过给不同类别的样本分配不同权重,放大少数类样本的损失贡献。优点是实现简单,计算开销小。缺点是权重需要手动调参,且对所有难易样本同等对待。
2. Focal Loss
由何恺明团队在 2017 年提出,通过引入调节因子 γ,自动降低易分类样本的权重,让模型更关注难样本。适用于存在大量简单负样本的场景(如目标检测)。
3. Class-Balanced Loss
通过有效样本数来重新平衡损失,更适合极端不平衡场景(如 1:1000)。但计算复杂度较高。
PyTorch 实现详解
加权 BCE 实现
import torch
import torch.nn as nn
# 假设正样本占比 10%
pos_weight = torch.tensor([9.0]) # 权重与类别频率成反比
# 定义损失函数
criterion = nn.BCEWithLogitsLoss(pos_weight=pos_weight)
# 使用示例
logits = model(inputs) # 模型输出
loss = criterion(logits, targets) # targets 是 0 / 1 标签
关键点:
pos_weight应设为负样本数 / 正样本数- 使用
BCEWithLogitsLoss比单独 Sigmoid+BCELoss 更数值稳定
Focal Loss 自定义实现
class FocalLoss(nn.Module):
def __init__(self, alpha=0.25, gamma=2.0):
super().__init__()
self.alpha = alpha
self.gamma = gamma
def forward(self, inputs, targets):
BCE_loss = nn.functional.binary_cross_entropy_with_logits(inputs, targets, reduction='none')
# Focal Loss 核心计算
pt = torch.exp(-BCE_loss) # p_t
focal_loss = self.alpha * (1-pt)**self.gamma * BCE_loss
return focal_loss.mean()
参数说明:
alpha:平衡类别权重,类似加权 BCEgamma:调节难易样本权重,越大对难样本关注度越高(通常 1 - 5 之间)
实验对比
我用一个信用卡欺诈检测数据集(正负比 1:100)做了简单对比:
| 方法 | 准确率 | 召回率 | F1 分数 |
|---|---|---|---|
| 标准 BCE | 0.99 | 0.05 | 0.09 |
| 加权 BCE | 0.97 | 0.68 | 0.80 |
| Focal Loss | 0.96 | 0.75 | 0.84 |
可以看到改进方法显著提升了召回率,虽然准确率略有下降,但对这类任务更有价值。
生产环境建议
- 权重选择原则:
- 加权 BCE:建议先用类别频率倒数作为初始值
-
Focal Loss:γ 从 2.0 开始尝试,α 设为少数类占比
-
监控指标:
- 不要只看整体准确率
-
重点关注召回率、精确率 -F1 分数曲线
-
组合策略:
- 可以先对多数类欠采样,再用 Focal Loss
- 对极不平衡数据(如 1:1000),考虑两阶段训练
延伸思考
除了调整损失函数,还可以尝试:
- 数据层面的方法:SMOTE 过采样、ADASYN 等
- 模型结构改进:在最后一层引入类别偏置项
- 集成方法:对少数类 boostrap 采样训练多个模型
在实践中,我经常发现组合策略效果最好。比如先用 SMOTE 平衡数据分布,再用 Focal Loss 进行训练,最后通过模型集成进一步提升鲁棒性。
希望这些经验对你有帮助。如果你在实践中发现其他有效策略,欢迎交流分享!
