class_docstr: Estimator implementation for YOLOv3.
  
  Parameters
  ----------
  config : dict
      Config in nested dict.
  logger : logging.Logger, default is None
      Optional logger for this estimator, can be `None` when default setting is used.
  reporter : callable, default is None
      If set, use reporter callback to report the metrics of the current estimator.
  
  Attributes
  ----------
  _logger : logging.Logger
      The customized/default logger for this estimator.
  _logdir : str
      The temporary dir for logs.
  _cfg : autocfg.dataclass
      The configurations.
class_docstr_tok: ["Estimator","implementation","for","YOLOv3",".","Parameters","--","--","--","--","--","config",":","dict","Config","in","nested","dict",".","logger",":","logging.Logger",",","default","is","None","Optional","logger","for","this","estimator",",","can","be","`","None","`","when","default","setting","is","used",".","reporter",":","callable",",","default","is","None","If","set",",","use","reporter","callback","to","report","the","metrics","of","the","current","estimator",".","Attributes","--","--","--","--","--","_logger",":","logging.Logger","The","customized\/default","logger","for","this","estimator",".","_logdir",":","str","The","temporary","dir","for","logs",".","_cfg",":","autocfg.dataclass","The","configurations","."]
code: def _train_loop(
      self, train_data, val_data, train_eval_data, time_limit=math.inf
  ):
      start_tic = time.time()
      # fix seed for mxnet, numpy and python builtin random generator.
      gutils.random.seed(self._cfg.train.seed)
  
      # metrics
      obj_metrics = mx.metric.Loss("ObjLoss")
      center_metrics = mx.metric.Loss("BoxCenterLoss")
      scale_metrics = mx.metric.Loss("BoxScaleLoss")
      cls_metrics = mx.metric.Loss("ClassLoss")
      trainer = self.trainer
      self._logger.info(
          "Start training from [Epoch %d]",
          max(self._cfg.train.start_epoch, self.epoch),
      )
      early_stopper = EarlyStopperOnPlateau(
          patience=self._cfg.train.early_stop_patience,
          min_delta=self._cfg.train.early_stop_min_delta,
          baseline_value=self._cfg.train.early_stop_baseline,
          max_value=self._cfg.train.early_stop_max_value,
      )
      mean_ap = [-1]
      cp_name = ""
      self._time_elapsed += time.time() - start_tic
      for self.epoch in range(
          max(self._cfg.train.start_epoch, self.epoch),
          self._cfg.train.epochs,
      ):
          epoch = self.epoch
          if self._best_map >= 1.0:
              self._logger.info(
                  "[Epoch {}] Early stopping as mAP is reaching 1.0".format(
                      epoch
                  )
              )
              break
          (
              should_stop,
              stop_message,
          ) = early_stopper.get_early_stop_advice()
          if should_stop:
              self._logger.info(
                  "[Epoch {}] ".format(epoch) + stop_message
              )
              break
          tic = time.time()
          last_tic = time.time()
          if self._cfg.train.mixup:
              # TODO(zhreshold): more elegant way to control mixup during runtime
              try:
                  train_data._dataset.set_mixup(
                      np.random.beta, 1.5, 1.5
                  )
              except AttributeError:
                  train_data._dataset._data.set_mixup(
                      np.random.beta, 1.5, 1.5
                  )
              if (
                  epoch
                  >= self._cfg.train.epochs
                  - self._cfg.train.no_mixup_epochs
              ):
                  try:
                      train_data._dataset.set_mixup(None)
                  except AttributeError:
                      train_data._dataset._data.set_mixup(None)
  
          mx.nd.waitall()
          self.net.hybridize()
          for i, batch in enumerate(train_data):
              btic = time.time()
              if self._time_elapsed > time_limit:
                  self._logger.warning(
                      f"`time_limit={time_limit}` reached, exit early..."
                  )
                  return {
                      "train_map": float(mean_ap[-1]),
                      "valid_map": self._best_map,
                      "time": self._time_elapsed,
                      "checkpoint": cp_name,
                  }
              data = gluon.utils.split_and_load(
                  batch[0],
                  ctx_list=self.ctx,
                  batch_axis=0,
                  even_split=False,
              )
              # objectness, center_targets, scale_targets, weights, class_targets
              fixed_targets = [
                  gluon.utils.split_and_load(
                      batch[it],
                      ctx_list=self.ctx,
                      batch_axis=0,
                      even_split=False,
                  )
                  for it in range(1, 6)
              ]
              gt_boxes = gluon.utils.split_and_load(
                  batch[6],
                  ctx_list=self.ctx,
                  batch_axis=0,
                  even_split=False,
              )
              sum_losses = []
              obj_losses = []
              center_losses = []
              scale_losses = []
              cls_losses = []
              with autograd.record():
                  for ix, x in enumerate(data):
                      (
                          obj_loss,
                          center_loss,
                          scale_loss,
                          cls_loss,
                      ) = self.net(
                          x,
                          gt_boxes[ix],
                          *[ft[ix] for ft in fixed_targets],
                      )
                      sum_losses.append(
                          obj_loss + center_loss + scale_loss + cls_loss
                      )
                      obj_losses.append(obj_loss)
                      center_losses.append(center_loss)
                      scale_losses.append(scale_loss)
                      cls_losses.append(cls_loss)
                  if self._cfg.yolo3.amp:
                      with amp.scale_loss(
                          sum_losses, trainer
                      ) as scaled_loss:
                          autograd.backward(scaled_loss)
                  else:
                      autograd.backward(sum_losses)
              trainer.step(self.batch_size)
              if not self._cfg.horovod or hvd.rank() == 0:
                  obj_metrics.update(0, obj_losses)
                  center_metrics.update(0, center_losses)
                  scale_metrics.update(0, scale_losses)
                  cls_metrics.update(0, cls_losses)
                  if (
                      self._cfg.train.log_interval
                      and not (i + 1) % self._cfg.train.log_interval
                  ):
                      name1, loss1 = obj_metrics.get()
                      name2, loss2 = center_metrics.get()
                      name3, loss3 = scale_metrics.get()
                      name4, loss4 = cls_metrics.get()
                      self._logger.info(
                          "[Epoch {}][Batch {}], LR: {:.2E}, Speed: {:.3f} samples/sec,"
                          " {}={:.3f}, {}={:.3f}, {}={:.3f}, {}={:.3f}".format(
                              epoch,
                              i,
                              trainer.learning_rate,
                              self._cfg.train.batch_size
                              / (time.time() - last_tic),
                              name1,
                              loss1,
                              name2,
                              loss2,
                              name3,
                              loss3,
                              name4,
                              loss4,
                          )
                      )
                      last_tic = time.time()
                  self._time_elapsed += time.time() - btic
  
          post_tic = time.time()
          if not self._cfg.horovod or hvd.rank() == 0:
              name1, loss1 = obj_metrics.get()
              name2, loss2 = center_metrics.get()
              name3, loss3 = scale_metrics.get()
              name4, loss4 = cls_metrics.get()
              self._logger.info(
                  "[Epoch {}] Training cost: {:.3f}, {}={:.3f}, {}={:.3f}, {}={:.3f}, {}={:.3f}".format(
                      epoch,
                      (time.time() - tic),
                      name1,
                      loss1,
                      name2,
                      loss2,
                      name3,
                      loss3,
                      name4,
                      loss4,
                  )
              )
              if not (epoch + 1) % self._cfg.valid.val_interval:
                  # consider reduce the frequency of validation to save time
                  map_name, mean_ap = self._evaluate(val_data)
                  val_msg = "\n".join(
                      [
                          "{}={}".format(k, v)
                          for k, v in zip(map_name, mean_ap)
                      ]
                  )
                  self._logger.info(
                      "[Epoch {}] Validation: \n{}".format(
                          epoch, val_msg
                      )
                  )
                  current_map = float(mean_ap[-1])
                  if current_map > self._best_map:
                      cp_name = os.path.join(
                          self._logdir, _BEST_CHECKPOINT_FILE
                      )
                      self._logger.info(
                          "[Epoch %d] Current best map: %f vs previous %f, saved to %s",
                          self.epoch,
                          current_map,
                          self._best_map,
                          cp_name,
                      )
                      self.save(cp_name)
                      self._best_map = current_map
                  if self._reporter:
                      self._reporter(
                          epoch=epoch, map_reward=current_map
                      )
                  early_stopper.update(current_map, epoch=epoch)
          self._time_elapsed += time.time() - post_tic
  
      # map on train data
      tic = time.time()
      map_name, mean_ap = self._evaluate(train_eval_data)
      self._time_elapsed += time.time() - tic
      return {
          "train_map": float(mean_ap[-1]),
          "valid_map": self._best_map,
          "time": self._time_elapsed,
          "checkpoint": cp_name,
      }
  
imports: import os
  import math
  import time
  import warnings
  from PIL import Image
  import pandas
  import numpy
  import mxnet
  from mxnet import gluon
  from mxnet import autograd
  from mxnet.contrib import amp
  from ....None import utils
  from ....data.batchify import Tuple, Stack, Pad
  from ....data.transforms.presets.yolo import YOLO3DefaultValTransform
  from ....data.transforms.presets.yolo import load_test, transform_test
  from ....model_zoo import get_model
  from ....model_zoo import custom_yolov3
  from ....utils.metrics.voc_detection import VOC07MApMetric, VOCMApMetric
  from ....utils import LRScheduler, LRSequential
  from ..base_estimator import BaseEstimator, set_default
  from .utils import _get_dataloader
  from ...data.dataset import ObjectDetectionDataset
  from ..conf import _BEST_CHECKPOINT_FILE
  from ..utils import EarlyStopperOnPlateau
  from .default import YOLOv3Cfg
label_desc: Use image node_id 4 for calling the YOLOv3Estimator obj's underlying member method code with example usage: obj._train_loop(train_data, val_data, train_eval_data, time_limit) and returns: dict, dict