class_docstr: A runner class to train and evaluate a model given a task and datasets.
  
  The runner uses pytorch distributed data parallel by default. Future release
  will support other distributed frameworks.
class_docstr_tok: ["A","runner","class","to","train","and","evaluate","a","model","given","a","task","and","datasets",".","The","runner","uses","pytorch","distributed","data","parallel","by","default",".","Future","release","will","support","other","distributed","frameworks","."]
code: def train(self):
      start_time = time.time()
      best_agg_metric = 0
      best_epoch = 0
  
      self.log_config()
  
      # resume from checkpoint if specified
      if not self.evaluate_only and self.resume_ckpt_path is not None:
          self._load_checkpoint(self.resume_ckpt_path)
  
      for cur_epoch in range(self.start_epoch, self.max_epoch):
          # training phase
          if not self.evaluate_only:
              logging.info("Start training")
              # See https://github.com/salesforce/LAVIS/issues/449
              # if cur_epoch == self.start_epoch:
              #     self.task.before_training(
              #         model=self.unwrap_dist_model(self.model),
              #         dataset=self.datasets["train"],
              #     )
              train_stats = self.train_epoch(cur_epoch)
              self.log_stats(split_name="train", stats=train_stats)
  
          # evaluation phase
          if len(self.valid_splits) > 0 and (
              self.evaluate_only or cur_epoch % self.val_freq == 0
          ):
              for split_name in self.valid_splits:
                  logging.info("Evaluating on {}.".format(split_name))
  
                  val_log = self.eval_epoch(
                      split_name=split_name, cur_epoch=cur_epoch
                  )
                  if val_log is not None:
                      if is_main_process():
                          assert (
                              "agg_metrics" in val_log
                          ), "No agg_metrics found in validation log."
  
                          agg_metrics = val_log["agg_metrics"]
                          if (
                              agg_metrics > best_agg_metric
                              and split_name == "val"
                          ):
                              best_epoch, best_agg_metric = (
                                  cur_epoch,
                                  agg_metrics,
                              )
                              if not self.evaluate_only:
                                  self._save_checkpoint(
                                      cur_epoch, is_best=True
                                  )
  
                          val_log.update({"best_epoch": best_epoch})
                          self.log_stats(val_log, split_name)
  
          else:
              # if no validation split is provided, we just save the checkpoint at the end of each epoch.
              if not self.evaluate_only:
                  self._save_checkpoint(cur_epoch, is_best=False)
  
          if self.evaluate_only:
              break
  
          # save checkpoint according to save freq
          if self.save_freq > 0 and cur_epoch % self.save_freq == 0:
              self._save_checkpoint(cur_epoch, is_best=False)
  
          dist.barrier()
  
      # save last checkpoint
      if self.save_last and not self.evaluate_only:
          self._save_checkpoint(cur_epoch, is_best=False)
  
      # testing phase
      test_epoch = "best" if len(self.valid_splits) > 0 else cur_epoch
      self.evaluate(
          cur_epoch=test_epoch, skip_reload=self.evaluate_only
      )
  
      total_time = time.time() - start_time
      total_time_str = str(datetime.timedelta(seconds=int(total_time)))
      logging.info("Training time {}".format(total_time_str))
  
imports: import datetime
  import json
  import logging
  import os
  import time
  from pathlib import Path
  import torch
  import torch.distributed
  import webdataset
  from lavis.common.dist_utils import download_cached_file, get_rank, get_world_size, is_main_process, main_process
  from lavis.common.registry import registry
  from lavis.common.utils import is_url
  from lavis.datasets.data_utils import concat_datasets, reorg_datasets_by_split
  from lavis.datasets.datasets.dataloader_utils import IterLoader, MultiIterLoader, PrefetchLoader
  from torch.nn.parallel import DistributedDataParallel
  from torch.utils.data import DataLoader, DistributedSampler
  from torch.utils.data.dataset import ChainDataset
label_desc: Use image node_id 26 for calling the RunnerBase obj's underlying member method code with example usage: obj.train() without return types