过拟合和概率校准是训练深度学习模型时出现的两个问题。深度学习中有很多正则化技术可以解决过拟合问题;权重衰减、早停机制和dropout是都是最常见的方式。Platt缩放和保序回归可以用于模型校准。

但是有没有一种方法可以同时对抗过度拟合和过度自信呢?

标签平滑是一种正则化技术,它扰动目标变量,使模型对其预测的确定性降低。它被视为一种正则化技术,因为它限制了softmax 函数的最大概率使最大概率不会比其他标签大得多(过度自信)。

pytorch正则化计算(正则化技巧标签平滑)(1)

在本文中,我们将解释标签平滑的原理,实现了一个使用这种技术的交叉熵损失函数,并评估了它的性能。

标签平滑

我们有一个多类分类问题。 在此类问题中,目标变量通常是一个one-hot向量,其中正确类别的位置为1,其他位置为0。 这是与二元分类不同的任务因为在二分类中只有两个可能的类,但是在多标签分类中,一个数据点中可以有多个正确的类。 因此,多标签分类问题的需要检测图像中存在的每个对象。

标签平滑将目标向量改变少量 ε。 因此,我们不是要求我们的模型为正确的类别预测 1,而是要求它为正确的类别预测 1-ε,并将所有其他类别预测为 ε。

带有标签平滑的交叉熵损失函数转化为下面的公式。

pytorch正则化计算(正则化技巧标签平滑)(2)

在这个公式中,ce(x) 表示 x 的标准交叉熵损失(例如 -log(p(x))),ε 是一个小的正数,i 是正确的类,N 是类的数量。

直观地说,标签平滑将正确类的概率值限制为更接近其他类的概率值。 通过这种方式,它被用作正则化技术和对抗模型过度自信的方法。

PyTorch 实现

在 PyTorch 中实现标签平滑交叉熵损失函数非常简单。 在这个例子中,我们使用 fast.ai 课程的一部分代码。

首先,让我们使用一个辅助函数来计算两个值之间的线性组合:

def linear_combination(x, y, epsilon): return epsilon*x (1-epsilon)*y

接下来,我们使用 PyTorch nn.Module实现一个新的损失函数

import torch.nn.functional as F def reduce_loss(loss, reduction='mean'): return loss.mean() if reduction=='mean' else loss.sum() if reduction=='sum' else loss class LabelSmoothingCrossEntropy(nn.Module): def __init__(self, epsilon:float=0.1, reduction='mean'): super().__init__() self.epsilon = epsilon self.reduction = reduction def forward(self, preds, target): n = preds.size()[-1] log_preds = F.log_softmax(preds, dim=-1) loss = reduce_loss(-log_preds.sum(dim=-1), self.reduction) nll = F.nll_loss(log_preds, target, reduction=self.reduction) return linear_combination(loss/n, nll, self.epsilon)

我们现在可以在我们的代码中使用这个类。 对于这个例子,我们使用标准的 fast.ai pets 例子。

from fastai.vision import * from fastai.metrics import error_rate # prepare the data path = untar_data(URLs.PETS) path_img = path/'images' fnames = get_image_files(path_img) bs = 64 np.random.seed(2) pat = r'/([^/] )_\d .jpg$' data = ImageDataBunch.from_name_re(path_img, fnames, pat, ds_tfms=get_transforms(), size=224, bs=bs) \ .normalize(imagenet_stats) # train the model learn = cnn_learner(data, models.resnet34, metrics=error_rate) learn.loss_func = LabelSmoothingCrossEntropy() learn.fit_one_cycle(4)

我们将数据转换为可供模型使用的格式,并使用 ResNet ,我们自定义的类作为损失。 经过四轮训练后,结果总结如下。

pytorch正则化计算(正则化技巧标签平滑)(3)

我们得到了只有 7.5% 的错误率,这对于十行左右的代码来说是可以接受的,因为我们使用的都是默认设置。

我们可以调整很多东西来使我们的模型表现得更好。 不同的优化器、超参数、模型架构等。

总结

在这篇文章中,我们研究了标签平滑,这是一种试图对抗过度拟合和过度自信的技术。 我们看到了何时使用它以及如何在 PyTorch 中实现它。 然后,我们训练了一个计算机视觉模型,用十行代码识别不同品种的猫和狗。

模型正则化和校准是两个重要的概念。 更好地理解这些概念可以帮你成为一个更好的深度学习实践者。

作者:Dimitris Poulopoulos

,