class_docstr: Abstract Trait.
  
  Applies unlikelihood loss based on the presence of negative rewards in the task.
class_docstr_tok: ["Abstract","Trait",".","Applies","unlikelihood","loss","based","on","the","presence","of","negative","rewards","in","the","task","."]
code: def compute_loss(self, batch, return_output=False):
      if batch.label_vec is None:
          raise ValueError("Cannot compute loss without a label.")
  
      model_output = self.model(
          *self._model_input(batch), ys=batch.label_vec
      )
      scores, preds, *_ = model_output  # scores is bsz x time x vocab
  
      scores = F.log_softmax(scores, dim=-1)
      scores_view = scores.view(-1, scores.size(-1))
      targets = batch.label_vec
      targets_view = targets.view(-1)
  
      notnull = targets.ne(self.NULL_IDX)
      if self.is_training:
          # note it's >= because convai2 and other teachers all provide a 0 reward
          mle_notnull = notnull & (batch.rewards >= 0).unsqueeze(
              1
          ).expand_as(notnull)
      else:
          mle_notnull = notnull
  
      mle_loss = (
          F.nll_loss(
              scores_view,
              targets_view,
              ignore_index=self.NULL_IDX,
              reduction="none",
          ).view_as(mle_notnull)
          * mle_notnull.float()
      ).sum()
  
      # limit loss to only the positive rewards
      mle_target_tokens = mle_notnull.long().sum()
      correct = ((targets == preds) * mle_notnull).sum()
      self.global_metrics.add(
          "token_acc", AverageMetric(correct, mle_target_tokens)
      )
      self.global_metrics.add(
          "nll_loss", AverageMetric(mle_loss, mle_target_tokens)
      )
      self.global_metrics.add(
          "ppl", PPLMetric(mle_loss, mle_target_tokens)
      )
      if mle_target_tokens > 0:
          mle_loss /= mle_target_tokens  # average loss per token
  
      if not self.is_training:
          if return_output:
              return (mle_loss, model_output)
          else:
              return mle_loss
  
      # and now we want the unlikelihood loss on the negative examples
      ul_notnull = notnull & (batch.rewards < 0).unsqueeze(1).expand_as(
          notnull
      )
      ul_target_tokens = ul_notnull.long().sum()
      range_ = torch.arange(targets_view.size(0)).to(
          batch.label_vec.device
      )
      ul_scores = scores_view[range_, targets_view]
      clamp_min = 1e-6 if self.opt["fp16"] else 1e-20
      ul_loss = (
          -torch.log(
              torch.clamp(1.0 - ul_scores.exp(), min=clamp_min)
          ).view_as(ul_notnull)
          * ul_notnull.float()
      ).sum()
      self.global_metrics.add(
          "ul_loss", AverageMetric(ul_loss, ul_target_tokens)
      )
      if ul_target_tokens > 0:
          ul_loss /= ul_target_tokens
  
      loss = mle_loss + self.opt["alpha"] * ul_loss
  
      if return_output:
          return (loss, model_output)
      else:
          return loss
  
imports: from typing import Optional
  from parlai.core.params import ParlaiParser
  from parlai.core.opt import Opt
  import json
  import math
  import os
  import torch
  import torch.nn.functional
  from collections import defaultdict, Counter
  from nltk import ngrams
  from parlai.core.torch_generator_agent import PPLMetric
  from parlai.agents.image_seq2seq.image_seq2seq import ImageSeq2seqAgent
  from parlai.agents.transformer.transformer import TransformerGeneratorAgent
  from parlai.core.metrics import AverageMetric, SumMetric, GlobalAverageMetric
  from parlai.utils.misc import round_sigfigs
  from parlai.utils.io import PathManager
label_desc: Use image node_id 2 for calling the RewardUnlikelihoodAgentTrait obj's underlying member method code with example usage: obj.compute_loss(batch, return_output) and returns: loss,  model_output, loss, mle_loss,  model_output, mle_loss