class_docstr: Abstract Trait.
  
  Applies unliikelihood loss to repetition some proportion of train steps by
  generating, marking repeats, and calculating loss accordingly.
class_docstr_tok: ["Abstract","Trait",".","Applies","unliikelihood","loss","to","repetition","some","proportion","of","train","steps","by","generating",",","marking","repeats",",","and","calculating","loss","accordingly","."]
code: def compute_loss(self, batch, return_output=False):
      if self.is_training and (
          torch.rand(1).item() >= self.opt["seq_ul_ratio"]
      ):
          total_loss, model_output = super().compute_loss(
              batch, return_output=True
          )
          # No sequence level unlikelihood
          if return_output:
              return total_loss, model_output
          else:
              return total_loss
  
      # Generate
      clamp_min = 1e-6 if self.opt["fp16"] else 1e-20
      maxlen = self.label_truncate or 256
      with torch.no_grad():
          beam_pred_scores, _ = self._generate(
              batch, self.beam_size, maxlen
          )
  
      # forward pass to create graph for beam search case
      generations = [g[1:] for (g, s, _) in beam_pred_scores]
      pred_toks = torch.nn.utils.rnn.pad_sequence(
          generations, batch_first=True
      )
      model_output = self.model(*self._model_input(batch), ys=pred_toks)
      logits, preds, _ = model_output
  
      # construct mask marking repeats
      n = self.opt["seq_ul_n"]  # label n-grams
      crep_mask = torch.zeros_like(pred_toks).type_as(logits)
      lrep_mask = torch.zeros_like(pred_toks).type_as(logits)
  
      for i, gen in enumerate(generations):
          gen_i = gen.tolist()
  
          # Collect context ngrams
          context_i = batch.text_vec[i].tolist()
          context_n_grams = self._count_n_grams(context_i, n)
  
          seen_n_grams = defaultdict(int)
  
          # penalize if there is a context repeat
          for j, n_gram in enumerate(NGramIterator(gen_i, n)):
              if context_n_grams[n_gram] > 0:
                  crep_mask[i, j : j + n] = 1
  
          # penalize if there is a label repeat
          for j, n_gram in enumerate(NGramIterator(gen_i, n)):
              if seen_n_grams[n_gram] > 0:
                  lrep_mask[i, j : j + n] = 1
              seen_n_grams[n_gram] += 1
  
      # Compute unlikelihood loss
      lprobs = self.pred_logsoftmax(logits)
      pred_lprobs = lprobs.view(-1, lprobs.size(2)).gather(
          1, pred_toks.view(-1, 1)
      )
      one_minus_probs = torch.clamp(
          (1.0 - pred_lprobs.exp()), min=clamp_min
      ).view(pred_toks.size(0), pred_toks.size(1))
  
      mask = ((1 - self.opt["ctxt_beta"]) * lrep_mask) + (
          self.opt["ctxt_beta"] * crep_mask
      )
  
      ul_loss = -(torch.log(one_minus_probs)) * mask
      total_loss = div(ul_loss.sum(), mask.sum())
      self.record_local_metric(
          "ul_loss",
          AverageMetric.many(ul_loss.sum(dim=-1), mask.sum(dim=-1)),
      )
  
      if not self.is_training:
          # in eval mode, we want metrics (e.g. PPL) provided by tga's compute_loss
          _, _ = super().compute_loss(batch, return_output=True)
  
      if return_output:
          return total_loss, model_output
      return total_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 5 for calling the RepetitionUnlikelihoodAgentTrait obj's underlying member method code with example usage: obj.compute_loss(batch, return_output) and returns: total_loss, total_loss,  model_output, total_loss,  model_output, total_loss