docstr: An inner training loop compatible with both epoch-based and iter-based training.
  
  When using epoch-based, training stops after one epoch; when using iter-based,
  training stops after #iters_per_epoch iterations.
docstr_tok: ["An","inner","training","loop","compatible","with","both","epoch-based","and","iter-based","training",".","When","using","epoch-based",",","training","stops","after","one","epoch",";","when","using","iter-based",",","training","stops","after","#","iters_per_epoch","iterations","."]
code: def _train_inner_loop(
      self,
      epoch,
      iters_per_epoch,
      model,
      data_loader,
      optimizer,
      lr_scheduler,
      scaler=None,
      start_iters=None,
      log_freq=50,
      cuda_enabled=False,
      accum_grad_iters=1,
  ):
      """
      An inner training loop compatible with both epoch-based and iter-based training.
  
      When using epoch-based, training stops after one epoch; when using iter-based,
      training stops after #iters_per_epoch iterations.
      """
      use_amp = scaler is not None
  
      if not hasattr(data_loader, "__next__"):
          # convert to iterator if not already
          data_loader = iter(data_loader)
  
      metric_logger = MetricLogger(delimiter="  ")
      metric_logger.add_meter(
          "lr", SmoothedValue(window_size=1, fmt="{value:.6f}")
      )
      metric_logger.add_meter(
          "loss", SmoothedValue(window_size=1, fmt="{value:.4f}")
      )
  
      # if iter-based runner, schedule lr based on inner epoch.
      logging.info(
          "Start training epoch {}, {} iters per inner epoch.".format(
              epoch, iters_per_epoch
          )
      )
      header = "Train: data epoch: [{}]".format(epoch)
      if start_iters is None:
          # epoch-based runner
          inner_epoch = epoch
      else:
          # In iter-based runner, we schedule the learning rate based on iterations.
          inner_epoch = start_iters // iters_per_epoch
          header = header + "; inner epoch [{}]".format(inner_epoch)
  
      for i in metric_logger.log_every(
          range(iters_per_epoch), log_freq, header
      ):
          # if using iter-based runner, we stop after iters_per_epoch iterations.
          if i >= iters_per_epoch:
              break
  
          samples = next(data_loader)
  
          samples = prepare_sample(samples, cuda_enabled=cuda_enabled)
  
          ## notify model that sample is empty (error occured)
          if not isinstance(samples, dict):
              samples = {"is_empty": True}
  
          samples.update(
              {
                  "epoch": inner_epoch,
                  "num_iters_per_epoch": iters_per_epoch,
                  "iters": i,
              }
          )
  
          lr_scheduler.step(cur_epoch=inner_epoch, cur_step=i)
  
          with torch.cuda.amp.autocast(enabled=use_amp):
              loss, loss_dict = self.train_step(
                  model=model, samples=samples
              )
              loss /= accum_grad_iters  # TODO: not affect loss_dict values for logging
  
          # after_train_step()
          if use_amp:
              scaler.scale(loss).backward()
          else:
              loss.backward()
  
          # update gradients every accum_grad_iters iterations
          if (i + 1) % accum_grad_iters == 0:
              if use_amp:
                  scaler.step(optimizer)
                  scaler.update()
              else:
                  optimizer.step()
              optimizer.zero_grad()
  
          metric_logger.update(**loss_dict)
          metric_logger.update(lr=optimizer.param_groups[0]["lr"])
  
      # after train_epoch()
      # gather the stats from all processes
      metric_logger.synchronize_between_processes()
      logging.info("Averaged stats: " + str(metric_logger.global_avg()))
      return {
          k: "{:.3f}".format(meter.global_avg)
          for k, meter in metric_logger.meters.items()
      }
  
imports: import logging
  import os
  import torch
  import torch.distributed
  from lavis.common.dist_utils import get_rank, get_world_size, is_main_process, is_dist_avail_and_initialized
  from lavis.common.logger import MetricLogger, SmoothedValue
  from lavis.common.registry import registry
  from lavis.datasets.data_utils import prepare_sample
label_desc: Use image node_id 14 for calling the BaseTask obj's underlying member method code with example usage: obj._train_inner_loop(epoch, iters_per_epoch, model, data_loader, optimizer, lr_scheduler, scaler, start_iters, log_freq, cuda_enabled, accum_grad_iters) and returns: unknown