class_docstr: Estimator implementation for Faster-RCNN.
  
  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","Faster-RCNN",".","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()
      # loss and metric
      rpn_cls_loss = gluon.loss.SigmoidBinaryCrossEntropyLoss(
          from_sigmoid=False
      )
      rpn_box_loss = gluon.loss.HuberLoss(
          rho=self._cfg.train.rpn_smoothl1_rho
      )  # == smoothl1
      rcnn_cls_loss = gluon.loss.SoftmaxCrossEntropyLoss()
      rcnn_box_loss = gluon.loss.HuberLoss(
          rho=self._cfg.train.rcnn_smoothl1_rho
      )  # == smoothl1
      metrics = [
          mx.metric.Loss("RPN_Conf"),
          mx.metric.Loss("RPN_SmoothL1"),
          mx.metric.Loss("RCNN_CrossEntropy"),
          mx.metric.Loss("RCNN_SmoothL1"),
      ]
  
      rpn_acc_metric = RPNAccMetric()
      rpn_bbox_metric = RPNL1LossMetric()
      rcnn_acc_metric = RCNNAccMetric()
      rcnn_bbox_metric = RCNNL1LossMetric()
      metrics2 = [
          rpn_acc_metric,
          rpn_bbox_metric,
          rcnn_acc_metric,
          rcnn_bbox_metric,
      ]
  
      # lr decay policy
      lr_decay = float(self._cfg.train.lr_decay)
      lr_steps = sorted(
          [float(ls) for ls in self._cfg.train.lr_decay_epoch]
      )
      lr_warmup = float(self._cfg.train.lr_warmup)  # avoid int division
  
      if self._cfg.train.verbose:
          self._logger.info("Trainable parameters:")
          self._logger.info(self.net.collect_train_params().keys())
      self._logger.info(
          "Start training from [Epoch %d]",
          max(self._cfg.train.start_epoch, self.epoch),
      )
      self.net.collect_params().reset_ctx(self.ctx)
      self.net.target_generator.collect_params().reset_ctx(self.ctx)
  
      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
          tic = time.time()
          last_tic = time.time()
          if self._best_map >= 1.0:
              self._logger.info(
                  "[Epoch %d] Early stopping as mAP is reaching 1.0",
                  epoch,
              )
              break
          (
              should_stop,
              stop_message,
          ) = early_stopper.get_early_stop_advice()
          if should_stop:
              self._logger.info(
                  "[Epoch {}] ".format(epoch) + stop_message
              )
              break
          rcnn_task = ForwardBackwardTask(
              self.net,
              self.trainer,
              rpn_cls_loss,
              rpn_box_loss,
              rcnn_cls_loss,
              rcnn_box_loss,
              mix_ratio=1.0,
              amp_enabled=self._cfg.faster_rcnn.amp,
          )
          executor = (
              Parallel(self._cfg.train.executor_threads, rcnn_task)
              if not self._cfg.horovod
              else None
          )
          mix_ratio = 1.0
          if not self._cfg.disable_hybridization:
              self.net.hybridize(
                  static_alloc=self._cfg.faster_rcnn.static_alloc
              )
          if self._cfg.train.mixup:
              # TODO(zhreshold) only support evenly mixup now, target generator needs to be
              #  modified otherwise
              train_data._dataset._data.set_mixup(
                  np.random.uniform, 0.5, 0.5
              )
              mix_ratio = 0.5
              if (
                  epoch
                  >= self._cfg.train.epochs
                  - self._cfg.train.no_mixup_epochs
              ):
                  train_data._dataset._data.set_mixup(None)
                  mix_ratio = 1.0
          while lr_steps and epoch >= lr_steps[0]:
              new_lr = self.trainer.learning_rate * lr_decay
              lr_steps.pop(0)
              self.trainer.set_learning_rate(new_lr)
              self._logger.info(
                  "[Epoch %d] Set learning rate to %f", epoch, new_lr
              )
          for metric in metrics:
              metric.reset()
          base_lr = self.trainer.learning_rate
          rcnn_task.mix_ratio = mix_ratio
          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,
                  }
              if epoch == 0 and i <= lr_warmup:
                  # adjust based on real percentage
                  new_lr = base_lr * _get_lr_at_iter(
                      i / lr_warmup, self._cfg.train.lr_warmup_factor
                  )
                  if new_lr != self.trainer.learning_rate:
                      if i % self._cfg.train.log_interval == 0:
                          self._logger.info(
                              "[Epoch 0 Iteration %d] Set learning rate to %f",
                              i,
                              new_lr,
                          )
                      self.trainer.set_learning_rate(new_lr)
              batch = _split_and_load(batch, ctx_list=self.ctx)
              metric_losses = [[] for _ in metrics]
              add_losses = [[] for _ in metrics2]
              if executor is not None:
                  for data in zip(*batch):
                      executor.put(data)
              for _ in range(len(self.ctx)):
                  if executor is not None:
                      result = executor.get()
                  else:
                      result = rcnn_task.forward_backward(
                          list(zip(*batch))[0]
                      )
                  if (not self._cfg.horovod) or hvd.rank() == 0:
                      for k, metric_loss in enumerate(metric_losses):
                          metric_loss.append(result[k])
                      for k, add_loss in enumerate(add_losses):
                          add_loss.append(
                              result[len(metric_losses) + k]
                          )
              for metric, record in zip(metrics, metric_losses):
                  metric.update(0, record)
              for metric, records in zip(metrics2, add_losses):
                  for pred in records:
                      metric.update(pred[0], pred[1])
              self.trainer.step(self.batch_size)
  
              # update metrics
              if (
                  (not self._cfg.horovod or hvd.rank() == 0)
                  and self._cfg.train.log_interval
                  and not (i + 1) % self._cfg.train.log_interval
              ):
                  msg = ",".join(
                      [
                          "{}={:.3f}".format(*metric.get())
                          for metric in metrics + metrics2
                      ]
                  )
                  self._logger.info(
                      "[Epoch {}][Batch {}], Speed: {:.3f} samples/sec, {}".format(
                          epoch,
                          i,
                          self._cfg.train.log_interval
                          * self.batch_size
                          / (time.time() - last_tic),
                          msg,
                      )
                  )
                  last_tic = time.time()
              self._time_elapsed += time.time() - btic
  
          post_tic = time.time()
          if not self._cfg.horovod or hvd.rank() == 0:
              msg = ",".join(
                  [
                      "{}={:.3f}".format(*metric.get())
                      for metric in metrics
                  ]
              )
              # pylint: disable=logging-format-interpolation
              self._logger.info(
                  "[Epoch {}] Training cost: {:.3f}, {}".format(
                      epoch, (time.time() - tic), msg
                  )
              )
              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 ....data.batchify import Tuple, Append
  from ....data.transforms.presets.rcnn import load_test, transform_test
  from ....data.transforms.presets.rcnn import FasterRCNNDefaultTrainTransform, FasterRCNNDefaultValTransform
  from ....model_zoo import get_model
  from ....model_zoo.rcnn.faster_rcnn.data_parallel import ForwardBackwardTask
  from ....nn.bbox import BBoxClipToImage
  from ....utils.parallel import Parallel
  from ....utils.metrics.rcnn import RPNAccMetric, RPNL1LossMetric, RCNNAccMetric, RCNNL1LossMetric
  from ....utils.metrics.voc_detection import VOC07MApMetric, VOCMApMetric
  from ..base_estimator import BaseEstimator, set_default
  from .utils import _get_lr_at_iter, _get_dataloader, _split_and_load
  from ...data.dataset import ObjectDetectionDataset
  from ..conf import _BEST_CHECKPOINT_FILE
  from ..utils import EarlyStopperOnPlateau
  from .default import FasterRCNNCfg
label_desc: Use image node_id 4 for calling the FasterRCNNEstimator 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