class_docstr: The base class of Runner, a training helper for PyTorch.
  
  All subclasses should implement the following APIs:
  
  - ``run()``
  - ``train()``
  - ``val()``
  - ``save_checkpoint()``
  
  Args:
      model (:obj:`torch.nn.Module`): The model to be run.
      batch_processor (callable): A callable method that process a data
          batch. The interface of this method should be
          `batch_processor(model, data, train_mode) -> dict`
      optimizer (dict or :obj:`torch.optim.Optimizer`): It can be either an
          optimizer (in most cases) or a dict of optimizers (in models that
          requires more than one optimizer, e.g., GAN).
      work_dir (str, optional): The working directory to save checkpoints
          and logs. Defaults to None.
      logger (:obj:`logging.Logger`): Logger used during training.
           Defaults to None. (The default value is just for backward
           compatibility)
      meta (dict | None): A dict records some import information such as
          environment info and seed, which will be logged in logger hook.
          Defaults to None.
      max_epochs (int, optional): Total training epochs.
      max_iters (int, optional): Total training iterations.
class_docstr_tok: ["The","base","class","of","Runner",",","a","training","helper","for","PyTorch",".","All","subclasses","should","implement","the","following","APIs",":","-","``","run","(",")","``","-","``","train","(",")","``","-","``","val","(",")","``","-","``","save_checkpoint","(",")","``","Args",":","model","(",":","obj",":","`","torch.nn.Module","`",")",":","The","model","to","be","run",".","batch_processor","(","callable",")",":","A","callable","method","that","process","a","data","batch",".","The","interface","of","this","method","should","be","`","batch_processor","(","model",",","data",",","train_mode",")","-",">","dict","`","optimizer","(","dict","or",":","obj",":","`","torch.optim.Optimizer","`",")",":","It","can","be","either","an","optimizer","(","in","most","cases",")","or","a","dict","of","optimizers","(","in","models","that","requires","more","than","one","optimizer",",","e.g.",",","GAN",")",".","work_dir","(","str",",","optional",")",":","The","working","directory","to","save","checkpoints","and","logs",".","Defaults","to","None",".","logger","(",":","obj",":","`","logging.Logger","`",")",":","Logger","used","during","training",".","Defaults","to","None",".","(","The","default","value","is","just","for","backward","compatibility",")","meta","(","dict","|","None",")",":","A","dict","records","some","import","information","such","as","environment","info","and","seed",",","which","will","be","logged","in","logger","hook",".","Defaults","to","None",".","max_epochs","(","int",",","optional",")",":","Total","training","epochs",".","max_iters","(","int",",","optional",")",":","Total","training","iterations","."]
code: def __init__(
      self,
      model,
      batch_processor=None,
      optimizer=None,
      work_dir=None,
      logger=None,
      meta=None,
      max_iters=None,
      max_epochs=None,
  ):
      if batch_processor is not None:
          if not callable(batch_processor):
              raise TypeError(
                  "batch_processor must be callable, "
                  f"but got {type(batch_processor)}"
              )
          warnings.warn(
              "batch_processor is deprecated, please implement "
              "train_step() and val_step() in the model instead."
          )
          # raise an error is `batch_processor` is not None and
          # `model.train_step()` exists.
          if is_module_wrapper(model):
              _model = model.module
          else:
              _model = model
          if hasattr(_model, "train_step") or hasattr(
              _model, "val_step"
          ):
              raise RuntimeError(
                  "batch_processor and model.train_step()/model.val_step() "
                  "cannot be both available."
              )
      else:
          assert hasattr(model, "train_step")
  
      # check the type of `optimizer`
      if isinstance(optimizer, dict):
          for name, optim in optimizer.items():
              if not isinstance(optim, Optimizer):
                  raise TypeError(
                      f"optimizer must be a dict of torch.optim.Optimizers, "
                      f'but optimizer["{name}"] is a {type(optim)}'
                  )
      elif (
          not isinstance(optimizer, Optimizer) and optimizer is not None
      ):
          raise TypeError(
              f"optimizer must be a torch.optim.Optimizer object "
              f"or dict or None, but got {type(optimizer)}"
          )
  
      # check the type of `logger`
      if not isinstance(logger, logging.Logger):
          raise TypeError(
              f"logger must be a logging.Logger object, "
              f"but got {type(logger)}"
          )
  
      # check the type of `meta`
      if meta is not None and not isinstance(meta, dict):
          raise TypeError(
              f"meta must be a dict or None, but got {type(meta)}"
          )
  
      self.model = model
      self.batch_processor = batch_processor
      self.optimizer = optimizer
      self.logger = logger
      self.meta = meta
      # create work_dir
      if mmcv.is_str(work_dir):
          self.work_dir = osp.abspath(work_dir)
          mmcv.mkdir_or_exist(self.work_dir)
      elif work_dir is None:
          self.work_dir = None
      else:
          raise TypeError('"work_dir" must be a str or None')
  
      # get model name from the model class
      if hasattr(self.model, "module"):
          self._model_name = self.model.module.__class__.__name__
      else:
          self._model_name = self.model.__class__.__name__
  
      self._rank, self._world_size = get_dist_info()
      self.timestamp = get_time_str()
      self.mode = None
      self._hooks = []
      self._epoch = 0
      self._iter = 0
      self._inner_iter = 0
  
      if max_epochs is not None and max_iters is not None:
          raise ValueError(
              "Only one of `max_epochs` or `max_iters` can be set."
          )
  
      self._max_epochs = max_epochs
      self._max_iters = max_iters
      # TODO: Redesign LogBuffer, it is not flexible and elegant enough
      self.log_buffer = LogBuffer()
  
imports: import copy
  import logging
  import os.path
  import warnings
  from abc import ABCMeta, abstractmethod
  import torch
  from torch.optim import Optimizer
  import annotator.uniformer.mmcv
  from ..parallel import is_module_wrapper
  from .checkpoint import load_checkpoint
  from .dist_utils import get_dist_info
  from .hooks import HOOKS, Hook
  from .log_buffer import LogBuffer
  from .priority import Priority, get_priority
  from .utils import get_time_str
label_desc: Use image node_id 1 to create a new BaseRunner object  with example: obj = BaseRunner(model, batch_processor, optimizer, work_dir, logger, meta, max_iters, max_epochs)