class_docstr: Class merges data from several dataset iterators. When used for batch generation batches from
  merged dataset iterators are united into one batch. If sizes of merged datasets are different
  smaller datasets are repeated until their size becomes equal to the largest dataset.
  
  Args:
      data: dictionary which keys are task names and values are dictionaries with fields
          ``"train", "valid", "test"``.
      num_train_epochs: number of training epochs
      tasks: dictionary which keys are task names and values are init params of dataset iterators. If task has
          key-value pair ``'use_task_defaults': False`` task_defaults for this task dataset iterator will be ignored.
      batch_size: batch_size
      sampling_mode: mode of sampling we use. It can be plain, uniform or anneal.
      gradient_accumulation_steps: number of gradient accumulation steps. Default is 1
      steps_per_epoch: number of steps per epoch. Nesessary if gradient_accumulation_steps > 1
      iterator_class_name: name of iterator class.
      use_label_name, seed, features - parameters for the iterator class
      one_element_tuples: if True, tuple of x consisting of one element is returned in this element. Default: True
      task_defaults: default task parameters.
      seed - random seed for sampling
  
  Attributes:
      data: dictionary of data with fields "train", "valid" and "test" (or some of them)
class_docstr_tok: ["Class","merges","data","from","several","dataset","iterators",".","When","used","for","batch","generation","batches","from","merged","dataset","iterators","are","united","into","one","batch",".","If","sizes","of","merged","datasets","are","different","smaller","datasets","are","repeated","until","their","size","becomes","equal","to","the","largest","dataset",".","Args",":","data",":","dictionary","which","keys","are","task","names","and","values","are","dictionaries","with","fields","``","``","train","''",",","``","valid","''",",","``","test","''","``",".","num_train_epochs",":","number","of","training","epochs","tasks",":","dictionary","which","keys","are","task","names","and","values","are","init","params","of","dataset","iterators",".","If","task","has","key-value","pair","``","'use_task_defaults","'",":","False","``","task_defaults","for","this","task","dataset","iterator","will","be","ignored",".","batch_size",":","batch_size","sampling_mode",":","mode","of","sampling","we","use",".","It","can","be","plain",",","uniform","or","anneal",".","gradient_accumulation_steps",":","number","of","gradient","accumulation","steps",".","Default","is","1","steps_per_epoch",":","number","of","steps","per","epoch",".","Nesessary","if","gradient_accumulation_steps",">","1","iterator_class_name",":","name","of","iterator","class",".","use_label_name",",","seed",",","features","-","parameters","for","the","iterator","class","one_element_tuples",":","if","True",",","tuple","of","x","consisting","of","one","element","is","returned","in","this","element",".","Default",":","True","task_defaults",":","default","task","parameters",".","seed","-","random","seed","for","sampling","Attributes",":","data",":","dictionary","of","data","with","fields","``","train","''",",","``","valid","''","and","``","test","''","(","or","some","of","them",")"]
docstr: Generates batches and expected output to train neural networks.
  If there are not enough samples from any task, samples are padded with None
  Args:
      batch_size: number of samples in batch
      data_type: can be either 'train', 'test', or 'valid'
      shuffle: whether to shuffle dataset before batching
  Yields:
      A tuple of a batch of inputs and a batch of expected outputs.
      Inputs and outputs are tuples. Element of inputs or outputs is a tuple which
      elements are x values of merged tasks in the order tasks are present in
      `tasks` argument of `__init__` method.
docstr_tok: ["Generates","batches","and","expected","output","to","train","neural","networks",".","If","there","are","not","enough","samples","from","any","task",",","samples","are","padded","with","None","Args",":","batch_size",":","number","of","samples","in","batch","data_type",":","can","be","either","'train","'",",","'test","'",",","or","'valid'","shuffle",":","whether","to","shuffle","dataset","before","batching","Yields",":","A","tuple","of","a","batch","of","inputs","and","a","batch","of","expected","outputs",".","Inputs","and","outputs","are","tuples",".","Element","of","inputs","or","outputs","is","a","tuple","which","elements","are","x","values","of","merged","tasks","in","the","order","tasks","are","present","in","`","tasks","`","argument","of","`","__init__","`","method","."]
code: def gen_batches(
      self,
      batch_size: int,
      data_type: str = "train",
      shuffle: bool = None,
  ) -> Iterator[Tuple[tuple, tuple]]:
      """
      Generates batches and expected output to train neural networks.
      If there are not enough samples from any task, samples are padded with None
      Args:
          batch_size: number of samples in batch
          data_type: can be either 'train', 'test', or 'valid'
          shuffle: whether to shuffle dataset before batching
      Yields:
          A tuple of a batch of inputs and a batch of expected outputs.
          Inputs and outputs are tuples. Element of inputs or outputs is a tuple which
          elements are x values of merged tasks in the order tasks are present in
          `tasks` argument of `__init__` method.
      """
  
      max_task_data_len = self.max_task_data_len[data_type]
      log.info(
          f"Batch size {batch_size} with gradient accumulation steps {self.gradient_accumulation_steps}"
      )
      log.info(
          f"Efficient batch size {batch_size // self.gradient_accumulation_steps}"
      )
      batch_size = batch_size // self.gradient_accumulation_steps
  
      if data_type == "train":
          generators = [
              SingleTaskBatchGenerator(
                  iter_, batch_size, data_type, shuffle
              )
              for iter_ in self.task_iterators.values()
          ]
          # probs only required while training
          probs = self._get_probs("train")
          for step in range(self.steps_per_epoch):
              if (
                  (self.steps_taken + 1)
                  % self.gradient_accumulation_steps
                  == 0
                  or self.task_id is None
              ):
                  self.task_id = np.random.choice(self.n_tasks, p=probs)
              x = [
                  [None for _ in range(batch_size)]
                  for _ in range(self.n_tasks)
              ]
              y = [
                  [None for _ in range(batch_size)]
                  for _ in range(self.n_tasks)
              ]
              x[self.task_id], y[self.task_id] = generators[
                  self.task_id
              ].__next__()
              if not all([s is None for s in x[self.task_id]]):
                  batch_to_yield = self._transform_before_yielding(
                      x, y, batch_size
                  )
                  yield batch_to_yield
  
          self.epochs_done += 1
          # one additional step is taken while logging training metrics
          self.steps_taken -= 1
      else:
          eval_batch_size = 1
          x = [
              [None for _ in range(eval_batch_size)]
              for _ in range(self.n_tasks)
          ]
          y = [
              [None for _ in range(eval_batch_size)]
              for _ in range(self.n_tasks)
          ]
          generators = [
              SingleTaskBatchGenerator(
                  iter_,
                  batch_size=eval_batch_size,
                  data_type=data_type,
                  shuffle=shuffle,
              )
              for iter_ in self.task_iterators.values()
          ]
          for step in range(max_task_data_len):
              for task_id in range(self.n_tasks):
                  x[task_id], y[task_id] = generators[
                      task_id
                  ].__next__()
  
              batches = self._transform_before_yielding(
                  x, y, eval_batch_size
              )
              yield batches
  
imports: import copy
  import math
  import random
  from logging import getLogger
  from typing import Iterator, Optional, Tuple, Union
  import numpy
  from deeppavlov.core.common.errors import ConfigError
  from deeppavlov.core.common.params import from_params
  from deeppavlov.core.common.registry import register
  from deeppavlov.core.data.data_learning_iterator import DataLearningIterator
label_desc: Use image node_id 6 for calling the MultiTaskIterator obj's underlying member method code with example usage: obj.gen_batches(batch_size, data_type, shuffle) without return types