예제 #1
0
 def test_qEI(self):
     for double in (True, False):
         self._setUp(double=double)
         qEI = qExpectedImprovement(self.model_st, best_f=0.0)
         candidates, _ = optimize_acqf(
             acq_function=qEI,
             bounds=self.bounds,
             q=3,
             num_restarts=10,
             raw_samples=20,
             options={"maxiter": 5},
         )
         self.assertTrue(torch.all(-EPS <= candidates))
         self.assertTrue(torch.all(candidates <= 1 + EPS))
         qEI = qExpectedImprovement(self.model_fn, best_f=0.0)
         candidates, _ = optimize_acqf(
             acq_function=qEI,
             bounds=self.bounds,
             q=3,
             num_restarts=10,
             raw_samples=20,
             options={"maxiter": 5},
         )
         self.assertTrue(torch.all(-EPS <= candidates))
         self.assertTrue(torch.all(candidates <= 1 + EPS))
         candidates_batch_limit, _ = optimize_acqf(
             acq_function=qEI,
             bounds=self.bounds,
             q=3,
             num_restarts=10,
             raw_samples=20,
             options={"maxiter": 5, "batch_limit": 5},
         )
         self.assertTrue(torch.all(-EPS <= candidates_batch_limit))
         self.assertTrue(torch.all(candidates_batch_limit <= 1 + EPS))
    def find_eta_c(self, rho_t):
        """
		Find the minimum of the posterior mean, i.e., min_x mu(x|D) s.t. Pr(g(x) <= 0) > rho_t, where D is the data set D={Y,X}, mu(x|D)
		is the posterior mean of the GP queried at location x, and rho_t depends on the current budget of failures.
		"""

        self.my_print("Finding min_x mu(x|D) s.t. Pr(g(x) <= 0) > 0.99")
        self.gp_mean_obj_cons.rho_t = rho_t

        options = {
            "batch_limit": 1,
            "maxiter": 200,
            "ftol": 1e-6,
            "method": self.method_opti
        }
        x_eta_c, _ = optimize_acqf(acq_function=self.gp_mean_obj_cons,
                                   bounds=self.bounds,
                                   q=1,
                                   num_restarts=self.Nrestarts_eta_c,
                                   raw_samples=500,
                                   return_best_only=True,
                                   options=options)

        self.my_print("Done!")
        # Revaluate the mean (because the one returned might be affected by the constant that is added to ensure non-negativity)
        eta_c = self.model_list[0](x_eta_c).mean.view(1)

        return x_eta_c, eta_c
예제 #3
0
    def optimize_acqf_and_get_observation(acq_func, args):
        """
        Optimizes the acquisition function, and returns a new candidate and a noisy observation.
        botorch defaults:  num_restarts=10, raw_samples=256, batch_limit=5, maxiter=200
        """

        batch_initial_conditions = gen_one_shot_kg_initial_conditions(
            acq_function=acq_func,
            bounds=bo_bounds,
            q=1,
            num_restarts=args.acqf_opt_num_restarts,
            raw_samples=args.acqf_opt_raw_samples,
            options={"batch_limit": args.acqf_opt_batch_limit,
                     "maxiter": args.acqf_opt_maxiter},
        )

        # optimize acquisition function
        candidates, _ = optimize_acqf(
            acq_function=acq_func,
            bounds=bo_bounds,
            q=1,
            num_restarts=args.acqf_opt_num_restarts,
            raw_samples=args.acqf_opt_raw_samples,  # used for intialization heuristic
            options={"batch_limit": args.acqf_opt_batch_limit,
                     "maxiter": args.acqf_opt_maxiter},
            batch_initial_conditions=batch_initial_conditions
        )

        # proposed evaluation
        new_theta = candidates.detach()

        # observe new noisy function evaluation
        new_G, new_G_sem = composite_simulation(new_theta.squeeze())

        return new_theta, new_G, new_G_sem
예제 #4
0
파일: bayrn.py 프로젝트: fdamken/SimuRLacra
    def argmax_posterior_mean(cands: to.Tensor, cands_values: to.Tensor,
                              ddp_space: BoxSpace, num_restarts: int,
                              num_samples: int) -> to.Tensor:
        """
        Compute the GP input with the maximal posterior mean.

        :param cands: candidates a.k.a. x
        :param cands_values: observed values a.k.a. y
        :param ddp_space: space of the domain distribution parameters, indicates the lower and upper bound
        :param num_restarts: number of restarts for the optimization of the acquisition function
        :param num_samples: number of samples for the optimization of the acquisition function
        :return: un-normalized candidate with maximum posterior value a.k.a. x
        """
        if not isinstance(cands, to.Tensor):
            raise pyrado.TypeErr(given=cands, expected_type=to.Tensor)
        if not isinstance(cands_values, to.Tensor):
            raise pyrado.TypeErr(given=cands_values, expected_type=to.Tensor)
        if not isinstance(ddp_space, BoxSpace):
            raise pyrado.TypeErr(given=ddp_space, expected_type=BoxSpace)

        # Normalize the input data and standardize the output data
        uc_projector = UnitCubeProjector(
            to.from_numpy(ddp_space.bound_lo).to(dtype=to.get_default_dtype()),
            to.from_numpy(ddp_space.bound_up).to(dtype=to.get_default_dtype()),
        )
        cands_norm = uc_projector.project_to(cands)
        cands_values_stdized = standardize(cands_values)

        if cands_norm.shape[0] > cands_values.shape[0]:
            print_cbt(
                f"There are {cands.shape[0]} candidates but only {cands_values.shape[0]} evaluations. Ignoring "
                f"the candidates without evaluation for computing the argmax.",
                "y",
            )
            cands_norm = cands_norm[:cands_values.shape[0], :]

        # Create and fit the GP model
        gp = SingleTaskGP(cands_norm, cands_values_stdized)
        gp.likelihood.noise_covar.register_constraint("raw_noise",
                                                      GreaterThan(1e-5))
        mll = ExactMarginalLogLikelihood(gp.likelihood, gp)
        fit_gpytorch_model(mll)

        # Find position with maximal posterior mean
        cand_norm, _ = optimize_acqf(
            acq_function=PosteriorMean(gp),
            bounds=to.stack(
                [to.zeros(ddp_space.flat_dim),
                 to.ones(ddp_space.flat_dim)]).to(dtype=to.float32),
            q=1,
            num_restarts=num_restarts,
            raw_samples=num_samples,
        )

        cand_norm = cand_norm.to(dtype=to.get_default_dtype())
        cand = uc_projector.project_back(cand_norm.detach())
        print_cbt(f"Converged to argmax of the posterior mean: {cand.numpy()}",
                  "g",
                  bright=True)
        return cand
예제 #5
0
def run():

	train_x, train_obj, train_con, best_observed_value_nei = generate_initial_data(n=10)

	# define models for objective and constraint
	model_obj = FixedNoiseGP(train_x, train_obj, train_yvar.expand_as(train_obj)).to(train_x)
	model_con = FixedNoiseGP(train_x, train_con, train_yvar.expand_as(train_con)).to(train_x)
	# combine into a multi-output GP model
	model = ModelListGP(model_obj, model_con)
	mll = SumMarginalLogLikelihood(model.likelihood, model)

	fit_gpytorch_model(mll)

	acqui_gpmean_cons = GPmeanConstrained(model=model,objective=constrained_obj)

	# Forward:
	# X = torch.rand(size=(1,6))
	# acqui_gpmean_cons.forward(X)

	method_opti = "SLSQP" # constraints
	# method_opti = "COBYLA" # constraints
	# method_opti = "L-BFGS-B"

	# Below, num_restarts must be equal to q, otherwise, it fails...
	options = {"batch_limit": 1,"maxiter": 200,"ftol":1e-6,"method":method_opti}
	x_eta_c, eta_c = optimize_acqf(acq_function=acqui_gpmean_cons,bounds=bounds,q=1,num_restarts=1,
																raw_samples=500,return_best_only=True,options=options)

	


	pdb.set_trace()
def optimize_acqf_and_get_observation(acq_func, obj_func, time_list,
                                      global_start_time):
    """Optimizes the acquisition function, and returns a new candidate and observation."""
    # optimize
    candidates, _ = optimize_acqf(
        acq_function=acq_func,
        bounds=standard_bounds,
        q=1,
        num_restarts=20,
        raw_samples=1024,  # used for initialization heuristic
        options={
            "batch_limit": 5,
            "maxiter": 200,
            "nonnegative": True
        },
        sequential=True,
    )
    # observe new values
    new_x = candidates.detach()
    new_obj = []
    new_con = []
    for x in new_x:
        res = obj_func(x)
        y = res['objs']
        c = res['constraints']
        new_obj.append(y)
        new_con.append(c)
        global_time = time.time() - global_start_time
        time_list.append(global_time)
    new_obj = torch.tensor(new_obj, **tkwargs).reshape(new_x.shape[0], -1)
    new_con = torch.tensor(new_con, **tkwargs).reshape(new_x.shape[0], -1)
    print(f'evaluate {new_x.shape[0]} configs on real objective')
    return new_x, new_obj, new_con
예제 #7
0
def test(dim=1):

	assert dim == 1

	X0 = torch.Tensor([[0.93452506],
								 [0.18872502],
								 [0.89790337],
								 [0.95841797],
								 [0.82335255],
								 [0.45000000],
								 [0.50000000]])
	Y0 = torch.Tensor([-0.4532849,-0.66614552,-0.92803395,0.08880341,-0.27683621,1.000000,1.500000])
	# Y0 = Y0[:,None]
	Neval = Y0.shape[0]

	train_x = X0
	train_y = Y0[:,None]
	Nrestarts = 10

	model = SingleTaskGP(train_x, train_y)
	EI = ExpectedImprovement(model, best_f=0.2)

	print("[get_next_point()] Computing next candidate by maximizing the acquisition function ...")
	options={"batch_limit": 50,"maxiter": 200,"ftol":1e-9,"method":"L-BFGS-B","iprint":2,"maxls":30,"disp":True}
	x_next,alpha_next = optimize_acqf(acq_function=EI,bounds=torch.Tensor([[0.0]*dim,[1.0]*dim],device=device),q=1,num_restarts=Nrestarts,
																		raw_samples=500,return_best_only=True,options=options)

	print("x_next:",x_next)
	print("alpha_next:",alpha_next)
    def find_eta(self):
        """
		Find the minimum of the posterior mean, i.e., min_x mu(x|D), where D is the data set D={Y,X}, and mu(x|D)
		is the posterior mean of the GP queried at location x. For this, we do local optimization with random
		restarts.
		"""

        logger.info("Finding min_x mu(x|D)...")

        options = {
            "batch_limit": 50,
            "maxiter": 200,
            "ftol": 1e-6,
            "method": self.method_opti
        }
        x_eta, _ = optimize_acqf(acq_function=self.gp_mean,
                                 bounds=self.bounds,
                                 q=1,
                                 num_restarts=self.Nrestarts_eta,
                                 raw_samples=500,
                                 return_best_only=True,
                                 options=options)

        logger.info("Done!")
        # Revaluate the mean (because the one returned might be affected by the constant that is added to ensure non-negativity)
        eta = self.model(x_eta).mean.view(1)

        return x_eta, eta
    def get_risky_evaluation(self):

        # Gather fmin samples, using the Frechet distribution:
        fmin_samples = get_fmin_samples_from_gp(
            model=self.model_list[0],
            Nsamples=self.Nsamples_fmin,
            eta=self.eta_c)  # This assumes self.eta has been updated
        self.update_u_vec(fmin_samples)

        self.which_mode = "risky"

        self.my_print(
            "[get_risky_evaluation()] Computing next candidate by maximizing the acquisition function ..."
        )
        options = {
            "batch_limit": 50,
            "maxiter": 300,
            "ftol": 1e-9,
            "method": self.method_risky,
            "iprint": 2,
            "maxls": 20,
            "disp": self.disp_info_scipy_opti
        }
        x_next, alpha_next = optimize_acqf(acq_function=self,
                                           bounds=self.bounds,
                                           q=1,
                                           num_restarts=self.Nrestarts_risky,
                                           raw_samples=500,
                                           return_best_only=True,
                                           options=options)
        self.my_print("Done!")

        return x_next, alpha_next
예제 #10
0
 def current_best(self, past_only: bool = False, **kwargs) -> Tuple[Tensor, Tensor]:
     """
     Get the current best solution and value
     :param past_only: If True, optimization is over previously evaluated points only.
     :param kwargs: ignored
     :return: Current best solution and value
     """
     inner = PosteriorMean(self.model)
     if past_only:
         with torch.no_grad():
             values = inner(self.X.reshape(-1, 1, self.dim_x))
         best = torch.argmax(values)
         current_best_sol = self.X[best]
         current_best_value = -values[best]
     else:
         current_best_sol, current_best_value = optimize_acqf(
             acq_function=inner,
             bounds=self.bounds,
             q=1,
             num_restarts=self.num_restarts,
             raw_samples=self.num_restarts * self.raw_multiplier,
         )
     # negated again to report the correct value
     if self.verbose:
         print(
             "Current best solution, value: ", current_best_sol, -current_best_value
         )
     return current_best_sol, -current_best_value
예제 #11
0
def get_candidate(model, acq, full_train_Y, q, bounds, dim):
    if acq == 'EI':
        if q == 1:
            EI = ExpectedImprovement(model, full_train_Y.max().item())
        else:
            EI = qExpectedImprovement(model, full_train_Y.max().item())

        bounds_t = torch.FloatTensor([[bounds[0]] * dim, [bounds[1]] * dim])
        candidate, acq_value = optimize_acqf(
            EI,
            bounds=bounds_t,
            q=q,
            num_restarts=15,
            raw_samples=5000,
        )

    elif acq == 'TS':
        sobol = SobolEngine(dim, scramble=True)
        n_candidates = min(5000, max(20000, 2000 * dim))
        pert = sobol.draw(n_candidates)
        X_cand = (bounds[1] - bounds[0]) * pert + bounds[0]
        thompson_sampling = MaxPosteriorSampling(model=model,
                                                 replacement=False)
        candidate = thompson_sampling(X_cand, num_samples=q)

    else:
        raise NotImplementedError('Only TS and EI are implemented')

    return candidate, EI if acq == 'EI' else None
예제 #12
0
    def get_bayes_pop(self, n_suggestions):
        """
        Parameters
        ----------
        n_suggestions: Number of new suggestions/trial solutions to generate using BO
        Returns
        The new set of trial solutions obtained by optimizing the acquisition function
        -------
        """

        try:
            candidates, _ = optimize_acqf(
                acq_function=self.acquisition,
                bounds=self.min_max_bounds,
                q=n_suggestions,
                num_restarts=10,
                raw_samples=512,  # used for initialization heuristic
                sequential=True)

            bayes_pop = unnormalize(candidates, self.torch_bounds).numpy()
        except Exception as e:
            print('Error in get_bayes_pop(): {}'.format(e))

        population = self.search_space.unwarp(
            bayes_pop)  # Translate the solution back to the original space

        return population
예제 #13
0
def bo_loop(gp_model: SingleTaskGP, acq_func_id: str,
            acq_func_kwargs: Dict[str, Any], acq_func_opt_kwargs: Dict[str,
                                                                       Any],
            bounds: Tensor, tkwargs: Dict[str, Any], q: int, num_restarts: int,
            raw_initial_samples, seed: int,
            num_MC_sample_acq: int) -> Iterable[Any]:
    # seed everything
    np.random.seed(seed)
    torch.manual_seed(seed)

    # put on proper device

    # we want to maximize
    fmax = torch.quantile(gp_model.train_targets, .9).item()
    print(f"Using good point cutoff {fmax:.2f}")

    device = gp_model.train_inputs[0].device

    bounds = bounds.to(**tkwargs)
    gp_model.eval()

    acq_func_kwargs['best_f'] = fmax
    acq_func = query_acq_func(acq_func_id=acq_func_id,
                              acq_func_kwargs=acq_func_kwargs,
                              gp_model=gp_model,
                              q=q,
                              num_MC_samples_acq=num_MC_sample_acq
                              )  # if q is 1 use analytic acquisitions
    acq_func.to(**tkwargs)

    options = {
        'batch_limit': 100
    } if acq_func_opt_kwargs == {} else acq_func_opt_kwargs
    print("Start acquisition function optimization...")
    if q == 1:
        # use optimize_acq (with LBFGS)
        candidate, acq_value = optimize_acqf(acq_function=acq_func,
                                             bounds=bounds,
                                             q=q,
                                             num_restarts=num_restarts,
                                             raw_samples=raw_initial_samples,
                                             return_best_only=True,
                                             options=options)
    else:
        candidate, acq_value = optimize_acqf_torch(
            acq_function=acq_func,
            bounds=bounds,
            q=q,
            num_restarts=num_restarts,
            raw_samples=raw_initial_samples,
            return_best_only=True,
            options=options,
        )
    print(f"Acquired {candidate} with acquisition value {acq_value}")
    return candidate.to(device=device)
예제 #14
0
def optimize_loop(model, loss, X_train, y_train, bounds, n_samples=10):
    best_value = y_train.max()
    acq_func = qExpectedImprovement(model, best_f=best_value)
    X_new, acq_value = optimize_acqf(acq_func,
                                     bounds=bounds,
                                     q=20,
                                     num_restarts=10,
                                     raw_samples=76)
    #X_new = X_new.view((n_samples,-1))
    print(X_new)
    return X_new
예제 #15
0
 def optimize_acqf_and_get_observation(self, acq, seed):
     """Optimizes the acquisition function, and returns a new candidate."""
     init = initializers.gen_batch_initial_conditions(
         acq, self.bounds, options={"seed": seed}, **self.optim_kwargs)
     # optimize
     candidate, acq_value = optimize_acqf(acq,
                                          bounds=self.bounds,
                                          batch_initial_conditions=init,
                                          **self.optim_kwargs)
     # observe new value
     new_x = candidate.detach()  #self.scale_to_bounds(candidate.detach())
     return new_x
    def optimize_acqui_use_restarts_as_batch(self, options):

        logger.info("[get_next_point()] Optimizing acquisition function ...")
        x_next, alpha_next = optimize_acqf(acq_function=self,
                                           bounds=self.bounds,
                                           q=1,
                                           num_restarts=self.Nrestarts,
                                           raw_samples=500,
                                           return_best_only=True,
                                           options=options)

        return x_next, alpha_next
예제 #17
0
 def _update_current_best(self) -> None:
     """
     Updates the current best solution and corresponding value
     """
     pm = PosteriorMean(self.model)
     self.current_best_sol, self.current_best_val = optimize_acqf(
         pm,
         Tensor([[0], [1]]).repeat(1, self.dim),
         q=1,
         num_restarts=self.num_restarts,
         raw_samples=self.raw_samples,
     )
예제 #18
0
 def test_EI(self):
     for double in (True, False):
         self._setUp(double=double)
         EI = ExpectedImprovement(self.model_st, best_f=0.0)
         candidates, _ = optimize_acqf(
             acq_function=EI,
             bounds=self.bounds,
             q=1,
             num_restarts=10,
             raw_samples=20,
             options={"maxiter": 5},
         )
         self.assertTrue(-EPS <= candidates <= 1 + EPS)
         EI = ExpectedImprovement(self.model_fn, best_f=0.0)
         candidates, _ = optimize_acqf(
             acq_function=EI,
             bounds=self.bounds,
             q=1,
             num_restarts=10,
             raw_samples=20,
             options={"maxiter": 5},
         )
         self.assertTrue(-EPS <= candidates <= 1 + EPS)
예제 #19
0
def select_next_points_botorch(observed_X: List[List[float]],
                               observed_y: List[float]) -> np.ndarray:
    """Generate the next sample to evaluate with XTB

    Uses BOTorch to pick the next sample using Expected Improvement

    Args:
        observed_X: Observed coordinates
        observed_y: Observed energies
    Returns:
        Next coordinates to try
    """

    # Clip the energies if needed
    observed_y = np.clip(observed_y, -np.inf,
                         2 + np.log10(np.clip(observed_y, 1, np.inf)))

    # Convert inputs to torch arrays
    train_X = torch.tensor(observed_X, dtype=torch.float)
    train_y = torch.tensor(observed_y, dtype=torch.float)
    train_y = train_y[:, None]
    train_y = standardize(-1 * train_y)

    # Make the GP
    gp = SingleTaskGP(train_X,
                      train_y,
                      covar_module=gpykernels.ScaleKernel(
                          gpykernels.ProductStructureKernel(
                              num_dims=train_X.shape[1],
                              base_kernel=gpykernels.PeriodicKernel(
                                  period_length_prior=NormalPrior(360, 0.1)))))
    mll = ExactMarginalLogLikelihood(gp.likelihood, gp)
    fit_gpytorch_model(mll)

    # Solve the optimization problem
    #  Following boss, we use Eq. 5 of https://arxiv.org/pdf/1012.2599.pdf with delta=0.1
    n_sampled, n_dim = train_X.shape
    kappa = np.sqrt(
        2 *
        np.log10(np.power(n_sampled, n_dim / 2 + 2) * np.pi**2 /
                 (3.0 * 0.1)))  # Results in more exploration over time
    ei = UpperConfidenceBound(gp, kappa)
    bounds = torch.zeros(2, train_X.shape[1])
    bounds[1, :] = 360
    candidate, acq_value = optimize_acqf(ei,
                                         bounds=bounds,
                                         q=1,
                                         num_restarts=64,
                                         raw_samples=64)
    return candidate.detach().numpy()[0, :]
예제 #20
0
    def _sample(self, candidates: Optional[np.array] = None) -> np.array:
        if len(self.X_observed) < self.num_initial_random_draws:
            return self.initial_sampler.sample(candidates=candidates)
        else:
            z_observed = torch.Tensor(self.transform_outputs(self.y_observed.numpy()))

            with torch.no_grad():
                # both (n, 1)
                #mu_pred, sigma_pred = self.thompson_sampling.prior(self.X_observed)
                mu_pred, sigma_pred = self.initial_sampler.prior.predict(self.X_observed)
                mu_pred = torch.Tensor(mu_pred)
                sigma_pred = torch.Tensor(sigma_pred)

            # (n, 1)
            r_observed = residual_transform(z_observed, mu_pred, sigma_pred)

            # build and fit GP on residuals
            gp = SingleTaskGP(
                train_X=self.X_observed,
                train_Y=r_observed,
                likelihood=GaussianLikelihood(noise_constraint=GreaterThan(1e-3)),
            )
            mll = ExactMarginalLogLikelihood(gp.likelihood, gp)
            fit_gpytorch_model(mll)

            acq = ShiftedExpectedImprovement(
                model=gp,
                best_f=z_observed.min(dim=0).values,
                mean_std_predictor=self.initial_sampler.prior.predict,
                maximize=False,
            )

            if candidates is None:
                candidate, acq_value = optimize_acqf(
                    acq,
                    bounds=self.bounds_tensor,
                    q=1,
                    num_restarts=5,
                    raw_samples=100,
                )
                # import matplotlib.pyplot as plt
                # x = torch.linspace(-1, 1).unsqueeze(dim=-1)
                # x = torch.cat((x, x * 0), dim=1)
                # plt.plot(x[:, 0].flatten().tolist(), acq(x.unsqueeze(dim=1)).tolist())
                # plt.show()
                return candidate[0]
            else:
                # (N,)
                ei = acq(torch.Tensor(candidates).unsqueeze(dim=-2))
                return torch.Tensor(candidates[ei.argmax()])
예제 #21
0
    def gen(self, num_points=1, **kwargs):

        self.model.eval()
        train_x = self.model.train_inputs[0]
        acq = self._get_acquisition_fn()

        new_candidate, batch_acq_values = optimize_acqf(
            acq_function=acq,
            bounds=torch.tensor(np.c_[self.lb, self.ub]).T.to(train_x),
            q=num_points,
            num_restarts=self.restarts,
            raw_samples=self.samps,
        )

        return new_candidate.numpy()
예제 #22
0
def optimize_acqf_and_get_observation(acq_func, dataset):
    """Optimizes the acquisition function, and returns a new candidate and a noisy observation."""
    # optimize
    candidates, _ = optimize_acqf(
        acq_function=acq_func,
        bounds=bounds,
        q=BATCH_SIZE,
        num_restarts=10,
        raw_samples=512,  # used for intialization heuristic
        options={"batch_limit": 5, "maxiter": 200},
    )
    # observe new values 
    new_x = candidates.detach()
    exact_obj = call_external(new_x, BATCH_SIZE, 5, dataset).unsqueeze(-1)  # add output dimension
    new_obj = exact_obj + NOISE_SE * torch.randn_like(exact_obj)
    return new_x, new_obj
예제 #23
0
def optimize_acqf_and_get_observation(acq_func, mean_y=None, std_y=None):
    """optimize acquisition function and evaluate new candidates
    """
    # optimize
    candidates, _ = optimize_acqf(
        acq_function=acq_func,
        bounds=bounds,
        q=BATCH_SIZE,
        num_restarts=10,
        raw_samples=512,  # used for intialization heuristic
    )

    # observe new values
    new_x = candidates.detach()
    new_y = evaluate_y(new_x, mean_y=mean_y, std_y=std_y)
    return new_x, new_y
예제 #24
0
def propose_candidates(args, prev_res):

    ## train a surrogate model
    gp = SingleTaskGP(prev_res['hparams'], prev_res['acc'])
    mll = ExactMarginalLogLikelihood(gp.likelihood, gp)
    fit_gpytorch_model(mll)

    ## construct an acquisition function and optimize it
    UCB = UpperConfidenceBound(gp, beta=0.1)

    candidates, acq_value = optimize_acqf(UCB,
                                          bounds=bounds,
                                          q=args.n_cand,
                                          num_restarts=5,
                                          raw_samples=20)

    return candidates
예제 #25
0
def optimize_loop(model, loss, X_train, y_train, X_test, y_test, bounds):
    best_value = y_train.min()
    acq_func = ExpectedImprovement(model, best_f=best_value, maximize=False)
    X_new, acq_value = optimize_acqf(acq_func, bounds=bounds, q=1, \
        num_restarts=100, raw_samples=100)
    X_new = X_new.view((1, 1))
    y_new = (eval_true_func(X_new) - y_mean) / y_std
    # concatenate new points to training set
    X_train_new = torch.cat((X_train, X_new))
    y_train_new = torch.cat((y_train, y_new))
    plot_acq_func(acq_func, X_test=X_test, X_train=X_train_new, X_new=X_new)
    # condition model on new observation
    gpr_model, gpr_mll = get_gpr_model(X_new, y_new, model=model)
    # plot model performance
    plot_testing(gpr_model, X_test=X_test, X_train=X_train_new, \
        y_train=y_train_new, y_test=y_test, X_new=X_new, y_new=y_new)
    return gpr_model, gpr_mll, X_train_new, y_train_new
예제 #26
0
 def _maximize_kg(self) -> None:
     """
     maximizes the KG acquisition function and stores the resulting value and
     the candidate
     """
     acq_func = qKnowledgeGradient(
         model=self.model, current_value=self.current_best_val
     )
     # acq_func = qExpectedImprovement(model=self.model, best_f=self.current_best_val)
     # acq_func = ExpectedImprovement(model=self.model, best_f=self.current_best_val)
     self.next_candidate, self.kg_value = optimize_acqf(
         acq_func,
         Tensor([[0], [1]]).repeat(1, self.dim),
         q=1,
         num_restarts=self.num_restarts,
         raw_samples=self.raw_samples,
     )
예제 #27
0
        def optimize_acqf_and_get_observation(acq_func):
            """Optimizes the acquisition function,
            and returns a new candidate and a noisy observation"""
            candidates, _ = optimize_acqf(
                acq_function=acq_func,
                bounds=torch.stack([
                    torch.zeros(d, dtype=dt),
                    torch.ones(d, dtype=dt),
                ]),
                q=1,
                num_restarts=10,
                raw_samples=200,
            )

            x = unnormalize(candidates.detach(), bounds=bounds)
            print('Hyper-parameter: ' + str(x))
            obj = self.train(x.view(-1)).unsqueeze(-1)
            print(print('Error: ' + str(obj)))
            return x, obj
예제 #28
0
def optimize_acqf_and_get_observation(acq_func):
    """Optimizes the acquisition function, and returns a new candidate and a noisy observation."""
    # optimize
    candidates, _ = optimize_acqf(
        acq_function=acq_func,
        bounds=bounds,
        q=BATCH_SIZE,
        num_restarts=10,
        raw_samples=500,  # used for intialization heuristic
        options={
            "batch_limit": 5,
            "max_iter": 200,
        })
    # observe new values
    new_x = candidates.detach()
    exact_obj = neg_hartmann6(new_x).unsqueeze(-1)  # add output dimension
    exact_con = outcome_constraint(new_x).unsqueeze(-1)  # add output dimension
    new_obj = exact_obj + NOISE_SE * torch.randn_like(exact_obj)
    new_con = exact_con + NOISE_SE * torch.randn_like(exact_con)
    return new_x, new_obj, new_con
예제 #29
0
    def argmax_posterior_mean(cands: to.Tensor, cands_values: to.Tensor,
                              uc_normalizer: UnitCubeProjector,
                              num_restarts: int,
                              num_samples: int) -> to.Tensor:
        """
        Compute the GP input with the maximal posterior mean.

        :param cands: candidates a.k.a. x
        :param cands_values: observed values a.k.a. y
        :param uc_normalizer: unit cube normalizer used during the experiments (can be recovered form the bounds)
        :param num_restarts: number of restarts for the optimization of the acquisition function
        :param num_samples: number of samples for the optimization of the acquisition function
        :return: un-normalized candidate with maximum posterior value a.k.a. x
        """
        # Normalize the input data and standardize the output data
        cands_norm = uc_normalizer.project_to(cands)
        cands_values_stdized = standardize(cands_values)

        # Create and fit the GP model
        gp = SingleTaskGP(cands_norm, cands_values_stdized)
        gp.likelihood.noise_covar.register_constraint('raw_noise',
                                                      GreaterThan(1e-5))
        mll = ExactMarginalLogLikelihood(gp.likelihood, gp)
        fit_gpytorch_model(mll)

        # Find position with maximal posterior mean
        cand_norm, acq_value = optimize_acqf(
            acq_function=PosteriorMean(gp),
            bounds=to.stack([
                to.zeros_like(uc_normalizer.bound_lo),
                to.ones_like(uc_normalizer.bound_up)
            ]),
            q=1,
            num_restarts=num_restarts,
            raw_samples=num_samples)

        cand = uc_normalizer.project_back(cand_norm.detach())
        print_cbt(f'Converged to argmax of the posterior mean\n{cand.numpy()}',
                  'g',
                  bright=True)
        return cand
예제 #30
0
def optimize_acqf_and_get_observation(acq_func):
    """
    Optimizes the acquisition function, and returns a new candidate and a noisy observation.

    :param acq_func: Acquisition function to use.
    :return: new_x: new candidate
             new_train_obj: noisy observation of g(x)
    """
    # optimize
    candidates, _ = optimize_acqf(
        acq_function=acq_func,
        bounds=bounds,
        q=BATCH_SIZE,
        num_restarts=10,
        raw_samples=512,  # used for initialization heuristic
        options={"batch_limit": 5, "maxiter": 200},
    )
    # observe new values
    new_x = candidates.detach()
    exact_obj, _, _ = exact_sin_objective(new_x, plot_sample=None, fplot=False)
    new_train_obj = train_sin_objective(new_x, fplot=False)
    return new_x, new_train_obj