# Source code for torchreid.losses.cross_entropy_loss

    from __future__ import absolute_import
    from __future__ import division

    import torch
    import torch.nn as nn

    class CrossEntropyLoss(nn.Module):
        r"""Cross entropy loss with label smoothing regularizer.

        Reference:
            Szegedy et al. Rethinking the Inception Architecture for Computer Vision. CVPR 2016.

        With label smoothing, the label :math:`y` for a class is computed by

        .. math::
            \begin{equation}
            (1 - \epsilon) \times y + \frac{\epsilon}{K},
            \end{equation}

        where :math:`K` denotes the number of classes and :math:`\epsilon` is a weight. When
        :math:`\epsilon = 0`, the loss function reduces to the normal cross entropy.

        Args:
            num_classes (int): number of classes.
            epsilon (float, optional): weight. Default is 0.1.
            use_gpu (bool, optional): whether to use gpu devices. Default is True.
            label_smooth (bool, optional): whether to apply label smoothing. Default is True.
        """

        def __init__(self, num_classes, epsilon=0.1, use_gpu=True, label_smooth=True):
            super(CrossEntropyLoss, self).__init__()
            self.num_classes = num_classes
            self.epsilon = epsilon if label_smooth else 0
            self.use_gpu = use_gpu
            self.logsoftmax = nn.LogSoftmax(dim=1)

        def forward(self, inputs, targets):
            """
            Args:
                inputs (torch.Tensor): prediction matrix (before softmax) with
                    shape (batch_size, num_classes).
                targets (torch.LongTensor): ground truth labels with shape (num_classes).
            """
            log_probs = self.logsoftmax(inputs)
            targets = torch.zeros(log_probs.size()).scatter_(1, targets.unsqueeze(1).data.cpu(), 1)
            if self.use_gpu: targets = targets.cuda()
            targets = (1 - self.epsilon) * targets + self.epsilon / self.num_classes
            return (- targets * log_probs).mean(0).sum()