网络知识 娱乐 标签平滑 Label Smoothing 详解及 pytorch tensorflow实现

标签平滑 Label Smoothing 详解及 pytorch tensorflow实现

定义

标签平滑(Label smoothing),像L1、L2和dropout一样,是机器学习领域的一种正则化方法,通常用于分类问题,目的是防止模型在训练时过于自信地预测标签,改善泛化能力差的问题。

背景

对于分类问题,我们通常认为训练数据中标签向量的目标类别概率应为1,非目标类别概率应为0。传统的one-hot编码的标签向量

从中我们可以看出,加了标签平滑之后(后两张图),每个类聚的更紧了,而且和其余类的距离大致一致。第二组实验为在CIFAR-100/ResNet-56(数据集/模型)上的实验结果,三个类分别为“河狸”、“海豚”与“水獭”,我们可以得到类似的结果:

在第三组实验中,作者测试了在ImageNet/Inception-v4(数据集/模型)上的表现,三个类分别为“猫鼬”、“鲤鱼”和“切刀肉”,结果如下:

因为ImageNet有很多细粒度的分类,可以用来测试比较相似的类之间的关系。作者在第四组实验中选择的三个类分别为“玩具贵宾犬”、“ 迷你贵宾犬”和“鲤鱼”,可以看出前两个类是很相似的,最后一个差别比较大的类在图中用蓝色表示,结果如下:

可以看出在使用硬目标的情况下,两个相似的类彼此比较靠近。但是标签平滑强制要求每个示例与所有剩余类的模板之间的距离相等,这就导致了后两张图中两个类距离较远,这在一定程度上造成了信息的损失。

代码实现

pytorch部分代码

class LabelSmoothing(nn.Module):
    def __init__(self, size, smoothing=0.0):
        super(LabelSmoothing, self).__init__()
        self.criterion = nn.KLDivLoss(size_average=False)
        #self.padding_idx = padding_idx
        self.confidence = 1.0 - smoothing#if i=y的公式
        self.smoothing = smoothing
        self.size = size
        self.true_dist = None
    
    def forward(self, x, target):
        """
        x表示输入 (N,M)N个样本,M表示总类数,每一个类的概率log P
        target表示label(M,)
        """
        assert x.size(1) == self.size
        true_dist = x.data.clone()#先深复制过来
        #print true_dist
        true_dist.fill_(self.smoothing / (self.size - 1))#otherwise的公式
        #print true_dist
        #变成one-hot编码,1表示按列填充,
        #target.data.unsqueeze(1)表示索引,confidence表示填充的数字
        true_dist.scatter_(1, target.data.unsqueeze(1), self.confidence)
        self.true_dist = true_dist

        return self.criterion(x, Variable(true_dist, requires_grad=False))
        
loss_function = LabelSmoothing(num_labels, 0.1)

tensorflow代码实现

def smoothing_cross_entropy(logits,labels,vocab_size,confidence):
  with tf.name_scope("smoothing_cross_entropy", values=[logits, labels]):
    # Low confidence is given to all non-true labels, uniformly.
    low_confidence = (1.0 - confidence) / to_float(vocab_size - 1)

    # Normalizing constant is the best cross-entropy value with soft targets.
    # We subtract it just for readability, makes no difference on learning.
    normalizing = -(
        confidence * tf.log(confidence) + to_float(vocab_size - 1) *
        low_confidence * tf.log(low_confidence + 1e-20))

    soft_targets = tf.one_hot(
          tf.cast(labels, tf.int32),
          depth=vocab_size,
          on_value=confidence,
          off_value=low_confidence)
    xentropy = tf.nn.softmax_cross_entropy_with_logits_v2(
        logits=logits, labels=soft_targets)
    return xentropy - normalizing

Ref

  1. https://www.jiqizhixin.com/articles/2019-07-09-7
  2. https://www.cnblogs.com/irvingluo/p/13873699.html
  3. https://proceedings.neurips.cc/paper/2019/file/f1748d6b0fd9d439f71450117eba2725-Paper.pdf