如何处理 Pytorch 中的小批量损失?

Posted

技术标签:

【中文标题】如何处理 Pytorch 中的小批量损失?【英文标题】:How to deal with mini-batch loss in Pytorch? 【发布时间】:2019-08-17 12:29:47 【问题描述】:

我将小批量数据提供给模型,我只想知道如何处理损失。我可以累积损失,然后像这样向后调用:

    ...
    def neg_log_likelihood(self, sentences, tags, length):
        self.batch_size = sentences.size(0)

        logits = self.__get_lstm_features(sentences, length)
        real_path_score = torch.zeros(1)
        total_score = torch.zeros(1)
        if USE_GPU:
            real_path_score = real_path_score.cuda()
            total_score = total_score.cuda()

        for logit, tag, leng in zip(logits, tags, length):
            logit = logit[:leng]
            tag = tag[:leng]
            real_path_score += self.real_path_score(logit, tag)
            total_score += self.total_score(logit, tag)
        return total_score - real_path_score
    ...
loss = model.neg_log_likelihood(sentences, tags, length)
loss.backward()
optimizer.step()

不知道堆积会不会导致梯度爆炸?

那么,我应该在循环中调用backward吗:

for sentence, tag , leng in zip(sentences, tags, length):
    loss = model.neg_log_likelihood(sentence, tag, leng)
    loss.backward()
    optimizer.step()

或者,像张量流中的 reduce_mean 一样使用平均损失

loss = reduce_mean(losses)
loss.backward()

【问题讨论】:

【参考方案1】:

loss 必须使用小批量大小减少mean。如果您查看原生 PyTorch 损失函数,例如 CrossEntropyLoss,则有一个单独的参数 reduction 仅用于此目的,默认行为是在 mini-batch 大小上执行 mean

【讨论】:

【参考方案2】:

我们通常

    通过损失函数得到损失 (如有必要)操纵损失,例如做类加权等 计算小批量的平均损失 通过loss.backward()计算梯度 (如有必要)操纵梯度,例如,对某些 RNN 模型进行梯度裁剪以避免梯度爆炸 使用optimizer.step() 函数更新权重

因此,在您的情况下,您可以先获取小批量的平均损失,然后使用 loss.backward() 函数计算梯度,然后使用 optimizer.step() 函数进行权重更新。

【讨论】:

以上是关于如何处理 Pytorch 中的小批量损失?的主要内容,如果未能解决你的问题,请参考以下文章

Pytorch Dataloader 如何处理可变大小的数据?

如何处理keras的单输出多重损失?

KnockoutJS:我应该如何处理繁重的小部件初始化代码?

PyTorch 在加载图像/掩码文件以进行图像分割时如何处理标签?

如何处理批次内不同实例中的不确定句子数量?

你如何处理大量的小文件?