Source code for autogluon.vision.object_detection.object_detection
"""Object Detection task"""
import copy
import pickle
import logging
from autogluon.core.utils import verbosity2loglevel
from gluoncv.auto.tasks import ObjectDetection as _ObjectDetection
__all__ = ['ObjectDetector']
[docs]class ObjectDetector(object):
"""AutoGluon Predictor for detecting objects in images
Parameters
----------
log_dir : str
The directory for saving logs, by default using `pwd`: the current working directory.
"""
# Dataset is a subclass of `pd.DataFrame`, with `image` and `bbox` columns.
Dataset = _ObjectDetection.Dataset
def __init__(self, log_dir=None):
self._log_dir = log_dir
self._detector = None
self._fit_summary = {}
[docs] def fit(self,
train_data,
val_data=None,
holdout_frac=0.1,
random_state=None,
time_limit=12*60*60,
num_trials=1,
hyperparameters=None,
search_strategy='random',
scheduler_options=None,
nthreads_per_trial=None,
ngpus_per_trial=None,
dist_ip_addrs=None,
verbosity=3):
"""Automatic fit process for object detection.
Parameters
----------
train_data : pd.DataFrame or str
Training data, can be a dataframe like image dataset.
For more details of how to construct a object detection dataset, please checkout:
`http://preview.d2l.ai/d8/main/object_detection/getting_started.html`.
If a string is provided, will search for k8 datasets.
val_data : pd.DataFrame or str, default = None
Training data, can be a dataframe like image dataset.
If a string is provided, will search for k8 datasets.
If `None`, the validation dataset will be randomly split from `train_data`.
holdout_frac : float, default = 0.1
The random split ratio for `val_data` if `val_data==None`.
random_state : numpy.random.state, default = None
The random_state for shuffling, only used if `val_data==None`.
Note that the `random_state` only affect the splitting process, not model training.
time_limit : int, default = 43200
Time limit in seconds, default is 12 hours. If `time_limit` is hit during `fit`, the
HPO process will interrupt and return the current best configuration.
num_trials : int, default = 1
The number of HPO trials. If `None`, will run infinite trials until `time_limit` is met.
hyperparameters : dict, default = None
Extra hyperparameters for specific models.
Accepted args includes(not limited to):
epochs : int, default value based on network
The `epochs` for model training.
batch_size : int
Mini batch size
lr : float
Trainer learning rate for optimization process.
You can get the list of accepted hyperparameters in `config.yaml` saved by this predictor.
search_strategy : str, default = 'random'
Searcher strategy for HPO, 'random' by default.
Options include: ‘random’ (random search), ‘bayesopt’ (Gaussian process Bayesian optimization),
‘skopt’ (SKopt Bayesian optimization), ‘grid’ (grid search).
scheduler_options : dict, default = None
Extra options for HPO scheduler, please refer to `autogluon.core.Searcher` for details.
nthreads_per_trial : int, default = (# cpu cores)
Number of CPU threads for each trial, if `None`, will detect the # cores on current instance.
ngpus_per_trial : int, default = (# gpus)
Number of GPUs to use for each trial, if `None`, will detect the # gpus on current instance.
dist_ip_addrs : list, default = None
If not `None`, will spawn tasks on distributed nodes.
verbosity : int, default = 3
Controls how detailed of a summary to ouput.
Set <= 0 for no output printing, 1 to print just high-level summary,
2 to print summary and create plots, >= 3 to print all information produced during fit().
"""
log_level = verbosity2loglevel(verbosity)
if self._detector is not None:
self._detector._logger.setLevel(log_level)
self._detector._logger.propagate = True
self._fit_summary = self._detector.fit(train_data, val_data, 1 - holdout_frac, random_state, resume=False)
return
# new HPO task
config={'log_dir': self._log_dir,
'num_trials': 99999 if num_trials is None else max(1, num_trials),
'time_limits': time_limit,
'search_strategy': search_strategy,
}
if nthreads_per_trial is not None:
config['nthreads_per_trial'] = nthreads_per_trial
if ngpus_per_trial is not None:
config['ngpus_per_trial'] = ngpus_per_trial
if dist_ip_addrs is not None:
config['dist_ip_addrs'] = dist_ip_addrs
if isinstance(hyperparameters, dict):
# check if hyperparameters overwriting existing config
for k, v in hyperparameters.items():
if k in config:
raise ValueError(f'Overwriting {k} = {config[k]} to {v} by hyperparameters is ambiguous.')
config.update(hyperparameters)
if scheduler_options is not None:
config.update(scheduler_options)
# verbosity
if log_level > logging.INFO:
logging.getLogger('gluoncv.auto.tasks.object_detection').propagate = False
for logger_name in ('SSDEstimator', 'CenterNetEstimator', 'YOLOv3Estimator', 'FasterRCNNEstimator'):
logging.getLogger(logger_name).setLevel(log_level)
logging.getLogger(logger_name).propagate = False
task = _ObjectDetection(config=config)
task._logger.setLevel(log_level)
task._logger.propagate = True
self._detector = task.fit(train_data, val_data, 1 - holdout_frac, random_state)
self._detector._logger.setLevel(log_level)
self._detector._logger.propagate = True
self._fit_summary = task.fit_summary()
[docs] def predict(self, x):
"""Predict objects in image, return the confidences, bounding boxes of each predicted object.
Parameters
----------
x : str, pd.DataFrame or ndarray
The input, can be str(filepath), pd.DataFrame with 'image' column, or raw ndarray input.
Returns
-------
pd.DataFrame
The returned dataframe will contain (`pred_score`, `pred_bbox`, `pred_id`).
If more than one image in input, the returned dataframe will contain `images` column,
and all results are concatenated.
"""
if self._detector is None:
raise RuntimeError('Detector is not initialized, try `fit` first.')
return self._detector.predict(x)
[docs] def evaluate(self, val_data):
"""Evaluate model performance on validation data.
Parameters
----------
val_data : pd.DataFrame or iterator
The validation data.
"""
if self._detector is None:
raise RuntimeError('Detector not initialized, try `fit` first.')
return self._detector.evaluate(val_data)
[docs] def fit_summary(self):
"""Return summary of last `fit` process.
Returns
-------
dict
The summary of last `fit` process. Major keys are ('train_map', 'val_map', 'total_time',...)
"""
return copy.copy(self._fit_summary)
[docs] def save(self, file_name):
"""Dump predictor to disk.
Parameters
----------
file_name : str
The file name of saved copy.
"""
with open(file_name, 'wb') as fid:
pickle.dump(self, fid)
[docs] @classmethod
def load(cls, file_name):
"""Load previously saved predictor.
Parameters
----------
file_name : str
The file name for saved pickle file.
"""
with open(file_name, 'rb') as fid:
obj = pickle.load(fid)
return obj