Pytorch:交叉熵损失(CrossEntropyLoss)以及标签平滑(LabelSmoothing)的实现

0. 前言

一般情况下我们都是直接调用Pytorch自带的交叉熵损失函数计算loss,但涉及到魔改以及优化时,我们需要自己动手实现loss function,在这个过程中如果能对交叉熵损失的代码实现有一定的了解会帮助我们写出更优美的代码。

其次是标签平滑这个trick通常简单有效,只需要改改损失函数既可带来性能上的提升,通常与交叉熵配合食用。

因此,本文基于这两个出发点,介绍基于Pytorch框架下的交叉熵损失实现以及标签平滑的实现。

1. 浅谈CrossEntropyLoss

相信大家对于如何计算交叉熵已经非常熟悉,常规步骤是①计算softmax得到各类别置信度;②计算交叉熵损失。但其实从Pytorch的官方文档可以看出,还有更一步到位的方法,如下:

这避免了softmax的计算。

代码实现

很简单,根据公式写代码就好了

class CELoss(nn.Module):
    ''' Cross Entropy Loss'''
    def __init__(self):
        super().__init__()

    def forward(self, pred, target):
        ''' 
        Args:
            pred: prediction of model output    [N, M]
            target: ground truth of sampler [N]
        '''
        eps = 1e-12
      	# standard cross entropy loss
        loss = -1.*pred.gather(1, target.unsqueeze(-1)) + torch.log(torch.exp(pred+eps).sum(dim=1))

        return loss.mean()

2. 浅谈Label Smoothing

Label Smoothing也称之为标签平滑,其实是一种防止过拟合的正则化方法。传统的分类loss采用softmax loss,先对全连接层的输出计算softmax,视为各类别的置信度概率,再利用交叉熵计算损失。
在这里插入图片描述
在这里插入图片描述

在这个过程中尽可能使得各样本在正确类别上的输出概率为1,这要使得对应的z值为+∞,这拉大了其与其他类别间的距离。

现在假设一个多分类任务标签是[1,0,0],如果它本身的label的出现了问题,这对模型的伤害是非常大的,因为在训练的过程中强行学习一个非本类的样本,并且让其概率非常高,这会影响对后验概率的估计。并且有时候类与类之间的并不是毫无关联,如果鼓励输出的概率间相差过大,这会导致一定程度上的过拟合。

因此Label Smoothing的想法是让目标不再是one-hot标签,而是变为如下形式:

在这里插入图片描述

其中ε为一个较小的常数,这使得softmax损失中的概率优目标不再为1和0,同时z值的最优解也不再是正无穷大,而是一个具体的数值。这在一定程度上避免了过拟合,也缓解了错误标签带来的影响。

代码实现

基于上一节的交叉熵实现增加标签平滑功能,代码如下:

class CELoss(nn.Module):
    ''' Cross Entropy Loss with label smoothing '''
    def __init__(self, label_smooth=None, class_num=137):
        super().__init__()
        self.label_smooth = label_smooth
        self.class_num = class_num

    def forward(self, pred, target):
        ''' 
        Args:
            pred: prediction of model output    [N, M]
            target: ground truth of sampler [N]
        '''
        eps = 1e-12
        
        if self.label_smooth is not None:
            # cross entropy loss with label smoothing
            logprobs = F.log_softmax(pred, dim=1)	# softmax + log
            target = F.one_hot(target, self.class_num)	# 转换成one-hot
            
            # label smoothing
            # 实现 1
            # target = (1.0-self.label_smooth)*target + self.label_smooth/self.class_num 	
            # 实现 2
            # implement 2
            target = torch.clamp(target.float(), min=self.label_smooth/(self.class_num-1), max=1.0-self.label_smooth)
            loss = -1*torch.sum(target*logprobs, 1)
        
        else:
            # standard cross entropy loss
            loss = -1.*pred.gather(1, target.unsqueeze(-1)) + torch.log(torch.exp(pred+eps).sum(dim=1))

        return loss.mean()

实现1采用了(1.0-self.label_smooth)*target + self.label_smooth/self.class_num实现,与原始公式不太一样。

后续在了解到pytorch的clamp接口后,发现能够利用其能正确实现原公式,见实现2

3. 实验验证

① 交叉熵损失正确率,与标准的交叉熵比较:

	loss1 = nn.CrossEntropyLoss()
    loss2 = CELoss(label_smooth=None, class_num=3)

    x = torch.tensor([[1, 8, 1], [1, 1, 8]], dtype=torch.float)
    y = torch.tensor([1, 2])

    print(loss1(x, y), loss2(x, y))
	# tensor(0.0018) tensor(0.0018)

② 标签平滑结果展示:

	loss1 = nn.CrossEntropyLoss()
    loss2 = CELoss(label_smooth=0.05, class_num=3)

    x = torch.tensor([[1, 8, 1], [1, 1, 8]], dtype=torch.float)
    y = torch.tensor([1, 2])

    print(loss1(x, y), loss2(x, y))
	# tensor(0.0018) tensor(0.2352)

另一组结果:

	x = torch.tensor([[0.1, 8, 0.1], [0.1, 0.1, 8]], dtype=torch.float)
    y = torch.tensor([1, 2])

    print(loss1(x, y), loss2(x, y))
    # tensor(0.0007) tensor(0.2641)

分析:拉大模型输出数值间的差距后,原始的交叉熵会变小,而增加了标签平滑的反而变大。这也反映了标签平滑后,并不是概率越接近于1越好,而是接近某个小于1的值,这使得模型的输出不再是越高(+∞)越好。

  • 36
    点赞
  • 147
    收藏
    觉得还不错? 一键收藏
  • 30
    评论
### 回答1: 以下是Ubuntu 18.04安装NVIDIA显卡驱动的教程: 1. 打开终端,输入以下命令以添加NVIDIA PPA存储库: sudo add-apt-repository ppa:graphics-drivers/ppa 2. 更新软件包列表: sudo apt-get update 3. 安装NVIDIA显卡驱动: sudo apt-get install nvidia-driver-440 (请注意,这里的“440”是指驱动程序的版本号,您可以根据您的显卡型号和要求选择不同的版本号) 4. 安装完成后,重新启动计算机: sudo reboot 5. 检查驱动程序是否正确安装: nvidia-smi 如果您看到了NVIDIA显卡的详细信息,则表示驱动程序已正确安装。 希望这个教程能够帮助您成功安装NVIDIA显卡驱动程序。 ### 回答2: Ubuntu 18.04是一款非常流行的Linux发行版,但是在安装nvidia显卡驱动时可能会遇到一些困难。接下来,我将为大家介绍ubuntu18.04安装nvidia显卡驱动的详细步骤。 第一步:检查系统是否自带nvidia驱动。 在安装nvidia显卡驱动之前,我们需要检查系统是否已经自带了它。可以使用以下命令来检查: ``` lsmod | grep nvidia ``` 如果系统中已经有nvidia驱动,则会显示以下信息: ``` nvidia_uvm 985673 0 nvidia_drm 45056 8 nvidia_modeset 1114112 15 nvidia_drm nvidia 20257792 431 nvidia_uvm,nvidia_modeset drm_kms_helper 172032 2 nvidia_drm,i915 drm 401408 13 drm_kms_helper,nvidia_drm,i915 ``` 如果没有输出,说明系统中没有自带的nvidia驱动。 第二步:下载nvidia显卡驱动。 我们需要从nvidia官网下载适用于我们显卡的驱动。可以使用以下命令查看本机的显卡信息: ``` lspci -vnn | grep VGA -A 12 ``` 然后根据显卡型号在nvidia官网下载对应的驱动,比如说我们的显卡型号是GTX 1060,则可以到以下网址下载: ``` https://www.nvidia.com/Download/index.aspx?lang=en-us ``` 第三步:安装nvidia显卡驱动。 1. 在安装nvidia驱动之前,我们需要先停止GUI界面,可以使用以下命令来停止: ``` sudo systemctl stop gdm ``` 2. 将下载的驱动复制到/home目录下,然后打开终端,使用以下命令将当前目录更改为/home目录: ``` cd ~ ``` 3. 使用以下命令将驱动文件修改为可执行文件: ``` chmod +x NVIDIA-Linux-x86_64-XXX.XX.run ``` 4. 运行以下命令安装驱动: ``` sudo ./NVIDIA-Linux-x86_64-XXX.XX.run ``` 注意:在安装驱动期间,将会提示你是否安装nvidia的DKMS驱动,这意味着如果更新内核则会自动重新编译模块。建议选择“是”。 5. 安装完成后,使用以下命令重启GUI界面: ``` sudo systemctl start gdm ``` 到此,ubuntu18.04安装nvidia显卡驱动的教程就介绍完了。希望对大家有所帮助。 ### 回答3: Ubuntu 18.04是一个广受欢迎的免费和开源的操作系统,可用于个人和企业计算机。对于拥有NVIDIA显卡的用户,安装正确的显卡驱动程序是非常重要的,这有助于显卡的稳定性和性能。以下是Ubuntu 18.04安装NVIDIA显卡驱动程序的教程。 第1步:检查NVIDIA驱动适用于您的显卡 在安装驱动程序之前,您需要确定正确的驱动程序版本适用于您的NVIDIA显卡。您可以在NVIDIA官方网站上找到相应的驱动程序。请注意,您需要知道您的显卡型号和操作系统位数(即32位或64位)。 第2步:更新Ubuntu 18.04 在安装NVIDIA显卡驱动程序之前,我们建议您先更新Ubuntu 18.04。这可以通过在终端中输入以下命令来完成: sudo apt update sudo apt upgrade 第3步:安装NVIDIA显卡驱动程序 要安装NVIDIA显卡驱动程序,请按照以下步骤操作: 1.打开“Software & Updates”(软件和更新)应用程序。 2.单击“Additional Drivers”(其他驱动程序)选项卡。 3.在这里,您将看到一个列表,其中包含可用的NVIDIA驱动程序版本。选择您想要的驱动程序版本并单击“Apply Changes”(应用更改)按钮。 4.驱动程序开始下载和安装。这可能需要一些时间。完成后,您需要重新启动计算机以使更改生效。 完成这些步骤后,您应该成功安装了NVIDIA显卡驱动程序。您可以通过在终端中输入以下命令来检查当前正在运行的驱动程序版本: nvidia-smi 希望这个教程对于想要在Ubuntu 18.04中安装NVIDIA显卡驱动程序的用户有所帮助。
评论 30
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值