class_docstr: Base class for training runner implementations.
docstr: Runs training.
  While this method is designed to be overriden by individual subclasses, it provides some functionality
  that is useful in general:
  
  - Building the env factory for env + wrappers
  - Estimating normalization statistics from the env
  - If successfully estimated, wrapping the env factory so that envs are already built with the statistics
  - Building the model composer from model config and env spaces config
  - Serializing the env spaces configuration (so that the model composer can be re-loaded for future rollout)
  - Initializing logging setup
  
  :param n_epochs: Number of epochs to train.
  :param train_kwargs: Additional arguments for trainer.train().
docstr_tok: ["Runs","training",".","While","this","method","is","designed","to","be","overriden","by","individual","subclasses",",","it","provides","some","functionality","that","is","useful","in","general",":","-","Building","the","env","factory","for","env","+","wrappers","-","Estimating","normalization","statistics","from","the","env","-","If","successfully","estimated",",","wrapping","the","env","factory","so","that","envs","are","already","built","with","the","statistics","-","Building","the","model","composer","from","model","config","and","env","spaces","config","-","Serializing","the","env","spaces","configuration","(","so","that","the","model","composer","can","be","re-loaded","for","future","rollout",")","-","Initializing","logging","setup",":","param","n_epochs",":","Number","of","epochs","to","train",".",":","param","train_kwargs",":","Additional","arguments","for","trainer.train","(",")","."]
code: def run(self, n_epochs: Optional[int] = None, **train_kwargs) -> None:
      """
      Runs training.
      While this method is designed to be overriden by individual subclasses, it provides some functionality
      that is useful in general:
  
      - Building the env factory for env + wrappers
      - Estimating normalization statistics from the env
      - If successfully estimated, wrapping the env factory so that envs are already built with the statistics
      - Building the model composer from model config and env spaces config
      - Serializing the env spaces configuration (so that the model composer can be re-loaded for future rollout)
      - Initializing logging setup
  
      :param n_epochs: Number of epochs to train.
      :param train_kwargs: Additional arguments for trainer.train().
      """
  
      self._trainer.train(
          n_epochs=self._cfg.algorithm.n_epochs
          if n_epochs is None
          else n_epochs,
          **train_kwargs,
      )
  
imports: import logging
  import os
  import dataclasses
  from typing import Optional, Callable, Union
  import omegaconf
  from omegaconf import DictConfig
  from maze.core.env.structured_env import StructuredEnv
  from maze.core.env.structured_env_spaces_mixin import StructuredEnvSpacesMixin
  from maze.core.utils.config_utils import EnvFactory, SwitchWorkingDirectoryToInput
  from maze.core.utils.factory import Factory
  from maze.core.wrappers.observation_normalization.normalization_strategies.base import StructuredStatisticsType
  from maze.core.utils.seeding import set_seeds_globally, MazeSeeding
  from maze.core.wrappers.observation_normalization.observation_normalization_utils import obtain_normalization_statistics, make_normalized_env_factory
  from maze.core.wrappers.observation_normalization.observation_normalization_wrapper import ObservationNormalizationWrapper
  from maze.core.wrappers.wrapper_factory import WrapperFactory
  from maze.perception.models.model_composer import BaseModelComposer
  from maze.perception.models.space_config import SpacesConfig
  from maze.runner import Runner
  from maze.train.trainers.common.model_selection.best_model_selection import BestModelSelection
  from maze.train.trainers.common.trainer import Trainer
  from maze.utils.bcolors import BColors
  from maze.utils.log_stats_utils import setup_logging
label_desc: Use image node_id 2 for calling the TrainingRunner obj's underlying member method code with example usage: obj.run(n_epochs) without return types