class_docstr: Object Detection general task.
  
  Parameters
  ----------
  config : dict
      The configurations, can be nested dict.
  logger : logging.Logger
      The desired logger object, use `None` for module specific logger with default setting.
class_docstr_tok: ["Object","Detection","general","task",".","Parameters","--","--","--","--","--","config",":","dict","The","configurations",",","can","be","nested","dict",".","logger",":","logging.Logger","The","desired","logger","object",",","use","`","None","`","for","module","specific","logger","with","default","setting","."]
docstr: Fit auto estimator given the input data.
  
  Parameters
  ----------
  train_data : pd.DataFrame or iterator
      Training data.
  val_data : pd.DataFrame or iterator, optional
      Validation data, optional. If `train_data` is DataFrame, `val_data` will be split from
      `train_data` given `train_size`.
  train_size : float
      The portion of train data split from original `train_data` if `val_data` is not provided.
  random_state : int
      Random state for splitting, for `np.random.seed`.
  time_limit : int, default is None
      The wall clock time limit(second) for fit process, if `None`, time limit is not enforced.
      If `fit` takes longer than `time_limit`, the process will terminate early and return the
      model prematurally.
      Due to callbacks and additional validation functions, the `time_limit` may not be very precise
      (few minutes allowance), but you can use it to safe-guard a very long training session.
      If `time_limits` key set in __init__ with config, the `time_limit` value will overwrite configuration
      if not `None`.
  
  Returns
  -------
  Estimator
      The estimator obtained by training on the specified dataset.
docstr_tok: ["Fit","auto","estimator","given","the","input","data",".","Parameters","--","--","--","--","--","train_data",":","pd.DataFrame","or","iterator","Training","data",".","val_data",":","pd.DataFrame","or","iterator",",","optional","Validation","data",",","optional",".","If","`","train_data","`","is","DataFrame",",","`","val_data","`","will","be","split","from","`","train_data","`","given","`","train_size","`",".","train_size",":","float","The","portion","of","train","data","split","from","original","`","train_data","`","if","`","val_data","`","is","not","provided",".","random_state",":","int","Random","state","for","splitting",",","for","`","np.random.seed","`",".","time_limit",":","int",",","default","is","None","The","wall","clock","time","limit","(","second",")","for","fit","process",",","if","`","None","`",",","time","limit","is","not","enforced",".","If","`","fit","`","takes","longer","than","`","time_limit","`",",","the","process","will","terminate","early","and","return","the","model","prematurally",".","Due","to","callbacks","and","additional","validation","functions",",","the","`","time_limit","`","may","not","be","very","precise","(","few","minutes","allowance",")",",","but","you","can","use","it","to","safe-guard","a","very","long","training","session",".","If","`","time_limits","`","key","set","in","__init__","with","config",",","the","`","time_limit","`","value","will","overwrite","configuration","if","not","`","None","`",".","Returns","--","--","--","-","Estimator","The","estimator","obtained","by","training","on","the","specified","dataset","."]
code: def fit(
      self,
      train_data,
      val_data=None,
      train_size=0.9,
      random_state=None,
      time_limit=None,
  ):
      """Fit auto estimator given the input data.
  
      Parameters
      ----------
      train_data : pd.DataFrame or iterator
          Training data.
      val_data : pd.DataFrame or iterator, optional
          Validation data, optional. If `train_data` is DataFrame, `val_data` will be split from
          `train_data` given `train_size`.
      train_size : float
          The portion of train data split from original `train_data` if `val_data` is not provided.
      random_state : int
          Random state for splitting, for `np.random.seed`.
      time_limit : int, default is None
          The wall clock time limit(second) for fit process, if `None`, time limit is not enforced.
          If `fit` takes longer than `time_limit`, the process will terminate early and return the
          model prematurally.
          Due to callbacks and additional validation functions, the `time_limit` may not be very precise
          (few minutes allowance), but you can use it to safe-guard a very long training session.
          If `time_limits` key set in __init__ with config, the `time_limit` value will overwrite configuration
          if not `None`.
  
      Returns
      -------
      Estimator
          The estimator obtained by training on the specified dataset.
  
      """
      config = self._config.copy()
      if time_limit is None:
          if config.get("time_limits", None):
              time_limit = config["time_limits"]
          else:
              time_limit = math.inf
      elif not isinstance(time_limit, int):
          raise TypeError(
              f"Invalid type `time_limit={time_limit}`, int or None expected"
          )
      self.scheduler_options["time_out"] = time_limit
      wall_clock_tick = time.time() + time_limit
      # split train/val before HPO to make fair comparisons
      if not isinstance(train_data, pd.DataFrame):
          assert (
              val_data is not None
          ), "Please provide `val_data` as we do not know how to split `train_data` of type: \
                  {}".format(
              type(train_data)
          )
  
      if val_data is None:
          assert 0 <= train_size <= 1.0
          if random_state:
              np.random.seed(random_state)
          split_mask = np.random.rand(len(train_data)) < train_size
          train = train_data[split_mask]
          val = train_data[~split_mask]
          self._logger.info(
              "Randomly split train_data into train[%d]/validation[%d] splits.",
              len(train),
              len(val),
          )
          train_data, val_data = train, val
  
      # automatically suggest some hyperparameters based on the dataset statistics(experimental)
      estimator = config.get("estimator", None)
      transfer = config.get("transfer", None)
      if not transfer:
          config["train_dataset"] = train_data
          auto_suggest(config, estimator, self._logger)
          config.pop("train_dataset")
  
      # register args
      config["train_data"] = train_data
      config["val_data"] = val_data
      config["wall_clock_tick"] = wall_clock_tick
      config["log_dir"] = os.path.join(
          config.get("log_dir", os.getcwd()), str(uuid.uuid4())[:8]
      )
      _train_object_detection.register_args(**config)
  
      start_time = time.time()
      self._fit_summary = {}
      self._results = {}
      if config.get("num_trials", 1) < 2:
          rand_config = RandomSearcher(
              _train_object_detection.cs
          ).get_config()
          self._logger.info("Starting fit without HPO")
          results = _train_object_detection(
              _train_object_detection.args, rand_config
          )
          best_config = sample_config(
              _train_object_detection.args, rand_config
          )
          best_config.pop("train_data", None)
          best_config.pop("val_data", None)
          self._fit_summary.update(
              {
                  "train_map": results.get("train_map", -1),
                  "valid_map": results.get("valid_map", -1),
                  "total_time": results.get(
                      "time", time.time() - start_time
                  ),
                  "best_config": best_config,
              }
          )
          self._results = self._fit_summary
      else:
          self._logger.info("Starting HPO experiments")
          results = self.run_fit(
              _train_object_detection,
              self.search_strategy,
              self.scheduler_options,
          )
          if isinstance(results, dict):
              ks = (
                  "best_reward",
                  "best_config",
                  "total_time",
                  "config_history",
                  "reward_attr",
              )
              self._results.update(
                  {k: v for k, v in results.items() if k in ks}
              )
      end_time = time.time()
      self._logger.info(
          "Finished, total runtime is %.2f s", end_time - start_time
      )
      if config.get("num_trials", 1) > 1:
          best_config = sample_config(
              _train_object_detection.args, results["best_config"]
          )
          # convert best config to nested form
          best_config = config_to_nested(best_config)
          best_config.pop("train_data", None)
          best_config.pop("val_data", None)
          self._fit_summary.update(
              {
                  "train_map": results.get("train_map", -1),
                  "valid_map": results.get(
                      "valid_map", results.get("best_reward", -1)
                  ),
                  "total_time": results.get(
                      "total_time", time.time() - start_time
                  ),
                  "best_config": best_config,
              }
          )
      self._logger.info(pprint.pformat(self._fit_summary, indent=2))
  
      if self._cleanup_disk:
          shutil.rmtree(config["log_dir"], ignore_errors=True)
      model_checkpoint = results.get("model_checkpoint", None)
      if model_checkpoint is None:
          if results.get("traceback", "") == "timeout":
              raise TimeoutError(
                  f"Unable to fit a usable model given `time_limit={time_limit}`"
              )
          raise RuntimeError(
              f"Unexpected error happened during fit: {pprint.pformat(results, indent=2)}"
          )
      estimator = pickle.loads(results["model_checkpoint"])
      return estimator
  
imports: import time
  import os
  import math
  import copy
  import logging
  import pprint
  import json
  import pickle
  from typing import Union, Tuple
  import uuid
  import shutil
  import numpy
  import pandas
  from autocfg import dataclass
  import autogluon.core
  from autogluon.core.decorator import sample_config
  from autogluon.core.scheduler.resource import get_cpu_count, get_gpu_count
  from autogluon.core.task.base import BaseTask
  from autogluon.core.searcher import RandomSearcher
  from ..estimators.base_estimator import BaseEstimator
  from ..estimators import SSDEstimator, FasterRCNNEstimator, YOLOv3Estimator, CenterNetEstimator
  from .utils import auto_suggest, config_to_nested
  from ..data.dataset import ObjectDetectionDataset
  from ..estimators.conf import _BEST_CHECKPOINT_FILE
label_desc: Use image node_id 2 for calling the ObjectDetection obj's underlying member method code with example usage: obj.fit(train_data, val_data, train_size, random_state, time_limit) and returns: estimator