Exemplo n.º 1
0
    def check_membership(
        self, parameterization: TParameterization, raise_error: bool = False
    ) -> bool:
        """Whether the given parameterization belongs in the search space.

        Checks that the given parameter values have the same name/type as
        search space parameters, are contained in the search space domain,
        and satisfy the parameter constraints.

        Args:
            parameterization: Dict from parameter name to value to validate.
            raise_error: If true parameterization does not belong, raises an error
                with detailed explanation of why.

        Returns:
            Whether the parameterization is contained in the search space.
        """
        if len(parameterization) != len(self._parameters):
            if raise_error:
                raise ValueError(
                    f"Parameterization has {len(parameterization)} parameters "
                    f"but search space has {len(self._parameters)}."
                )
            return False

        for name, value in parameterization.items():
            if name not in self._parameters:
                if raise_error:
                    raise ValueError(
                        f"Parameter {name} not defined in search space"
                        f"with parameters {self._parameters}"
                    )
                return False

            if not self._parameters[name].validate(value):
                if raise_error:
                    raise ValueError(
                        f"{value} is not a valid value for "
                        f"parameter {self._parameters[name]}"
                    )
                return False

        # parameter constraints only accept numeric parameters
        numerical_param_dict = {
            # pyre-fixme[6]: Expected `typing.Union[...oat]` but got `unknown`.
            name: float(value)
            for name, value in parameterization.items()
            if self._parameters[name].is_numeric
        }

        for constraint in self._parameter_constraints:
            if not constraint.check(numerical_param_dict):
                if raise_error:
                    raise ValueError(f"Parameter constraint {constraint} is violated.")
                return False

        return True
Exemplo n.º 2
0
    def check_types(
        self,
        parameterization: TParameterization,
        allow_none: bool = True,
        raise_error: bool = False,
    ) -> bool:
        """Checks that the given parameterization's types match the search space.

        Args:
            parameterization: Dict from parameter name to value to validate.
            allow_none: Whether None is a valid parameter value.
            raise_error: If true and parameterization does not belong, raises an error
                with detailed explanation of why.

        Returns:
            Whether the parameterization has valid types.
        """
        for name, value in parameterization.items():
            if name not in self._parameters:
                if raise_error:
                    raise ValueError(
                        f"Parameter {name} not defined in search space")
                return False

            if value is None and allow_none:
                continue

            if not self._parameters[name].is_valid_type(value):
                if raise_error:
                    raise ValueError(f"{value} is not a valid value for "
                                     f"parameter {self._parameters[name]}")
                return False

        return True
Exemplo n.º 3
0
    def check_all_parameters_present(
        self,
        parameterization: TParameterization,
        raise_error: bool = False,
    ) -> bool:
        """Whether a given parameterization contains all the parameters in the
        search space.

        Args:
            parameterization: Dict from parameter name to value to validate.
            raise_error: If true parameterization does not belong, raises an error
                with detailed explanation of why.

        Returns:
            Whether the parameterization is contained in the search space.
        """
        parameterization_params = set(parameterization.keys())
        ss_params = set(self._parameters.keys())
        if parameterization_params != ss_params:
            if raise_error:
                raise ValueError(
                    f"Parameterization has parameters: {parameterization_params}, "
                    f"but search space has parameters: {ss_params}.")
            return False
        return True
Exemplo n.º 4
0
def _numpy_types_to_python_types(
    parameterization: TParameterization, ) -> TParameterization:
    """If applicable, coerce values of the parameterization from Numpy int/float to
    Python int/float.
    """
    return {
        name: numpy_type_to_python_type(value)
        for name, value in parameterization.items()
    }
Exemplo n.º 5
0
def randomized_round_parameters(
        parameters: TParameterization,
        transform_parameters: Set[str]) -> TParameterization:
    rounded_parameters = copy(parameters)
    for p_name in transform_parameters:
        # pyre: param is declared to have type `float` but is used as
        # pyre-fixme[9]: type `Optional[typing.Union[bool, float, str]]`.
        param: float = parameters.get(p_name)
        rounded_parameters[p_name] = randomized_round(param)
    return rounded_parameters
Exemplo n.º 6
0
    def check_membership(
        self,
        parameterization: TParameterization,
        raise_error: bool = False,
        check_all_parameters_present: bool = True,
    ) -> bool:
        """Whether the given parameterization belongs in the search space.

        Checks that the given parameter values have the same name/type as
        search space parameters, are contained in the search space domain,
        and satisfy the parameter constraints.

        Args:
            parameterization: Dict from parameter name to value to validate.
            raise_error: If true parameterization does not belong, raises an error
                with detailed explanation of why.
            check_all_parameters_present: Ensure that parameterization specifies
                values for all parameters as expected by the search space and its
                hierarchical structure.

        Returns:
            Whether the parameterization is contained in the search space.
        """
        super().check_membership(
            parameterization=parameterization,
            raise_error=raise_error,
            check_all_parameters_present=False,
        )

        # Check that each arm "belongs" in the hierarchical
        # search space; ensure that it only has the parameters that make sense
        # with each other (and does not contain dependent parameters if the
        # parameter they depend on does not have the correct value).
        cast_to_hss_params = set(
            self._cast_parameterization(
                parameters=parameterization,
                check_all_parameters_present=check_all_parameters_present,
            ).keys()
        )
        parameterization_params = set(parameterization.keys())
        if cast_to_hss_params != parameterization_params:
            if raise_error:
                raise ValueError(
                    "Parameterization violates the hierarchical structure of the search"
                    f"space; cast version would have parameters: {cast_to_hss_params},"
                    f" but full version contains parameters: {parameterization_params}."
                )

            return False

        return True
Exemplo n.º 7
0
def _parameterization_probability(
    parameterization: TParameterization,
    coefficients: Dict[str, Dict[TParamValue, float]],
    noise_var: float = 0.0,
) -> float:
    z = 0.0
    for factor, level in parameterization.items():
        if factor not in coefficients.keys():
            raise ValueError("{} not in supplied coefficients".format(factor))
        if level not in coefficients[factor].keys():
            raise ValueError("{} not a valid level of {}".format(level, factor))
        z += coefficients[factor][level]
    z += np.sqrt(noise_var) * np.random.randn()
    return np.exp(z) / (1 + np.exp(z))
Exemplo n.º 8
0
    def md5hash(parameters: TParameterization) -> str:
        """Return unique identifier for arm's parameters.

        Args:
            parameters: Parameterization; mapping of param name
                to value.

        Returns:
            Hash of arm's parameters.

        """
        for k, v in parameters.items():
            parameters[k] = numpy_type_to_python_type(v)
        parameters_str = json.dumps(parameters, sort_keys=True)
        return hashlib.md5(parameters_str.encode("utf-8")).hexdigest()
Exemplo n.º 9
0
    def check_types(
        self,
        parameterization: TParameterization,
        allow_none: bool = True,
        raise_error: bool = False,
    ) -> bool:
        """Checks that the given parameterization's types match the search space.

        Checks that the names of the parameterization match those specified in
        the search space, and the given values are of the correct type.

        Args:
            parameterization: Dict from parameter name to value to validate.
            allow_none: Whether None is a valid parameter value.
            raise_error: If true and parameterization does not belong, raises an error
                with detailed explanation of why.

        Returns:
            Whether the parameterization has valid types.
        """
        if len(parameterization) != len(self._parameters):
            if raise_error:
                raise ValueError(
                    f"Parameterization has {len(parameterization)} parameters "
                    f"but search space has {len(self._parameters)}.\n"
                    f"Parameterization: {parameterization}.\n"
                    f"Search Space: {self._parameters}."
                )
            return False

        for name, value in parameterization.items():
            if name not in self._parameters:
                if raise_error:
                    raise ValueError(f"Parameter {name} not defined in search space")
                return False

            if value is None and allow_none:
                continue

            if not self._parameters[name].is_valid_type(value):
                if raise_error:
                    raise ValueError(
                        f"{value} is not a valid value for "
                        f"parameter {self._parameters[name]}"
                    )
                return False

        return True
Exemplo n.º 10
0
def _format_dict(param_dict: TParameterization,
                 name: str = "Parameterization") -> str:
    """Format a dictionary for labels.

    Args:
        param_dict: Dictionary to be formatted
        name: String name of the thing being formatted.

    Returns: stringified blob.
    """
    if len(param_dict) >= 10:
        blob = "{} has too many items to render on hover ({}).".format(
            name, len(param_dict))
    else:
        blob = "<br><em>{}:</em><br>{}".format(
            name,
            "<br>".join("{}: {}".format(n, v) for n, v in param_dict.items()))
    return blob
Exemplo n.º 11
0
    def _cast_parameterization(
        self,
        parameters: TParameterization,
        check_all_parameters_present: bool = True,
    ) -> TParameterization:
        """Cast parameterization (of an arm, observation features, etc.) to the
        hierarchical structure of this search space.

        Args:
            parameters: Parameterization to cast to hierarchical structure.
            check_all_parameters_present: Whether to raise an error if a paramete
                 that is expected to be present (according to values of other
                 parameters and the hierarchical structure of the search space)
                 is not specified.
        """
        def _find_applicable_parameters(root: Parameter) -> Set[str]:
            applicable = {root.name}
            if check_all_parameters_present and root.name not in parameters:
                raise RuntimeError(
                    f"Parameter '{root.name}' not in parameterization to cast."
                )

            if not root.is_hierarchical:
                return applicable

            for val, deps in root.dependents.items():
                if parameters[root.name] == val:
                    for dep in deps:
                        applicable.update(
                            _find_applicable_parameters(root=self[dep]))

            return applicable

        applicable_paramers = _find_applicable_parameters(root=self.root)
        if not all(k in parameters for k in applicable_paramers):
            raise RuntimeError(
                f"Parameters {applicable_paramers- set(parameters.keys())} "
                "missing from the arm.")

        return {
            k: v
            for k, v in parameters.items() if k in applicable_paramers
        }
Exemplo n.º 12
0
def _filter_dict(param_dict: TParameterization,
                 subset_keys: List[str]) -> TParameterization:
    """Filter a dictionary to keys present in a given list."""
    return {k: v for k, v in param_dict.items() if k in subset_keys}
Exemplo n.º 13
0
def _get_sum(parameterization: TParameterization) -> float:
    param_names = list(parameterization.keys())
    if any(param_name not in param_names for param_name in ["x1", "x2"]):
        raise ValueError("Parametrization does not contain x1 or x2")
    x1, x2 = parameterization["x1"], parameterization["x2"]
    return x1 + x2