class_docstr: The Model class encapsulates a PyTorch network, a PyTorch optimizer, a loss function and
  metric functions. It allows the user to train a neural network without hand-coding the
  epoch/step logic.
  
  Args:
      network (torch.nn.Module): A PyTorch network.
      optimizer (Union[torch.optim.Optimizer, str, dict]): If torch.optim.Optimier, an initialized PyTorch.
          If str, should be the name of the optimizer in Pytorch (i.e. 'Adam' for torch.optim.Adam).
          If dict, should contain a key ``'optim'`` with the value be the name of the optimizer; other
          entries are passed to the optimizer as keyword arguments.
          (Default value = None)
      loss_function(Union[Callable, str]) It can be any PyTorch loss layer or custom loss function. It
          can also be a string with the same name as a PyTorch loss function (either the functional or
          object name). The loss function must have the signature ``loss_function(input, target)`` where
          ``input`` is the prediction of the network and ``target`` is the ground truth.
          (Default value = None)
      batch_metrics (list): List of functions with the same signature as a loss function or objects with the same
          signature as either :class:`~poutyne.Metric` or :class:`torchmetrics.Metric <torchmetrics.Metric>`. It can
          also be a string with the same name as a PyTorch loss function (either the functional or object name).
          Some metrics, such as  'accuracy' (or just 'acc'), are also available as strings. See :ref:`metrics` and
          the `TorchMetrics documentation <https://torchmetrics.readthedocs.io/en/latest/references/modules.html>`__
          for available metrics.
  
          Batch metric are computed on computed for each batch.
          (Default value = None)
  
          .. warning:: When using this argument, the metrics are computed for each batch. This can significantly slow
              down the compuations depending on the metrics used. This mostly happens on non-decomposable metrics
              such as :class:`torchmetrics.AUROC <torchmetrics.AUROC>` where an ordering of the elements is necessary
              to compute the metric. In such case, we advise to use them as epoch metrics instead.
      epoch_metrics (list): List of functions with the same signature as a loss function or objects with the same
          signature as either :class:`~poutyne.Metric` or :class:`torchmetrics.Metric <torchmetrics.Metric>`. It can
          also be a string with the same name as a PyTorch loss function (either the functional or object name).
          Some metrics, such as  'accuracy' (or just 'acc'), are also available as strings. See :ref:`metrics` and
          the `TorchMetrics documentation <https://torchmetrics.readthedocs.io/en/latest/references/modules.html>`__
          for available metrics.
  
          Epoch metrics are computed only at the end of the epoch.
          (Default value = None)
      device (Union[torch.torch.device, List[torch.torch.device]]): The device to which the network is
          sent or the list of device to which the network is sent. See :func:`~Model.to()` for details.
  
  Note:
      The name of each batch and epoch metric can be change by passing a tuple ``(name, metric)`` instead
      of simply the metric function or object, where ``name`` is the alternative name of the metric.
      Batch and epoch metrics can return multiple metrics (e.g. an epoch metric could return an F1-score
      with the associated precision and recall). See :ref:`multiple metrics at once` for more details.
  
  
  Attributes:
      network (torch.nn.Module): The associated PyTorch network.
      optimizer (torch.optim.Optimizer): The associated PyTorch optimizer.
      loss_function: The associated loss function.
      batch_metrics (list): The associated metric functions for every batch.
      epoch_metrics (list): The associated metric functions for every epoch.
  
  Examples:
      Using Numpy arrays (or tensors) dataset::
  
          from poutyne import Model
          import torch
          import numpy as np
          import torchmetrics
  
          num_features = 20
          num_classes = 5
  
          # Our training dataset with 800 samples.
          num_train_samples = 800
          train_x = np.random.randn(num_train_samples, num_features).astype('float32')
          train_y = np.random.randint(num_classes, size=num_train_samples).astype('int64')
  
          # Our validation dataset with 200 samples.
          num_valid_samples = 200
          valid_x = np.random.randn(num_valid_samples, num_features).astype('float32')
          valid_y = np.random.randint(num_classes, size=num_valid_samples).astype('int64')
  
          pytorch_network = torch.nn.Linear(num_features, num_classes) # Our network
  
          # We create and optimize our model
          model = Model(pytorch_network, 'sgd', 'cross_entropy',
                        batch_metrics=['accuracy'],
                        epoch_metrics=[torchmetrics.AUROC(num_classes=num_classes, task="multiclass")])
          model.fit(train_x, train_y,
                    validation_data=(valid_x, valid_y),
                    epochs=5,
                    batch_size=32)
  
      .. code-block:: none
  
          Epoch: 1/5 Train steps: 25 Val steps: 7 0.51s loss: 1.757784 acc: 20.750000 auroc: 0.494891
          val_loss: 1.756639 val_acc: 18.500000 val_auroc: 0.499404
          Epoch: 2/5 Train steps: 25 Val steps: 7 0.03s loss: 1.749623 acc: 20.375000 auroc: 0.496878
          val_loss: 1.748795 val_acc: 19.000000 val_auroc: 0.499723
          Epoch: 3/5 Train steps: 25 Val steps: 7 0.03s loss: 1.742070 acc: 20.250000 auroc: 0.499461
          val_loss: 1.741379 val_acc: 19.000000 val_auroc: 0.498577
          ...
  
      Using PyTorch DataLoader::
  
         import torch
         from torch.utils.data import DataLoader, TensorDataset
         from poutyne import Model
         import torchmetrics
  
         num_features = 20
         num_classes = 5
  
         # Our training dataset with 800 samples.
         num_train_samples = 800
         train_x = torch.rand(num_train_samples, num_features)
         train_y = torch.randint(num_classes, (num_train_samples,), dtype=torch.long)
         train_dataset = TensorDataset(train_x, train_y)
         train_generator = DataLoader(train_dataset, batch_size=32)
  
         # Our validation dataset with 200 samples.
         num_valid_samples = 200
         valid_x = torch.rand(num_valid_samples, num_features)
         valid_y = torch.randint(num_classes, (num_valid_samples,), dtype=torch.long)
         valid_dataset = TensorDataset(valid_x, valid_y)
         valid_generator = DataLoader(valid_dataset, batch_size=32)
  
         pytorch_network = torch.nn.Linear(num_features, num_classes)
  
         model = Model(pytorch_network, 'sgd', 'cross_entropy',
                       batch_metrics=['accuracy'],
                       epoch_metrics=[torchmetrics.AUROC(num_classes=num_classes, task="multiclass")])
         model.fit_generator(train_generator,
                             valid_generator,
                             epochs=5)
  
      .. code-block:: none
  
          Epoch: 1/5 Train steps: 25 Val steps: 7 0.07s loss: 1.614473 acc: 20.500000 auroc: 0.516850
          val_loss: 1.617141 val_acc: 21.500000 val_auroc: 0.522068
          Epoch: 2/5 Train steps: 25 Val steps: 7 0.03s loss: 1.614454 acc: 20.125000 auroc: 0.517618
          val_loss: 1.615585 val_acc: 22.000000 val_auroc: 0.521051
          Epoch: 3/5 Train steps: 25 Val steps: 7 0.03s loss: 1.613709 acc: 20.125000 auroc: 0.518307
          val_loss: 1.614440 val_acc: 22.000000 val_auroc: 0.520762
          ...
class_docstr_tok: ["The","Model","class","encapsulates","a","PyTorch","network",",","a","PyTorch","optimizer",",","a","loss","function","and","metric","functions",".","It","allows","the","user","to","train","a","neural","network","without","hand-coding","the","epoch\/step","logic",".","Args",":","network","(","torch.nn.Module",")",":","A","PyTorch","network",".","optimizer","(","Union","[","torch.optim.Optimizer",",","str",",","dict","]",")",":","If","torch.optim.Optimier",",","an","initialized","PyTorch",".","If","str",",","should","be","the","name","of","the","optimizer","in","Pytorch","(","i.e",".","'Adam","'","for","torch.optim.Adam",")",".","If","dict",",","should","contain","a","key","``","'optim","'","``","with","the","value","be","the","name","of","the","optimizer",";","other","entries","are","passed","to","the","optimizer","as","keyword","arguments",".","(","Default","value","=","None",")","loss_function","(","Union","[","Callable",",","str","]",")","It","can","be","any","PyTorch","loss","layer","or","custom","loss","function",".","It","can","also","be","a","string","with","the","same","name","as","a","PyTorch","loss","function","(","either","the","functional","or","object","name",")",".","The","loss","function","must","have","the","signature","``","loss_function","(","input",",","target",")","``","where","``","input","``","is","the","prediction","of","the","network","and","``","target","``","is","the","ground","truth",".","(","Default","value","=","None",")","batch_metrics","(","list",")",":","List","of","functions","with","the","same","signature","as","a","loss","function","or","objects","with","the","same","signature","as","either",":","class",":","`","~poutyne.Metric","`","or",":","class",":","`","torchmetrics.Metric","<","torchmetrics.Metric",">","`",".","It","can","also","be","a","string","with","the","same","name","as","a","PyTorch","loss","function","(","either","the","functional","or","object","name",")",".","Some","metrics",",","such","as","'accuracy","'","(","or","just","'acc","'",")",",","are","also","available","as","strings",".","See",":","ref",":","`","metrics","`","and","the","`","TorchMetrics","documentation","<","https",":","\/\/torchmetrics.readthedocs.io\/en\/latest\/references\/modules.html",">","`","__","for","available","metrics",".","Batch","metric","are","computed","on","computed","for","each","batch",".","(","Default","value","=","None",")","..","warning",":",":","When","using","this","argument",",","the","metrics","are","computed","for","each","batch",".","This","can","significantly","slow","down","the","compuations","depending","on","the","metrics","used",".","This","mostly","happens","on","non-decomposable","metrics","such","as",":","class",":","`","torchmetrics.AUROC","<","torchmetrics.AUROC",">","`","where","an","ordering","of","the","elements","is","necessary","to","compute","the","metric",".","In","such","case",",","we","advise","to","use","them","as","epoch","metrics","instead",".","epoch_metrics","(","list",")",":","List","of","functions","with","the","same","signature","as","a","loss","function","or","objects","with","the","same","signature","as","either",":","class",":","`","~poutyne.Metric","`","or",":","class",":","`","torchmetrics.Metric","<","torchmetrics.Metric",">","`",".","It","can","also","be","a","string","with","the","same","name","as","a","PyTorch","loss","function","(","either","the","functional","or","object","name",")",".","Some","metrics",",","such","as","'accuracy","'","(","or","just","'acc","'",")",",","are","also","available","as","strings",".","See",":","ref",":","`","metrics","`","and","the","`","TorchMetrics","documentation","<","https",":","\/\/torchmetrics.readthedocs.io\/en\/latest\/references\/modules.html",">","`","__","for","available","metrics",".","Epoch","metrics","are","computed","only","at","the","end","of","the","epoch",".","(","Default","value","=","None",")","device","(","Union","[","torch.torch.device",",","List","[","torch.torch.device","]","]",")",":","The","device","to","which","the","network","is","sent","or","the","list","of","device","to","which","the","network","is","sent",".","See",":","func",":","`","~Model.to","(",")","`","for","details",".","Note",":","The","name","of","each","batch","and","epoch","metric","can","be","change","by","passing","a","tuple","``","(","name",",","metric",")","``","instead","of","simply","the","metric","function","or","object",",","where","``","name","``","is","the","alternative","name","of","the","metric",".","Batch","and","epoch","metrics","can","return","multiple","metrics","(","e.g",".","an","epoch","metric","could","return","an","F1-score","with","the","associated","precision","and","recall",")",".","See",":","ref",":","`","multiple","metrics","at","once","`","for","more","details",".","Attributes",":","network","(","torch.nn.Module",")",":","The","associated","PyTorch","network",".","optimizer","(","torch.optim.Optimizer",")",":","The","associated","PyTorch","optimizer",".","loss_function",":","The","associated","loss","function",".","batch_metrics","(","list",")",":","The","associated","metric","functions","for","every","batch",".","epoch_metrics","(","list",")",":","The","associated","metric","functions","for","every","epoch",".","Examples",":","Using","Numpy","arrays","(","or","tensors",")","dataset",":",":","from","poutyne","import","Model","import","torch","import","numpy","as","np","import","torchmetrics","num_features","=","20","num_classes","=","5","#","Our","training","dataset","with","800","samples",".","num_train_samples","=","800","train_x","=","np.random.randn","(","num_train_samples",",","num_features",")",".astype","(","'float32","'",")","train_y","=","np.random.randint","(","num_classes",",","size=num_train_samples",")",".astype","(","'int64","'",")","#","Our","validation","dataset","with","200","samples",".","num_valid_samples","=","200","valid_x","=","np.random.randn","(","num_valid_samples",",","num_features",")",".astype","(","'float32","'",")","valid_y","=","np.random.randint","(","num_classes",",","size=num_valid_samples",")",".astype","(","'int64","'",")","pytorch_network","=","torch.nn.Linear","(","num_features",",","num_classes",")","#","Our","network","#","We","create","and","optimize","our","model","model","=","Model","(","pytorch_network",",","'sgd","'",",","'cross_entropy","'",",","batch_metrics=","[","'accuracy","'","]",",","epoch_metrics=","[","torchmetrics.AUROC","(","num_classes=num_classes",",","task=","''","multiclass","''",")","]",")","model.fit","(","train_x",",","train_y",",","validation_data=","(","valid_x",",","valid_y",")",",","epochs=5",",","batch_size=32",")","..","code-block",":",":","none","Epoch",":","1\/5","Train","steps",":","25","Val","steps",":","7","0.51s","loss",":","1.757784","acc",":","20.750000","auroc",":","0.494891","val_loss",":","1.756639","val_acc",":","18.500000","val_auroc",":","0.499404","Epoch",":","2\/5","Train","steps",":","25","Val","steps",":","7","0.03s","loss",":","1.749623","acc",":","20.375000","auroc",":","0.496878","val_loss",":","1.748795","val_acc",":","19.000000","val_auroc",":","0.499723","Epoch",":","3\/5","Train","steps",":","25","Val","steps",":","7","0.03s","loss",":","1.742070","acc",":","20.250000","auroc",":","0.499461","val_loss",":","1.741379","val_acc",":","19.000000","val_auroc",":","0.498577","...","Using","PyTorch","DataLoader",":",":","import","torch","from","torch.utils.data","import","DataLoader",",","TensorDataset","from","poutyne","import","Model","import","torchmetrics","num_features","=","20","num_classes","=","5","#","Our","training","dataset","with","800","samples",".","num_train_samples","=","800","train_x","=","torch.rand","(","num_train_samples",",","num_features",")","train_y","=","torch.randint","(","num_classes",",","(","num_train_samples",",",")",",","dtype=torch.long",")","train_dataset","=","TensorDataset","(","train_x",",","train_y",")","train_generator","=","DataLoader","(","train_dataset",",","batch_size=32",")","#","Our","validation","dataset","with","200","samples",".","num_valid_samples","=","200","valid_x","=","torch.rand","(","num_valid_samples",",","num_features",")","valid_y","=","torch.randint","(","num_classes",",","(","num_valid_samples",",",")",",","dtype=torch.long",")","valid_dataset","=","TensorDataset","(","valid_x",",","valid_y",")","valid_generator","=","DataLoader","(","valid_dataset",",","batch_size=32",")","pytorch_network","=","torch.nn.Linear","(","num_features",",","num_classes",")","model","=","Model","(","pytorch_network",",","'sgd","'",",","'cross_entropy","'",",","batch_metrics=","[","'accuracy","'","]",",","epoch_metrics=","[","torchmetrics.AUROC","(","num_classes=num_classes",",","task=","''","multiclass","''",")","]",")","model.fit_generator","(","train_generator",",","valid_generator",",","epochs=5",")","..","code-block",":",":","none","Epoch",":","1\/5","Train","steps",":","25","Val","steps",":","7","0.07s","loss",":","1.614473","acc",":","20.500000","auroc",":","0.516850","val_loss",":","1.617141","val_acc",":","21.500000","val_auroc",":","0.522068","Epoch",":","2\/5","Train","steps",":","25","Val","steps",":","7","0.03s","loss",":","1.614454","acc",":","20.125000","auroc",":","0.517618","val_loss",":","1.615585","val_acc",":","22.000000","val_auroc",":","0.521051","Epoch",":","3\/5","Train","steps",":","25","Val","steps",":","7","0.03s","loss",":","1.613709","acc",":","20.125000","auroc",":","0.518307","val_loss",":","1.614440","val_acc",":","22.000000","val_auroc",":","0.520762","..."]
docstr: Trains the network on a dataset. This method creates dataloaders and calls the
  :func:`~Model.fit_generator()` method.
  
  Args:
      train_dataset (~torch.utils.data.Dataset): Training dataset.
      valid_dataset (~torch.utils.data.Dataset): Validation dataset.
      batch_size (int): Number of samples given to the network at one time.
          (Default value = 32)
      epochs (int): Number of times the entire training dataset is seen.
          (Default value = 1000)
      steps_per_epoch (int, optional): Number of batch used during one epoch. Obviously, using
          this argument may cause one epoch not to see the entire training dataset or see it
          multiple times.
          (Defaults the number of steps needed to see the entire training dataset)
      validation_steps (int, optional): Same as for ``steps_per_epoch`` but for the validation
          dataset.
          (Defaults to the number of steps needed to see the entire validation dataset)
      batches_per_step (int): Number of batches on which to compute the running loss before
          backpropagating it through the network. Note that the total loss used for backpropagation is
          the mean of the `batches_per_step` batch losses.
          (Default value = 1)
      initial_epoch (int, optional): Epoch at which to start training
          (useful for resuming a previous training run).
          (Default value = 1)
      verbose (bool): Whether to display the progress of the training.
          (Default value = True)
      progress_options (dict, optional): Keyword arguments to pass to the default progression callback used
          in Poutyne (See :class:`~poutyne.ProgressionCallback` for the available arguments).
          (Default value = None)
      callbacks (List[~poutyne.Callback]): List of callbacks that will be called
          during training.
          (Default value = None)
      dataloader_kwargs (dict, optional): Keyword arguments to pass to the PyTorch dataloaders created
          internally. By default, ``shuffle=True`` is passed for the training dataloader but this can be
          overridden by using this argument.
      num_workers (int, optional): how many subprocesses to use for data loading.
          ``0`` means that the data will be loaded in the main process.
          (Default value = 0)
      collate_fn (Callable, optional): merges a list of samples to form a mini-batch of Tensor(s).
          Used when using batched loading from a map-style dataset.
  
  Returns:
      List of dict containing the history of each epoch.
  
  See :class:`~torch.utils.data.DataLoader` for details on ``batch_size``, ``num_workers`` and ``collate_fn``.
  
  Example:
      .. code-block:: python
  
          model = Model(pytorch_network, optimizer, loss_function)
          history = model.fit(train_dataset,
                              valid_dataset,
                              epochs=num_epochs,
                              batch_size=batch_size,
                              verbose=False)
          print(*history, sep="\n")
  
      .. code-block:: python
  
          {'epoch': 1, 'loss': 1.7198852968215943, 'time': 0.019999928001197986, 'acc': 19.375, 'val_loss': 1.6674459838867188, 'val_acc': 22.0}
          {'epoch': 2, 'loss': 1.7054892110824584, 'time': 0.015421080999658443, 'acc': 19.75, 'val_loss': 1.660806336402893, 'val_acc': 22.0}
          {'epoch': 3, 'loss': 1.6923445892333984, 'time': 0.01363091799794347, 'acc': 19.625, 'val_loss': 1.6550078630447387, 'val_acc': 22.5}
          ...
docstr_tok: ["Trains","the","network","on","a","dataset",".","This","method","creates","dataloaders","and","calls","the",":","func",":","`","~Model.fit_generator","(",")","`","method",".","Args",":","train_dataset","(","~torch.utils.data.Dataset",")",":","Training","dataset",".","valid_dataset","(","~torch.utils.data.Dataset",")",":","Validation","dataset",".","batch_size","(","int",")",":","Number","of","samples","given","to","the","network","at","one","time",".","(","Default","value","=","32",")","epochs","(","int",")",":","Number","of","times","the","entire","training","dataset","is","seen",".","(","Default","value","=","1000",")","steps_per_epoch","(","int",",","optional",")",":","Number","of","batch","used","during","one","epoch",".","Obviously",",","using","this","argument","may","cause","one","epoch","not","to","see","the","entire","training","dataset","or","see","it","multiple","times",".","(","Defaults","the","number","of","steps","needed","to","see","the","entire","training","dataset",")","validation_steps","(","int",",","optional",")",":","Same","as","for","``","steps_per_epoch","``","but","for","the","validation","dataset",".","(","Defaults","to","the","number","of","steps","needed","to","see","the","entire","validation","dataset",")","batches_per_step","(","int",")",":","Number","of","batches","on","which","to","compute","the","running","loss","before","backpropagating","it","through","the","network",".","Note","that","the","total","loss","used","for","backpropagation","is","the","mean","of","the","`","batches_per_step","`","batch","losses",".","(","Default","value","=","1",")","initial_epoch","(","int",",","optional",")",":","Epoch","at","which","to","start","training","(","useful","for","resuming","a","previous","training","run",")",".","(","Default","value","=","1",")","verbose","(","bool",")",":","Whether","to","display","the","progress","of","the","training",".","(","Default","value","=","True",")","progress_options","(","dict",",","optional",")",":","Keyword","arguments","to","pass","to","the","default","progression","callback","used","in","Poutyne","(","See",":","class",":","`","~poutyne.ProgressionCallback","`","for","the","available","arguments",")",".","(","Default","value","=","None",")","callbacks","(","List","[","~poutyne.Callback","]",")",":","List","of","callbacks","that","will","be","called","during","training",".","(","Default","value","=","None",")","dataloader_kwargs","(","dict",",","optional",")",":","Keyword","arguments","to","pass","to","the","PyTorch","dataloaders","created","internally",".","By","default",",","``","shuffle=True","``","is","passed","for","the","training","dataloader","but","this","can","be","overridden","by","using","this","argument",".","num_workers","(","int",",","optional",")",":","how","many","subprocesses","to","use","for","data","loading",".","``","0","``","means","that","the","data","will","be","loaded","in","the","main","process",".","(","Default","value","=","0",")","collate_fn","(","Callable",",","optional",")",":","merges","a","list","of","samples","to","form","a","mini-batch","of","Tensor","(","s",")",".","Used","when","using","batched","loading","from","a","map-style","dataset",".","Returns",":","List","of","dict","containing","the","history","of","each","epoch",".","See",":","class",":","`","~torch.utils.data.DataLoader","`","for","details","on","``","batch_size","``",",","``","num_workers","``","and","``","collate_fn","``",".","Example",":","..","code-block",":",":","python","model","=","Model","(","pytorch_network",",","optimizer",",","loss_function",")","history","=","model.fit","(","train_dataset",",","valid_dataset",",","epochs=num_epochs",",","batch_size=batch_size",",","verbose=False",")","print","(","*","history",",","sep=","''","\\n","''",")","..","code-block",":",":","python","{","'epoch","'",":","1",",","'loss","'",":","1.7198852968215943",",","'time","'",":","0.019999928001197986",",","'acc","'",":","19.375",",","'val_loss","'",":","1.6674459838867188",",","'val_acc","'",":","22.0","}","{","'epoch","'",":","2",",","'loss","'",":","1.7054892110824584",",","'time","'",":","0.015421080999658443",",","'acc","'",":","19.75",",","'val_loss","'",":","1.660806336402893",",","'val_acc","'",":","22.0","}","{","'epoch","'",":","3",",","'loss","'",":","1.6923445892333984",",","'time","'",":","0.01363091799794347",",","'acc","'",":","19.625",",","'val_loss","'",":","1.6550078630447387",",","'val_acc","'",":","22.5","}","..."]
code: def fit_dataset(
      self,
      train_dataset,
      valid_dataset=None,
      *,
      batch_size=32,
      epochs=1000,
      steps_per_epoch=None,
      validation_steps=None,
      batches_per_step=1,
      initial_epoch=1,
      verbose=True,
      progress_options=None,
      callbacks=None,
      num_workers=0,
      collate_fn=None,
      dataloader_kwargs=None,
  ):
      # pylint: disable=line-too-long,too-many-locals
      """
      Trains the network on a dataset. This method creates dataloaders and calls the
      :func:`~Model.fit_generator()` method.
  
      Args:
          train_dataset (~torch.utils.data.Dataset): Training dataset.
          valid_dataset (~torch.utils.data.Dataset): Validation dataset.
          batch_size (int): Number of samples given to the network at one time.
              (Default value = 32)
          epochs (int): Number of times the entire training dataset is seen.
              (Default value = 1000)
          steps_per_epoch (int, optional): Number of batch used during one epoch. Obviously, using
              this argument may cause one epoch not to see the entire training dataset or see it
              multiple times.
              (Defaults the number of steps needed to see the entire training dataset)
          validation_steps (int, optional): Same as for ``steps_per_epoch`` but for the validation
              dataset.
              (Defaults to the number of steps needed to see the entire validation dataset)
          batches_per_step (int): Number of batches on which to compute the running loss before
              backpropagating it through the network. Note that the total loss used for backpropagation is
              the mean of the `batches_per_step` batch losses.
              (Default value = 1)
          initial_epoch (int, optional): Epoch at which to start training
              (useful for resuming a previous training run).
              (Default value = 1)
          verbose (bool): Whether to display the progress of the training.
              (Default value = True)
          progress_options (dict, optional): Keyword arguments to pass to the default progression callback used
              in Poutyne (See :class:`~poutyne.ProgressionCallback` for the available arguments).
              (Default value = None)
          callbacks (List[~poutyne.Callback]): List of callbacks that will be called
              during training.
              (Default value = None)
          dataloader_kwargs (dict, optional): Keyword arguments to pass to the PyTorch dataloaders created
              internally. By default, ``shuffle=True`` is passed for the training dataloader but this can be
              overridden by using this argument.
          num_workers (int, optional): how many subprocesses to use for data loading.
              ``0`` means that the data will be loaded in the main process.
              (Default value = 0)
          collate_fn (Callable, optional): merges a list of samples to form a mini-batch of Tensor(s).
              Used when using batched loading from a map-style dataset.
  
      Returns:
          List of dict containing the history of each epoch.
  
      See :class:`~torch.utils.data.DataLoader` for details on ``batch_size``, ``num_workers`` and ``collate_fn``.
  
      Example:
          .. code-block:: python
  
              model = Model(pytorch_network, optimizer, loss_function)
              history = model.fit(train_dataset,
                                  valid_dataset,
                                  epochs=num_epochs,
                                  batch_size=batch_size,
                                  verbose=False)
              print(*history, sep="\\n")
  
          .. code-block:: python
  
              {'epoch': 1, 'loss': 1.7198852968215943, 'time': 0.019999928001197986, 'acc': 19.375, 'val_loss': 1.6674459838867188, 'val_acc': 22.0}
              {'epoch': 2, 'loss': 1.7054892110824584, 'time': 0.015421080999658443, 'acc': 19.75, 'val_loss': 1.660806336402893, 'val_acc': 22.0}
              {'epoch': 3, 'loss': 1.6923445892333984, 'time': 0.01363091799794347, 'acc': 19.625, 'val_loss': 1.6550078630447387, 'val_acc': 22.5}
              ...
  
      """
      if dataloader_kwargs is None:
          dataloader_kwargs = {}
      dataloader_kwargs = {
          "batch_size": batch_size,
          "num_workers": num_workers,
          "collate_fn": collate_fn,
          **dataloader_kwargs,
      }
  
      train_generator = DataLoader(
          train_dataset, **{"shuffle": True, **dataloader_kwargs}
      )
      valid_generator = None
      if valid_dataset is not None:
          valid_generator = DataLoader(
              valid_dataset, **dataloader_kwargs
          )
  
      return self.fit_generator(
          train_generator,
          valid_generator=valid_generator,
          epochs=epochs,
          steps_per_epoch=steps_per_epoch,
          validation_steps=validation_steps,
          batches_per_step=batches_per_step,
          initial_epoch=initial_epoch,
          verbose=verbose,
          progress_options=progress_options,
          callbacks=callbacks,
      )
  
imports: import contextlib
  import timeit
  from collections import defaultdict
  from typing import Any, Iterable, List, Mapping, Tuple, Union
  import numpy
  import torch
  import torch.nn
  import torch.optim
  from torch.nn.utils.rnn import PackedSequence
  from torch.utils.data import DataLoader
  from poutyne.framework.callbacks import Callback, CallbackList, ProgressionCallback
  from poutyne.framework.iterators import EpochIterator, StepIterator, _get_step_iterator
  from poutyne.framework.metrics import flatten_metric_names, get_callables_and_names, get_metric, rename_doubles
  from poutyne.framework.metrics.decomposable import convert_decomposable_metric_to_object
  from poutyne.framework.optimizers import get_optimizer
  from poutyne.utils import TensorDataset, _concat, get_batch_size, numpy_to_torch, torch_to, torch_to_numpy
label_desc: Use image node_id 7 for calling the Model obj's underlying member method code with example usage: obj.fit_dataset(train_dataset, valid_dataset) and returns: self