Beispiel #1
0
    def __compute_alternative_params(self):
        # Copied directly from skopt
        transformed_bounds = np.array(self.__opt.space.transformed_bounds)
        est = clone(self.__opt.base_estimator)

        with warnings.catch_warnings():
            warnings.simplefilter("ignore")
            est.fit(self.__opt.space.transform(self.__opt.Xi), self.__opt.yi)

        X = self.__opt.space.transform(self.__opt.space.rvs(
            n_samples=self.__opt.n_points, random_state=self.__opt.rng))

        values = _gaussian_acquisition(X=X, model=est, y_opt=np.min(self.__opt.yi),
                                       acq_func='EI',
                                       acq_func_kwargs=dict(n_points=10000))

        print('original point ei: %s' % np.min(values))
        discount_width = .5
        values = self.__discount_leased_params(X, values, discount_width)
        while np.min(values) > -1e-5 and discount_width > 1e-2:
            discount_width *= .9
            values = _gaussian_acquisition(X=X, model=est, y_opt=np.min(self.__opt.yi),
                                           acq_func='EI',
                                           acq_func_kwargs=dict(n_points=10000))
            values = self.__discount_leased_params(X, values, discount_width)
        next_x = X[np.argmin(values)]
        print('new point ei: %s' % np.min(values))

        if not self.__opt.space.is_categorical:
            next_x = np.clip(next_x, transformed_bounds[:, 0], transformed_bounds[:, 1])

        return self.__opt.space.inverse_transform(next_x.reshape((1, -1)))[0]
Beispiel #2
0
 def evaluate(X, surrogate_model, y_opt, acq_func_kwargs=None):
     return _gaussian_acquisition(
         X=X,
         model=surrogate_model,
         y_opt=y_opt,
         acq_func="PI",
         acq_func_kwargs=acq_func_kwargs,
     )
Beispiel #3
0
def test_acquisition_per_second(acq_func):
    X = np.reshape(np.linspace(4.0, 8.0, 10), (-1, 1))
    y = np.vstack((np.ones(10), np.ravel(np.log(X)))).T
    cgpr = ConstantGPRSurrogate(Space(((1.0, 9.0),)))
    cgpr.fit(X, y)

    X_pred = np.reshape(np.linspace(1.0, 11.0, 20), (-1, 1))
    indices = np.arange(6)
    vals = _gaussian_acquisition(X_pred, cgpr, y_opt=1.0, acq_func=acq_func)
    for fast, slow in zip(indices[:-1], indices[1:]):
        assert vals[slow] > vals[fast]

    acq_wo_time = _gaussian_acquisition(
        X, cgpr.estimators_[0], y_opt=1.2, acq_func=acq_func[:2])
    acq_with_time = _gaussian_acquisition(
        X, cgpr, y_opt=1.2, acq_func=acq_func)
    assert_array_almost_equal(acq_wo_time / acq_with_time, np.ravel(X), 2)
def test_acquisition_per_second(acq_func):
    X = np.reshape(np.linspace(4.0, 8.0, 10), (-1, 1))
    y = np.vstack((np.ones(10), np.ravel(np.log(X)))).T
    cgpr = ConstantGPRSurrogate(Space(((1.0, 9.0),)))
    cgpr.fit(X, y)

    X_pred = np.reshape(np.linspace(1.0, 11.0, 20), (-1, 1))
    indices = np.arange(6)
    vals = _gaussian_acquisition(X_pred, cgpr, y_opt=1.0, acq_func=acq_func)
    for fast, slow in zip(indices[:-1], indices[1:]):
        assert_greater(vals[slow], vals[fast])

    acq_wo_time = _gaussian_acquisition(
        X, cgpr.estimators_[0], y_opt=1.2, acq_func=acq_func[:2])
    acq_with_time = _gaussian_acquisition(
        X, cgpr, y_opt=1.2, acq_func=acq_func)
    assert_array_almost_equal(acq_wo_time / acq_with_time, np.ravel(X), 2)
    def _tell(self, x, y, fit=True):
        """Perform the actual work of incorporating one or more new points.
        See `tell()` for the full description.
        This method exists to give access to the internals of adding points
        by side stepping all input validation and transformation."""

        if "ps" in self.acq_func:
            if is_2Dlistlike(x):
                self.Xi.extend(x)
                self.yi.extend(y)
                self._n_initial_points -= len(y)
            elif is_listlike(x):
                self.Xi.append(x)
                self.yi.append(y)
                self._n_initial_points -= 1
        # if y isn't a scalar it means we have been handed a batch of points
        elif is_listlike(y) and is_2Dlistlike(x):
            self.Xi.extend(x)
            self.yi.extend(y)
            self._n_initial_points -= len(y)
        elif is_listlike(x):
            self.Xi.append(x)
            self.yi.append(y)
            self._n_initial_points -= 1
        else:
            raise ValueError("Type of arguments `x` (%s) and `y` (%s) "
                             "not compatible." % (type(x), type(y)))

        # optimizer learned something new - discard cache
        self.cache_ = {}

        # after being "told" n_initial_points we switch from sampling
        # random points to using a surrogate model
        #mprint("starting fit gpr......")

        if (fit and self._n_initial_points <= 0
                and self.base_estimator_ is not None):
            #print('start finding next x.....')
            transformed_bounds = np.array(self.space.transformed_bounds)
            est = clone(self.base_estimator_)
            start_clock = time.time()
            with warnings.catch_warnings():
                warnings.simplefilter("ignore")
                est.fit(self.space.transform(self.Xi), self.yi)
            self.regressiontime = time.time() - start_clock
            self.tt_regressiontime.append(self.regressiontime)
            if hasattr(self, "next_xs_") and self.acq_func == "gp_hedge":
                self.gains_ -= est.predict(np.vstack(self.next_xs_))
            self.models.append(est)

            #mprint("finished fit gpr......")

            # even with BFGS as optimizer we want to sample a large number
            # of points and then pick the best ones as starting points
            start_clock_ac = time.time()
            X = self.space.transform(
                self.space.rvs(n_samples=self.n_points, random_state=self.rng))

            self.next_xs_ = []
            for cand_acq_func in self.cand_acq_funcs_:
                values = _gaussian_acquisition(
                    X=X,
                    model=est,
                    y_opt=np.min(self.yi),
                    acq_func=cand_acq_func,
                    acq_func_kwargs=self.acq_func_kwargs)
                self.values = values
                # Find the minimum of the acquisition function by randomly
                # sampling points from the space
                if self.acq_optimizer == "sampling":
                    next_x = X[np.argmin(values)]

                # Use BFGS to find the mimimum of the acquisition function, the
                # minimization starts from `n_restarts_optimizer` different
                # points and the best minimum is used
                elif self.acq_optimizer == "lbfgs":
                    x0 = X[np.argsort(values)[:self.n_restarts_optimizer]]

                    with warnings.catch_warnings():
                        warnings.simplefilter("ignore")
                        results = Parallel(n_jobs=self.n_jobs)(
                            delayed(fmin_l_bfgs_b)(
                                gaussian_acquisition_1D,
                                x,
                                args=(est, np.min(self.yi), cand_acq_func,
                                      self.acq_func_kwargs),
                                bounds=self.space.transformed_bounds,
                                approx_grad=False,
                                maxiter=20) for x in x0)

                    cand_xs = np.array([r[0] for r in results])
                    cand_acqs = np.array([r[1] for r in results])
                    next_x = cand_xs[np.argmin(cand_acqs)]
                self.actime = start_clock_ac - time.time()
                self.tt_actime.append(self.actime)
                # lbfgs should handle this but just in case there are
                # precision errors.
                if not self.space.is_categorical:
                    next_x = np.clip(next_x, transformed_bounds[:, 0],
                                     transformed_bounds[:, 1])
                self.next_xs_.append(next_x)

            if self.acq_func == "gp_hedge":
                logits = np.array(self.gains_)
                logits -= np.max(logits)
                exp_logits = np.exp(self.eta * logits)
                probs = exp_logits / np.sum(exp_logits)
                next_x = self.next_xs_[np.argmax(self.rng.multinomial(
                    1, probs))]
            else:
                next_x = self.next_xs_[0]

            # note the need for [0] at the end
            self._next_x = self.space.inverse_transform(next_x.reshape(
                (1, -1)))[0]

        # Pack results
        return create_result(self.Xi,
                             self.yi,
                             self.space,
                             self.rng,
                             models=self.models)
    def _tell(self, x, y, fit=True):
        """Perform the actual work of incorporating one or more new points. See :meth:`tell` for
        the full description. This method exists to give access to the internals of adding points
        by side-stepping all input validation and transformation"""
        #################### Collect Search Points and Evaluations ####################
        # TODO: Clean up below - Looks like the 4 extend/append blocks may be duplicated
        if "ps" in self.acq_func:
            if is_2d_list_like(x):
                self.Xi.extend(x)
                self.yi.extend(y)
                self._n_initial_points -= len(y)
            elif is_list_like(x):
                self.Xi.append(x)
                self.yi.append(y)
                self._n_initial_points -= 1
        # If `y` isn't a scalar, we have been handed a batch of points
        elif is_list_like(y) and is_2d_list_like(x):
            self.Xi.extend(x)
            self.yi.extend(y)
            self._n_initial_points -= len(y)
        elif is_list_like(x):
            self.Xi.append(x)
            self.yi.append(y)
            self._n_initial_points -= 1
        else:
            raise ValueError(
                f"Incompatible argument types: `x` ({type(x)}) and `y` ({type(y)})"
            )

        # Optimizer learned something new. Discard `cache_`
        self.cache_ = {}

        #################### Fit Surrogate Model ####################
        # After being `tell`-ed `n_initial_points`, use surrogate model instead of random sampling
        # TODO: Clean up and separate below. Pretty hard to follow the whole thing
        if fit and self._n_initial_points <= 0 and self.base_estimator is not None:
            transformed_bounds = np.array(self.space.transformed_bounds)
            est = clone(self.base_estimator)

            with warnings.catch_warnings():
                warnings.simplefilter("ignore")
                est.fit(self.space.transform(self.Xi), self.yi)

            if hasattr(self, "next_xs_") and self.acq_func == "gp_hedge":
                self.gains_ -= est.predict(np.vstack(self.next_xs_))
            self.models.append(est)

            # Even with BFGS optimizer, we want to sample a large number of points, and
            #   pick the best ones as starting points
            X = self.space.transform(
                self.space.rvs(n_samples=self.n_points, random_state=self.rng))

            self.next_xs_ = []
            for cand_acq_func in self.cand_acq_funcs_:
                # TODO: Rename `values` - Maybe `utilities`?
                values = _gaussian_acquisition(
                    X=X,
                    model=est,
                    y_opt=np.min(self.yi),
                    acq_func=cand_acq_func,
                    acq_func_kwargs=self.acq_func_kwargs,
                )

                #################### Find Acquisition Function Minimum ####################
                # Find acquisition function minimum by randomly sampling points from the space
                if self.acq_optimizer == "sampling":
                    next_x = X[np.argmin(values)]

                # Use BFGS to find the minimum of the acquisition function, the minimization starts
                #   from `n_restarts_optimizer` different points and the best minimum is used
                elif self.acq_optimizer == "lbfgs":
                    x0 = X[np.argsort(values)[:self.n_restarts_optimizer]]

                    with warnings.catch_warnings():
                        warnings.simplefilter("ignore")
                        results = Parallel(n_jobs=self.n_jobs)(
                            delayed(fmin_l_bfgs_b)(
                                gaussian_acquisition_1D,
                                x,
                                args=(est, np.min(self.yi), cand_acq_func,
                                      self.acq_func_kwargs),
                                bounds=self.space.transformed_bounds,
                                approx_grad=False,
                                maxiter=20,
                            ) for x in x0)

                    cand_xs = np.array([r[0] for r in results])
                    cand_acqs = np.array([r[1] for r in results])
                    next_x = cand_xs[np.argmin(cand_acqs)]
                else:
                    # `acq_optimizer` should have already been checked, so this shouldn't be hit,
                    #   but, it's here anyways to prevent complaints about `next_x` not existing in
                    #   the absence of this `else` clause
                    raise RuntimeError(
                        f"Invalid `acq_optimizer` value: {self.acq_optimizer}")

                # L-BFGS-B should handle this, but just in case of precision errors...
                if not self.space.is_categorical:
                    next_x = np.clip(next_x, transformed_bounds[:, 0],
                                     transformed_bounds[:, 1])
                self.next_xs_.append(next_x)

            if self.acq_func == "gp_hedge":
                logits = np.array(self.gains_)
                logits -= np.max(logits)
                exp_logits = np.exp(self.eta * logits)
                probs = exp_logits / np.sum(exp_logits)
                next_x = self.next_xs_[np.argmax(self.rng.multinomial(
                    1, probs))]
            else:
                next_x = self.next_xs_[0]

            # Note the need for [0] at the end
            self._next_x = self.space.inverse_transform(next_x.reshape(
                (1, -1)))[0]

        # Pack results
        return create_result(self.Xi,
                             self.yi,
                             self.space,
                             self.rng,
                             models=self.models)
Beispiel #7
0
def test_gaussian_acquisition_check_inputs():
    model = ConstantGPRSurrogate(Space(((1.0, 9.0), )))
    with pytest.raises(ValueError) as err:
        _gaussian_acquisition(np.arange(1, 5), model)
    assert ("it must be 2-dimensional" in err.value.args[0])
Beispiel #8
0
    def _tell(self, x, y, fit=True):
        # Copied from skopt
        """Perform the actual work of incorporating one or more new points.
		See `tell()` for the full description.

		This method exists to give access to the internals of adding points
		by side stepping all input validation and transformation."""

        if "ps" in self.acq_func:
            if is_2Dlistlike(x):
                self.Xi.extend(x)
                self.yi.extend(y)
                self._n_initial_points -= len(y)
            elif is_listlike(x):
                self.Xi.append(x)
                self.yi.append(y)
                self._n_initial_points -= 1
        # if y isn't a scalar it means we have been handed a batch of points
        elif is_listlike(y) and is_2Dlistlike(x):
            self.Xi.extend(x)
            self.yi.extend(y)
            self._n_initial_points -= len(y)
        elif is_listlike(x):
            self.Xi.append(x)
            self.yi.append(y)
            self._n_initial_points -= 1
        else:
            raise ValueError(
                "Type of arguments `x` (%s) and `y` (%s) not compatible." %
                (type(x), type(y)))

        # optimizer learned something new - discard cache
        self.cache_ = {}

        # after being "told" n_initial_points we switch from sampling
        # random points to using a surrogate model
        if fit and self._n_initial_points <= 0 and self.base_estimator_ is not None:
            transformed_bounds = np.array(self.space.transformed_bounds)
            est = clone(self.base_estimator_)

            with warnings.catch_warnings():
                warnings.simplefilter("ignore")
                est.fit(self.space.transform(self.Xi), self.yi)

            if hasattr(self, "next_xs_") and self.acq_func == "gp_hedge":
                self.gains_ -= est.predict(np.vstack(self.next_xs_))
            self.models.append(est)

            # We're gonna lie to the estimator by telling it a loss for the points that are still being evaluated,
            # similar to what we do when we ask for multiple points in ask().
            points_running = self.watch_list.keys()
            num_points_running = len(points_running)
            points_to_lie_about = [
                self.all_dim_values[run_ind] for run_ind in points_running
            ]
            strategy = "cl_mean"
            if strategy == "cl_min":
                y_lie = np.min(self.yi) if self.yi else 0.0  # CL-min lie
            elif strategy == "cl_mean":
                y_lie = np.mean(self.yi) if self.yi else 0.0  # CL-mean lie
            else:
                y_lie = np.max(self.yi) if self.yi else 0.0  # CL-max lie
            # Lie to the fake optimizer.
            fake_est = copy.deepcopy(est)
            X_to_tell = self.Xi + points_to_lie_about
            X_to_tell = self.space.transform(X_to_tell)
            y_to_tell = self.yi + list(np.ones(num_points_running) * y_lie)

            fake_est.fit(X_to_tell, y_to_tell)

            # even with BFGS as optimizer we want to sample a large number
            # of points and then pick the best ones as starting points
            # X = self.space.transform(self.space.rvs(
            # 	n_samples=self.n_points, random_state=self.rng))
            Xspace = self.space.rvs(n_samples=self.n_points,
                                    random_state=self.rng)
            param_thr = self.adapt_param['param_thr']
            par_cnt_scheme = self.adapt_param['par_cnt_scheme']
            suitable_X, _ = check_parameter_count_for_sample(
                Xspace, self.hyper_param_names, param_thr, par_cnt_scheme)
            # for x in Xspace:
            # 	vals_suitable, _ = check_parameter_count_for_sample(
            # 		x, self.hyper_param_names, param_thr, par_cnt_scheme)
            # 	suitable_X.append(vals_suitable)

            Xspace = [
                Xspace[ind] for ind, suit in enumerate(suitable_X) if suit
            ]
            X = self.space.transform(Xspace)

            self.next_xs_ = []
            for cand_acq_func in self.cand_acq_funcs_:
                values = _gaussian_acquisition(
                    X=X,
                    model=fake_est,
                    y_opt=np.min(self.yi),
                    acq_func=cand_acq_func,
                    acq_func_kwargs=self.acq_func_kwargs)
                # Find the minimum of the acquisition function by randomly
                # sampling points from the space
                if self.acq_optimizer == "sampling":
                    next_x = X[np.argmin(values)]

                # Use BFGS to find the mimimum of the acquisition function, the
                # minimization starts from `n_restarts_optimizer` different
                # points and the best minimum is used
                elif self.acq_optimizer == "lbfgs":
                    x0 = X[np.argsort(values)[:self.n_restarts_optimizer]]

                    with warnings.catch_warnings():
                        warnings.simplefilter("ignore")
                        results = Parallel(n_jobs=self.n_jobs)(
                            delayed(fmin_l_bfgs_b)(
                                gaussian_acquisition_1D,
                                x,
                                args=(fake_est, np.min(self.yi), cand_acq_func,
                                      self.acq_func_kwargs),
                                bounds=self.space.transformed_bounds,
                                approx_grad=False,
                                maxiter=20) for x in x0)

                    cand_xs = np.array([r[0] for r in results])
                    cand_acqs = np.array([r[1] for r in results])
                    next_x = cand_xs[np.argmin(cand_acqs)]

                # lbfgs should handle this but just in case there are
                # precision errors.
                if not self.space.is_categorical:
                    next_x = np.clip(next_x, transformed_bounds[:, 0],
                                     transformed_bounds[:, 1])
                self.next_xs_.append(next_x)

            if self.acq_func == "gp_hedge":
                logits = np.array(self.gains_)
                logits -= np.max(logits)
                exp_logits = np.exp(self.eta * logits)
                probs = exp_logits / np.sum(exp_logits)
                next_x = self.next_xs_[np.argmax(self.rng.multinomial(
                    1, probs))]
            else:
                next_x = self.next_xs_[0]

            # note the need for [0] at the end
            self._next_x = self.space.inverse_transform(next_x.reshape(
                (1, -1)))[0]

        # Pack results
        return create_result(self.Xi,
                             self.yi,
                             self.space,
                             self.rng,
                             models=self.models)
    x_obs = np.array([-4, -1.5, 0, 1.5, 2.5, 2.7])
    y_obs = f(x_obs)
    x_s = np.linspace(-5, 3, 80)

    i = 0
    cov_amplitude = ConstantKernel(1.0)
    other_kernel = Matern()

    print(x_obs, y_obs)
    est = GaussianProcessRegressor(kernel=cov_amplitude*other_kernel)
    b_s = x_s
    s = []
    while i < len(x_s):
        x_obs = x_obs.reshape(len(x_obs), 1)
        x_s = x_s.reshape(len(x_s), 1)
        est.fit(x_obs, y_obs)
        values = _gaussian_acquisition(X=x_s, model=est)
        next_x = b_s[np.random.randint(0, 80)]
        s.append(next_x)
        x_obs = np.append(x_obs, np.array(next_x))
        y_obs = np.append(y_obs, f(next_x))
        i = i + 1

    import matplotlib.pyplot as plt
    y_mean, y_std = est.predict(np.array(s).reshape(len(s), 1), return_std=True)
    y_upper = y_mean + y_std
    y_lower = y_mean - y_std
    l1, l2, l3 = plt.plot(xs, ys, 'r-', s, y_mean, 'b-', s, y_upper, 'g-')
    plt.legend(handles=[l1, l2, l3], labels=['True Function', 'Mean', 'UPPER'])
    plt.show()
Beispiel #10
0
    def _tell(self, x, y, fit=True):
        if 'ps' in self.acq_func:
            # TODO: ps
            pass
        elif is_listlike(y) and is_2d_listlike(x):
            self.xi.extend(x)
            self.yi.extend(y)
            self.n_initial_points -= len(y)
        elif is_listlike(x):
            self.xi.append(x)
            self.yi.append(y)
            self.n_initial_points -= 1
        else:
            raise ValueError('x {} and y {} are not compatible'.format(x, y))

        self.cache = {}
        if (fit and self.n_initial_points <= 0
                and self.base_estimator is not None):
            transformed_bounds = np.array(self.space.transformed_bounds)
            estimator = self.base_estimator
            estimator.fit(self.space.transform(self.xi), self.yi)

            if hasattr(self, 'next_xs_') and self.acq_func == 'gp_hedge':
                self.gains -= estimator.predict(np.vstack(self.next_xs_))

            if self.max_model_queue_size is None:
                self.models.append(estimator)
            elif len(self.models) < self.max_model_queue_size:
                self.models.append(estimator)
            else:
                self.models.pop(0)
                self.models.append(estimator)

            x = self.space.transform(
                self.space.rvs(n_samples=self.n_points, random_state=self.rs))
            self.next_xs_ = []
            for cand_acq_func in self.cand_acq_funcs:
                values = _gaussian_acquisition(
                    X=x,
                    model=estimator,
                    y_opt=np.min(self.yi),
                    acq_func=cand_acq_func,
                    acq_func_kwargs=self.acq_func_kwargs)
                if self.acq_optimizer == 'sampling':
                    next_x = x[np.argmin(values)]
                elif self.acq_optimizer == 'lbfgs':
                    x0 = np.asarray(x)[np.argsort(values)
                                       [:self.n_restarts_optimizer]]
                    res = [
                        fmin_l_bfgs_b(gaussian_acquisition_1D,
                                      xx,
                                      args=(estimator, np.min(self.yi),
                                            cand_acq_func,
                                            self.acq_func_kwargs),
                                      bounds=self.space.transformed_bounds,
                                      approx_grad=False,
                                      maxiter=20) for xx in x0
                    ]
                    cand_xs = np.array([r[0] for r in res])
                    cand_acqs = np.array([r[1] for r in res])
                    next_x = cand_xs[np.argmin(cand_acqs)]

                if not self.space.is_categorical:
                    next_x = np.clip(next_x, transformed_bounds[:, 0],
                                     transformed_bounds[:, 1])
                self.next_xs_.append(next_x)

            if self.acq_func == 'gp_hedge':
                logits = np.array(self.gains)
                logits -= np.max(logits)
                exp_logits = np.exp(self.eta * logits)
                probs = exp_logits / np.sum(exp_logits)
                next_x = self.next_xs_[np.argmax(self.rs.multinomial(1,
                                                                     probs))]
            else:
                next_x = self.next_xs_[0]
            self._next_x = self.space.inverse_transform(next_x.reshape(
                (1, -1)))[0]

        return create_result(self.xi,
                             self.yi,
                             self.space,
                             self.rs,
                             models=self.models)