code: def do_train(cfg, model, resume=False):
      model.train()
      optimizer = build_optimizer(cfg, model)
      scheduler = build_lr_scheduler(cfg, optimizer)
  
      checkpointer = DetectionCheckpointer(
          model,
          cfg.OUTPUT_DIR,
          optimizer=optimizer,
          scheduler=scheduler,
      )
      start_iter = (
          checkpointer.resume_or_load(
              cfg.MODEL.WEIGHTS, resume=resume
          ).get("iteration", -1)
          + 1
      )
      max_iter = cfg.SOLVER.MAX_ITER
  
      periodic_checkpointer = PeriodicCheckpointer(
          checkpointer, cfg.SOLVER.CHECKPOINT_PERIOD, max_iter=max_iter
      )
  
      writers = (
          default_writers(cfg.OUTPUT_DIR, max_iter)
          if comm.is_main_process()
          else []
      )
  
      # compared to "train_net.py", we do not support accurate timing and
      # precise BN here, because they are not trivial to implement in a small training loop
      data_loader = build_detection_train_loader(cfg)
      logger.info(
          "Starting training from iteration {}".format(start_iter)
      )
      with EventStorage(start_iter) as storage:
          for data, iteration in zip(
              data_loader, range(start_iter, max_iter)
          ):
              storage.iter = iteration
  
              loss_dict = model(data)
              losses = sum(loss_dict.values())
              assert torch.isfinite(losses).all(), loss_dict
  
              loss_dict_reduced = {
                  k: v.item()
                  for k, v in comm.reduce_dict(loss_dict).items()
              }
              losses_reduced = sum(
                  loss for loss in loss_dict_reduced.values()
              )
              if comm.is_main_process():
                  storage.put_scalars(
                      total_loss=losses_reduced, **loss_dict_reduced
                  )
  
              optimizer.zero_grad()
              losses.backward()
              optimizer.step()
              storage.put_scalar(
                  "lr",
                  optimizer.param_groups[0]["lr"],
                  smoothing_hint=False,
              )
              scheduler.step()
  
              if (
                  cfg.TEST.EVAL_PERIOD > 0
                  and (iteration + 1) % cfg.TEST.EVAL_PERIOD == 0
                  and iteration != max_iter - 1
              ):
                  do_test(cfg, model)
                  # Compared to "train_net.py", the test results are not dumped to EventStorage
                  comm.synchronize()
  
              if iteration - start_iter > 5 and (
                  (iteration + 1) % 20 == 0 or iteration == max_iter - 1
              ):
                  for writer in writers:
                      writer.write()
              periodic_checkpointer.step(iteration)
  
file_path: detectron2/tools/plain_train_net.py
imports: import logging
  import os
  from collections import OrderedDict
  import torch
  from torch.nn.parallel import DistributedDataParallel
  import detectron2.utils.comm
  from detectron2.checkpoint import DetectionCheckpointer, PeriodicCheckpointer
  from detectron2.config import get_cfg
  from detectron2.data import MetadataCatalog, build_detection_test_loader, build_detection_train_loader
  from detectron2.engine import default_argument_parser, default_setup, default_writers, launch
  from detectron2.evaluation import CityscapesInstanceEvaluator, CityscapesSemSegEvaluator, COCOEvaluator, COCOPanopticEvaluator, DatasetEvaluators, LVISEvaluator, PascalVOCDetectionEvaluator, SemSegEvaluator, inference_on_dataset, print_csv_format
  from detectron2.modeling import build_model
  from detectron2.solver import build_lr_scheduler, build_optimizer
  from detectron2.utils.events import EventStorage
label_desc: Use image node_id 3 for calling a global function with example usage: do_train(cfg, model, resume) without return types