Deep Learning/Pytorch

[Label Smoothing] 요약 정리

족제비다아 2020. 7. 28. 17:08

Label Smoothing논문

1. Label Smoothing?

  • 모델이 Ground Truth(GT)를 정확하게 예측하지 않아도 되게 만들어 주는 것.
  • 모델이 정확하지 않은 학습 데이터셋에 치중되는 경향(overconfident)을 막아 calibration 및 regularization 효과를 가질 수 있다.

2. Why?

  • 보통 학습에 사용되는 데이터셋은 사람이 직접 annotation 하기 때문에 실수의 가능성이 존재하며 100% 정확한 GT 데이터로 생각하면 안된다.
  • 즉, GT데이터가 잘 정제되어 있지 않다면 오분류된 데이터(mislabeled data)가 있을 수 있어 모델이 이를 유하게 학습시키도록 하면 더 효과적이기 때문이다.

3. 정말 좋아?

  • Label smoothing은 mislabel data를 고려하기 때문에 model generalization과 calibration에 도움이 된다고 한다
  • When Does Label Smoothing help?
 

When Does Label Smoothing Help?

The generalization and learning speed of a multi-class neural network can often be significantly improved by using soft targets that are a weighted average of the hard targets and the uniform distribution over labels. Smoothing the labels in this way preve

arxiv.org

4. 어떻게 구현하지?

class LabelSmoothingLoss(nn.Module):
    """
    With label smoothing,
    KL-divergence between q_{smoothed ground truth prob.}(w)
    and p_{prob. computed by model}(w) is minimized.
    """
    def __init__(self, label_smoothing, tgt_vocab_size, ignore_index=-100):
        assert 0.0 < label_smoothing <= 1.0
        self.ignore_index = ignore_index
        super(LabelSmoothingLoss, self).__init__()

        smoothing_value = label_smoothing / (tgt_vocab_size - 2)
        one_hot = torch.full((tgt_vocab_size,), smoothing_value)
        one_hot[self.ignore_index] = 0
        self.register_buffer('one_hot', one_hot.unsqueeze(0))

        self.confidence = 1.0 - label_smoothing

    def forward(self, output, target):
        """
        output (FloatTensor): batch_size x n_classes
        target (LongTensor): batch_size
        """
        model_prob = self.one_hot.repeat(target.size(0), 1)
        model_prob.scatter_(1, target.unsqueeze(1), self.confidence)
        model_prob.masked_fill_((target == self.ignore_index).unsqueeze(1), 0)

        return F.kl_div(output, model_prob, reduction='sum')
  • PyTorch를 이용한 또다른 예제
class LabelSmoothingLoss(nn.Module):
    def __init__(self, classes, smoothing=0.0, dim=-1):
        super(LabelSmoothingLoss, self).__init__()
        self.confidence = 1.0 - smoothing
        self.smoothing = smoothing
        self.cls = classes
        self.dim = dim

    def forward(self, pred, target):
        pred = pred.log_softmax(dim=self.dim)
        with torch.no_grad():
            # true_dist = pred.data.clone()
            true_dist = torch.zeros_like(pred)
            true_dist.fill_(self.smoothing / (self.cls - 1))
            true_dist.scatter_(1, target.data.unsqueeze(1), self.confidence)
        return torch.mean(torch.sum(-true_dist * pred, dim=self.dim))