本文目录导读:

“损失重新加权”(Loss Reweighting)是机器学习,特别是在处理不平衡数据集、噪声标签或不同任务重要性时常用的一种技术,其核心思想是:不再将每个样本(或类别)的损失视为同等重要,而是根据特定策略动态或静态地为每个样本分配不同的权重,从而引导模型关注更重要的样本或困难样本。
这通常是对标准的损失函数(如交叉熵、MSE)进行修改,形式化为:
[ L = \frac{1}{N} \sum_{i=1}^{N} w_i \cdot \ell(f(x_i), y_i) ]
(\ell) 是原始损失,(w_i) 是赋予第 (i) 个样本的权重,(N) 是批量大小。
以下是“损失重新加权”主要的应用场景、常见策略及优缺点:
主要应用场景
- 类别不平衡(最常见):正负样本比例悬殊(如欺诈检测、罕见病诊断)。
- 噪声标签:训练数据标签可能错误,希望能降低被污染样本的权重。
- 困难样本挖掘:让模型更多地关注当前难以正确分类的样本。
- 多任务学习:不同的任务(如分类、回归、分割)损失值尺度不同,需要加权平衡。
- 课程学习:训练初期关注简单样本,后期关注困难样本。
常见策略
根据类别频率加权
这是处理不平衡数据最直接的方法。
- 逆类频率加权:权重 (w_c = \frac{N}{n_c})((N)为总样本数,(n_c)为c类样本数)。
- 平滑逆频率:(w_c = \frac{1}{\log(1.0 + n_c)}) 或 (\frac{1}{\sqrt{n_c}}),避免稀有类权重过大导致过拟合。
Focal Loss(焦点损失)—— 最经典
由何恺明团队在 RetinaNet 中提出,专为解决密集物体检测中的正负样本极度不平衡和难易样本问题。
- 公式:(\text{FL}(p_t) = -(1 - p_t)^\gamma \log(p_t))
- (p_t) 是模型预测的正确类别的概率。
- (\gamma)(聚焦参数,通常2)> 0。
- 原理:
- 当样本分类正确且置信度很高(如 (p_t = 0.9))时,((1-p_t)^\gamma \approx 0.01),损失被大幅降低。
- 当样本分类错误或置信度低(如 (p_t = 0.3))时,((1-p_t)^\gamma \approx 0.49),损失保持较大。
- 效果:自动抑制简单样本的权重,让模型专注于困难样本,它天生就能处理类别不平衡,因为多数类往往容易判断,从而被抑制。
梯度引导加权
- 基于梯度的元加权:不是直接设置权重,而是通过学习一个元网络来输出权重,目标是最小化在干净验证集上的损失,这种方法很强大,但计算复杂。
- 自适应加权:根据样本梯度范数调整权重,抑制那些梯度异常(可能是噪声)的样本。
多任务损失加权
- 不确定性加权 (Kendall et al., 2018):将每个任务的同方差不确定性(噪声参数)作为一个可学习的量,根据不确定性自动调整任务权重,损失形式为: [ L = \frac{1}{2\sigma_1^2}L_1 + \frac{1}{2\sigma_2^2}L_2 + \log\sigma_1\sigma_2 ] 不确定性越高((\sigma)大),权重越低。
课程学习与预定义调度
- 线性/指数退火:随着训练epoch增加,逐步增加对困难样本的关注。
- 基于动态置信度:在训练过程中,如果一个样本被模型持续低置信度预测,则增加它的权重。
需要注意的地方(陷阱)
- 过拟合噪声:如果数据标签本身有大量噪声,盲目对“困难样本”加权(如Focal Loss)反而会导致模型去拟合错误的标签,需要先进行样本筛选或结合噪声检测。
- 权重爆炸:对于极度罕见的类别,逆频率加权可能导致权重极大,模型难以收敛。
- 与数据增强的配合:在采用强数据增强(如Mixup, CutMix)时,简单的类频率加权可能失效,因为样本的标签变成了混合标签,此时需要混合标签比例加权。
- 重新加权 vs. 重采样:
- 重新加权:计算方便,不改变数据分布,在批量梯度下降时引入方差。
- 重采样(过采样/欠采样):改变数据分布,可能导致模型过拟合少数类或丢失多数类信息。两者常结合使用。
代码示例(PyTorch风格)
import torch
import torch.nn.functional as F
# 1. 类频率权重 (用于CrossEntropyLoss)
# 假设 num_samples_per_class = [950, 50]
class_weights = torch.tensor([1.0, 19.0]) # 或 1/class_freq...
criterion = torch.nn.CrossEntropyLoss(weight=class_weights)
# 2. Focal Loss 实现 (简化版)
def focal_loss(logits, targets, gamma=2.0, alpha=0.25):
# alpha 用于平衡正负样本 (类别不平衡),有时设为1
ce_loss = F.cross_entropy(logits, targets, reduction='none')
pt = torch.exp(-ce_loss) # pt 是预测正确类的概率
focal_loss = alpha * (1 - pt) ** gamma * ce_loss
return focal_loss.mean()
# 3. 动态样本权重 (基于训练进度)
def get_course_learning_weight(epoch, max_epochs, hard_sample_pool):
# 假设 hard_sample_pool 存储了之前epoch中loss大的样本索引
# 早期只关注简单样本,后期关注难样本
if epoch < max_epochs * 0.3:
return 1.0 # 基础权重
else:
# 为困难样本增加权重
for idx in hard_sample_pool:
sample_weights[idx] *= 1.2
总结建议
- 如果你遇到类别极端不平衡:首选 Focal Loss 或带平滑的逆类频率加权。
- 如果你不确定数据是否有噪声:先用标准损失训练一个模型,观察哪些样本loss长期居高不下(可能是噪声或难例),如果是噪声,使用截断损失或对比学习;如果是难例,再使用梯度引导加权。
- 如果你在做多任务学习:首选不确定性加权,它最稳定且易于实现。
损失重新加权不是一个万能药,需要结合你对数据的理解(噪声水平、分布特征)来设计策略,你具体遇到了什么问题场景(长尾分类、目标检测、还是多任务),我可以给出更针对性的建议。