class_docstr: A task for training primal model and dual models jointly.
  It takes:
      - unlabelled source (aka source monolingual data for translation task),
      - unlabelled target (aka target monolingual data for translation task),
      - labelled (source, target) (aka parallel data for translation task),
class_docstr_tok: ["A","task","for","training","primal","model","and","dual","models","jointly",".","It","takes",":","-","unlabelled","source","(","aka","source","monolingual","data","for","translation","task",")",",","-","unlabelled","target","(","aka","target","monolingual","data","for","translation","task",")",",","-","labelled","(","source",",","target",")","(","aka","parallel","data","for","translation","task",")",","]
code: def __init__(
      self,
      args,
      primal_src_dict,
      primal_tgt_dict,
      dual_src_dict,
      dual_tgt_dict,
  ):
      if not torch.cuda.is_available():
          raise NotImplementedError("Training on CPU is not supported.")
      super().__init__(args)
      self.primal_src_dict = primal_src_dict
      self.primal_tgt_dict = primal_tgt_dict
      self.dual_src_dict = dual_src_dict
      self.dual_tgt_dict = dual_tgt_dict
      self.use_char_source = (args.char_source_vocab_file != "") or (
          args.char_source_vocab_file
      )
      self.task_criterion = UnsupervisedCriterion(args, self).cuda()
      self.criterion = WeightedLabelSmoothedCrossEntropyCriterion(
          args, self
      ).cuda()
      self.num_update = 0
  
imports: from collections import OrderedDict
  import torch
  from fairseq import optim, utils
  from fairseq.criterions import CRITERION_REGISTRY
  from fairseq.data import LanguagePairDataset, RoundRobinZipDatasets
  from fairseq.tasks import LegacyFairseqTask, register_task
  from pytorch_translate.data import dictionary, utils
  from pytorch_translate.dual_learning import dual_learning_models
  from pytorch_translate.dual_learning.dual_learning_criterion import UnsupervisedCriterion
  from pytorch_translate.tasks.pytorch_translate_task import PytorchTranslateTask
  from pytorch_translate.weighted_criterions import WeightedLabelSmoothedCrossEntropyCriterion
label_desc: Use image node_id 2 to create a new DualLearningTask object from inherited base classes: LegacyFairseqTask with example: obj = DualLearningTask(args, primal_src_dict, primal_tgt_dict, dual_src_dict, dual_tgt_dict)