我正在使用迁移学习为 斯坦福汽车 数据集构建一个 ResNet-18
分类模型。我想实施 标签平滑 来惩罚过度自信的预测并提高泛化能力。
TensorFlow
在 CrossEntropyLoss
中有一个简单的关键字参数。有没有人为 PyTorch
构建了一个我可以即插即用的类似功能?
原文由 Jared Nielsen 发布,翻译遵循 CC BY-SA 4.0 许可协议
我正在使用迁移学习为 斯坦福汽车 数据集构建一个 ResNet-18
分类模型。我想实施 标签平滑 来惩罚过度自信的预测并提高泛化能力。
TensorFlow
在 CrossEntropyLoss
中有一个简单的关键字参数。有没有人为 PyTorch
构建了一个我可以即插即用的类似功能?
原文由 Jared Nielsen 发布,翻译遵循 CC BY-SA 4.0 许可协议
我一直在寻找源自 _Loss
的选项,就像 PyTorch 中的其他损失类一样,并尊重基本参数,例如 reduction
。不幸的是,我找不到直接的替代品,所以最终自己写了。但是,我还没有对此进行全面测试:
import torch
from torch.nn.modules.loss import _WeightedLoss
import torch.nn.functional as F
class SmoothCrossEntropyLoss(_WeightedLoss):
def __init__(self, weight=None, reduction='mean', smoothing=0.0):
super().__init__(weight=weight, reduction=reduction)
self.smoothing = smoothing
self.weight = weight
self.reduction = reduction
@staticmethod
def _smooth_one_hot(targets:torch.Tensor, n_classes:int, smoothing=0.0):
assert 0 <= smoothing < 1
with torch.no_grad():
targets = torch.empty(size=(targets.size(0), n_classes),
device=targets.device) \
.fill_(smoothing /(n_classes-1)) \
.scatter_(1, targets.data.unsqueeze(1), 1.-smoothing)
return targets
def forward(self, inputs, targets):
targets = SmoothCrossEntropyLoss._smooth_one_hot(targets, inputs.size(-1),
self.smoothing)
lsm = F.log_softmax(inputs, -1)
if self.weight is not None:
lsm = lsm * self.weight.unsqueeze(0)
loss = -(targets * lsm).sum(-1)
if self.reduction == 'sum':
loss = loss.sum()
elif self.reduction == 'mean':
loss = loss.mean()
return loss
其他选项:
原文由 Shital Shah 发布,翻译遵循 CC BY-SA 4.0 许可协议
2 回答5.2k 阅读✓ 已解决
2 回答1.1k 阅读✓ 已解决
4 回答1.4k 阅读✓ 已解决
3 回答1.3k 阅读✓ 已解决
3 回答1.3k 阅读✓ 已解决
2 回答869 阅读✓ 已解决
1 回答1.7k 阅读✓ 已解决
多类神经网络的泛化和学习速度通常可以通过使用 软目标 来显着提高,软目标是 硬目标 的 加权平均值 和标签上的 均匀分布。以这种方式平滑标签可防止网络变得过于自信,标签平滑已用于许多最先进的模型,包括图像分类、语言翻译和语音识别。
标签平滑 已经在
Tensorflow
的交叉熵损失函数中实现。 二元交叉熵, 分类 交叉熵。但是目前,在PyTorch
中没有正式实现 Label Smoothing 。然而,目前正在进行积极的讨论,希望它能提供一个官方包。这是讨论主题: 问题#7455 。在这里,我们将从
PyTorch
实践者那里带来一些可用的 标签平滑 (LS) 的最佳实现。基本上,有很多方法可以实现 LS 。请参考这个关于这个的具体讨论,一个在 这里, 另一个在这里。在这里,我们将以 两种 独特的方式实现,每种方式都有两个版本;所以总共 4 。选项 1:CrossEntropyLossWithProbs
这样,它接受了
one-hot
目标向量。用户必须手动平滑他们的目标矢量。它可以在with torch.no_grad()
范围内完成,因为它暂时将所有requires_grad
标志设置为 false。此外,我们在
self. smoothing
上添加了一个断言复选标记,并为此实现添加了损失加权支持。Shital 已经在这里发布了答案。这里我们要指出的是,这个实现类似于 Devin Yang 的上述实现。然而,在这里我们提到他的代码,并最小化了一点
code syntax
。查看
选项 2:LabelSmoothingCrossEntropyLoss
通过这种方式,它接受目标向量并使用不手动平滑目标向量,而是内置模块负责标签平滑。它允许我们根据
F.nll_loss
实施标签平滑。(一种)。 Wangleiofficial : 来源- (AFAIK), Original Poster
(二). Datasaurus : Source - 添加了加权支持
此外,我们略微减少了代码编写,使其更加简洁。
查看
更新: 正式添加