首页 > 编程问答 >如何在 PyTorch 中使用类权重和焦点损失来处理多类分类的不平衡数据集

如何在 PyTorch 中使用类权重和焦点损失来处理多类分类的不平衡数据集

时间:2024-07-23 12:10:26浏览次数:15  
标签:python machine-learning deep-learning neural-network pytorch

我正在研究语言任务的多类分类(4 类),并使用 BERT 模型进行分类任务。我正在关注这篇博文 NLP 的迁移学习:微调 BERT 用于文本分类 我的 BERT 微调模型返回 nn.LogSoftmax(dim=1)

我的数据非常不平衡,所以我使用了| ||计算类别的权重并使用损失中的权重。 sklearn.utils.class_weight.compute_class_weight 我的结果不太好,所以我想到用

class_weights = compute_class_weight('balanced', np.unique(train_labels), train_labels)
weights= torch.tensor(class_weights,dtype=torch.float)
cross_entropy  = nn.NLLLoss(weight=weights) 

进行实验,并有一个焦点损失的代码。 Focal Loss 我现在有 3 个问题。首先也是最重要的是

class FocalLoss(nn.Module):
  def __init__(self, alpha=1, gamma=2, logits=False, reduce=True):
    super(FocalLoss, self).__init__()
    self.alpha = alpha
    self.gamma = gamma
    self.logits = logits
    self.reduce = reduce

  def forward(self, inputs, targets):
    BCE_loss = nn.CrossEntropyLoss()(inputs, targets)

    pt = torch.exp(-BCE_loss)
    F_loss = self.alpha * (1-pt)**self.gamma * BCE_loss

    if self.reduce:
      return torch.mean(F_loss)
    else:
      return F_loss

我应该使用带有焦点损失的类权重吗?

  1. 如果我必须在这个
  2. 中实现权重,我可以在 Focal Loss 里面使用 weights 参数 nn.CrossEntropyLoss()
  3. 如果这个实现不正确,包括权重在内的正确代码应该是什么(如果可能)

当然,让我们分解如何在 PyTorch 中使用类权重和焦点损失来处理不平衡的多类分类问题。

了解问题

当某些类在数据集中比其他类出现的频率更高时,就会出现类不平衡。这可能会导致模型偏向多数类,在少数类上的表现不佳。类权重和焦点损失是解决此问题并在类之间实现更公平训练的两种技术。

1. 类权重

类权重为每个类分配一个权重,与该类的频率成反比。这意味着在计算损失时,少数类获得更高的权重,这有助于平衡多数类的影响。

已经在使用 sklearn.utils.class_weight.compute_class_weight 正确计算类权重。在 PyTorch 中,通常将其与 nn.CrossEntropyLoss 一起使用:

class_weights = compute_class_weight('balanced', np.unique(train_labels), train_labels)
weights= torch.tensor(class_weights,dtype=torch.float).to(device)  # 将权重发送到设备
cross_entropy  = nn.CrossEntropyLoss(weight=weights) 

请确保的 device 与的输入数据和模型(CPU 或 GPU)相同。

2. 焦点损失

焦点损失(Lin 等人,2017 年)通过降低易分类样本(即模型有信心地正确分类的样本)的损失来扩展交叉熵损失。它侧重于对模型具有挑战性的样本。

下面是 PyTorch 中焦点损失的一种常见实现:

class FocalLoss(nn.Module):
    def __init__(self, alpha=1, gamma=2, reduce=True):
        super(FocalLoss, self).__init__()
        self.alpha = alpha
        self.gamma = gamma
        self.reduce = reduce

    def forward(self, inputs, targets):
        ce_loss = nn.CrossEntropyLoss(reduction='none')(inputs, targets) 
        pt = torch.exp(-ce_loss)  # 获取每个样本的概率
        F_loss = self.alpha * (1 - pt)**self.gamma * ce_loss

        if self.reduce:
            return torch.mean(F_loss)
        else:
            return F_loss

组合类权重和焦点损失

是的,可以组合类权重和焦点损失来解决类不平衡问题。实际上,这可能非常有效。可以修改焦点损失实现以包含类权重:

class FocalLossWithWeights(nn.Module):
    def __init__(self, alpha=1, gamma=2, weights=None, reduce=True):
        super(FocalLossWithWeights, self).__init__()
        self.alpha = alpha
        self.gamma = gamma
        self.weights = weights
        self.reduce = reduce

    def forward(self, inputs, targets):
        ce_loss = nn.CrossEntropyLoss(weight=self.weights, reduction='none')(inputs, targets)
        pt = torch.exp(-ce_loss)
        F_loss = self.alpha * (1 - pt)**self.gamma * ce_loss

        if self.reduce:
            return torch.mean(F_loss)
        else:
            return F_loss

使用修改后的焦点损失

# ...(的代码用于数据加载和模型定义)

# 假设已经计算了 class_weights
focal_loss_with_weights = FocalLossWithWeights(alpha=1, gamma=2, weights=weights.to(device)) 

# 在的训练循环中:
# ...
logits = model(input_ids, attention_mask) 
loss = focal_loss_with_weights(logits, labels)
# ...

解释

  • 在组合的实现中,我们将 nn.CrossEntropyLoss(reduction='none') 用于逐个样本损失,而不会聚合。
  • 然后,我们将类权重直接应用于 nn.CrossEntropyLoss 中的逐个样本损失。
  • alpha gamma 参数控制焦点损失行为。 alpha 调节类权重,而 gamma 控制对错误分类样本的关注程度。

通过试验不同的 alpha gamma 值以及类权重计算方法(例如, 'balanced' 或自定义权重),找到适合的特定数据集和问题的最佳组合非常重要。

标签:python,machine-learning,deep-learning,neural-network,pytorch
From: 64751157

相关文章

  • 如何用可变长度注释Python列表
    如何为可变长度或None的Python列表编写注释?当我这样写时,它会返回一个错误。defsome_function(params:list[str,...])#thisgiveserror:`TypeError:'type'objectisnotsubscriptable`defsome_function(params:List[str,...])#thisalsogiveserro......
  • Python 协议和 Django 模型
    假设我有一个简单的协议A和一个未能实现该协议的类B:fromtypingimportProtocolclassA(Protocol):deffoo(self)->str:...classB:pass当下面的代码进行类型检查时,Mypy将正确地抱怨x:A=B()mypy.error:Incompatibletypes......
  • Python字段的字符串注释
    Python是否支持类字段的任何类型的字符串注释?例如,在Golang中,我可以定义这样的结构,带有可选的字符串标签:typeUserstruct{Namestring`example:"name"`}我需要在Python中定义一个新类,其中包含包含点.的字段名称。我希望可能有某种方法来注释字段,或者......
  • 具有未定义变量和注释的有效 Python 行
    我来了一篇文章,其中包含未定义的变量名称和某些类型注释。该行有效。它有什么作用以及可能的用途是什么?withundefinedvariablenamewithsometypeannotation.Thelineisvalid.Whatitdoesandwhatarepossibleusages?>>>x:int>>>xTraceback(mostr......
  • 使用 Python 通过逻辑应用运行长时间运行的 Azure Functions
    我已经尝试解决这个问题有一段时间了,但我似乎找不到解决方案。因此,正如标题所示,我试图通过函数在逻辑应用程序中运行长时间运行的操作。我有一个python代码,可以比较2个excel文件并进行一些转换。它工作正常,但是,Excel文件包含近20k行(它是动态的,将来会添加更多行),因此......
  • Pytorch从基础数据中学习时出现巨大损失
    我正在尝试制作一个非常基本的机器学习应用程序,基本上我希望模型能够根据我提供的虚拟数据尝试预测明年的每个月,但我遭受了巨大的损失Loss:5206342.5000并且预测值与我的预期相差如此之远Predictedvaluesforeachmonthofnextyear:[-0.043424129486083984,......
  • 使用递归函数计算阶乘时,我在 python 中遇到类型错误
    defcalc_fact(n):如果(n==1或n==0):返回1别的:n*calc_fact(n-1)print(calc_fact(5))试图创建函数来计算阶乘,不支持类型错误操作数*:对于int或Nonetype我不知道为什么谢谢Python代码中出现“类型错误:不支持的操作数类型为*:'int'和'NoneType'”表明你......
  • 如何调试 python Flask [84] [CRITICAL] WORKER TIMEOUT?
    调试:gtts.tts:保存到temp.mp37月22日09:10:56PM[2024-07-2215:40:56+0000][84][严重]工作超时(pid:87)|||7月22日09:10:56PM[2024-07-2215:40:56+0000][87][INFO]工人退出(pid:87)7月22日09:10:57PM[2024-07-2215:40:57+0000][95][INF......
  • 类型错误:无法将函数返回值转换为 Python 类型!签名是 () -> 处理 anaconda spider
    这是代码:importosimportrandomimportnumpyasnpimportpandasaspdimporttensorflowastffromtensorflow.kerasimportbackendasKfromtensorflow.keras.layersimportDense,Dropout,Flatten,Conv2D,MaxPool2D,Input......
  • python进阶---闭包与装饰器
    一、闭包        在Python中,闭包是指一个函数内部定义的函数,这个内部函数可以访问并修改其外部函数的局部变量,即使外部函数已经执行完毕。闭包可以通过多层函数嵌套来实现。    闭包的三要素:    1、外部函数嵌套内部函数    2、外部函数返......