Source code for evalml.tuners.tuner

from abc import ABC, abstractmethod

from skopt.space import Categorical, Integer, Real


[docs]class Tuner(ABC): """Defines API for Tuners. Tuners implement different strategies for sampling from a search space. They're used in EvalML to search the space of pipeline hyperparameters. """
[docs] def __init__(self, pipeline_hyperparameter_ranges, random_seed=0): """Base Tuner class Arguments: pipeline_hyperparameter_ranges (dict): a set of hyperparameter ranges corresponding to a pipeline's parameters random_seed (int): The random state. Defaults to 0. """ self._pipeline_hyperparameter_ranges = pipeline_hyperparameter_ranges self._parameter_names_map = dict() self._search_space_names = [] self._search_space_ranges = [] if not isinstance(pipeline_hyperparameter_ranges, dict): raise ValueError('pipeline_hyperparameter_ranges must be a dict but is of type {}'.format(type(pipeline_hyperparameter_ranges))) self._component_names = list(pipeline_hyperparameter_ranges.keys()) for component_name, component_ranges in pipeline_hyperparameter_ranges.items(): if not isinstance(component_ranges, dict): raise ValueError('pipeline_hyperparameter_ranges has invalid entry for {}: {}'.format(component_name, component_ranges)) for parameter_name, parameter_range in component_ranges.items(): if parameter_range is None: raise ValueError('pipeline_hyperparameter_ranges has invalid dimensions for ' + '{} parameter {}: None.'.format(component_name, parameter_name)) if not isinstance(parameter_range, (Real, Integer, Categorical, list, tuple)): continue flat_parameter_name = '{}: {}'.format(component_name, parameter_name) self._parameter_names_map[flat_parameter_name] = (component_name, parameter_name) self._search_space_names.append(flat_parameter_name) self._search_space_ranges.append(parameter_range)
def _convert_to_flat_parameters(self, pipeline_parameters): """Convert from pipeline parameters to a flat list of values""" flat_parameter_values = [] for flat_parameter_name in self._search_space_names: component_name, parameter_name = self._parameter_names_map[flat_parameter_name] if component_name not in pipeline_parameters or parameter_name not in pipeline_parameters[component_name]: raise TypeError('Pipeline parameters missing required field "{}" for component "{}"'.format(parameter_name, component_name)) flat_parameter_values.append(pipeline_parameters[component_name][parameter_name]) return flat_parameter_values def _convert_to_pipeline_parameters(self, flat_parameters): """Convert from a flat list of values to a dict of pipeline parameters""" pipeline_parameters = {component_name: dict() for component_name in self._component_names} for flat_parameter_name, parameter_value in zip(self._search_space_names, flat_parameters): component_name, parameter_name = self._parameter_names_map[flat_parameter_name] pipeline_parameters[component_name][parameter_name] = parameter_value return pipeline_parameters
[docs] @abstractmethod def add(self, pipeline_parameters, score): """Register a set of hyperparameters with the score obtained from training a pipeline with those hyperparameters. Arguments: pipeline_parameters (dict): a dict of the parameters used to evaluate a pipeline score (float): the score obtained by evaluating the pipeline with the provided parameters Returns: None """
[docs] @abstractmethod def propose(self): """Returns a suggested set of parameters to train and score a pipeline with, based off the search space dimensions and prior samples. Returns: dict: Proposed pipeline parameters """
[docs] def is_search_space_exhausted(self): """Optional. If possible search space for tuner is finite, this method indicates whether or not all possible parameters have been scored. Returns: bool: Returns true if all possible parameters in a search space has been scored. """ return False