def _get_jobs(self, jobs=None) -> list: if jobs is None: jobs = list(self.models.keys()) elif isinstance(jobs, str): jobs = [jobs] result = [] for name in jobs: identifier = name.split(".", 1) try: model = self.models[identifier[0]] except KeyError: raise DescriptorError(f'Job "{name}" was not found') if len(identifier) == 2: try: job = model.jobs[identifier[1]] except KeyError: raise DescriptorError(f'Job "{name}" was not found') else: result.append(job) else: for job in model.jobs.values(): result.append(job) return result
def _get_estimator(self, estimator, model, job, properties, hyperparameters): def remove_attribute(properties, attribute): if attribute in properties: del properties[attribute] identifiers = estimator.strip().split(".") class_name = identifiers[-1] module_name = ".".join(identifiers[:-1]) if not module_name: raise DescriptorError(f'Error creating estimator "{estimator}"') try: module = importlib.import_module(module_name) class_ = getattr(module, class_name) except ModuleNotFoundError: raise DescriptorError(f'Error creating estimator "{estimator}"') except AttributeError: raise DescriptorError(f'Error creating estimator "{estimator}"') else: remove_attribute(properties, "model") remove_attribute(properties, "job") remove_attribute(properties, "hyperparameters") try: return class_( model=model, job=job, hyperparameters=hyperparameters, **properties, ) except TypeError as e: raise DescriptorError( f'Error creating estimator "{estimator}". {str(e)}' )
def _load_descriptor(self, descriptor_file_path) -> None: try: with open(descriptor_file_path) as f: data = yaml.load(f, Loader=yaml.FullLoader) except FileNotFoundError: raise except ScannerError as e: raise DescriptorError( f"The specified file is not a valid descriptor. Error: {str(e)}" ) except ParserError as e: raise DescriptorError( f"The specified file is not a valid descriptor. Error: {str(e)}" ) else: self._parse_descriptor(data)
def _parse_descriptor(self, data: dict()) -> None: if not isinstance(data, dict): raise DescriptorError("The specified file is not a valid descriptor") try: descriptor_models = data["models"] except KeyError: raise DescriptorError( 'Descriptor file is missing the root element "models".' ) else: if descriptor_models is None: return for name, data in descriptor_models.items(): self.__models[str(name)] = Model(str(name), data)
def _get_continuous_parameter(self, data): if "min_value" not in data: raise DescriptorError( 'The "min_value" attribute of a continuous parameter is required' ) if "max_value" not in data: raise DescriptorError( 'The "max_value" attribute of a continuous parameter is required' ) return ContinuousParameter( min_value=data["min_value"], max_value=data["max_value"], scaling_type=data.get("scaling_type", "Auto"), )
def _get_integer_parameter(self, data): if "min_value" not in data: raise DescriptorError( 'The "min_value" attribute of an integer parameter is required' ) if "max_value" not in data: raise DescriptorError( 'The "max_value" attribute of an integer parameter is required' ) return IntegerParameter( min_value=data["min_value"], max_value=data["max_value"], scaling_type=data.get("scaling_type", "Auto"), )
def _get_categorical_parameter(self, data): if "values" not in data: raise DescriptorError( 'The "values" attribute of a categorical parameter is required' ) return CategoricalParameter(values=data["values"])
def __init__(self, descriptor) -> None: self.__models = dict() if isinstance(descriptor, dict): self._parse_descriptor(data=descriptor) elif isinstance(descriptor, str) or isinstance(descriptor, Path): self._load_descriptor(descriptor_file_path=descriptor) else: raise DescriptorError( "Invalid descriptor source. Must be a dictionary, or " "the path of the descriptor file." )
def _get_hyperparameter_ranges(self, hyperparameter_ranges): if not hyperparameter_ranges: return dict() result = dict() for parameter, data in hyperparameter_ranges.items(): if "type" not in data: raise DescriptorError( f'Parameter "{parameter}" doesn\'t have a "type" specified' ) if data["type"] == "categorical": result[parameter] = self._get_categorical_parameter(data) elif data["type"] == "integer": result[parameter] = self._get_integer_parameter(data) elif data["type"] == "continuous": result[parameter] = self._get_continuous_parameter(data) else: raise DescriptorError( f"Parameter type \"{data['type']}\" is not supported" ) return result