class_docstr: RPA UL Agent.
  
  Performs unlikelihood such that tokens which lead to misclassification are
  penalized.
class_docstr_tok: ["RPA","UL","Agent",".","Performs","unlikelihood","such","that","tokens","which","lead","to","misclassification","are","penalized","."]
docstr: Compute Label Mask for UL.
  
  We classify the generations from a model in a left-to-right fashion.
  
  The topk tokens for which the character classification drops the most
  are chosen to apply UL loss.
  
  :param label_mask:
      label mask to fill
  :param generations:
      generations from the model
  :param batch:
      batch being considered
  
  :return (label_mask, wrong_cnt, wrong_cnt_below_threshold, right_cnt):
      label_mask: mask indicating which tokens to apply UL
      wrong_cnt: how many generations were classified as the wrong character (above a certain threshold)
      wrong_class_all_cnt: how many *total* generations were classified as wrong character
      right_cnt: how many generations were classified as the right character
docstr_tok: ["Compute","Label","Mask","for","UL",".","We","classify","the","generations","from","a","model","in","a","left-to-right","fashion",".","The","topk","tokens","for","which","the","character","classification","drops","the","most","are","chosen","to","apply","UL","loss",".",":","param","label_mask",":","label","mask","to","fill",":","param","generations",":","generations","from","the","model",":","param","batch",":","batch","being","considered",":","return","(","label_mask",",","wrong_cnt",",","wrong_cnt_below_threshold",",","right_cnt",")",":","label_mask",":","mask","indicating","which","tokens","to","apply","UL","wrong_cnt",":","how","many","generations","were","classified","as","the","wrong","character","(","above","a","certain","threshold",")","wrong_class_all_cnt",":","how","many","*","total","*","generations","were","classified","as","wrong","character","right_cnt",":","how","many","generations","were","classified","as","the","right","character"]
code: def compute_ul_label_mask(
      self,
      label_mask: torch.Tensor,
      generations: List[torch.LongTensor],
      batch: Batch,
  ) -> Tuple[torch.Tensor, List[int], List[int], List[int]]:
      """
      Compute Label Mask for UL.
  
      We classify the generations from a model in a left-to-right fashion.
  
      The topk tokens for which the character classification drops the most
      are chosen to apply UL loss.
  
      :param label_mask:
          label mask to fill
      :param generations:
          generations from the model
      :param batch:
          batch being considered
  
      :return (label_mask, wrong_cnt, wrong_cnt_below_threshold, right_cnt):
          label_mask: mask indicating which tokens to apply UL
          wrong_cnt: how many generations were classified as the wrong character (above a certain threshold)
          wrong_class_all_cnt: how many *total* generations were classified as wrong character
          right_cnt: how many generations were classified as the right character
      """
      wrong_class_cnt = []
      wrong_class_all_cnt = []
      right_class_cnt = []
  
      for i, gen in enumerate(generations):
          gen_i = gen.tolist()
  
          obs_i = batch.observations[i]
          context = obs_i["full_text"]
  
          # first, classify full response
          me, _you = self.classifier.get_predictor_label_candidates(
              obs_i, context
          )
          full_classification = self.classifier.classify(
              context, self._v2t(gen_i)
          )
          if full_classification["text"] == me:
              right_class_cnt.append(1)
              wrong_class_cnt.append(0)
              wrong_class_all_cnt.append(0)
              continue
          else:
              scores = self.character_softmax(
                  full_classification["sorted_scores"].float(), dim=0
              )
              if scores[0] > self.initial_classification_threshold:
                  right_class_cnt.append(0)
                  wrong_class_cnt.append(1)
                  wrong_class_all_cnt.append(1)
              else:
                  right_class_cnt.append(0)
                  wrong_class_cnt.append(0)
                  wrong_class_all_cnt.append(1)
                  continue
  
          # classify tokens left to right
          classifications = self.classifier.batch_classify(
              [context] * (len(gen_i) - 1),
              [
                  self._v2t(gen_i[:end_idx])
                  for end_idx in range(1, len(gen_i))
              ],
          )
          preds = []
          scores = []
          me_scores = torch.zeros(len(classifications))
          for j, c in enumerate(classifications):
              pred_c = c["text"]
              scores_c = self.character_softmax(
                  c["sorted_scores"].float(), dim=0
              )
              preds.append(pred_c)
              scores.append(scores_c)
              me_scores[j] = (
                  scores_c[0] if pred_c == me else scores_c[1]
              )
  
          if self.only_wrong_class_toks:
              # we normalize all correct classifications here to be 1.0.
              # therefore, it is necessarily the case that the topk diffs
              # will only be tokens that yield wrong classification
              me_mask = me_scores > 0.5
              me_scores[me_mask] = 1.0
          me_scores_shift = torch.cat([me_scores[0:1], me_scores[:-1]])
          # for each token t_{i}, subtract prob t_{i-1} to see difference in
          # probability. if this is positive, it means the correct character probability
          # **decreased**. Thus, we take the topk
          if self.all_wrong_class_toks:
              assert self.only_wrong_class_toks
              top_offenders = (
                  (me_scores_shift - me_scores)
                  .greater(0)
                  .nonzero()
                  .squeeze()
              )
          elif self.random_toks:
              top_offenders = torch.randint(
                  me_scores.size(0), (self.top_k,)
              )
          else:
              top_offenders = (
                  (me_scores_shift - me_scores).topk(self.top_k).indices
              )
          label_mask[i, top_offenders] = 1
  
      return (
          label_mask,
          wrong_class_cnt,
          wrong_class_all_cnt,
          right_class_cnt,
      )
  
imports: from typing import Optional, List, Tuple
  from parlai.core.params import ParlaiParser
  from parlai.core.opt import Opt
  from parlai.core.torch_agent import Batch
  import torch
  import torch.nn
  import torch.nn.functional
  from parlai.agents.transformer.transformer import TransformerGeneratorAgent
  from parlai.core.torch_agent import Output
  from parlai.core.metrics import AverageMetric
  from projects.light_whoami.agents.rpa_rerank import RPAReranker
  from projects.msc.agents.long_tga import TransformerVariantAgent
label_desc: Use image node_id 6 for calling the RpaUlAgent obj's underlying member method code with example usage: obj.compute_ul_label_mask(label_mask, generations, batch) and returns: label_mask,  wrong_class_cnt,  wrong_class_all_cnt,  right_class_cnt