text: import torch
  import torch.nn as nn
  import torch.nn.functional as F
  import torch.nn.modules.loss
  
  
  class KLDivLoss2(torch.nn.modules.loss._Loss):
      r"""The `Kullback-Leibler divergence`_ Loss as provided by torch.nn with
      the only difference being that the loss now applies log_softmax before
      computing the KL divergence.
  
      The original doc:
      KL divergence is a useful distance measure for continuous distributions
      and is often useful when performing direct regression over the space of
      (discretely sampled) continuous output distributions.
  
      As with `NLLLoss`, the `input` given is expected to contain
      *log-probabilities*, however unlike `ClassNLLLoss`, `input` is not
      restricted to a 2D Tensor, because the criterion is applied element-wise.
  
      This criterion expects a `target` `Tensor` of the same size as the
      `input` `Tensor`.
  
      The loss can be described as:
  
      .. math::
          \ell(x, y) = L = \{l_1,\dots,l_N\}^\top, \quad
          l_n = y_n \odot \left( \log y_n - x_n \right),
  
      where :math:`N` is the batch size. If reduce is ``True``, then:
  
      .. math::
          \ell(x, y) = \begin{cases}
              \operatorname{mean}(L), & \text{if}\; \text{size_average} = \text{True},\\
              \operatorname{sum}(L),  & \text{if}\; \text{size_average} = \text{False}.
          \end{cases}
  
      By default, the losses are averaged for each minibatch over observations
      **as well as** over dimensions. However, if the field
      `size_average` is set to ``False``, the losses are instead summed.
  
      .. _Kullback-Leibler divergence:
          https://en.wikipedia.org/wiki/Kullback-Leibler_divergence
  
      Args:
          size_average (bool, optional: By default, the losses are averaged
              for each minibatch over observations **as well as** over
              dimensions. However, if ``False`` the losses are instead summed.
          reduce (bool, optional): By default, the losses are averaged
              over observations for each minibatch, or summed, depending on
              size_average. When reduce is ``False``, returns a loss per input/target
              element instead and ignores size_average. Default: ``True``
  
      Shape:
          - input: :math:`(N, *)` where `*` means, any number of additional
            dimensions
          - target: :math:`(N, *)`, same shape as the input
          - output: scalar. If `reduce` is ``True``, then :math:`(N, *)`,
              same shape as the input
  
      """
      def __init__(self, reduction='none'):
          super(KLDivLoss2, self).__init__(reduction=reduction)
  
      def forward(self, input, target):
          #torch.nn.modules.loss._assert_no_grad(target)
          # We go with double here as the probs for unrelated 
          # classes can be extremely small
          return F.kl_div(F.log_softmax(input, 1).double(),
                                  target.double(),
                                  reduction=self.reduction).sum(1).mean()
  
  class BCEWithLogitsLoss2(torch.nn.modules.loss._Loss):
      r"""
      Binary cross-entropy as provided by torch.nn, with the only difference being a
      different aggregation strategy, which matches the aggregation used in the normal cross
      entropy loss.
  
      Original doc:
      This loss combines a `Sigmoid` layer and the `BCELoss` in one single
      class. This version is more numerically stable than using a plain `Sigmoid`
      followed by a `BCELoss` as, by combining the operations into one layer,
      we take advantage of the log-sum-exp trick for numerical stability.
  
      The loss can be described as:
  
      .. math::
          \ell(x, y) = L = \{l_1,\dots,l_N\}^\top, \quad
          l_n = - w_n \left[ t_n \cdot \log \sigma(x_n)
          + (1 - t_n) \cdot \log (1 - \sigma(x_n)) \right],
  
      where :math:`N` is the batch size. If reduce is ``True``, then
  
      .. math::
          \ell(x, y) = \begin{cases}
              \operatorname{mean}(L), & \text{if}\; \text{size_average} = \text{True},\\
              \operatorname{sum}(L),  & \text{if}\; \text{size_average} = \text{False}.
          \end{cases}
  
      This is used for measuring the error of a reconstruction in for example
      an auto-encoder. Note that the targets `t[i]` should be numbers
      between 0 and 1.
  
      It's possible to trade off recall and precision by adding weights to positive examples.
      In this case the loss can be described as:
  
      .. math::
          \ell(x, y) = L = \{l_1,\dots,l_N\}^\top, \quad
          l_n = - w_n \left[ p_n t_n \cdot \log \sigma(x_n)
          + (1 - t_n) \cdot \log (1 - \sigma(x_n)) \right],
  
      where :math:`p_n` is the positive weight of class :math:`n`.
      :math:`p_n > 1` increases the recall, :math:`p_n < 1` increases the precision.
  
      For example, if a dataset contains 100 positive and 300 negative examples of a single class,
      then `pos_weight` for the class should be equal to :math:`\frac{300}{100}=3`.
      The loss would act as if the dataset contains math:`3\times 100=300` positive examples.
  
      Args:
          weight (Tensor, optional): a manual rescaling weight given to the loss
              of each batch element. If given, has to be a Tensor of size
              "nbatch".
          size_average (bool, optional): Deprecated (see :attr:`reduction`). By default,
              the losses are averaged over each loss element in the batch. Note that for
              some losses, there multiple elements per sample. If the field :attr:`size_average`
              is set to ``False``, the losses are instead summed for each minibatch. Ignored
              when reduce is ``False``. Default: ``True``
          reduce (bool, optional): Deprecated (see :attr:`reduction`). By default, the
              losses are averaged or summed over observations for each minibatch depending
              on :attr:`size_average`. When :attr:`reduce` is ``False``, returns a loss per
              batch element instead and ignores :attr:`size_average`. Default: ``True``
          reduction (string, optional): Specifies the reduction to apply to the output:
              'none' | 'elementwise_mean' | 'sum'. 'none': no reduction will be applied,
              'elementwise_mean': the sum of the output will be divided by the number of
              elements in the output, 'sum': the output will be summed. Note: :attr:`size_average`
              and :attr:`reduce` are in the process of being deprecated, and in the meantime,
              specifying either of those two args will override :attr:`reduction`. Default: 'elementwise_mean'
          pos_weight (Tensor, optional): a weight of positive examples.
                  Must be a vector with length equal to the number of classes.
  
       Shape:
           - Input: :math:`(N, *)` where `*` means, any number of additional
             dimensions
           - Target: :math:`(N, *)`, same shape as the input
  
       Examples::
  
          >>> loss = nn.BCEWithLogitsLoss()
          >>> input = torch.randn(3, requires_grad=True)
          >>> target = torch.empty(3).random_(2)
          >>> output = loss(input, target)
          >>> output.backward()
      """
      def __init__(self, weight=None, size_average=None, reduce=None, pos_weight=None):
          super(BCEWithLogitsLoss2, self).__init__(size_average, reduce, reduction='none')
          self.register_buffer('weight', weight)
          self.register_buffer('pos_weight', pos_weight)
  
      def forward(self, input, target):
          return F.binary_cross_entropy_with_logits(input.double(), 
                                                    target.double(),
                                                    self.weight.double() if self.weight else self.weight,
                                                    pos_weight=self.pos_weight.double() if self.pos_weight else self.pos_weight,
                                                    reduction='none').sum(1).mean()
  