class_docstr: Joint training on the entire stream.
  
  JointTraining performs joint training (also called offline training) on
  the entire stream of data. This means that it is not a continual
  learning strategy but it can be used as an "offline" upper bound for
  them.
  
  .. warnings also::
      Currently :py:class:`JointTraining` adapts its own dataset.
      Please check that the plugins you are using do not implement
      :py:meth:`adapt_trainin_dataset`. Otherwise, they are incompatible
      with :py:class:`JointTraining`.
class_docstr_tok: ["Joint","training","on","the","entire","stream",".","JointTraining","performs","joint","training","(","also","called","offline","training",")","on","the","entire","stream","of","data",".","This","means","that","it","is","not","a","continual","learning","strategy","but","it","can","be","used","as","an","``","offline","''","upper","bound","for","them",".","..","warnings","also",":",":","Currently",":","py",":","class",":","`","JointTraining","`","adapts","its","own","dataset",".","Please","check","that","the","plugins","you","are","using","do","not","implement",":","py",":","meth",":","`","adapt_trainin_dataset","`",".","Otherwise",",","they","are","incompatible","with",":","py",":","class",":","`","JointTraining","`","."]
docstr: Training loop.
  
  JointTraining concatenates all the experiences together and
  trains on all of them at the same time (a.k.a. offline training).
  
  :param experiences: single Experience or sequence.
  :param eval_streams: list of streams for evaluation.
      If None: use training experiences for evaluation.
      Use [] if you do not want to evaluate during training.
  
  :return: dictionary containing last recorded value for
      each metric name.
docstr_tok: ["Training","loop",".","JointTraining","concatenates","all","the","experiences","together","and","trains","on","all","of","them","at","the","same","time","(","a.k.a",".","offline","training",")",".",":","param","experiences",":","single","Experience","or","sequence",".",":","param","eval_streams",":","list","of","streams","for","evaluation",".","If","None",":","use","training","experiences","for","evaluation",".","Use","[","]","if","you","do","not","want","to","evaluate","during","training",".",":","return",":","dictionary","containing","last","recorded","value","for","each","metric","name","."]
code: def train(
      self,
      experiences: Union[
          TDatasetExperience, Iterable[TDatasetExperience]
      ],
      eval_streams: Optional[
          Sequence[
              Union[TDatasetExperience, Iterable[TDatasetExperience]]
          ]
      ] = None,
      **kwargs,
  ):
      """Training loop.
  
      JointTraining concatenates all the experiences together and
      trains on all of them at the same time (a.k.a. offline training).
  
      :param experiences: single Experience or sequence.
      :param eval_streams: list of streams for evaluation.
          If None: use training experiences for evaluation.
          Use [] if you do not want to evaluate during training.
  
      :return: dictionary containing last recorded value for
          each metric name.
      """
      self.is_training = True
      self.model.train()
      self.model.to(self.device)
  
      if self._is_fitted:
          raise AlreadyTrainedError(
              "JointTraining can be trained only once. "
              "Please call the train method once on the entire stream."
          )
  
      # Normalize training and eval data.
      experiences_list: Iterable[
          TDatasetExperience
      ] = _experiences_parameter_as_iterable(experiences)
  
      if eval_streams is None:
          eval_streams = [experiences_list]
  
      self._eval_streams = _group_experiences_by_stream(eval_streams)
  
      self._experiences = list(experiences_list)
      self._before_training(**kwargs)
      for self.experience in self._experiences:
          self._before_training_exp(**kwargs)
          self._train_exp(self.experience, eval_streams, **kwargs)
          self._after_training_exp(**kwargs)
          # Joint training only needs a single step because
          # it concatenates all the data at once.
          break
      self._after_training(**kwargs)
  
      res = self.evaluator.get_last_metrics()
      self._is_fitted = True
      return res
  
file_path: avalanche/avalanche/training/supervised/joint_training.py
imports: from typing import Callable, Iterable, List, Optional, Sequence, TypeVar, Union
  import torch
  from torch.nn import Module
  from torch.optim import Optimizer
  from avalanche.benchmarks import DatasetExperience
  from avalanche.benchmarks.utils.utils import concat_datasets
  from avalanche.core import BasePlugin
  from avalanche.training.plugins.evaluation import EvaluationPlugin, default_evaluator
  from avalanche.training.templates import SupervisedTemplate
  from avalanche.models import DynamicModule
  from avalanche.training.templates.base import _experiences_parameter_as_iterable, _group_experiences_by_stream
label_desc: Use image node_id 2 for calling the JointTraining obj's underlying member method code with example usage: obj.train(experiences, eval_streams) and returns: res