class_docstr: The :class:`~poutyne.ModelBundle` class provides a straightforward experimentation tool for efficient and entirely
  customizable finetuning of the whole neural network training procedure with PyTorch. The
  :class:`~poutyne.ModelBundle` object takes care of the training and testing processes while also managing to keep
  traces of all pertinent information via the automatic logging option.
  
  Use ``ModelBundle.from_*`` methods to instanciate a :class:`~poutyne.ModelBundle`.
class_docstr_tok: ["The",":","class",":","`","~poutyne.ModelBundle","`","class","provides","a","straightforward","experimentation","tool","for","efficient","and","entirely","customizable","finetuning","of","the","whole","neural","network","training","procedure","with","PyTorch",".","The",":","class",":","`","~poutyne.ModelBundle","`","object","takes","care","of","the","training","and","testing","processes","while","also","managing","to","keep","traces","of","all","pertinent","information","via","the","automatic","logging","option",".","Use","``","ModelBundle.from_","*","``","methods","to","instanciate","a",":","class",":","`","~poutyne.ModelBundle","`","."]
code: def _train(
      self,
      training_func,
      *args,
      callbacks: Union[List, None] = None,
      lr_schedulers: Union[List, None] = None,
      keep_only_last_best: bool = False,
      save_every_epoch: bool = False,
      disable_tensorboard: bool = False,
      seed: int = 42,
      **kwargs,
  ) -> List[Dict]:
      set_seeds(seed)
  
      lr_schedulers = [] if lr_schedulers is None else lr_schedulers
  
      expt_callbacks = []
  
      tensorboard_writer = None
      initial_epoch = 1
      if self.logging:
          if not os.path.exists(self.directory):
              os.makedirs(self.directory)
  
          # Restarting optimization if needed.
          initial_epoch = self._load_epoch_state(lr_schedulers)
  
          expt_callbacks += [
              AtomicCSVLogger(
                  self.log_filename,
                  separator="\t",
                  append=initial_epoch != 1,
              )
          ]
  
          if self.monitoring:
              expt_callbacks += self._init_model_restoring_callbacks(
                  initial_epoch, keep_only_last_best, save_every_epoch
              )
  
          if save_every_epoch:
              expt_callbacks += [
                  ModelCheckpoint(
                      self.best_checkpoint_filename,
                      save_best_only=False,
                      restore_best=False,
                      verbose=False,
                  )
              ]
  
          expt_callbacks += [
              ModelCheckpoint(
                  self.model_checkpoint_filename, verbose=False
              )
          ]
          expt_callbacks += [
              OptimizerCheckpoint(
                  self.optimizer_checkpoint_filename, verbose=False
              )
          ]
          expt_callbacks += [
              RandomStatesCheckpoint(
                  self.random_state_checkpoint_filename, verbose=False
              )
          ]
  
          # We save the last epoch number after the end of the epoch so that the
          # _load_epoch_state() knows which epoch to restart the optimization.
          expt_callbacks += [
              PeriodicSaveLambda(
                  lambda fd, epoch, logs: print(epoch, file=fd),
                  self.epoch_filename,
                  open_mode="w",
              )
          ]
  
          (
              tensorboard_writer,
              cb_list,
          ) = self._init_tensorboard_callbacks(disable_tensorboard)
          expt_callbacks += cb_list
      else:
          if self.monitoring:
              expt_callbacks += [
                  BestModelRestore(
                      monitor=self.monitor_metric,
                      mode=self.monitor_mode,
                      verbose=True,
                  )
              ]
  
      # This method returns callbacks that checkpoints the LR scheduler if logging is enabled.
      # Otherwise, it just returns the list of LR schedulers with a BestModelRestore callback.
      expt_callbacks += self._init_lr_scheduler_callbacks(lr_schedulers)
  
      if callbacks is not None:
          expt_callbacks += callbacks
  
      try:
          return training_func(
              *args,
              initial_epoch=initial_epoch,
              callbacks=expt_callbacks,
              **kwargs,
          )
      finally:
          if self.logging:
              self._save_history()
  
          if tensorboard_writer is not None:
              tensorboard_writer.close()
  
imports: import os
  import warnings
  from typing import Any, Callable, Dict, List, Tuple, Union
  import torch
  from poutyne.framework.callbacks import AtomicCSVLogger, BestModelRestore, LRSchedulerCheckpoint, ModelCheckpoint, OptimizerCheckpoint, PeriodicSaveLambda, RandomStatesCheckpoint, TensorBoardLogger
  from poutyne.framework.model import Model
  from poutyne.plotting import plot_history
  from poutyne.utils import load_random_states, set_seeds
label_desc: Use image node_id 22 for calling the ModelBundle obj's underlying member method code with example usage: obj._train(training_func) and returns: training_func