class_docstr: Estimator implementation for Mask-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","Mask-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","."]
docstr: Fit Mask R-CNN models.
docstr_tok: ["Fit","Mask","R-CNN","models","."]
code: def _fit(self, train_data, val_data, time_limit=math.inf):
      """
      Fit Mask R-CNN models.
      """
      # TODO(zhreshold): remove 'dataset' in config, use train_data/val_data instead
      self._cfg.kv_store = (
          "device"
          if (self._cfg.mask_rcnn.amp and "nccl" in self._cfg.kv_store)
          else self._cfg.kv_store
      )
      kv = mx.kvstore.create(self._cfg.kv_store)
      self.net.collect_params().setattr("grad_req", "null")
      self.net.collect_train_params().setattr("grad_req", "write")
      for k, v in self.net.collect_params(".*bias").items():
          v.wd_mult = 0.0
      optimizer_params = {
          "learning_rate": self._cfg.train.lr,
          "wd": self._cfg.train.wd,
          "momentum": self._cfg.train.momentum,
      }
      if self._cfg.train.clip_gradient > 0.0:
          optimizer_params[
              "clip_gradient"
          ] = self._cfg.train.clip_gradient
      if self._cfg.mask_rcnn.amp:
          optimizer_params["multi_precision"] = True
      if self._cfg.horovod:
          hvd.broadcast_parameters(
              self.net.collect_params(), root_rank=0
          )
          trainer = hvd.DistributedTrainer(
              self.net.collect_train_params(),  # fix batchnorm, fix first stage, etc...
              "sgd",
              optimizer_params,
          )
      else:
          trainer = gluon.Trainer(
              self.net.collect_train_params(),  # fix batchnorm, fix first stage, etc...
              "sgd",
              optimizer_params,
              update_on_kvstore=(
                  False if self._cfg.mask_rcnn.amp else None
              ),
              kvstore=kv,
          )
  
      if self._cfg.mask_rcnn.amp:
          amp.init_trainer(trainer)
  
      # 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]", self._cfg.train.start_epoch
      )
  
      base_lr = trainer.learning_rate
      for epoch in range(
          self._cfg.train.start_epoch, self._cfg.train.epochs
      ):
          self.epoch = epoch
          rcnn_task = ForwardBackwardTask(
              self.net,
              trainer,
              self.rpn_cls_loss,
              self.rpn_box_loss,
              self.rcnn_cls_loss,
              self.rcnn_box_loss,
              self.rcnn_mask_loss,
              amp_enabled=self._cfg.mask_rcnn.amp,
          )
          executor = (
              Parallel(self._cfg.train.executor_threads, rcnn_task)
              if not self._cfg.horovod
              else None
          )
          if not self._cfg.disable_hybridization:
              self.net.hybridize(
                  static_alloc=self._cfg.mask_rcnn.static_alloc
              )
          while lr_steps and epoch >= lr_steps[0]:
              new_lr = trainer.learning_rate * lr_decay
              lr_steps.pop(0)
              trainer.set_learning_rate(new_lr)
              self._logger.info(
                  "[Epoch %d] Set learning rate to %f", epoch, new_lr
              )
          for metric in self.metrics:
              metric.reset()
          tic = time.time()
          btic = time.time()
          train_data_iter = iter(self._train_data)
          next_data_batch = next(train_data_iter)
          next_data_batch = _split_and_load(
              next_data_batch, ctx_list=self.ctx
          )
          for i in range(len(self._train_data)):
              batch = next_data_batch
              if i + epoch * len(self._train_data) <= lr_warmup:
                  # adjust based on real percentage
                  new_lr = base_lr * _get_lr_at_iter(
                      (i + epoch * len(self._train_data)) / lr_warmup,
                      self._cfg.train.lr_warmup_factor,
                  )
                  if new_lr != trainer.learning_rate:
                      if i % self._cfg.train.log_interval == 0:
                          self._logger.info(
                              "[Epoch %d Iteration %d] Set learning rate to %f",
                              epoch,
                              i,
                              new_lr,
                          )
                      trainer.set_learning_rate(new_lr)
              metric_losses = [[] for _ in self.metrics]
              add_losses = [[] for _ in self.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 in range(len(metric_losses)):
                          metric_losses[k].append(result[k])
                      for k in range(len(add_losses)):
                          add_losses[k].append(
                              result[len(metric_losses) + k]
                          )
              try:
                  # prefetch next batch
                  next_data_batch = next(train_data_iter)
                  next_data_batch = _split_and_load(
                      next_data_batch, ctx_list=self.ctx
                  )
              except StopIteration:
                  pass
  
              for metric, record in zip(self.metrics, metric_losses):
                  metric.update(0, record)
              for metric, records in zip(self.metrics2, add_losses):
                  for pred in records:
                      metric.update(pred[0], pred[1])
              trainer.step(self.batch_size)
              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 self.metrics + self.metrics2
                      ]
                  )
                  self._logger.info(
                      "[Epoch {}][Batch {}], Speed: {:.3f} samples/sec, {}".format(
                          epoch,
                          i,
                          self._cfg.train.log_interval
                          * self._cfg.train.batch_size
                          / (time.time() - btic),
                          msg,
                      )
                  )
                  btic = time.time()
          # validate and save params
          if (not self._cfg.horovod) or hvd.rank() == 0:
              msg = ",".join(
                  [
                      "{}={:.3f}".format(*metric.get())
                      for metric in self.metrics
                  ]
              )
              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
              self._validate(
                  self._val_data,
                  self.async_eval_processes,
                  self.ctx,
                  self.eval_metric,
                  self._logger,
                  epoch,
                  self.best_map,
              )
          elif (not self._cfg.horovod) or hvd.rank() == 0:
              current_map = 0.0
              _save_params(
                  self.net,
                  self._logger,
                  self.best_map,
                  current_map,
                  epoch,
                  self._cfg.save_interval,
                  os.path.join(self._logdir, self._cfg.save_prefix),
              )
          if self._reporter:
              self._reporter(epoch=epoch, map_reward=current_map)
      for thread in self.async_eval_processes:
          thread.join()
  
imports: import os
  import math
  import time
  import logging
  from multiprocessing import Process
  import numpy
  import mxnet
  from mxnet import gluon
  from mxnet.contrib import amp
  from ....None import data
  from ....None import utils
  from ....data import COCODetection, VOCDetection
  from ....data.transforms import presets
  from ....data.transforms.presets.rcnn import MaskRCNNDefaultTrainTransform, MaskRCNNDefaultValTransform
  from ....model_zoo import get_model
  from ....model_zoo.rcnn.mask_rcnn.data_parallel import ForwardBackwardTask
  from ....nn.bbox import BBoxClipToImage
  from ....utils.parallel import Parallel
  from ....utils.metrics.rcnn import RPNAccMetric, RPNL1LossMetric, RCNNAccMetric, RCNNL1LossMetric, MaskAccMetric, MaskFGAccMetric
  from ..base_estimator import BaseEstimator, set_default
  from .utils import _get_dataset, _get_dataloader, _save_params, _split_and_load, _get_lr_at_iter
  from .default import MaskRCNNCfg
label_desc: Use image node_id 3 for calling the MaskRCNNEstimator obj's underlying member method code with example usage: obj._fit(train_data, val_data, time_limit) without return types