Label-Smoothing

论文:Rethinking the Inception Architecture for Computer Vision        

个人理解:

就是让softmax不那么相信某一类的数据,增强泛化性。主要操作就是,在制作标签的时候,属于那一类就让网络90%相信他,其他10%平均相信其他人。

和focalloss的想法不太一样,focalloss是让分错的东西对网络多做点贡献,学的比较好的就少做点贡献。

今天来进行讨论深度学习中的一种优化方法Label smoothing Regularization(LSR),即“标签平滑归一化”。由名字可以知道,它的优化对象是Label(Train_y)。

对于分类问题,尤其是多类别分类问题中,常常把类别向量做成one-hot vector(独热向量)。

简单地说,就是对于多分类向量,计算机中往往用[0, 1, 3]等此类离散的、随机的而非有序(连续)的向量表示,而one-hot vector 对应的向量便可表示为[0, 1, 0],即对于长度为n 的数组,只有一个元素是1,其余都为0。

 之后在网络的最后一层(全连接层)后加一层softmax层,由于softmax输出是归一化的,所以认为该层的输出就是样本属于某类别的概率。而由于样本label是独热向量,因此表征我们已知样本属于某一类别的概率是为1的确定事件,属于其他类别的概率则均为0。

一、首先明确一些变量的含义

zi:也为logits,未被归一化的对数概率;

p:predicted probability,预测的example的概率;

q:groundtruth probablity,真实的example的label概率;对于one-hot,真实概率为Dirac函数,即​q(k)=δk,y​q(k)=δk,y,其中y是真实类别。

loss:Cross Entropy,采用交叉熵损失。

Label-Smoothing_第1张图片

二、one-hot 带来的问题

  对于损失函数,我们需要用预测概率去拟合真实概率,而拟合one-hot的真实概率函数会带来两个问题:1)无法保证模型的泛化能力,容易造成过拟合;2) 全概率和0概率鼓励所属类别和其他类别之间的差距尽可能加大,而由梯度有界可知,这种情况很难adapt。会造成模型过于相信预测的类别。

三、解决方案

Label-Smoothing_第2张图片

四、优化结果

文章表示,对K = 1000,ϵ = 0.1的优化参数,实验结果有0.2%的性能提升。

五、代码实现

import torch
import torch.nn as nn

class NMTCritierion(nn.Module):
    """
    TODO:
    1. Add label smoothing
    """
    def __init__(self, label_smoothing=0.0):
        super(NMTCritierion, self).__init__()
        self.label_smoothing = label_smoothing
        self.LogSoftmax = nn.LogSoftmax()

        if label_smoothing > 0:
            self.criterion = nn.KLDivLoss(size_average=False)
        else:
            self.criterion = nn.NLLLoss(size_average=False, ignore_index=100000)
        self.confidence = 1.0 - label_smoothing

    def _smooth_label(self, num_tokens):
        # When label smoothing is turned on,
        # KL-divergence between q_{smoothed ground truth prob.}(w)
        # and p_{prob. computed by model}(w) is minimized.
        # If label smoothing value is set to zero, the loss
        # is equivalent to NLLLoss or CrossEntropyLoss.
        # All non-true labels are uniformly set to low-confidence.
        one_hot = torch.randn(1, num_tokens)
        one_hot.fill_(self.label_smoothing / (num_tokens - 1))
        return one_hot

    def _bottle(self, v):
        return v.view(-1, v.size(2))

    def forward(self, dec_outs, labels):
        scores = self.LogSoftmax(dec_outs)
        num_tokens = scores.size(-1)

        # conduct label_smoothing module
        gtruth = labels.view(-1)
        if self.confidence < 1:
            tdata = gtruth.detach()
            one_hot = self._smooth_label(num_tokens)  # Do label smoothing, shape is [M]
            if labels.is_cuda:
                one_hot = one_hot.cuda()
            tmp_ = one_hot.repeat(gtruth.size(0), 1)  # [N, M]
            tmp_.scatter_(1, tdata.unsqueeze(1), self.confidence)  # after tdata.unsqueeze(1) , tdata shape is [N,1]
            gtruth = tmp_.detach()
        loss = self.criterion(scores, gtruth)
        return loss

使用上面这段代码:

criterion = NMTCritierion(0.1)
outputs = net(img)
loss = criterion(outputs, lb)

转自:https://www.cnblogs.com/zyrb/p/9699168.html

你可能感兴趣的:(论文笔记)