如何给损失函数加权重 【拓展篇 解答】
-
解决方案
针对前文提出的问题,经过探索,我终于发现了一个极简的解决方案,其他想法和思路这里就不赘述了,直接看代码把。
回顾
先简单回顾一下问题
- 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() ...
搞定!