Navigation

    Gpushare.com

    • Register
    • Login
    • Search
    • Popular
    • Categories
    • Recent
    • Tags

    如何给损失函数加权重 【拓展篇 解答】

    技术分享📚有奖励
    1
    1
    31
    Loading More Posts
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
    Reply
    • Reply as topic
    Log in to reply
    This topic has been deleted. Only users with topic management privileges can see it.
    • 173****7719
      阿洲 last edited by

      解决方案

      针对前文提出的问题,经过探索,我终于发现了一个极简的解决方案,其他想法和思路这里就不赘述了,直接看代码把。

      回顾

      先简单回顾一下问题

      • N_total:数据总个数
      • C: 类别数
      • N_batch: 每个batch被分到的数据数量

      假设我们有数据 N_total 个 input: 不管是几维的,当算损失值的时候 (每个batch更新一次参数),损失函数的输入维度分别是

      • input (模型的输出,损失函数的输入 ):(N_batch,C)
      • target (对应的标签):(N_batch, )
      loss = nn.CrossEntropyLoss(reduction='none')
      output = loss(input, target)
      

      由于设置了reduction=‘none’, 这里的output维度为 (N_batch, )

      前文已经说明,当计算损失函数的时候,如果要对每个样本进行加权,最终的损失值计算如下:

      final_loss = (w*output).sum()/w.sum()
      

      w 就是每个样本的权重, 维度为 (N_batch, )

      现在的问题是当我们对数据进行封装的时候,也就是获得DataLoader迭代器的时候,如何获得被分配好的样本的原索引,以便我们可以获得其对应的权重?

      问题拆解

      在寻找答案的过程中,我发现获得这些数据的原索引是一个比较困难的问题,但是如果我们的目的只是获得被分配好的样本的权重,其实并不需要通过获得索引的方式,可以把权重一起加入分配过程就好了。

      解决方案

      假设我们有 N_total 个

      • input 样本
      • target 标签
      • weights 权重

      PS: 都是torch tensor
      在封装之前我们可以简单使用TensorDataset把weights加进去就好了

      import torch
      from torch.utils.data import DataLoader
      from torch.utils.data import TensorDataset
      
      train_dataset = TensorDataset(input, target, weights)
      
      train_loader = DataLoader(train_dataset, batch_size=N_batch)
      
      ...
      loss = nn.CrossEntropyLoss(reduction='none')
      for i, (x, y, w) in enumerate(train_loader):
          outputs = model(x)
          losses= loss(outputs, y)
          final_loss = (w*losses).sum()/w.sum()
          final_loss.backward()
      ...
      

      搞定!

      1 Reply Last reply Reply Quote 1
      • First post
        Last post