标签平滑(label smoothing)

目录

1.标签平滑主要解决什么问题?

2.标签平滑是怎么操作的?

3.标签平滑公式

4.代码实现


标签平滑(label smoothing)出自GoogleNet v3

关于one-hot编码的详细知识请见:One-hot编码

1.标签平滑主要解决什么问题?

传统的one-hot编码会带来的问题无法保证模型的泛化能力,使网络过于自信会导致过拟合。
全概率和0概率鼓励所属类别和其他类别之间的差距尽可能加大,而由梯度有界可知,这种情况很难adapt。会造成模型过于相信预测的类别。而标签平滑可以缓解这个问题。
 

2.标签平滑是怎么操作的?

标签平滑是把one-hot中概率为1的那一项进行衰减,避免过度自信,衰减的那部分的自信被平均分到每一个类别中

例如:

一个4分类任务,label = (0,1,0,0)

labeling smoothing = (\frac{0.001}{4},1-0.001+\frac{0.001}{4}\frac{0.001}{4}\frac{0.001}{4})=(0.00025,0.99925,0.00025,0.00025)

 其中,概率加起来等于1。

 

3.标签平滑公式

交叉熵(Cross Entropy):H(q,p)=-\sum_{k=1}^{k}log(p_k)q_k

其中,q为标签值,p为预测结果,k为类别。即q为one-hot编码结果。

labeling smothing:将q进行标签平滑变为q',让模型输出的p分布去逼近q'

q'(k|x)=(1-\varepsilon )\delta _{k,y} +\varepsilon u(k),其中u(k)为一个概率分布,这里采用均匀分布u(k)=\frac{1}{k}),则得到q'(k|x)=(1-\varepsilon )\delta _{k,y} +\frac{\varepsilon }{k}

        其中,\delta _{k,y}为原分布q, ϵ ∈(0,1)是一个超参数。

        由以上公式可以看出,这种方式使label有 ϵ  概率来自于均匀分布 1−ϵ 概率来自于原分布。这就相当于在原label上增加噪声,让模型的预测值不要过度集中于概率较高的类别,把一些概率放在概率较低的类别。

故标签平滑后的交叉熵损失函数为:H(q',p)=-\sum_{k=1}^{k}logp(k)q'(k)=(1-\varepsilon )H(q,p)+\varepsilon H(u,p)

那这个公式是怎么得来的呢?

将q'(k|x)带入交叉熵损失函数:

H(q',p)=-\sum_{k=1}^{k}log(p_k)q'_k

=-\sum_{k=1}^{k}log(p_k)[(1-\varepsilon )\delta _{k,y}+\frac{\varepsilon }{k}]

=-\sum_{k=1}^{k}log(p_k)(1-\varepsilon )\delta _{k,y}+[-\sum_{k=1}^{k}log(p_k)\frac{\varepsilon }{k}]

=(1-\varepsilon )*[-\sum_{k=1}^{k}log(p_k)\delta _{k,y}]+\varepsilon *[-\sum_{k=1}^{k}log(p_k)\frac{1}{k}]

=(1-\varepsilon )*H(q,p)+\varepsilon *H(u,p)

这样就得到了标签平滑公式。

4.代码实现

class LabelSmoothingCrossEntropy(nn.Module):
    def __init__(self, eps=0.1, reduction='mean', ignore_index=-100):
        super(LabelSmoothingCrossEntropy, self).__init__()
        self.eps = eps
        self.reduction = reduction
        self.ignore_index = ignore_index

    def forward(self, output, target):
        c = output.size()[-1]
        log_pred = torch.log_softmax(output, dim=-1)
        if self.reduction == 'sum':
            loss = -log_pred.sum()
        else:
            loss = -log_pred.sum(dim=-1)
            if self.reduction == 'mean':
                loss = loss.mean()


        return loss * self.eps / c + (1 - self.eps) * torch.nn.functional.nll_loss(log_pred, target,
                                                                                   reduction=self.reduction,
                                                                                   ignore_index=self.ignore_index)

你可能感兴趣的:(深度学习基础知识,python,算法,机器学习)