コード例 #1
0
 def test_linear_mc_objective(self):
     for dtype in (torch.float, torch.double):
         weights = torch.rand(3, device=self.device, dtype=dtype)
         obj = LinearMCObjective(weights=weights)
         samples = torch.randn(4, 2, 3, device=self.device, dtype=dtype)
         self.assertTrue(
             torch.allclose(obj(samples), (samples * weights).sum(dim=-1))
         )
         samples = torch.randn(5, 4, 2, 3, device=self.device, dtype=dtype)
         self.assertTrue(
             torch.allclose(obj(samples), (samples * weights).sum(dim=-1))
         )
         # make sure this errors if sample output dimensions are incompatible
         with self.assertRaises(RuntimeError):
             obj(samples=torch.randn(2, device=self.device, dtype=dtype))
         with self.assertRaises(RuntimeError):
             obj(samples=torch.randn(1, device=self.device, dtype=dtype))
         # make sure we can't construct objectives with multi-dim. weights
         with self.assertRaises(ValueError):
             LinearMCObjective(
                 weights=torch.rand(2, 3, device=self.device, dtype=dtype)
             )
         with self.assertRaises(ValueError):
             LinearMCObjective(
                 weights=torch.tensor(1.0, device=self.device, dtype=dtype)
             )
コード例 #2
0
 def test_construct_inputs_qEI(self):
     c = get_acqf_input_constructor(qExpectedImprovement)
     mock_model = mock.Mock()
     kwargs = c(model=mock_model, training_data=self.bd_td)
     self.assertEqual(kwargs["model"], mock_model)
     self.assertIsNone(kwargs["objective"])
     self.assertIsNone(kwargs["X_pending"])
     self.assertIsNone(kwargs["sampler"])
     X_pending = torch.rand(2, 2)
     objective = LinearMCObjective(torch.rand(2))
     kwargs = c(
         model=mock_model,
         training_data=self.bd_td_mo,
         objective=objective,
         X_pending=X_pending,
     )
     self.assertEqual(kwargs["model"], mock_model)
     self.assertTrue(
         torch.equal(kwargs["objective"].weights, objective.weights))
     self.assertTrue(torch.equal(kwargs["X_pending"], X_pending))
     self.assertIsNone(kwargs["sampler"])
     best_f_expected = objective(self.bd_td_mo.Y).max()
     self.assertEqual(kwargs["best_f"], best_f_expected)
     # Check explicitly specifying `best_f`.
     best_f_expected = best_f_expected - 1  # Random value.
     kwargs = c(
         model=mock_model,
         training_data=self.bd_td_mo,
         objective=objective,
         X_pending=X_pending,
         best_f=best_f_expected,
     )
     self.assertEqual(kwargs["best_f"], best_f_expected)
コード例 #3
0
def get_botorch_objective(
    model: Model,
    objective_weights: Tensor,
    use_scalarized_objective: bool = True,
    outcome_constraints: Optional[Tuple[Tensor, Tensor]] = None,
    objective_thresholds: Optional[Tensor] = None,
    X_observed: Optional[Tensor] = None,
) -> AcquisitionObjective:
    """Constructs a BoTorch `AcquisitionObjective` object.

    Args:
        model: A BoTorch Model
        objective_weights: The objective is to maximize a weighted sum of
            the columns of f(x). These are the weights.
        use_scalarized_objective: A boolean parameter that defaults to True,
            specifying whether ScalarizedObjective should be used.
            NOTE: when using outcome_constraints, use_scalarized_objective
            will be ignored.
        outcome_constraints: A tuple of (A, b). For k outcome constraints
            and m outputs at f(x), A is (k x m) and b is (k x 1) such that
            A f(x) <= b. (Not used by single task models)
        objective_thresholds: A tensor containing thresholds forming a reference point
            from which to calculate pareto frontier hypervolume. Points that do not
            dominate the objective_thresholds contribute nothing to hypervolume.
        X_observed: Observed points that are feasible and appear in the
            objective or the constraints. None if there are no such points.

    Returns:
        A BoTorch `AcquisitionObjective` object. It will be one of:
        `ScalarizedObjective`, `LinearMCOObjective`, `ConstrainedMCObjective`.
    """
    if objective_thresholds is not None:
        nonzero_idcs = torch.nonzero(objective_weights).view(-1)
        objective_weights = objective_weights[nonzero_idcs]
        return WeightedMCMultiOutputObjective(weights=objective_weights,
                                              outcomes=nonzero_idcs.tolist())
    if X_observed is None:
        raise UnsupportedError(
            "X_observed is required to construct a BoTorch Objective.")
    if outcome_constraints:
        if use_scalarized_objective:
            logger.warning(
                "Currently cannot use ScalarizedObjective when there are outcome "
                "constraints. Ignoring (default) kwarg `use_scalarized_objective`"
                "= True. Creating ConstrainedMCObjective.")
        obj_tf = get_objective_weights_transform(objective_weights)

        def objective(samples: Tensor, X: Optional[Tensor] = None) -> Tensor:
            return obj_tf(samples)

        con_tfs = get_outcome_constraint_transforms(outcome_constraints)
        inf_cost = get_infeasible_cost(X=X_observed,
                                       model=model,
                                       objective=obj_tf)
        return ConstrainedMCObjective(objective=objective,
                                      constraints=con_tfs or [],
                                      infeasible_cost=inf_cost)
    elif use_scalarized_objective:
        return ScalarizedObjective(weights=objective_weights)
    return LinearMCObjective(weights=objective_weights)
コード例 #4
0
def get_NEI(
    model: Model,
    objective_weights: Tensor,
    outcome_constraints: Optional[Tuple[Tensor, Tensor]] = None,
    X_observed: Optional[Tensor] = None,
    X_pending: Optional[Tensor] = None,
    **kwargs: Any,
) -> AcquisitionFunction:
    r"""Instantiates a qNoisyExpectedImprovement acquisition function.

    Args:
        objective_weights: The objective is to maximize a weighted sum of
            the columns of f(x). These are the weights.
        outcome_constraints: A tuple of (A, b). For k outcome constraints
            and m outputs at f(x), A is (k x m) and b is (k x 1) such that
            A f(x) <= b. (Not used by single task models)
        X_observed: A tensor containing points observed for all objective
            outcomes and outcomes that appear in the outcome constraints (if
            there are any).
        X_pending: A tensor containing points whose evaluation is pending (i.e.
            that have been submitted for evaluation) present for all objective
            outcomes and outcomes that appear in the outcome constraints (if
            there are any).
        mc_samples: The number of MC samples to use (default: 512).
        qmc: If True, use qMC instead of MC (default: True).
        prune_baseline: If True, prune the baseline points for NEI (default: True).

    Returns:
        qNoisyExpectedImprovement: The instantiated acquisition function.
    """
    if X_observed is None:
        raise ValueError("There are no feasible observed points.")
    # Parse random_scalarization params
    objective_weights = _extract_random_scalarization_settings(
        objective_weights, outcome_constraints, **kwargs)
    # construct Objective module
    if outcome_constraints is None:
        objective = LinearMCObjective(weights=objective_weights)
    else:
        obj_tf = get_objective_weights_transform(objective_weights)
        con_tfs = get_outcome_constraint_transforms(outcome_constraints)
        X_observed = torch.as_tensor(X_observed)
        inf_cost = get_infeasible_cost(X=X_observed,
                                       model=model,
                                       objective=obj_tf)
        objective = ConstrainedMCObjective(objective=obj_tf,
                                           constraints=con_tfs or [],
                                           infeasible_cost=inf_cost)
    return get_acquisition_function(
        acquisition_function_name="qNEI",
        model=model,
        objective=objective,
        X_observed=X_observed,
        X_pending=X_pending,
        prune_baseline=kwargs.get("prune_baseline", True),
        mc_samples=kwargs.get("mc_samples", 512),
        qmc=kwargs.get("qmc", True),
        seed=torch.randint(1, 10000, (1, )).item(),
    )
コード例 #5
0
 def test_init(self):
     mm = MockModel(MockPosterior(mean=None))
     MPS = MaxPosteriorSampling(mm)
     self.assertEqual(MPS.model, mm)
     self.assertTrue(MPS.replacement)
     self.assertIsInstance(MPS.objective, IdentityMCObjective)
     obj = LinearMCObjective(torch.rand(2))
     MPS = MaxPosteriorSampling(mm, objective=obj, replacement=False)
     self.assertEqual(MPS.objective, obj)
     self.assertFalse(MPS.replacement)
コード例 #6
0
 def test_get_best_f_mc(self):
     with self.assertRaises(NotImplementedError):
         get_best_f_mc(training_data=self.nbd_td)
     best_f = get_best_f_mc(training_data=self.bd_td)
     best_f_expected = self.bd_td.Y.squeeze().max()
     self.assertEqual(best_f, best_f_expected)
     with self.assertRaises(UnsupportedError):
         get_best_f_mc(training_data=self.bd_td_mo)
     obj = LinearMCObjective(weights=torch.rand(2))
     best_f = get_best_f_mc(training_data=self.bd_td_mo, objective=obj)
     best_f_expected = (self.bd_td_mo.Y @ obj.weights).max()
     self.assertEqual(best_f, best_f_expected)
コード例 #7
0
    def test_optimize_objective(self, mock_optimize_acqf):
        from botorch.acquisition.input_constructors import optimize_objective

        mock_model = MockModel(
            posterior=MockPosterior(mean=None, variance=None))
        bounds = torch.rand(2, len(self.bounds))

        A = torch.rand(1, bounds.shape[-1])
        b = torch.zeros([1, 1])
        idx = A[0].nonzero(as_tuple=False).squeeze()
        inequality_constraints = ((idx, -A[0, idx], -b[0, 0]), )

        with self.subTest("scalarObjective_linearConstraints"):
            post_tf = ScalarizedPosteriorTransform(
                weights=torch.rand(bounds.shape[-1]))
            _ = optimize_objective(
                model=mock_model,
                bounds=bounds,
                q=1,
                posterior_transform=post_tf,
                linear_constraints=(A, b),
                fixed_features=None,
            )

            kwargs = mock_optimize_acqf.call_args[1]
            self.assertIsInstance(kwargs["acq_function"], PosteriorMean)
            self.assertTrue(torch.equal(kwargs["bounds"], bounds))
            self.assertEqual(len(kwargs["inequality_constraints"]), 1)
            for a, b in zip(kwargs["inequality_constraints"][0],
                            inequality_constraints[0]):
                self.assertTrue(torch.equal(a, b))

        with self.subTest("mcObjective_fixedFeatures"):
            _ = optimize_objective(
                model=mock_model,
                bounds=bounds,
                q=1,
                objective=LinearMCObjective(
                    weights=torch.rand(bounds.shape[-1])),
                fixed_features={0: 0.5},
            )

            kwargs = mock_optimize_acqf.call_args[1]
            self.assertIsInstance(kwargs["acq_function"],
                                  FixedFeatureAcquisitionFunction)
            self.assertIsInstance(kwargs["acq_function"].acq_func,
                                  qSimpleRegret)
            self.assertTrue(torch.equal(kwargs["bounds"], bounds[:, 1:]))
コード例 #8
0
    def test_construct_inputs_mes(self):
        func = get_acqf_input_constructor(qMaxValueEntropy)
        kwargs = func(
            model=mock.Mock(),
            training_data=self.bd_td,
            objective=LinearMCObjective(torch.rand(2)),
            bounds=self.bounds,
            candidate_size=17,
            maximize=False,
        )

        self.assertFalse(kwargs["maximize"])
        self.assertGreaterEqual(kwargs["candidate_set"].min(), 0.0)
        self.assertLessEqual(kwargs["candidate_set"].max(), 1.0)
        self.assertEqual([int(s) for s in kwargs["candidate_set"].shape],
                         [17, len(self.bounds)])
コード例 #9
0
def get_botorch_objective(
    model: Model,
    objective_weights: Tensor,
    use_scalarized_objective: bool = True,
    outcome_constraints: Optional[Tuple[Tensor, Tensor]] = None,
    X_observed: Optional[Tensor] = None,
) -> AcquisitionObjective:
    """Constructs a BoTorch `AcquisitionObjective` object.

    Args:
        model: A BoTorch Model
        objective_weights: The objective is to maximize a weighted sum of
            the columns of f(x). These are the weights.
        use_scalarized_objective: A boolean parameter that defaults to True,
            specifying whether ScalarizedObjective should be used.
            NOTE: when using outcome_constraints, use_scalarized_objective
            will be ignored.
        outcome_constraints: A tuple of (A, b). For k outcome constraints
            and m outputs at f(x), A is (k x m) and b is (k x 1) such that
            A f(x) <= b. (Not used by single task models)
        X_observed: Observed points that are feasible and appear in the
            objective or the constraints. None if there are no such points.

    Returns:
        A BoTorch `AcquisitionObjective` object. It will be one of:
        `ScalarizedObjective`, `LinearMCOObjective`, `ConstrainedMCObjective`.
    """
    if X_observed is None:
        raise UnsupportedError(
            "X_observed is required to construct a BoTorch Objective.")
    if outcome_constraints:
        if use_scalarized_objective:
            logger.warning(
                "Currently cannot use ScalarizedObjective when there are outcome "
                "constraints. Ignoring (default) kwarg `use_scalarized_objective`"
                "= True. Creating ConstrainedMCObjective.")
        obj_tf = get_objective_weights_transform(objective_weights)
        con_tfs = get_outcome_constraint_transforms(outcome_constraints)
        inf_cost = get_infeasible_cost(X=X_observed,
                                       model=model,
                                       objective=obj_tf)
        return ConstrainedMCObjective(objective=obj_tf,
                                      constraints=con_tfs or [],
                                      infeasible_cost=inf_cost)
    if use_scalarized_objective:
        return ScalarizedObjective(weights=objective_weights)
    return LinearMCObjective(weights=objective_weights)
コード例 #10
0
 def test_get_best_f_mc(self):
     with self.assertRaises(NotImplementedError):
         get_best_f_mc(training_data=self.nbd_td)
     best_f = get_best_f_mc(training_data=self.bd_td)
     best_f_expected = self.bd_td.Y.squeeze().max()
     self.assertEqual(best_f, best_f_expected)
     with self.assertRaises(UnsupportedError):
         get_best_f_mc(training_data=self.bd_td_mo)
     obj = LinearMCObjective(weights=torch.rand(2))
     best_f = get_best_f_mc(training_data=self.bd_td_mo, objective=obj)
     best_f_expected = (self.bd_td_mo.Y @ obj.weights).max()
     self.assertEqual(best_f, best_f_expected)
     post_tf = ScalarizedPosteriorTransform(weights=torch.ones(2))
     best_f = get_best_f_mc(training_data=self.bd_td_mo,
                            posterior_transform=post_tf)
     best_f_expected = (self.bd_td_mo.Y.sum(dim=-1)).max()
     self.assertEqual(best_f, best_f_expected)
コード例 #11
0
 def test_construct_inputs_mc_base(self):
     c = get_acqf_input_constructor(qSimpleRegret)
     mock_model = mock.Mock()
     kwargs = c(model=mock_model, training_data=self.bd_td)
     self.assertEqual(kwargs["model"], mock_model)
     self.assertIsNone(kwargs["objective"])
     self.assertIsNone(kwargs["X_pending"])
     self.assertIsNone(kwargs["sampler"])
     X_pending = torch.rand(2, 2)
     objective = LinearMCObjective(torch.rand(2))
     kwargs = c(
         model=mock_model,
         training_data=self.bd_td,
         objective=objective,
         X_pending=X_pending,
     )
     self.assertEqual(kwargs["model"], mock_model)
     self.assertTrue(
         torch.equal(kwargs["objective"].weights, objective.weights))
     self.assertTrue(torch.equal(kwargs["X_pending"], X_pending))
     self.assertIsNone(kwargs["sampler"])
コード例 #12
0
    def test_construct_inputs_kg(self):
        current_value = torch.tensor(1.23)
        with mock.patch(
                target=
                "botorch.acquisition.input_constructors.optimize_objective",
                return_value=(None, current_value),
        ):
            from botorch.acquisition import input_constructors

            func = input_constructors.get_acqf_input_constructor(
                qKnowledgeGradient)
            kwargs = func(
                model=mock.Mock(),
                training_data=self.bd_td,
                objective=LinearMCObjective(torch.rand(2)),
                bounds=self.bounds,
                num_fantasies=33,
            )

            self.assertEqual(kwargs["num_fantasies"], 33)
            self.assertEqual(kwargs["current_value"], current_value)
コード例 #13
0
 def test_construct_inputs_qUCB(self):
     c = get_acqf_input_constructor(qUpperConfidenceBound)
     mock_model = mock.Mock()
     kwargs = c(model=mock_model, training_data=self.bd_td)
     self.assertEqual(kwargs["model"], mock_model)
     self.assertIsNone(kwargs["objective"])
     self.assertIsNone(kwargs["X_pending"])
     self.assertIsNone(kwargs["sampler"])
     self.assertEqual(kwargs["beta"], 0.2)
     X_pending = torch.rand(2, 2)
     objective = LinearMCObjective(torch.rand(2))
     kwargs = c(
         model=mock_model,
         training_data=self.bd_td,
         objective=objective,
         X_pending=X_pending,
         beta=0.1,
     )
     self.assertEqual(kwargs["model"], mock_model)
     self.assertTrue(
         torch.equal(kwargs["objective"].weights, objective.weights))
     self.assertTrue(torch.equal(kwargs["X_pending"], X_pending))
     self.assertIsNone(kwargs["sampler"])
     self.assertEqual(kwargs["beta"], 0.1)
コード例 #14
0
    def test_KnowledgeGradient_helpers(self):
        model = KnowledgeGradient()
        model.fit(
            Xs=self.Xs,
            Ys=self.Ys,
            Yvars=self.Yvars,
            search_space_digest=SearchSpaceDigest(
                feature_names=self.feature_names,
                bounds=self.bounds,
            ),
            metric_names=self.metric_names,
        )

        # test _instantiate_KG
        objective = ScalarizedObjective(weights=self.objective_weights)

        # test acquisition setting
        acq_function = _instantiate_KG(model=model.model,
                                       objective=objective,
                                       n_fantasies=10,
                                       qmc=True)
        self.assertIsInstance(acq_function.sampler, SobolQMCNormalSampler)
        self.assertIsInstance(acq_function.objective, ScalarizedObjective)
        self.assertEqual(acq_function.num_fantasies, 10)

        acq_function = _instantiate_KG(model=model.model,
                                       objective=objective,
                                       n_fantasies=10,
                                       qmc=False)
        self.assertIsInstance(acq_function.sampler, IIDNormalSampler)

        acq_function = _instantiate_KG(model=model.model,
                                       objective=objective,
                                       qmc=False)
        self.assertIsNone(acq_function.inner_sampler)

        acq_function = _instantiate_KG(model=model.model,
                                       objective=objective,
                                       qmc=True,
                                       X_pending=self.X_dummy)
        self.assertIsNone(acq_function.inner_sampler)
        self.assertTrue(torch.equal(acq_function.X_pending, self.X_dummy))

        # test _get_best_point_acqf
        acq_function, non_fixed_idcs = model._get_best_point_acqf(
            objective_weights=self.objective_weights,
            outcome_constraints=self.outcome_constraints,
            X_observed=self.X_dummy,
        )
        self.assertIsInstance(acq_function, qSimpleRegret)
        self.assertIsInstance(acq_function.sampler, SobolQMCNormalSampler)
        self.assertIsNone(non_fixed_idcs)

        acq_function, non_fixed_idcs = model._get_best_point_acqf(
            objective_weights=self.objective_weights,
            outcome_constraints=self.outcome_constraints,
            X_observed=self.X_dummy,
            qmc=False,
        )
        self.assertIsInstance(acq_function.sampler, IIDNormalSampler)
        self.assertIsNone(non_fixed_idcs)

        with self.assertRaises(RuntimeError):
            model._get_best_point_acqf(
                objective_weights=self.objective_weights,
                outcome_constraints=self.outcome_constraints,
                X_observed=self.X_dummy,
                target_fidelities={1: 1.0},
            )

        # multi-fidelity tests

        model = KnowledgeGradient()
        model.fit(
            Xs=self.Xs,
            Ys=self.Ys,
            Yvars=self.Yvars,
            search_space_digest=SearchSpaceDigest(
                feature_names=self.feature_names,
                bounds=self.bounds,
                fidelity_features=[-1],
            ),
            metric_names=self.metric_names,
        )

        acq_function = _instantiate_KG(
            model=model.model,
            objective=objective,
            target_fidelities={2: 1.0},
            current_value=0,
        )
        self.assertIsInstance(acq_function, qMultiFidelityKnowledgeGradient)

        acq_function = _instantiate_KG(
            model=model.model,
            objective=LinearMCObjective(weights=self.objective_weights),
        )
        self.assertIsInstance(acq_function.inner_sampler,
                              SobolQMCNormalSampler)

        # test error that target fidelity and fidelity weight indices must match
        with self.assertRaises(RuntimeError):
            _instantiate_KG(
                model=model.model,
                objective=objective,
                target_fidelities={1: 1.0},
                fidelity_weights={2: 1.0},
                current_value=0,
            )

        # test _get_best_point_acqf
        acq_function, non_fixed_idcs = model._get_best_point_acqf(
            objective_weights=self.objective_weights,
            outcome_constraints=self.outcome_constraints,
            X_observed=self.X_dummy,
            target_fidelities={2: 1.0},
        )
        self.assertIsInstance(acq_function, FixedFeatureAcquisitionFunction)
        self.assertIsInstance(acq_function.acq_func.sampler,
                              SobolQMCNormalSampler)
        self.assertEqual(non_fixed_idcs, [0, 1])

        acq_function, non_fixed_idcs = model._get_best_point_acqf(
            objective_weights=self.objective_weights,
            outcome_constraints=self.outcome_constraints,
            X_observed=self.X_dummy,
            target_fidelities={2: 1.0},
            qmc=False,
        )
        self.assertIsInstance(acq_function, FixedFeatureAcquisitionFunction)
        self.assertIsInstance(acq_function.acq_func.sampler, IIDNormalSampler)
        self.assertEqual(non_fixed_idcs, [0, 1])

        # test error that fixed features are provided
        with self.assertRaises(RuntimeError):
            model._get_best_point_acqf(
                objective_weights=self.objective_weights,
                outcome_constraints=self.outcome_constraints,
                X_observed=self.X_dummy,
                qmc=False,
            )

        # test error if fixed features are also fidelity features
        with self.assertRaises(RuntimeError):
            model._get_best_point_acqf(
                objective_weights=self.objective_weights,
                outcome_constraints=self.outcome_constraints,
                X_observed=self.X_dummy,
                fixed_features={2: 2.0},
                target_fidelities={2: 1.0},
                qmc=False,
            )
コード例 #15
0
    def test_init(
        self,
        mock_botorch_acqf_class,
        mock_compute_model_deps,
        mock_get_objective_and_transform,
        mock_subset_model,
        mock_get_X,
    ):
        with self.assertRaisesRegex(TypeError, ".* missing .* 'botorch_acqf_class'"):
            Acquisition(
                surrogate=self.surrogate,
                search_space_digest=self.search_space_digest,
                objective_weights=self.objective_weights,
            )

        botorch_objective = LinearMCObjective(weights=torch.tensor([1.0]))
        mock_get_objective_and_transform.return_value = (botorch_objective, None)
        mock_get_X.return_value = (self.pending_observations[0], self.X[:1])
        acquisition = Acquisition(
            surrogate=self.surrogate,
            search_space_digest=self.search_space_digest,
            objective_weights=self.objective_weights,
            botorch_acqf_class=self.botorch_acqf_class,
            pending_observations=self.pending_observations,
            outcome_constraints=self.outcome_constraints,
            linear_constraints=self.linear_constraints,
            fixed_features=self.fixed_features,
            options=self.options,
            objective_thresholds=self.objective_thresholds,
        )

        # Check `_get_X_pending_and_observed` kwargs
        mock_get_X.assert_called_with(
            Xs=[self.training_data.X],
            pending_observations=self.pending_observations,
            objective_weights=self.objective_weights,
            outcome_constraints=self.outcome_constraints,
            bounds=self.search_space_digest.bounds,
            linear_constraints=self.linear_constraints,
            fixed_features=self.fixed_features,
        )
        # Call `subset_model` only when needed
        mock_subset_model.assert_called_with(
            model=acquisition.surrogate.model,
            objective_weights=self.objective_weights,
            outcome_constraints=self.outcome_constraints,
            objective_thresholds=self.objective_thresholds,
        )
        mock_subset_model.reset_mock()
        mock_get_objective_and_transform.reset_mock()
        self.mock_input_constructor.reset_mock()
        mock_botorch_acqf_class.reset_mock()
        self.options[Keys.SUBSET_MODEL] = False
        acquisition = Acquisition(
            surrogate=self.surrogate,
            search_space_digest=self.search_space_digest,
            objective_weights=self.objective_weights,
            botorch_acqf_class=self.botorch_acqf_class,
            pending_observations=self.pending_observations,
            outcome_constraints=self.outcome_constraints,
            linear_constraints=self.linear_constraints,
            fixed_features=self.fixed_features,
            options=self.options,
        )
        mock_subset_model.assert_not_called()
        # Check `get_botorch_objective_and_transform` kwargs
        mock_get_objective_and_transform.assert_called_once()
        _, ckwargs = mock_get_objective_and_transform.call_args
        self.assertIs(ckwargs["model"], self.acquisition.surrogate.model)
        self.assertIs(ckwargs["objective_weights"], self.objective_weights)
        self.assertIs(ckwargs["outcome_constraints"], self.outcome_constraints)
        self.assertTrue(torch.equal(ckwargs["X_observed"], self.X[:1]))
        # Check final `acqf` creation
        model_deps = {Keys.CURRENT_VALUE: 1.2}
        self.mock_input_constructor.assert_called_once()
        mock_botorch_acqf_class.assert_called_once()
        _, ckwargs = self.mock_input_constructor.call_args
        self.assertIs(ckwargs["model"], self.acquisition.surrogate.model)
        self.assertIs(ckwargs["objective"], botorch_objective)
        self.assertTrue(torch.equal(ckwargs["X_pending"], self.pending_observations[0]))
        for k, v in chain(self.options.items(), model_deps.items()):
            self.assertEqual(ckwargs[k], v)
コード例 #16
0
    def test_init(
        self,
        mock_botorch_acqf_class,
        mock_compute_model_deps,
        mock_get_objective,
        mock_subset_model,
        mock_get_X,
    ):
        self.acquisition.default_botorch_acqf_class = None
        with self.assertRaisesRegex(
                ValueError,
                ".*`botorch_acqf_class` argument must be specified."):
            Acquisition(
                surrogate=self.surrogate,
                bounds=self.bounds,
                objective_weights=self.objective_weights,
            )

        botorch_objective = LinearMCObjective(weights=torch.tensor([1.0]))
        mock_get_objective.return_value = botorch_objective
        mock_get_X.return_value = (self.pending_observations[0], self.X[:1])
        acquisition = Acquisition(
            surrogate=self.surrogate,
            bounds=self.bounds,
            objective_weights=self.objective_weights,
            botorch_acqf_class=self.botorch_acqf_class,
            pending_observations=self.pending_observations,
            outcome_constraints=self.outcome_constraints,
            linear_constraints=self.linear_constraints,
            fixed_features=self.fixed_features,
            target_fidelities=self.target_fidelities,
            options=self.options,
        )

        # Check `_get_X_pending_and_observed` kwargs
        mock_get_X.assert_called_with(
            Xs=[self.training_data.X],
            pending_observations=self.pending_observations,
            objective_weights=self.objective_weights,
            outcome_constraints=self.outcome_constraints,
            bounds=self.bounds,
            linear_constraints=self.linear_constraints,
            fixed_features=self.fixed_features,
        )
        # Call `subset_model` only when needed
        mock_subset_model.assert_called_with(
            acquisition.surrogate.model,
            objective_weights=self.objective_weights,
            outcome_constraints=self.outcome_constraints,
            objective_thresholds=self.objective_thresholds,
        )
        mock_subset_model.reset_mock()
        mock_get_objective.reset_mock()
        mock_botorch_acqf_class.reset_mock()
        self.options[Keys.SUBSET_MODEL] = False
        acquisition = Acquisition(
            surrogate=self.surrogate,
            bounds=self.bounds,
            objective_weights=self.objective_weights,
            botorch_acqf_class=self.botorch_acqf_class,
            pending_observations=self.pending_observations,
            outcome_constraints=self.outcome_constraints,
            linear_constraints=self.linear_constraints,
            fixed_features=self.fixed_features,
            target_fidelities=self.target_fidelities,
            options=self.options,
        )
        mock_subset_model.assert_not_called()
        # Check `get_botorch_objective` kwargs
        mock_get_objective.assert_called_once()
        _, ckwargs = mock_get_objective.call_args
        self.assertIs(ckwargs["model"], self.acquisition.surrogate.model)
        self.assertIs(ckwargs["objective_weights"], self.objective_weights)
        self.assertIs(ckwargs["outcome_constraints"], self.outcome_constraints)
        self.assertTrue(torch.equal(ckwargs["X_observed"], self.X[:1]))
        self.assertFalse(ckwargs["use_scalarized_objective"])
        # Check final `acqf` creation
        model_deps = {Keys.CURRENT_VALUE: 1.2}
        mock_botorch_acqf_class.assert_called_once()
        _, ckwargs = mock_botorch_acqf_class.call_args
        self.assertIs(ckwargs["model"], self.acquisition.surrogate.model)
        self.assertIs(ckwargs["objective"], botorch_objective)
        self.assertTrue(
            torch.equal(ckwargs["X_pending"], self.pending_observations[0]))
        for k, v in chain(self.options.items(), model_deps.items()):
            self.assertEqual(ckwargs[k], v)
コード例 #17
0
    def test_init(
        self,
        mock_botorch_acqf_class,
        mock_compute_data_deps,
        mock_compute_model_deps,
        mock_get_objective,
        mock_subset_model,
        mock_get_X,
    ):
        self.acquisition.default_botorch_acqf_class = None
        with self.assertRaisesRegex(
            ValueError, ".*`botorch_acqf_class` argument must be specified."
        ):
            Acquisition(
                surrogate=self.surrogate,
                bounds=self.bounds,
                objective_weights=self.objective_weights,
            )

        botorch_objective = LinearMCObjective(weights=torch.tensor([1.0]))
        mock_get_objective.return_value = botorch_objective
        acquisition = Acquisition(
            surrogate=self.surrogate,
            bounds=self.bounds,
            objective_weights=self.objective_weights,
            botorch_acqf_class=self.botorch_acqf_class,
            pending_observations=self.pending_observations,
            outcome_constraints=self.outcome_constraints,
            linear_constraints=self.linear_constraints,
            fixed_features=self.fixed_features,
            target_fidelities=self.target_fidelities,
            options=self.options,
        )

        # Check `_get_X_pending_and_observed` kwargs
        mock_get_X.assert_called_with(
            Xs=[self.training_data.X],
            pending_observations=self.pending_observations,
            objective_weights=self.objective_weights,
            outcome_constraints=self.outcome_constraints,
            bounds=self.bounds,
            linear_constraints=self.linear_constraints,
            fixed_features=self.fixed_features,
        )
        # Call `subset_model` only when needed
        mock_subset_model.assert_called_with(
            acquisition.surrogate.model,
            objective_weights=self.objective_weights,
            outcome_constraints=self.outcome_constraints,
        )
        mock_subset_model.reset_mock()
        self.options[Keys.SUBSET_MODEL] = False
        acquisition = Acquisition(
            surrogate=self.surrogate,
            bounds=self.bounds,
            objective_weights=self.objective_weights,
            botorch_acqf_class=self.botorch_acqf_class,
            pending_observations=self.pending_observations,
            outcome_constraints=self.outcome_constraints,
            linear_constraints=self.linear_constraints,
            fixed_features=self.fixed_features,
            target_fidelities=self.target_fidelities,
            options=self.options,
        )
        mock_subset_model.assert_not_called()
        # Check `get_botorch_objective` kwargs
        mock_get_objective.assert_called_with(
            model=self.acquisition.surrogate.model,
            objective_weights=self.objective_weights,
            outcome_constraints=self.outcome_constraints,
            X_observed=torch.tensor([3.0]),
            use_scalarized_objective=False,
        )
        # Check `compute_model_dependencies` kwargs
        mock_compute_model_deps.assert_called_with(
            surrogate=self.surrogate,
            bounds=self.bounds,
            objective_weights=self.objective_weights,
            pending_observations=self.pending_observations,
            outcome_constraints=self.outcome_constraints,
            linear_constraints=self.linear_constraints,
            fixed_features=self.fixed_features,
            target_fidelities=self.target_fidelities,
            options=self.options,
        )
        # Check `compute_data_dependencies` kwargs
        mock_compute_data_deps.assert_called_with(training_data=self.training_data)
        # Check final `acqf` creation
        model_deps = {Keys.CURRENT_VALUE: 1.2}
        data_deps = {}
        mock_botorch_acqf_class.assert_called_with(
            model=self.acquisition.surrogate.model,
            objective=botorch_objective,
            X_pending=torch.tensor([2.0]),
            X_baseline=torch.tensor([3.0]),
            **self.options,
            **model_deps,
            **data_deps,
        )
コード例 #18
0
    def test_construct_inputs_mf_base(self):
        target_fidelities = {0: 0.123}
        fidelity_weights = {0: 0.456}
        cost_intercept = 0.789
        num_trace_observations = 0

        with self.subTest("test_fully_specified"):
            kwargs = construct_inputs_mf_base(
                model=mock.Mock(),
                training_data=self.bd_td,
                objective=LinearMCObjective(torch.rand(2)),
                target_fidelities=target_fidelities,
                fidelity_weights=fidelity_weights,
                cost_intercept=cost_intercept,
                num_trace_observations=num_trace_observations,
            )

            self.assertEqual(kwargs["target_fidelities"], target_fidelities)

            X = torch.rand(3, 2)
            self.assertTrue(isinstance(kwargs["expand"], Callable))
            self.assertTrue(
                torch.equal(
                    kwargs["expand"](X),
                    expand_trace_observations(
                        X=X,
                        fidelity_dims=sorted(target_fidelities),
                        num_trace_obs=num_trace_observations,
                    ),
                ))

            self.assertTrue(isinstance(kwargs["project"], Callable))
            self.assertTrue(
                torch.equal(
                    kwargs["project"](X),
                    project_to_target_fidelity(
                        X, target_fidelities=target_fidelities),
                ))

            cm = kwargs["cost_aware_utility"].cost_model
            w = torch.tensor(list(fidelity_weights.values()),
                             dtype=cm.weights.dtype)
            self.assertEqual(cm.fixed_cost, cost_intercept)
            self.assertTrue(torch.allclose(cm.weights, w))

        with self.subTest("test_missing_fidelity_weights"):
            kwargs = construct_inputs_mf_base(
                model=mock.Mock(),
                training_data=self.bd_td,
                objective=LinearMCObjective(torch.rand(2)),
                target_fidelities=target_fidelities,
                cost_intercept=cost_intercept,
            )
            cm = kwargs["cost_aware_utility"].cost_model
            self.assertTrue(
                torch.allclose(cm.weights, torch.ones_like(cm.weights)))

        with self.subTest("test_mismatched_weights"):
            with self.assertRaisesRegex(RuntimeError,
                                        "Must provide the same indices for"):
                _ = construct_inputs_mf_base(
                    model=mock.Mock(),
                    training_data=self.bd_td,
                    objective=LinearMCObjective(torch.rand(2)),
                    target_fidelities={0: 1.0},
                    fidelity_weights={1: 0.5},
                    cost_intercept=cost_intercept,
                )