正则化技巧:标签平滑(Label Smoothing)以及在 PyTorch 中的实现

共 2532字,需浏览 6分钟

 ·

2021-11-30 03:33

来源:DeepHub IMBA

本文约1200字,建议阅读5分钟

在这篇文章中,我们研究了标签平滑,这是一种试图对抗过度拟合和过度自信的技术。


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

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

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

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

标签平滑


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

标签平滑将目标向量改变少量 ε。因此,我们不是要求我们的模型为正确的类别预测 1,而是要求它为正确的类别预测 1-ε,并将所有其他类别预测为 ε。
带有标签平滑的交叉熵损失函数转化为下面的公式。

在这个公式中,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 datapath = untar_data(URLs.PETS)path_img = path/'images'fnames = get_image_files(path_img)
bs = 64np.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 modellearn = cnn_learner(data, models.resnet34, metrics=error_rate)learn.loss_func = LabelSmoothingCrossEntropy()learn.fit_one_cycle(4)

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


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

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

总结


在这篇文章中,我们研究了标签平滑,这是一种试图对抗过度拟合和过度自信的技术。

我们看到了何时使用它以及如何在 PyTorch 中实现它。然后,我们训练了一个计算机视觉模型,用十行代码识别不同品种的猫和狗。

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

编辑:于腾凯
校对:林亦霖
浏览 42
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报
评论
图片
表情
推荐
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报