def _get_model(n, fixed_noise=False, use_octf=False, **tkwargs):
    train_x1, train_y1 = _get_random_data(batch_shape=torch.Size(),
                                          m=1,
                                          n=10,
                                          **tkwargs)
    train_x2, train_y2 = _get_random_data(batch_shape=torch.Size(),
                                          m=1,
                                          n=11,
                                          **tkwargs)
    octfs = [Standardize(m=1), Standardize(m=1)] if use_octf else [None, None]
    if fixed_noise:
        train_y1_var = 0.1 + 0.1 * torch.rand_like(train_y1, **tkwargs)
        train_y2_var = 0.1 + 0.1 * torch.rand_like(train_y2, **tkwargs)
        model1 = FixedNoiseGP(
            train_X=train_x1,
            train_Y=train_y1,
            train_Yvar=train_y1_var,
            outcome_transform=octfs[0],
        )
        model2 = FixedNoiseGP(
            train_X=train_x2,
            train_Y=train_y2,
            train_Yvar=train_y2_var,
            outcome_transform=octfs[1],
        )
    else:
        model1 = SingleTaskGP(train_X=train_x1,
                              train_Y=train_y1,
                              outcome_transform=octfs[0])
        model2 = SingleTaskGP(train_X=train_x2,
                              train_Y=train_y2,
                              outcome_transform=octfs[1])
    model = ModelListGP(model1, model2)
    return model.to(**tkwargs)
Example #2
0
    def fit_model(self):
        """
        If no state_dict exists, fits the model and saves the state_dict.
        Otherwise, constructs the model but uses the fit given by the state_dict.
        """
        # read the data
        data_list = list()
        for i in range(1, 31):
            data_file = os.path.join(script_dir, "port_evals",
                                     "port_n=100_seed=%d" % i)
            data_list.append(torch.load(data_file))

        # join the data together
        X = torch.cat([data_list[i]["X"] for i in range(len(data_list))],
                      dim=0).squeeze(-2)
        Y = torch.cat([data_list[i]["Y"] for i in range(len(data_list))],
                      dim=0).squeeze(-2)

        # fit GP
        noise_prior = GammaPrior(1.1, 0.5)
        noise_prior_mode = (noise_prior.concentration - 1) / noise_prior.rate
        likelihood = GaussianLikelihood(
            noise_prior=noise_prior,
            batch_shape=[],
            noise_constraint=GreaterThan(
                0.000005,  # minimum observation noise assumed in the GP model
                transform=None,
                initial_value=noise_prior_mode,
            ),
        )

        # We save the state dict to avoid fitting the GP every time which takes ~3 mins
        try:
            state_dict = torch.load(
                os.path.join(script_dir, "portfolio_surrogate_state_dict.pt"))
            model = SingleTaskGP(X,
                                 Y,
                                 likelihood,
                                 outcome_transform=Standardize(m=1))
            model.load_state_dict(state_dict)
        except FileNotFoundError:
            model = SingleTaskGP(X,
                                 Y,
                                 likelihood,
                                 outcome_transform=Standardize(m=1))
            mll = ExactMarginalLogLikelihood(model.likelihood, model)
            from time import time

            start = time()
            fit_gpytorch_model(mll)
            print("fitting took %s seconds" % (time() - start))
            torch.save(
                model.state_dict(),
                os.path.join(script_dir, "portfolio_surrogate_state_dict.pt"),
            )
        self.model = model
Example #3
0
 def fit_gp_model(self,
                  arm: int,
                  alternative: int = None,
                  update: bool = False) -> None:
     """
     Fits a GP model to the given arm
     :param arm: Arm index
     :param alternative: Last sampled arm alternative. Used when adding samples
         without refitting
     :param update: Forces GP to be fitted. Otherwise, it is fitted every
         self.gp_update_freq samples.
     :return: None
     """
     arm_sample_count = sum([len(e) for e in self.observations[arm]])
     if update or arm_sample_count % self.gp_update_freq == 0:
         train_X_list = list()
         train_Y_list = list()
         for j in range(len(self.alternative_points[arm])):
             for k in range(len(self.observations[arm][j])):
                 train_X_list.append(
                     self.alternative_points[arm][j].unsqueeze(-2))
                 train_Y_list.append(
                     self.observations[arm][j][k].unsqueeze(-2))
         train_X = torch.cat(train_X_list, dim=0)
         train_Y = torch.cat(train_Y_list, dim=0)
         if self.noise_std is None:
             model = SingleTaskGP(train_X,
                                  train_Y,
                                  outcome_transform=Standardize(m=1))
         else:
             model = FixedNoiseGP(
                 train_X,
                 train_Y,
                 train_Yvar=torch.tensor([self.noise_std**2
                                          ]).expand_as(train_Y),
                 outcome_transform=Standardize(m=1),
             )
         mll = ExactMarginalLogLikelihood(model.likelihood, model)
         fit_gpytorch_model(mll)
         self.models[arm] = model
     else:
         last_point = self.alternative_points[arm][alternative].reshape(
             1, -1)
         last_observation = self.observations[arm][alternative][-1].reshape(
             1, -1)
         self.models[arm].condition_on_observations(last_point,
                                                    last_observation,
                                                    noise=self.noise_std**2)
Example #4
0
    def test_fantasize(self):
        for batch_shape, m, dtype, use_octf in itertools.product(
            (torch.Size(), torch.Size([2])),
            (1, 2),
            (torch.float, torch.double),
            (False, True),
        ):
            tkwargs = {"device": self.device, "dtype": dtype}
            octf = Standardize(m=m, batch_shape=batch_shape) if use_octf else None
            model, _ = self._get_model_and_data(
                batch_shape=batch_shape, m=m, outcome_transform=octf, **tkwargs
            )
            # fantasize
            X_f = torch.rand(torch.Size(batch_shape + torch.Size([4, 1])), **tkwargs)
            sampler = SobolQMCNormalSampler(num_samples=3)
            fm = model.fantasize(X=X_f, sampler=sampler)
            self.assertIsInstance(fm, model.__class__)
            fm = model.fantasize(X=X_f, sampler=sampler, observation_noise=False)
            self.assertIsInstance(fm, model.__class__)

        # check that input transforms are applied to X.
        tkwargs = {"device": self.device, "dtype": torch.float}
        intf = Normalize(d=1, bounds=torch.tensor([[0], [10]], **tkwargs))
        model, _ = self._get_model_and_data(
            batch_shape=torch.Size(),
            m=1,
            input_transform=intf,
            **tkwargs,
        )
        X_f = torch.rand(4, 1, **tkwargs)
        fm = model.fantasize(X_f, sampler=SobolQMCNormalSampler(num_samples=3))
        self.assertTrue(
            torch.allclose(fm.train_inputs[0][:, -4:], intf(X_f).expand(3, -1, -1))
        )
    def initialize_model(train_x, train_y, train_y_sem):
        """
        Defines a GP given X, Y, and noise observations (standard error of mean)

        train_x (theta):        (n_observations, n_parameters)
        train_y (G_obs):        (n_observations, n_black_box_outputs)
        train_y (G_obs_sem):    (n_observations, n_black_box_outputs)
        """

        train_ynoise = train_y_sem.pow(2.0)  # noise is in variance units

        # standardize outputs to zero mean, unit variance (over n_observations dimension)
        n_output_dims = (n_days * n_age if per_age_group_objective else n_days) \
                        if args.model_multi_output_simulator else 1
        outcome_transform = Standardize(m=n_output_dims)
        # train_y = standardize(train_y) (the above also normalizes noise)

        # choose model
        if args.model_noise_via_sem:
            assert (args.model_multi_output_simulator)
            model = FixedNoiseGP(train_x,
                                 train_y,
                                 train_ynoise,
                                 outcome_transform=outcome_transform)
        else:
            model = SingleTaskGP(train_x,
                                 train_y,
                                 outcome_transform=outcome_transform)

        # "Loss" for GPs - the marginal log likelihood
        mll = ExactMarginalLogLikelihood(model.likelihood, model)

        return mll, model
Example #6
0
 def test_subset_model(self):
     for batch_shape, dtype, use_octf in itertools.product(
         (torch.Size(), torch.Size([2])), (torch.float, torch.double),
         (True, False)):
         tkwargs = {"device": self.device, "dtype": dtype}
         octf = Standardize(m=2,
                            batch_shape=batch_shape) if use_octf else None
         model, model_kwargs = self._get_model_and_data(
             batch_shape=batch_shape,
             m=2,
             outcome_transform=octf,
             **tkwargs)
         subset_model = model.subset_output([0])
         X = torch.rand(torch.Size(batch_shape + torch.Size([3, 1])),
                        **tkwargs)
         p = model.posterior(X)
         p_sub = subset_model.posterior(X)
         self.assertTrue(
             torch.allclose(p_sub.mean,
                            p.mean[..., [0]],
                            atol=1e-4,
                            rtol=1e-4))
         self.assertTrue(
             torch.allclose(p_sub.variance,
                            p.variance[..., [0]],
                            atol=1e-4,
                            rtol=1e-4))
Example #7
0
 def _initialize_model(self, num_init_samples: int) -> None:
     """
     initialize the GP model with num_init_samples of initial samples
     """
     self.train_X = torch.rand((num_init_samples, self.dim))
     self.train_Y = self._function_call(self.train_X)
     self.model = SingleTaskGP(
         self.train_X, self.train_Y, outcome_transform=Standardize(m=1)
     )
     mll = ExactMarginalLogLikelihood(self.model.likelihood, self.model)
     fit_gpytorch_model(mll)
Example #8
0
    def initialize_model(train_x, train_y, train_y_sem):
        """
        Defines a GP given X, Y, and noise observations (standard error of mean)
        """
        
        train_ynoise = train_y_sem.pow(2.0) # noise is in variance units
        
        # standardize outputs to zero mean, unit variance to have good hyperparameter tuning
        model = FixedNoiseGP(train_x, train_y, train_ynoise, outcome_transform=Standardize(m=n_days * n_age))

        # "Loss" for GPs - the marginal log likelihood
        mll = ExactMarginalLogLikelihood(model.likelihood, model)

        return mll, model
Example #9
0
    def test_input_transforms(self):
        for infer_noise in [True, False]:
            tkwargs = {"device": self.device, "dtype": torch.double}
            train_X, train_Y, train_Yvar, test_X = self._get_unnormalized_data(
                infer_noise=infer_noise, **tkwargs
            )
            n, d = train_X.shape

            lb, ub = train_X.min(dim=0).values, train_X.max(dim=0).values
            mu, sigma = train_Y.mean(), train_Y.std()

            # Fit without transforms
            with torch.random.fork_rng():
                torch.manual_seed(0)
                gp1 = SaasFullyBayesianSingleTaskGP(
                    train_X=(train_X - lb) / (ub - lb),
                    train_Y=(train_Y - mu) / sigma,
                    train_Yvar=train_Yvar / sigma ** 2
                    if train_Yvar is not None
                    else train_Yvar,
                )
                fit_fully_bayesian_model_nuts(
                    gp1, warmup_steps=8, num_samples=5, thinning=2, disable_progbar=True
                )
                posterior1 = gp1.posterior(
                    (test_X - lb) / (ub - lb), marginalize_over_mcmc_samples=True
                )
                pred_mean1 = mu + sigma * posterior1.mean
                pred_var1 = (sigma ** 2) * posterior1.variance

            # Fit with transforms
            with torch.random.fork_rng():
                torch.manual_seed(0)
                gp2 = SaasFullyBayesianSingleTaskGP(
                    train_X=train_X,
                    train_Y=train_Y,
                    train_Yvar=train_Yvar,
                    input_transform=Normalize(d=train_X.shape[-1]),
                    outcome_transform=Standardize(m=1),
                )
                fit_fully_bayesian_model_nuts(
                    gp2, warmup_steps=8, num_samples=5, thinning=2, disable_progbar=True
                )
                posterior2 = gp2.posterior(test_X, marginalize_over_mcmc_samples=True)
                pred_mean2, pred_var2 = posterior2.mean, posterior2.variance

            self.assertTrue(torch.allclose(pred_mean1, pred_mean2))
            self.assertTrue(torch.allclose(pred_var1, pred_var2))
Example #10
0
 def test_decoupled_sampler(self):
     # tests the sample shape to ensure everything is working
     for train_n, dim, test_n, sample_shape, num_basis, transform in [
         [5, 1, 3, [1], 1, None],
         [20, 5, 15, [3, 5, 6], 5,
          Standardize(m=1)],
     ]:
         model = SingleTaskGP(
             torch.rand(train_n, dim),
             torch.rand(train_n, 1),
             # outcome_transform=transform,
         )
         sampler = decoupled_sampler(model=model,
                                     sample_shape=sample_shape,
                                     num_basis=num_basis)
         test_X = torch.rand(test_n, dim)
         out = sampler(test_X)
         self.assertTupleEqual((*sample_shape, test_n, 1), tuple(out.shape))
Example #11
0
 def test_fantasize(self):
     for batch_shape, m, dtype, use_octf in itertools.product(
         (torch.Size(), torch.Size([2])),
         (1, 2),
         (torch.float, torch.double),
         (False, True),
     ):
         tkwargs = {"device": self.device, "dtype": dtype}
         octf = Standardize(m=m, batch_shape=batch_shape) if use_octf else None
         model, _ = self._get_model_and_data(
             batch_shape=batch_shape, m=m, outcome_transform=octf, **tkwargs
         )
         # fantasize
         X_f = torch.rand(torch.Size(batch_shape + torch.Size([4, 1])), **tkwargs)
         sampler = SobolQMCNormalSampler(num_samples=3)
         fm = model.fantasize(X=X_f, sampler=sampler)
         self.assertIsInstance(fm, model.__class__)
         fm = model.fantasize(X=X_f, sampler=sampler, observation_noise=False)
         self.assertIsInstance(fm, model.__class__)
Example #12
0
def generate_random_gp(dim: int, num_train: int, standardized: bool = True):
    r"""
    Returns a fitted gp trained on random input. Useful for testing purposes.

    Args:
        dim: Input dimension
        num_train: Number of training points
        standardized: If True, the train outcomes are standardized

    Returns:
        A fitted SingleTaskGP model
    """
    if standardized:
        transform = Standardize(m=1)
    else:
        transform = None
    train_X = torch.rand(num_train, dim)
    train_Y = torch.rand(num_train, 1)
    model = SingleTaskGP(train_X, train_Y, outcome_transform=transform)
    mll = ExactMarginalLogLikelihood(model.likelihood, model)
    fit_gpytorch_model(mll)
    return model
Example #13
0
    def fit_gp(self) -> None:
        """
        Re-fits the GP using the most up to date data.
        """
        noise_prior = GammaPrior(1.1, 0.5)
        noise_prior_mode = (noise_prior.concentration - 1) / noise_prior.rate
        likelihood = GaussianLikelihood(
            noise_prior=noise_prior,
            batch_shape=[],
            noise_constraint=GreaterThan(
                # 0.000005,  # minimum observation noise assumed in the GP model
                0.0001,
                transform=None,
                initial_value=noise_prior_mode,
            ),
        )

        self.model = SingleTaskGP(
            self.X, self.Y, likelihood, outcome_transform=Standardize(m=1)
        )
        mll = ExactMarginalLogLikelihood(self.model.likelihood, self.model)
        fit_gpytorch_model(mll)

        # dummy computation to be safe with gp fit
        try:
            dummy = torch.rand(
                (1, self.q, self.dim), dtype=self.dtype, device=self.device
            )
            _ = self.model.posterior(dummy).mean
        except RuntimeError as err:
            if self.fit_count < 5:
                self.fit_count += 1
                self.Y = self.Y + torch.randn_like(self.Y) * 0.001
                self.fit_gp()
            else:
                raise err
        self.fit_count = 0
        self.passed = False
Example #14
0
    def test_gp(self):
        for batch_shape, m, dtype, use_octf in itertools.product(
            (torch.Size(), torch.Size([2])),
            (1, 2),
            (torch.float, torch.double),
            (False, True),
        ):
            tkwargs = {"device": self.device, "dtype": dtype}
            octf = Standardize(m=m,
                               batch_shape=batch_shape) if use_octf else None
            model, _ = self._get_model_and_data(batch_shape=batch_shape,
                                                m=m,
                                                outcome_transform=octf,
                                                **tkwargs)
            mll = ExactMarginalLogLikelihood(model.likelihood,
                                             model).to(**tkwargs)
            with warnings.catch_warnings():
                warnings.filterwarnings("ignore", category=OptimizationWarning)
                fit_gpytorch_model(mll, options={"maxiter": 1}, max_retries=1)

            # test init
            self.assertIsInstance(model.mean_module, ConstantMean)
            self.assertIsInstance(model.covar_module, ScaleKernel)
            matern_kernel = model.covar_module.base_kernel
            self.assertIsInstance(matern_kernel, MaternKernel)
            self.assertIsInstance(matern_kernel.lengthscale_prior, GammaPrior)
            if use_octf:
                self.assertIsInstance(model.outcome_transform, Standardize)

            # test param sizes
            params = dict(model.named_parameters())
            for p in params:
                self.assertEqual(params[p].numel(),
                                 m * torch.tensor(batch_shape).prod().item())

            # test posterior
            # test non batch evaluation
            X = torch.rand(batch_shape + torch.Size([3, 1]), **tkwargs)
            expected_shape = batch_shape + torch.Size([3, m])
            posterior = model.posterior(X)
            self.assertIsInstance(posterior, GPyTorchPosterior)
            self.assertEqual(posterior.mean.shape, expected_shape)
            self.assertEqual(posterior.variance.shape, expected_shape)

            # test adding observation noise
            posterior_pred = model.posterior(X, observation_noise=True)
            self.assertIsInstance(posterior_pred, GPyTorchPosterior)
            self.assertEqual(posterior_pred.mean.shape, expected_shape)
            self.assertEqual(posterior_pred.variance.shape, expected_shape)
            if use_octf:
                # ensure un-transformation is applied
                tmp_tf = model.outcome_transform
                del model.outcome_transform
                pp_tf = model.posterior(X, observation_noise=True)
                model.outcome_transform = tmp_tf
                expected_var = tmp_tf.untransform_posterior(pp_tf).variance
                self.assertTrue(
                    torch.allclose(posterior_pred.variance, expected_var))
            else:
                pvar = posterior_pred.variance
                pvar_exp = _get_pvar_expected(posterior, model, X, m)
                self.assertTrue(
                    torch.allclose(pvar, pvar_exp, rtol=1e-4, atol=1e-5))

            # test batch evaluation
            X = torch.rand(2, *batch_shape, 3, 1, **tkwargs)
            expected_shape = torch.Size([2]) + batch_shape + torch.Size([3, m])

            posterior = model.posterior(X)
            self.assertIsInstance(posterior, GPyTorchPosterior)
            self.assertEqual(posterior.mean.shape, expected_shape)
            # test adding observation noise in batch mode
            posterior_pred = model.posterior(X, observation_noise=True)
            self.assertIsInstance(posterior_pred, GPyTorchPosterior)
            self.assertEqual(posterior_pred.mean.shape, expected_shape)
            if use_octf:
                # ensure un-transformation is applied
                tmp_tf = model.outcome_transform
                del model.outcome_transform
                pp_tf = model.posterior(X, observation_noise=True)
                model.outcome_transform = tmp_tf
                expected_var = tmp_tf.untransform_posterior(pp_tf).variance
                self.assertTrue(
                    torch.allclose(posterior_pred.variance, expected_var))
            else:
                pvar = posterior_pred.variance
                pvar_exp = _get_pvar_expected(posterior, model, X, m)
                self.assertTrue(
                    torch.allclose(pvar, pvar_exp, rtol=1e-4, atol=1e-5))
Example #15
0
    def test_condition_on_observations(self):
        for batch_shape, m, dtype, use_octf in itertools.product(
            (torch.Size(), torch.Size([2])),
            (1, 2),
            (torch.float, torch.double),
            (False, True),
        ):
            tkwargs = {"device": self.device, "dtype": dtype}
            octf = Standardize(m=m,
                               batch_shape=batch_shape) if use_octf else None
            model, model_kwargs = self._get_model_and_data(
                batch_shape=batch_shape,
                m=m,
                outcome_transform=octf,
                **tkwargs)
            # evaluate model
            model.posterior(torch.rand(torch.Size([4, 1]), **tkwargs))
            # test condition_on_observations
            fant_shape = torch.Size([2])
            # fantasize at different input points
            X_fant, Y_fant = _get_random_data(fant_shape + batch_shape,
                                              m,
                                              n=3,
                                              **tkwargs)
            c_kwargs = ({
                "noise": torch.full_like(Y_fant, 0.01)
            } if isinstance(model, FixedNoiseGP) else {})
            cm = model.condition_on_observations(X_fant, Y_fant, **c_kwargs)
            # fantasize at same input points (check proper broadcasting)
            c_kwargs_same_inputs = ({
                "noise": torch.full_like(Y_fant[0], 0.01)
            } if isinstance(model, FixedNoiseGP) else {})
            cm_same_inputs = model.condition_on_observations(
                X_fant[0], Y_fant, **c_kwargs_same_inputs)

            test_Xs = [
                # test broadcasting single input across fantasy and model batches
                torch.rand(4, 1, **tkwargs),
                # separate input for each model batch and broadcast across
                # fantasy batches
                torch.rand(batch_shape + torch.Size([4, 1]), **tkwargs),
                # separate input for each model and fantasy batch
                torch.rand(fant_shape + batch_shape + torch.Size([4, 1]),
                           **tkwargs),
            ]
            for test_X in test_Xs:
                posterior = cm.posterior(test_X)
                self.assertEqual(posterior.mean.shape,
                                 fant_shape + batch_shape + torch.Size([4, m]))
                posterior_same_inputs = cm_same_inputs.posterior(test_X)
                self.assertEqual(
                    posterior_same_inputs.mean.shape,
                    fant_shape + batch_shape + torch.Size([4, m]),
                )

                # check that fantasies of batched model are correct
                if len(batch_shape) > 0 and test_X.dim() == 2:
                    state_dict_non_batch = {
                        key: (val[0] if val.numel() > 1 else val)
                        for key, val in model.state_dict().items()
                    }
                    model_kwargs_non_batch = {
                        "train_X": model_kwargs["train_X"][0],
                        "train_Y": model_kwargs["train_Y"][0],
                    }
                    if "train_Yvar" in model_kwargs:
                        model_kwargs_non_batch["train_Yvar"] = model_kwargs[
                            "train_Yvar"][0]
                    if "outcome_transform" in model_kwargs:
                        model_kwargs_non_batch[
                            "outcome_transform"] = Standardize(m=m)
                    model_non_batch = type(model)(**model_kwargs_non_batch)
                    model_non_batch.load_state_dict(state_dict_non_batch)
                    model_non_batch.eval()
                    model_non_batch.likelihood.eval()
                    model_non_batch.posterior(
                        torch.rand(torch.Size([4, 1]), **tkwargs))
                    c_kwargs = ({
                        "noise": torch.full_like(Y_fant[0, 0, :], 0.01)
                    } if isinstance(model, FixedNoiseGP) else {})
                    cm_non_batch = model_non_batch.condition_on_observations(
                        X_fant[0][0], Y_fant[:, 0, :], **c_kwargs)
                    non_batch_posterior = cm_non_batch.posterior(test_X)
                    self.assertTrue(
                        torch.allclose(
                            posterior_same_inputs.mean[:, 0, ...],
                            non_batch_posterior.mean,
                            atol=1e-3,
                        ))
                    self.assertTrue(
                        torch.allclose(
                            posterior_same_inputs.mvn.
                            covariance_matrix[:, 0, :, :],
                            non_batch_posterior.mvn.covariance_matrix,
                            atol=1e-3,
                        ))
    def test_gp(self):
        for (iteration_fidelity, data_fidelity) in self.FIDELITY_TEST_PAIRS:
            num_dim = 1 + (iteration_fidelity is not None) + (data_fidelity
                                                              is not None)
            for batch_shape, m, dtype, lin_trunc, use_octf in itertools.product(
                (torch.Size(), torch.Size([2])),
                (1, 2),
                (torch.float, torch.double),
                (False, True),
                (False, True),
            ):
                tkwargs = {"device": self.device, "dtype": dtype}
                octf = Standardize(
                    m=m, batch_shape=batch_shape) if use_octf else None
                model, _ = _get_model_and_data(
                    iteration_fidelity=iteration_fidelity,
                    data_fidelity=data_fidelity,
                    batch_shape=batch_shape,
                    m=m,
                    lin_truncated=lin_trunc,
                    outcome_transform=octf,
                    **tkwargs,
                )
                mll = ExactMarginalLogLikelihood(model.likelihood, model)
                mll.to(**tkwargs)
                with warnings.catch_warnings():
                    warnings.filterwarnings("ignore",
                                            category=OptimizationWarning)
                    fit_gpytorch_model(mll,
                                       sequential=False,
                                       options={"maxiter": 1})

                # test init
                self.assertIsInstance(model.mean_module, ConstantMean)
                self.assertIsInstance(model.covar_module, ScaleKernel)
                if use_octf:
                    self.assertIsInstance(model.outcome_transform, Standardize)

                # test param sizes
                params = dict(model.named_parameters())
                for p in params:
                    self.assertEqual(
                        params[p].numel(),
                        m * torch.tensor(batch_shape).prod().item())

                # test posterior
                # test non batch evaluation
                X = torch.rand(*batch_shape, 3, num_dim, **tkwargs)
                expected_shape = batch_shape + torch.Size([3, m])
                posterior = model.posterior(X)
                self.assertIsInstance(posterior, GPyTorchPosterior)
                self.assertEqual(posterior.mean.shape, expected_shape)
                self.assertEqual(posterior.variance.shape, expected_shape)
                if use_octf:
                    # ensure un-transformation is applied
                    tmp_tf = model.outcome_transform
                    del model.outcome_transform
                    pp_tf = model.posterior(X)
                    model.outcome_transform = tmp_tf
                    expected_var = tmp_tf.untransform_posterior(pp_tf).variance
                    self.assertTrue(
                        torch.allclose(posterior.variance, expected_var))

                # test batch evaluation
                X = torch.rand(2, *batch_shape, 3, num_dim, **tkwargs)
                expected_shape = torch.Size([2]) + batch_shape + torch.Size(
                    [3, m])
                posterior = model.posterior(X)
                self.assertIsInstance(posterior, GPyTorchPosterior)
                self.assertEqual(posterior.mean.shape, expected_shape)
                self.assertEqual(posterior.variance.shape, expected_shape)
                if use_octf:
                    # ensure un-transformation is applied
                    tmp_tf = model.outcome_transform
                    del model.outcome_transform
                    pp_tf = model.posterior(X)
                    model.outcome_transform = tmp_tf
                    expected_var = tmp_tf.untransform_posterior(pp_tf).variance
                    self.assertTrue(
                        torch.allclose(posterior.variance, expected_var))
Example #17
0
 def test_gpytorch_model(self):
     for dtype, use_octf in itertools.product((torch.float, torch.double),
                                              (False, True)):
         tkwargs = {"device": self.device, "dtype": dtype}
         octf = Standardize(m=1) if use_octf else None
         train_X = torch.rand(5, 1, **tkwargs)
         train_Y = torch.sin(train_X)
         # basic test
         model = SimpleGPyTorchModel(train_X, train_Y, octf)
         self.assertEqual(model.num_outputs, 1)
         self.assertEqual(model.batch_shape, torch.Size())
         test_X = torch.rand(2, 1, **tkwargs)
         posterior = model.posterior(test_X)
         self.assertIsInstance(posterior, GPyTorchPosterior)
         self.assertEqual(posterior.mean.shape, torch.Size([2, 1]))
         if use_octf:
             # ensure un-transformation is applied
             tmp_tf = model.outcome_transform
             del model.outcome_transform
             p_tf = model.posterior(test_X)
             model.outcome_transform = tmp_tf
             expected_var = tmp_tf.untransform_posterior(p_tf).variance
             self.assertTrue(
                 torch.allclose(posterior.variance, expected_var))
         # test observation noise
         posterior = model.posterior(test_X, observation_noise=True)
         self.assertIsInstance(posterior, GPyTorchPosterior)
         self.assertEqual(posterior.mean.shape, torch.Size([2, 1]))
         posterior = model.posterior(test_X,
                                     observation_noise=torch.rand(
                                         2, 1, **tkwargs))
         self.assertIsInstance(posterior, GPyTorchPosterior)
         self.assertEqual(posterior.mean.shape, torch.Size([2, 1]))
         # test noise shape validation
         with self.assertRaises(BotorchTensorDimensionError):
             model.posterior(test_X,
                             observation_noise=torch.rand(2, **tkwargs))
         # test conditioning on observations
         cm = model.condition_on_observations(torch.rand(2, 1, **tkwargs),
                                              torch.rand(2, 1, **tkwargs))
         self.assertIsInstance(cm, SimpleGPyTorchModel)
         self.assertEqual(cm.train_targets.shape, torch.Size([7]))
         # test subset_output
         with self.assertRaises(NotImplementedError):
             model.subset_output([0])
         # test fantasize
         sampler = SobolQMCNormalSampler(num_samples=2)
         cm = model.fantasize(torch.rand(2, 1, **tkwargs), sampler=sampler)
         self.assertIsInstance(cm, SimpleGPyTorchModel)
         self.assertEqual(cm.train_targets.shape, torch.Size([2, 7]))
         cm = model.fantasize(torch.rand(2, 1, **tkwargs),
                              sampler=sampler,
                              observation_noise=True)
         self.assertIsInstance(cm, SimpleGPyTorchModel)
         self.assertEqual(cm.train_targets.shape, torch.Size([2, 7]))
         cm = model.fantasize(
             torch.rand(2, 1, **tkwargs),
             sampler=sampler,
             observation_noise=torch.rand(2, 1, **tkwargs),
         )
         self.assertIsInstance(cm, SimpleGPyTorchModel)
         self.assertEqual(cm.train_targets.shape, torch.Size([2, 7]))
import torch
from botorch.test_functions import Branin
from botorch.models import SingleTaskGP
from botorch.fit import fit_gpytorch_model
from botorch.models.transforms import Standardize
from gpytorch.mlls import ExactMarginalLogLikelihood
from parametric_bandit.discrete_KG import DiscreteKGAlg

torch.manual_seed(0)

# generate input
n = 10
noise_std = 0.1
function = Branin(noise_std=0.1)
dim = function.dim
train_X = torch.rand((n, dim))
train_Y = function(train_X).unsqueeze(-1)

# fit model
gp = SingleTaskGP(train_X, train_Y, outcome_transform=Standardize(m=1))
mll = ExactMarginalLogLikelihood(gp.likelihood, gp)
fit_gpytorch_model(mll)

# get mu and Sigma
mu = gp.posterior(train_X).mean
Sigma = gp.posterior(train_X).mvn.covariance_matrix

# initiate the algorithm for testing
dkg = DiscreteKGAlg(M=n, error=noise_std**2, mu_0=mu, Sigma_0=Sigma)
print(dkg.find_maximizer())
Example #19
0
def EI_run(seed,
           alpha,
           rho,
           x0=5,
           n0=100,
           iter_count=1000,
           mu_1=2,
           mu_2=5,
           sigma_1=1,
           sigma_2=1,
           SAA_seed=None):
    """
    Does a single run of the Expected Improvement algorithm for the simple normal problem, without derivatives
    :param seed: random seed
    :param alpha: risk level
    :param rho: risk measure
    :param x0: Ignored! Just to keep the same arglist as others
    :param n0: outer sample starting size
    :param iter_count: number of iterations
    :param kwargs: passed to estimator
    :param SAA_seed: if given, an SAA version is run with this seed.
    :return:
    """
    np.random.seed(seed)
    begin = datetime.datetime.now()
    args = (n0, alpha, rho, mu_1, mu_2, sigma_1, sigma_2, SAA_seed)

    points = torch.empty(iter_count, 1)
    values = torch.empty(points.shape)
    points[:4] = draw_sobol_samples(torch.tensor([[-5.], [5.]]), n=4,
                                    q=1).reshape(-1, 1)
    for i in range(4):
        values[i] = estimate_no_grad(points[i], *args)

    for i in range(4, iter_count):
        # fit gp
        # this transforms the GP to unit domain - botorch priors work best there
        transformed_points = points / 10. + 0.5
        model = SingleTaskGP(transformed_points[:i],
                             values[:i],
                             outcome_transform=Standardize(m=1))
        mll = ExactMarginalLogLikelihood(model.likelihood, model)
        fit_gpytorch_model(mll)

        # optimize EI to get the candidate
        acqf = ExpectedImprovement(model,
                                   best_f=torch.min(values),
                                   maximize=False)
        best_p, _ = optimize_acqf(acqf,
                                  bounds=torch.tensor([[0.], [1.]]),
                                  q=1,
                                  num_restarts=10,
                                  raw_samples=50)
        # transform it back to original domain
        best_p = best_p.detach() * 10. - 5.
        points[i] = best_p
        values[i] = estimate_no_grad(points[i], *args)

    best_list = torch.empty(points.shape)
    for i in range(1, iter_count + 1):
        # pick the arg min of the history to return
        best_ind = torch.argmin(values[:i], dim=0)
        best_list[i - 1] = points[best_ind]

    x_list = best_list
    now = datetime.datetime.now()
    print('done time: %s' % (now - begin))
    print('call count: %d' % call_count)
    # np.save("sa_out/normal/EI_" + rho + "_" + str(alpha) + "_iter_" + str(iter_count) + "_x.npy", x_list)
    return x_list
    def test_gp(self):
        d = 3
        bounds = torch.tensor([[-1.0] * d, [1.0] * d])
        for batch_shape, m, ncat, dtype in itertools.product(
            (torch.Size(), torch.Size([2])),
            (1, 2),
            (0, 1, 3),
            (torch.float, torch.double),
        ):
            tkwargs = {"device": self.device, "dtype": dtype}
            train_X, train_Y = _get_random_data(
                batch_shape=batch_shape, m=m, d=d, **tkwargs
            )
            cat_dims = list(range(ncat))
            # test unsupported options
            with self.assertRaises(UnsupportedError):
                MixedSingleTaskGP(
                    train_X,
                    train_Y,
                    cat_dims=cat_dims,
                    outcome_transform=Standardize(m=m, batch_shape=batch_shape),
                )
            with self.assertRaises(UnsupportedError):
                MixedSingleTaskGP(
                    train_X,
                    train_Y,
                    cat_dims=cat_dims,
                    input_transform=Normalize(
                        d=d, bounds=bounds.to(**tkwargs), transform_on_preprocess=True
                    ),
                )
            if len(cat_dims) == 0:
                with self.assertRaises(ValueError):
                    MixedSingleTaskGP(train_X, train_Y, cat_dims=cat_dims)
                continue

            model = MixedSingleTaskGP(train_X, train_Y, cat_dims=cat_dims)
            mll = ExactMarginalLogLikelihood(model.likelihood, model).to(**tkwargs)
            with warnings.catch_warnings():
                warnings.filterwarnings("ignore", category=OptimizationWarning)
                fit_gpytorch_model(mll, options={"maxiter": 1}, max_retries=1)

            # test init
            self.assertIsInstance(model.mean_module, ConstantMean)
            if ncat < 3:
                self.assertIsInstance(model.covar_module, AdditiveKernel)
                sum_kernel, prod_kernel = model.covar_module.kernels
                self.assertIsInstance(sum_kernel, ScaleKernel)
                self.assertIsInstance(sum_kernel.base_kernel, AdditiveKernel)
                self.assertIsInstance(prod_kernel, ScaleKernel)
                self.assertIsInstance(prod_kernel.base_kernel, ProductKernel)
                sum_cont_kernel, sum_cat_kernel = sum_kernel.base_kernel.kernels
                prod_cont_kernel, prod_cat_kernel = prod_kernel.base_kernel.kernels
                self.assertIsInstance(sum_cont_kernel, MaternKernel)
                self.assertIsInstance(sum_cat_kernel, ScaleKernel)
                self.assertIsInstance(sum_cat_kernel.base_kernel, CategoricalKernel)
                self.assertIsInstance(prod_cont_kernel, MaternKernel)
                self.assertIsInstance(prod_cat_kernel, CategoricalKernel)
            else:
                self.assertIsInstance(model.covar_module, ScaleKernel)
                self.assertIsInstance(model.covar_module.base_kernel, CategoricalKernel)

            # test posterior
            # test non batch evaluation
            X = torch.rand(batch_shape + torch.Size([4, d]), **tkwargs)
            expected_shape = batch_shape + torch.Size([4, m])
            posterior = model.posterior(X)
            self.assertIsInstance(posterior, GPyTorchPosterior)
            self.assertEqual(posterior.mean.shape, expected_shape)
            self.assertEqual(posterior.variance.shape, expected_shape)

            # test adding observation noise
            posterior_pred = model.posterior(X, observation_noise=True)
            self.assertIsInstance(posterior_pred, GPyTorchPosterior)
            self.assertEqual(posterior_pred.mean.shape, expected_shape)
            self.assertEqual(posterior_pred.variance.shape, expected_shape)
            pvar = posterior_pred.variance
            pvar_exp = _get_pvar_expected(posterior, model, X, m)
            self.assertTrue(torch.allclose(pvar, pvar_exp, rtol=1e-4, atol=1e-5))

            # test batch evaluation
            X = torch.rand(2, *batch_shape, 3, d, **tkwargs)
            expected_shape = torch.Size([2]) + batch_shape + torch.Size([3, m])
            posterior = model.posterior(X)
            self.assertIsInstance(posterior, GPyTorchPosterior)
            self.assertEqual(posterior.mean.shape, expected_shape)
            # test adding observation noise in batch mode
            posterior_pred = model.posterior(X, observation_noise=True)
            self.assertIsInstance(posterior_pred, GPyTorchPosterior)
            self.assertEqual(posterior_pred.mean.shape, expected_shape)
            pvar = posterior_pred.variance
            pvar_exp = _get_pvar_expected(posterior, model, X, m)
            self.assertTrue(torch.allclose(pvar, pvar_exp, rtol=1e-4, atol=1e-5))
Example #21
0
                    rbounds[0] -= rdelta
                    rbounds[1] += rdelta
                    r_train_target = normalize(r_train, rbounds)

                train_kw_error = dict(
                    train_x=x_train,
                    train_y=r_train_target,
                    n_inducing_points=500,
                    tkwargs=tkwargs,
                    init=True,
                    scale=True,
                    covar_name=ker_name,
                    gp_file='',
                    save_file=os.path.join(data_folder, f"{gp_recon_model_name_str}/gp.npz"),
                    input_wp=inp_w,
                    outcome_transform=Standardize(m=1) if transfo == 'standardize' else None,
                    options={'lr': 1e-2, 'maxiter': 500}
                )

                gp_recon_model = gp_torch_train(**train_kw_error)
                gp_recon_model.eval()

                # ========================================================================
                # Test Models
                # ========================================================================
                with torch.no_grad():
                    pred_r_train_mean = gp_recon_model.posterior(x_train).mean
                    pred_r_train_std = gp_recon_model.posterior(x_train).variance.sqrt()
                    pred_r_test_mean = gp_recon_model.posterior(x_val).mean
                    pred_r_test_std = gp_recon_model.posterior(x_val).variance.sqrt()