Пример #1
0
    def select(self, keys):
        """Only select or only drop the specified keys

        For a pair (key, value) in the dictionnary, value=0 means the key will not be included
        while value=1 means it will.

        All specified keys should be 0 or 1. They cannot have different values with the exception
        of _id which can be specified to 0 while the others are at 1. The _id field is always
        returned unless specified with 0.

        Parameters
        ----------
        keys: dict
            Pairs of keys and 0 or 1s. When a key is associated with 1, it is kept in the selection,
            otherwise it is dropped.

        """
        if not keys:
            return unflatten(self._data)

        keys = flatten(keys)
        keys = self._validate_keys(keys)

        selection = dict()

        def key_is_match(key, selected_key):
            """Test if key matches the selected key

            key_is_match(abc.def.ghi, abc.def.ghi) -> True
            key_is_match(abc.def.ghi, abc.def) -> True
            key_is_match(abc.def.ghi, abc.de) -> False
            key_is_match(abc.def.ghi, xyz) -> False
            """
            return (key == selected_key
                    or (key.startswith(selected_key)
                        and key.replace(selected_key, '')[0] == "."))

        for selected_key, include in filter(lambda item: item[1],
                                            keys.items()):
            match = False
            for key, value in self._data.items():
                if include and key_is_match(key, selected_key):
                    match = True
                    selection[key] = value

            if not match:
                selection[selected_key] = None

        return unflatten(selection)
Пример #2
0
    def workon(self, fct, max_trials=infinity, **kwargs):
        """Optimize a given function

        Parameters
        ----------
        fct: callable
            Function to optimize. Must take arguments provided by trial.params. Additional constant
            parameter can be passed as ``**kwargs`` to `workon`. Function must return the final
            objective.
        max_trials: int, optional
            Maximum number of trials to execute within `workon`. If the experiment or algorithm
            reach status is_done before, the execution of `workon` terminates.
        **kwargs
            Constant argument to pass to `fct` in addition to trial.params. If values in kwargs are
            present in trial.params, the latter takes precedence.

        Raises
        ------
        `ValueError`
             If results returned by `fct` have invalid format

        """
        trials = 0
        kwargs = flatten(kwargs)
        while not self.is_done and trials < max_trials:
            trial = self.suggest()
            if trial is None:
                log.warning('Algorithm could not sample new points')
                return trials
            kwargs.update(flatten(trial.params))
            results = fct(**unflatten(kwargs))
            self.observe(trial, results=results)
            trials += 1

        return trials
Пример #3
0
def _optimize(trial, fct, trial_arg, **kwargs):
    """Execute a trial on a worker"""

    kwargs.update(flatten(trial.params))

    if trial_arg:
        kwargs[trial_arg] = trial

    return fct(**unflatten(kwargs))
Пример #4
0
    def __call__(self, rng, space, params):
        """Execute perturbation

        Given a set of parameter values, this exploration object randomly perturb them with a given
        ``factor``. It will multiply the value of a dimension with probability 0.5, otherwise divide
        it. Values are clamped to limits of the search space when exceeding it. For categorical
        dimensions, a new value is sampled from categories with equal probability for each
        categories.

        Parameters
        ----------
        rng: numpy.random.Generator
            A random number generator. It is not contained in ``BaseExplore`` because the explore
            class must be stateless.
        space: Space
            The search space optimized by the algorithm.
        params: dict
            Dictionary representing the parameters of the current trial under examination
            (`trial.params`).

        Returns
        -------
        ``dict``
            The new set of parameters for the trial to be branched.

        """

        new_params = {}
        params = flatten(params)
        for dim in space.values():
            dim_value = params[dim.name]
            if dim.type == "real":
                dim_value = self.perturb_real(rng, dim_value, dim.interval())
            elif dim.type == "integer":
                dim_value = self.perturb_int(rng, dim_value, dim.interval())
            elif dim.type == "categorical":
                dim_value = self.perturb_cat(rng, dim_value, dim)
            elif dim.type == "fidelity":
                # do nothing
                pass
            else:
                raise ValueError(f"Unsupported dimension type {dim.type}")

            new_params[dim.name] = dim_value

        return unflatten(new_params)
Пример #5
0
    def update(self, data):
        """Update the values of the document.

        Parameters
        ----------
        data: dict
            Dictionary of data to update the document. If `$set` is in
            the data, the corresponding `data[$set]` will be used instead.

        """
        if "$set" in data:
            unflattened_data = unflatten(self._data)
            for key, value in data["$set"].items():
                if isinstance(value, dict):
                    value = flatten(value)
                unflattened_data[key] = value
            self._data = flatten(unflattened_data)
        else:
            self._data.update(flatten(data))
Пример #6
0
def fetch_config_from_cmdargs(cmdargs):
    """Turn flat cmdargs into nested dicts like orion.core.config."""
    config_file = cmdargs.pop("config", None)
    tmp_cmdargs = copy.deepcopy(cmdargs)
    tmp_cmdargs["config"] = config_file
    cmdargs["config"] = config_file
    cmdargs = tmp_cmdargs

    cmdargs_config = {}

    if cmdargs.get("max_trials") is not None:
        log.warning("--max-trials is deprecated and will be removed in v0.3. "
                    "Use --exp-max-trials instead")
        cmdargs_config["experiment.max_trials"] = cmdargs.pop("max_trials")

    if cmdargs.get("worker_trials") is not None:
        log.warning(
            "--worker-trials is deprecated and will be removed in v0.3. "
            "Use --worker-max-trials instead")
        cmdargs_config["worker.max_trials"] = cmdargs.pop("worker_trials")

    mappings = dict(
        experiment=dict(max_broken="exp_max_broken",
                        max_trials="exp_max_trials"),
        worker=dict(max_broken="worker_max_broken",
                    max_trials="worker_max_trials"),
        evc=dict(enable="enable_evc"),
    )

    global_config = orion.core.config.to_dict()

    for key in ["config", "user_args"]:
        if cmdargs.get(key) not in [False, None]:
            cmdargs_config[key] = cmdargs[key]

    for key in ["name", "user", "version"]:
        if cmdargs.get(key) not in [False, None]:
            cmdargs_config[f"experiment.{key}"] = cmdargs[key]

    for key in ["branch_from", "branch_to"]:
        if cmdargs.get(key) not in [False, None]:
            cmdargs_config[f"evc.{key}"] = cmdargs[key]

    # Apply config at the root
    for key in ["debug"]:

        # Adapt to cli arguments
        cli_key = mappings.get(key, key)

        value = cmdargs.pop(cli_key, None)
        if value is not None:
            cmdargs_config[f"{key}"] = value

    # Apply to subconfigs
    for key in ["experiment", "worker", "evc"]:
        for subkey in global_config[key].keys():

            # Adapt to cli arguments
            cli_key = mappings.get(key, {}).get(subkey, subkey)

            value = cmdargs.pop(cli_key, None)
            if value is not None:
                cmdargs_config[f"{key}.{subkey}"] = value

    return unflatten(cmdargs_config)
Пример #7
0
def fetch_config(args):
    """Return the config inside the .yaml file if present."""
    orion_file = args.get("config")
    local_config = {}
    if orion_file:
        log.debug("Found orion configuration file at: %s",
                  os.path.abspath(orion_file.name))
        orion_file.seek(0)
        tmp_config = yaml.safe_load(orion_file)

        global_config = orion.core.config.to_dict()

        tmp_config = _convert_dashes(tmp_config, global_config)

        # Fix deprecations first because some names are shared by experiment and worker
        max_trials = tmp_config.pop("max_trials", None)
        if max_trials is not None:
            log.warning(
                "(DEPRECATED) Option `max_trials` is deprecated "
                "and will be removed in v0.3. Use instead the option"
                "\nexperiment:\n  max_trials: %s",
                max_trials,
            )
            local_config["experiment.max_trials"] = max_trials

        worker_trials = tmp_config.get("experiment",
                                       {}).pop("worker_trials", None)
        if worker_trials is not None:
            log.warning(
                "(DEPRECATED) Option `experiment.worker_trials` is deprecated "
                "and will be removed in v0.3. Use instead the option"
                "\nworker:\n  max_trials: %s",
                worker_trials,
            )
            local_config["worker.max_trials"] = worker_trials

        worker_trials = tmp_config.pop("worker_trials", None)
        if worker_trials is not None:
            log.warning(
                "(DEPRECATED) Option `worker_trials` is deprecated "
                "and will be removed in v0.3. Use instead the option"
                "\nworker:\n  max_trials: %s",
                worker_trials,
            )
            local_config["worker.max_trials"] = worker_trials

        # TODO: Remove for v0.3
        producer = tmp_config.pop("producer", None)
        if producer is not None:
            log.warning(
                "(DEPRECATED) Option `producer` is deprecated "
                "and will be removed in v0.3. Use instead the option"
                "\nexperiment:\n  strategy: %s",
                producer["strategy"],
            )
            local_config["experiment.strategy"] = producer["strategy"]

        # TODO: Remove for v0.3
        producer = tmp_config.get("experiment", {}).pop("producer", None)
        if producer is not None:
            log.warning(
                "(DEPRECATED) Option `experiment.producer` is deprecated "
                "and will be removed in v0.3. Use instead the option"
                "\nexperiment:\n  strategy: %s",
                producer["strategy"],
            )
            local_config["experiment.strategy"] = producer["strategy"]

        local_config = unflatten(local_config)

        # For backward compatibility
        for key in ["storage", "experiment", "worker", "evc"]:
            subkeys = list(global_config[key].keys())

            # Arguments that are only supported locally
            if key == "experiment":
                subkeys += ["name", "version", "user"]
            elif key == "evc":
                subkeys += ["branch_from", "branch_to"]

            for subkey in subkeys:
                # Backward compatibility
                backward_value = tmp_config.pop(subkey, None)
                if backward_value is not None:
                    log.warning(
                        "(DEPRECATED) Option `%s` and will be removed in v0.3. "
                        "Use instead the option"
                        "\n%s:\n  %s:\n    %s",
                        subkey,
                        key,
                        subkey,
                        yaml.dump(backward_value, indent=6),
                    )
                value = tmp_config.get(key, {}).pop(subkey, backward_value)
                if value is not None:
                    local_config.setdefault(key, {})
                    local_config[key][subkey] = value

    return local_config
Пример #8
0
 def params(self):
     """Parameters of the trial"""
     return unflatten({param.name: param.value for param in self._params})
Пример #9
0
def fetch_config(args):
    """Return the config inside the .yaml file if present."""
    orion_file = args.get('config')
    local_config = {}
    if orion_file:
        log.debug("Found orion configuration file at: %s", os.path.abspath(orion_file.name))
        orion_file.seek(0)
        tmp_config = yaml.safe_load(orion_file)

        global_config = config.to_dict()

        tmp_config = _convert_dashes(tmp_config, global_config)

        # Fix deprecations first because some names are shared by experiment and worker
        max_trials = tmp_config.pop('max_trials', None)
        if max_trials is not None:
            log.warning(
                '(DEPRECATED) Option `max_trials` is deprecated '
                'and will be removed in v0.3. Use instead the option'
                '\nexperiment:\n  max_trials: %s', max_trials)
            local_config['experiment.max_trials'] = max_trials

        worker_trials = tmp_config.get('experiment', {}).pop('worker_trials', None)
        if worker_trials is not None:
            log.warning(
                '(DEPRECATED) Option `experiment.worker_trials` is deprecated '
                'and will be removed in v0.3. Use instead the option'
                '\nworker:\n  max_trials: %s', worker_trials)
            local_config['worker.max_trials'] = worker_trials

        worker_trials = tmp_config.pop('worker_trials', None)
        if worker_trials is not None:
            log.warning(
                '(DEPRECATED) Option `worker_trials` is deprecated '
                'and will be removed in v0.3. Use instead the option'
                '\nworker:\n  max_trials: %s', worker_trials)
            local_config['worker.max_trials'] = worker_trials

        producer = tmp_config.pop('producer', None)
        if producer is not None:
            log.warning(
                '(DEPRECATED) Option `producer` is deprecated '
                'and will be removed in v0.3. Use instead the option'
                '\nexperiment:\n  strategy: %s', producer['strategy'])
            local_config['experiment.strategy'] = producer['strategy']

        producer = tmp_config.get('experiment', {}).pop('producer', None)
        if producer is not None:
            log.warning(
                '(DEPRECATED) Option `experiment.producer` is deprecated '
                'and will be removed in v0.3. Use instead the option'
                '\nexperiment:\n  strategy: %s', producer['strategy'])
            local_config['experiment.strategy'] = producer['strategy']

        local_config = unflatten(local_config)

        # For backward compatibility
        for key in ['storage', 'experiment', 'worker', 'evc']:
            subkeys = list(global_config[key].keys())

            # Arguments that are only supported locally
            if key == 'experiment':
                subkeys += ['name', 'version', 'user']
            elif key == 'evc':
                subkeys += ['branch_from', 'branch_to']

            for subkey in subkeys:
                # Backward compatibility
                backward_value = tmp_config.pop(subkey, None)
                if backward_value is not None:
                    log.warning(
                        '(DEPRECATED) Option `%s` and will be removed in v0.3. '
                        'Use instead the option' '\n%s:\n  %s:\n    %s',
                        subkey, key, subkey, yaml.dump(backward_value, indent=6))
                value = tmp_config.get(key, {}).pop(subkey, backward_value)
                if value is not None:
                    local_config.setdefault(key, {})
                    local_config[key][subkey] = value

    return local_config
Пример #10
0
def fetch_config_from_cmdargs(cmdargs):
    """Turn flat cmdargs into nested dicts like orion.core.config."""
    config_file = cmdargs.pop('config', None)
    tmp_cmdargs = copy.deepcopy(cmdargs)
    tmp_cmdargs['config'] = config_file
    cmdargs['config'] = config_file
    cmdargs = tmp_cmdargs

    cmdargs_config = {}

    if cmdargs.get('max_trials') is not None:
        log.warning(
            '--max-trials is deprecated and will be removed in v0.3. '
            'Use --exp-max-trials instead')
        cmdargs_config['experiment.max_trials'] = cmdargs.pop('max_trials')

    if cmdargs.get('worker_trials') is not None:
        log.warning(
            '--worker-trials is deprecated and will be removed in v0.3. '
            'Use --worker-max-trials instead')
        cmdargs_config['worker.max_trials'] = cmdargs.pop('worker_trials')

    mappings = dict(
        experiment=dict(
            exp_max_broken='max_broken',
            exp_max_trials='max_trials'),
        worker=dict(
            worker_max_broken='max_broken',
            worker_max_trials='max_trials'))

    mappings = dict(
        experiment=dict(
            max_broken='exp_max_broken',
            max_trials='exp_max_trials'),
        worker=dict(
            max_broken='worker_max_broken',
            max_trials='worker_max_trials'))

    global_config = config.to_dict()

    for key in ['config', 'user_args']:
        if cmdargs.get(key) not in [False, None]:
            cmdargs_config[key] = cmdargs[key]

    for key in ['name', 'user', 'version']:
        if cmdargs.get(key) not in [False, None]:
            cmdargs_config[f'experiment.{key}'] = cmdargs[key]

    for key in ['branch_from', 'branch_to']:
        if cmdargs.get(key) not in [False, None]:
            cmdargs_config[f'evc.{key}'] = cmdargs[key]

    # Apply config at the root
    for key in ['debug']:

        # Adapt to cli arguments
        cli_key = mappings.get(key, key)

        value = cmdargs.pop(cli_key, None)
        if value is not None:
            cmdargs_config[f'{key}'] = value

    # Apply to subconfigs
    for key in ['experiment', 'worker', 'evc']:
        for subkey in global_config[key].keys():

            # Adapt to cli arguments
            cli_key = mappings.get(key, {}).get(subkey, subkey)

            value = cmdargs.pop(cli_key, None)
            if value is not None:
                cmdargs_config[f'{key}.{subkey}'] = value

    return unflatten(cmdargs_config)
Пример #11
0
    def params(self):
        """See `~orion.core.worker.trial.Trial`"""
        if self.memory is not None:
            return self.memory.params

        return unflatten({param.name: param.value for param in self._params})
Пример #12
0
def test_unflatten():
    """Test than unflatten(flatten(x)) is idempotent"""
    a = {"b": 2, "c": 3}
    d = {"a": a, "d": {"e": a}}
    assert unflatten(flatten(d)) == d