过拟合和概率校准是训练深度学习模型时出现的两个问题。深度学习中有很多正则化技术可以解决过拟合问题;权重衰减、早停机制和dropout是都是最常见的方式。Platt缩放和保序回归可以用于模型校准。
但是有没有一种方法可以同时对抗过度拟合和过度自信呢?
标签平滑是一种正则化技术,它扰动目标变量,使模型对其预测的确定性降低。它被视为一种正则化技术,因为它限制了softmax 函数的最大概率使最大概率不会比其他标签大得多(过度自信)。
在本文中,我们将解释标签平滑的原理,实现了一个使用这种技术的交叉熵损失函数,并评估了它的性能。
标签平滑
我们有一个多类分类问题。在此类问题中,目标变量通常是一个one-hot向量,其中正确类别的位置为1,其他位置为0。这是与二元分类不同的任务因为在二分类中只有两个可能的类,但是在多标签分类中,一个数据点中可以有多个正确的类。因此,多标签分类问题的需要检测图像中存在的每个对象。
标签平滑将目标向量改变少量 ε。因此,我们不是要求我们的模型为正确的类别预测 1,而是要求它为正确的类别预测 1-ε,并将所有其他类别预测为 ε。
带有标签平滑的交叉熵损失函数转化为下面的公式。
在这个公式中,ce(x) 表示 x 的标准交叉熵损失(例如 -log(p(x))),ε 是一个小的正数,i 是正确的类,N 是类的数量。
直观地说,标签平滑将正确类的概率值限制为更接近其他类的概率值。通过这种方式,它被用作正则化技术和对抗模型过度自信的方法。
PyTorch 实现
在 PyTorch 中实现标签平滑交叉熵损失函数非常简单。在这个例子中,我们使用 fast.ai 课程的一部分代码。
首先,让我们使用一个辅助函数来计算两个值之间的线性组合:
代码语言:javascript复制def linear_combination(x, y, epsilon):
return epsilon*x (1-epsilon)*y
接下来,我们使用 PyTorch nn.Module实现一个新的损失函数
代码语言:javascript复制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 例子。
代码语言:javascript复制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 ,我们自定义的类作为损失。经过四轮训练后,结果总结如下。
我们得到了只有 7.5% 的错误率,这对于十行左右的代码来说是可以接受的,因为我们使用的都是默认设置。
我们可以调整很多东西来使我们的模型表现得更好。不同的优化器、超参数、模型架构等。
总结
在这篇文章中,我们研究了标签平滑,这是一种试图对抗过度拟合和过度自信的技术。我们看到了何时使用它以及如何在 PyTorch 中实现它。然后,我们训练了一个计算机视觉模型,用十行代码识别不同品种的猫和狗。
模型正则化和校准是两个重要的概念。更好地理解这些概念可以帮你成为一个更好的深度学习实践者。
作者:Dimitris Poulopoulos