docstr: Check if a training phase should be done as configured by num_consecutive_playing_steps.
  If it should, then do several training steps as configured by num_consecutive_training_steps.
  A single training iteration: Sample a batch, train on it and update target networks.
  
  :return: The total training loss during the training iterations.
docstr_tok: ["Check","if","a","training","phase","should","be","done","as","configured","by","num_consecutive_playing_steps",".","If","it","should",",","then","do","several","training","steps","as","configured","by","num_consecutive_training_steps",".","A","single","training","iteration",":","Sample","a","batch",",","train","on","it","and","update","target","networks",".",":","return",":","The","total","training","loss","during","the","training","iterations","."]
code: def train(self) -> float:
      """
      Check if a training phase should be done as configured by num_consecutive_playing_steps.
      If it should, then do several training steps as configured by num_consecutive_training_steps.
      A single training iteration: Sample a batch, train on it and update target networks.
  
      :return: The total training loss during the training iterations.
      """
      loss = 0
      if self._should_train():
          if self.ap.is_batch_rl_training:
              # when training an agent for generating a dataset in batch-rl, we don't want it to be counted as part of
              # the training epochs. we only care for training epochs in batch-rl anyway.
              self.training_epoch += 1
          for network in self.networks.values():
              network.set_is_training(True)
  
          # At the moment we only support a single batch size for all the networks
          networks_parameters = list(self.ap.network_wrappers.values())
          assert all(
              net.batch_size == networks_parameters[0].batch_size
              for net in networks_parameters
          )
  
          batch_size = networks_parameters[0].batch_size
  
          # we either go sequentially through the entire replay buffer in the batch RL mode,
          # or sample randomly for the basic RL case.
          training_schedule = (
              self.call_memory(
                  "get_shuffled_training_data_generator", batch_size
              )
              if self.ap.is_batch_rl_training
              else [
                  self.call_memory("sample", batch_size)
                  for _ in range(
                      self.ap.algorithm.num_consecutive_training_steps
                  )
              ]
          )
  
          for batch in training_schedule:
              # update counters
              self.training_iteration += 1
              if self.pre_network_filter is not None:
                  update_internal_state = (
                      self.ap.algorithm.update_pre_network_filters_state_on_train
                  )
                  batch = self.pre_network_filter.filter(
                      batch,
                      update_internal_state=update_internal_state,
                      deep_copy=False,
                  )
  
              # if the batch returned empty then there are not enough samples in the replay buffer -> skip
              # training step
              if len(batch) > 0:
                  # train
                  batch = Batch(batch)
                  (
                      total_loss,
                      losses,
                      unclipped_grads,
                  ) = self.learn_from_batch(batch)
                  loss += total_loss
  
                  self.unclipped_grads.add_sample(unclipped_grads)
  
                  # TODO: this only deals with the main network (if exists), need to do the same for other networks
                  #  for instance, for DDPG, the LR signal is currently not shown. Probably should be done through the
                  #  network directly instead of here
                  # decay learning rate
                  if (
                      "main" in self.ap.network_wrappers
                      and self.ap.network_wrappers[
                          "main"
                      ].learning_rate_decay_rate
                      != 0
                  ):
                      self.curr_learning_rate.add_sample(
                          self.networks["main"].sess.run(
                              self.networks[
                                  "main"
                              ].online_network.current_learning_rate
                          )
                      )
                  else:
                      self.curr_learning_rate.add_sample(
                          networks_parameters[0].learning_rate
                      )
  
                  if (
                      any(
                          [
                              network.has_target
                              for network in self.networks.values()
                          ]
                      )
                      and self._should_update_online_weights_to_target()
                  ):
                      for network in self.networks.values():
                          network.update_target_network(
                              self.ap.algorithm.rate_for_copying_weights_to_target
                          )
  
                      self.agent_logger.create_signal_value(
                          "Update Target Network", 1
                      )
                  else:
                      self.agent_logger.create_signal_value(
                          "Update Target Network", 0, overwrite=False
                      )
  
                  self.loss.add_sample(loss)
  
                  if self.imitation:
                      self.log_to_screen()
  
          if (
              self.ap.visualization.dump_csv
              and self.parent_level_manager.parent_graph_manager.time_metric
              == TimeTypes.Epoch
          ):
              # in BatchRL, or imitation learning, the agent never acts, so we have to get the stats out here.
              # we dump the data out every epoch
              self.update_log()
  
          for network in self.networks.values():
              network.set_is_training(False)
  
          # run additional commands after the training is done
          self.post_training_commands()
  
      return loss
  
imports: import copy
  import random
  from collections import OrderedDict
  from typing import Dict, List, Union, Tuple
  import numpy
  from six.moves import range
  from rl_coach.agents.agent_interface import AgentInterface
  from rl_coach.architectures.network_wrapper import NetworkWrapper
  from rl_coach.base_parameters import AgentParameters, Device, DeviceType, DistributedTaskParameters, Frameworks
  from rl_coach.core_types import RunPhase, PredictionType, EnvironmentEpisodes, ActionType, Batch, Episode, StateType
  from rl_coach.core_types import Transition, ActionInfo, TrainingSteps, EnvironmentSteps, EnvResponse
  from rl_coach.logger import screen, Logger, EpisodeLogger
  from rl_coach.memories.episodic.episodic_experience_replay import EpisodicExperienceReplay
  from rl_coach.saver import SaverCollection
  from rl_coach.spaces import SpacesDefinition, VectorObservationSpace, GoalsSpace, AttentionActionSpace
  from rl_coach.utils import Signal, force_list
  from rl_coach.utils import dynamic_import_and_instantiate_module_from_params
  from rl_coach.memories.backend.memory_impl import get_memory_backend
  from rl_coach.core_types import TimeTypes
  from rl_coach.off_policy_evaluators.ope_manager import OpeManager
  from rl_coach.core_types import PickledReplayBuffer, CsvDataset
label_desc: Use image node_id 25 for calling the Agent obj's underlying member method code with example usage: obj.train() and returns: loss