class_docstr: Base class for actor critic trainers. Suitable for multi-step and multi-agent training.
  
  :param algorithm_config: Algorithm parameters.
  :param rollout_generator: The rollout generator to use. This object encapsulates the env.
  :param evaluator: The evaluator to use.
  :param model: Structured torch actor critic model.
  :param model_selection: Optional model selection class, receives model evaluation results.
docstr: Main train method of the actor critic trainer. This is used in order to do algorithm specific operations
  around this method in the main train method which is called by the runner. (e.g. this is used when it comes to
  multiprocessing)
  
  :param n_epochs: Number of epochs to train.
docstr_tok: ["Main","train","method","of","the","actor","critic","trainer",".","This","is","used","in","order","to","do","algorithm","specific","operations","around","this","method","in","the","main","train","method","which","is","called","by","the","runner",".","(","e.g",".","this","is","used","when","it","comes","to","multiprocessing",")",":","param","n_epochs",":","Number","of","epochs","to","train","."]
code: def train(self, n_epochs: Optional[int] = None) -> None:
      """Main train method of the actor critic trainer. This is used in order to do algorithm specific operations
      around this method in the main train method which is called by the runner. (e.g. this is used when it comes to
      multiprocessing)
  
      :param n_epochs: Number of epochs to train.
      """
  
      n_epochs = (
          self.algorithm_config.n_epochs
          if n_epochs is None
          else n_epochs
      )
  
      # init minimum best model selection for early stopping
      if self.model_selection is None:
          self.model_selection = BestModelSelection(
              dump_file=None, model=None
          )
  
      # preserve original training coef setting
      value_loss_coef = self.algorithm_config.value_loss_coef
      policy_loss_coef = self.algorithm_config.policy_loss_coef
      entropy_coef = self.algorithm_config.entropy_coef
  
      # run training epochs
      if n_epochs <= 0:
          n_epochs = sys.maxsize
  
      for epoch in range(n_epochs):
          start = time.time()
          print("Update epoch - {}".format(epoch))
  
          # check for critic burn in and reset coefficient to only update the critic
          if epoch < self.algorithm_config.critic_burn_in_epochs:
              self.algorithm_config.value_loss_coef = 1.0
              self.algorithm_config.policy_loss_coef = 0.0
              self.algorithm_config.entropy_coef = 0.0
          else:
              self.algorithm_config.value_loss_coef = value_loss_coef
              self.algorithm_config.policy_loss_coef = policy_loss_coef
              self.algorithm_config.entropy_coef = entropy_coef
  
          # compute evaluation reward
          reward = -np.inf
          if self.evaluator:
              self.evaluate()
          # take training reward and notify best model selection manually
          else:
              if epoch > 0:
                  prev_reward = reward
                  try:
                      reward = self.rollout_generator.get_stats_value(
                          BaseEnvEvents.reward,
                          LogStatsLevel.EPOCH,
                          name="mean",
                      )
                  except:
                      reward = prev_reward
  
              self.model_selection.update(reward)
  
          # early stopping
          if (
              self.algorithm_config.patience
              and self.model_selection.last_improvement
              > self.algorithm_config.patience
          ):
              BColors.print_colored(
                  "-> no improvement since {} epochs: EARLY STOPPING!".format(
                      self.algorithm_config.patience
                  ),
                  color=BColors.WARNING,
              )
              increment_log_step()
              break
  
          # policy update
          for _ in tqdm(range(self.algorithm_config.epoch_length)):
              update_start = time.time()
              self._update()
              self.ac_events.time_update(time.time() - update_start)
  
          epoch_time = time.time() - start
          self.ac_events.time_epoch(epoch_time)
  
          # increase step counter (which in turn triggers the log statistics writing)
          increment_log_step()
  
          print("Time required for epoch: {:.2f}s".format(epoch_time))
  
imports: import sys
  import time
  from abc import ABC, abstractmethod
  from typing import List, Union, Dict, Optional
  import numpy
  import torch
  import torch.nn
  from maze.core.agent.torch_actor_critic import TorchActorCritic
  from maze.core.annotations import override
  from maze.core.env.base_env_events import BaseEnvEvents
  from maze.core.env.structured_env import ActorID
  from maze.core.log_stats.log_stats import increment_log_step, LogStatsLevel
  from maze.core.rollout.rollout_generator import RolloutGenerator
  from maze.core.trajectory_recording.records.structured_spaces_record import StructuredSpacesRecord
  from maze.train.parallelization.distributed_actors.distributed_actors import DistributedActors
  from maze.train.trainers.a2c.a2c_algorithm_config import A2CAlgorithmConfig
  from maze.train.trainers.common.actor_critic.actor_critic_events import ActorCriticEvents
  from maze.train.trainers.common.evaluators.rollout_evaluator import RolloutEvaluator
  from maze.train.trainers.common.model_selection.best_model_selection import BestModelSelection
  from maze.train.trainers.common.trainer import Trainer
  from maze.train.trainers.impala.impala_algorithm_config import ImpalaAlgorithmConfig
  from maze.train.trainers.ppo.ppo_algorithm_config import PPOAlgorithmConfig
  from maze.train.utils.train_utils import compute_gradient_norm
  from maze.utils.bcolors import BColors
  from tqdm import tqdm
  from typing.io import BinaryIO
label_desc: Use image node_id 2 for calling the ActorCritic obj's underlying member method code with example usage: obj.train(n_epochs) without return types