コード例 #1
0
 def test_current_generator_run_limit_unlimited_second_step(self):
     NUM_INIT_TRIALS = 5
     SECOND_STEP_PARALLELISM = 3
     NUM_ROUNDS = 4
     exp = get_branin_experiment()
     sobol_gs_with_parallelism_limits = GenerationStrategy(steps=[
         GenerationStep(
             model=Models.SOBOL,
             num_trials=NUM_INIT_TRIALS,
             min_trials_observed=3,
         ),
         GenerationStep(
             model=Models.SOBOL,
             num_trials=-1,
             max_parallelism=SECOND_STEP_PARALLELISM,
         ),
     ])
     sobol_gs_with_parallelism_limits._experiment = exp
     could_gen = self._run_GS_for_N_rounds(
         gs=sobol_gs_with_parallelism_limits,
         exp=exp,
         num_rounds=NUM_ROUNDS)
     # We expect trials from first generation step + trials from remaining rounds in
     # batches limited by parallelism setting in the second step.
     self.assertEqual(
         len(exp.trials),
         NUM_INIT_TRIALS + (NUM_ROUNDS - 1) * SECOND_STEP_PARALLELISM,
     )
     self.assertTrue(all(t.status.is_completed
                         for t in exp.trials.values()))
     self.assertEqual(could_gen, [NUM_INIT_TRIALS] +
                      [SECOND_STEP_PARALLELISM] * (NUM_ROUNDS - 1))
コード例 #2
0
 def setUp(self):
     self.branin_experiment = get_branin_experiment()
     self.branin_experiment._properties[
         Keys.IMMUTABLE_SEARCH_SPACE_AND_OPT_CONF] = True
     self.branin_experiment_no_impl_metrics = Experiment(
         search_space=get_branin_search_space(),
         optimization_config=OptimizationConfig(objective=Objective(
             metric=Metric(name="branin"))),
     )
     self.sobol_GPEI_GS = choose_generation_strategy(
         search_space=get_branin_search_space())
     self.two_sobol_steps_GS = GenerationStrategy(  # Contrived GS to ensure
         steps=[  # that `DataRequiredError` is property handled in scheduler.
             GenerationStep(  # This error is raised when not enough trials
                 model=Models.
                 SOBOL,  # have been observed to proceed to next
                 num_trials=5,  # geneneration step.
                 min_trials_observed=3,
                 max_parallelism=2,
             ),
             GenerationStep(model=Models.SOBOL,
                            num_trials=-1,
                            max_parallelism=3),
         ])
     # GS to force the scheduler to poll completed trials after each ran trial.
     self.sobol_GS_no_parallelism = GenerationStrategy(steps=[
         GenerationStep(
             model=Models.SOBOL, num_trials=-1, max_parallelism=1)
     ])
コード例 #3
0
 def test_sobol_GPEI_strategy_keep_generating(self, mock_GPEI_gen,
                                              mock_GPEI_update,
                                              mock_GPEI_init):
     exp = get_branin_experiment()
     sobol_GPEI_generation_strategy = GenerationStrategy(steps=[
         GenerationStep(model=Models.SOBOL, num_arms=5),
         GenerationStep(model=Models.GPEI, num_arms=-1),
     ])
     self.assertEqual(sobol_GPEI_generation_strategy.name, "Sobol+GPEI")
     self.assertEqual(sobol_GPEI_generation_strategy.generator_changes, [5])
     exp.new_trial(
         generator_run=sobol_GPEI_generation_strategy.gen(exp)).run()
     for i in range(1, 15):
         # Passing in all experiment data should cause an error as only
         # new data should be passed into `gen`.
         if i > 1:
             with self.assertRaisesRegex(ValueError, "Data for arm"):
                 g = sobol_GPEI_generation_strategy.gen(
                     exp, exp.fetch_data())
         g = sobol_GPEI_generation_strategy.gen(
             exp, exp._fetch_trial_data(trial_index=i - 1))
         exp.new_trial(generator_run=g).run()
         if i > 4:
             self.assertIsInstance(sobol_GPEI_generation_strategy.model,
                                   TorchModelBridge)
コード例 #4
0
ファイル: decoder.py プロジェクト: sailfish009/Ax
 def generation_strategy_from_sqa(
         self, gs_sqa: SQAGenerationStrategy) -> GenerationStrategy:
     """Convert SQALchemy generation strategy to Ax `GenerationStrategy`."""
     steps = object_from_json(gs_sqa.steps)
     gs = GenerationStrategy(name=gs_sqa.name, steps=steps)
     gs._curr = gs._steps[gs_sqa.curr_index]
     gs._generator_runs = [
         self.generator_run_from_sqa(gr) for gr in gs_sqa.generator_runs
     ]
     if len(gs._generator_runs) > 0:
         # Generation strategy had an initialized model.
         # pyre-ignore[16]: SQAGenerationStrategy does not have `experiment` attr.
         gs._experiment = self.experiment_from_sqa(gs_sqa.experiment)
         # If model in the current step was not directly from the `Models` enum,
         # pass its type to `restore_model_from_generator_run`, which will then
         # attempt to use this type to recreate the model.
         if type(gs._curr.model) != Models:
             models_enum = type(gs._curr.model)
             assert issubclass(models_enum, Models)
             # pyre-ignore[6]: `models_enum` typing hackiness
             gs._restore_model_from_generator_run(models_enum=models_enum)
         else:
             gs._restore_model_from_generator_run()
     gs._db_id = gs_sqa.id
     return gs
コード例 #5
0
    def _run_GS_for_N_rounds(self, gs: GenerationStrategy, exp: Experiment,
                             num_rounds: int) -> List[int]:
        could_gen = []
        for _ in range(num_rounds):
            (
                num_trials_to_gen,
                opt_complete,
            ) = gs.current_generator_run_limit()
            self.assertFalse(opt_complete)
            could_gen.append(num_trials_to_gen)
            trials = []

            for _ in range(num_trials_to_gen):
                gr = gs.gen(
                    experiment=exp,
                    pending_observations=get_pending(experiment=exp),
                )
                trials.append(
                    exp.new_trial(gr).mark_running(no_runner_required=True))

            for trial in trials:
                exp.attach_data(get_branin_data(trial_indices=[trial.index]))
                trial.mark_completed()

        return could_gen
コード例 #6
0
    def setUp(self):
        self.gr = GeneratorRun(arms=[Arm(parameters={"x1": 1, "x2": 2})])

        # Mock out slow GPEI.
        self.torch_model_bridge_patcher = patch(
            f"{TorchModelBridge.__module__}.TorchModelBridge", spec=True)
        self.mock_torch_model_bridge = self.torch_model_bridge_patcher.start()
        self.mock_torch_model_bridge.return_value.gen.return_value = self.gr

        # Mock out slow TS.
        self.discrete_model_bridge_patcher = patch(
            f"{DiscreteModelBridge.__module__}.DiscreteModelBridge", spec=True)
        self.mock_discrete_model_bridge = self.discrete_model_bridge_patcher.start(
        )
        self.mock_discrete_model_bridge.return_value.gen.return_value = self.gr

        # Mock in `Models` registry
        self.registry_setup_dict_patcher = patch.dict(
            f"{Models.__module__}.MODEL_KEY_TO_MODEL_SETUP",
            {
                "Factorial":
                MODEL_KEY_TO_MODEL_SETUP["Factorial"]._replace(
                    bridge_class=self.mock_discrete_model_bridge),
                "Thompson":
                MODEL_KEY_TO_MODEL_SETUP["Thompson"]._replace(
                    bridge_class=self.mock_discrete_model_bridge),
                "GPEI":
                MODEL_KEY_TO_MODEL_SETUP["GPEI"]._replace(
                    bridge_class=self.mock_torch_model_bridge),
            },
        )
        self.mock_in_registry = self.registry_setup_dict_patcher.start()

        # model bridges are mocked, which makes kwargs' validation difficult,
        # so for now we will skip it in the generation strategy tests.
        # NOTE: Starting with Python3.8 this is not a problem as `autospec=True`
        # ensures that the mocks have correct signatures, but in earlier
        # versions kwarg validation on mocks does not really work.
        self.step_model_kwargs = {"silently_filter_kwargs": True}
        self.hss_experiment = get_hierarchical_search_space_experiment()
        self.sobol_GPEI_GS = GenerationStrategy(
            name="Sobol+GPEI",
            steps=[
                GenerationStep(
                    model=Models.SOBOL,
                    num_trials=5,
                    model_kwargs=self.step_model_kwargs,
                ),
                GenerationStep(model=Models.GPEI,
                               num_trials=2,
                               model_kwargs=self.step_model_kwargs),
            ],
        )
        self.sobol_GS = GenerationStrategy(steps=[
            GenerationStep(
                Models.SOBOL,
                num_trials=-1,
                should_deduplicate=True,
            )
        ])
コード例 #7
0
 def test_sobol_GPEI_strategy_batches(self):
     mock_GPEI_gen = self.mock_torch_model_bridge.return_value.gen
     mock_GPEI_gen.return_value = GeneratorRun(
         arms=[
             Arm(parameters={"x1": 1, "x2": 2}),
             Arm(parameters={"x1": 3, "x2": 4}),
         ]
     )
     exp = get_branin_experiment()
     sobol_GPEI_generation_strategy = GenerationStrategy(
         name="Sobol+GPEI",
         steps=[
             GenerationStep(model=Models.SOBOL, num_trials=1),
             GenerationStep(model=Models.GPEI, num_trials=6),
         ],
     )
     self.assertEqual(sobol_GPEI_generation_strategy.name, "Sobol+GPEI")
     self.assertEqual(sobol_GPEI_generation_strategy.model_transitions, [1])
     gr = sobol_GPEI_generation_strategy.gen(exp, n=2)
     exp.new_batch_trial(generator_run=gr).run()
     for i in range(1, 8):
         if i == 7:
             # Check completeness error message.
             with self.assertRaises(GenerationStrategyCompleted):
                 g = sobol_GPEI_generation_strategy.gen(exp, n=2)
         else:
             g = sobol_GPEI_generation_strategy.gen(exp, n=2)
         exp.new_batch_trial(generator_run=g).run()
     self.assertIsInstance(sobol_GPEI_generation_strategy.model, TorchModelBridge)
コード例 #8
0
ファイル: dispatch_utils.py プロジェクト: liangshi7/Ax
def choose_generation_strategy(
    search_space: SearchSpace,
    arms_per_trial: int = 1,
    enforce_sequential_optimization: bool = True,
    random_seed: Optional[int] = None,
    winsorize_botorch_model: bool = False,
    winsorization_limits: Optional[Tuple[Optional[float], Optional[float]]] = None,
    no_bayesian_optimization: bool = False,
) -> GenerationStrategy:
    """Select an appropriate generation strategy based on the properties of
    the search space.

    Args:
        search_space: SearchSpace, based on the properties of which to select the
            generation strategy.
        arms_per_trial: If a trial is batched, how many arms will be in each batch.
            Defaults to 1, which corresponds to a regular, non-batched, `Trial`.
        enforce_sequential_optimization: Whether to enforce that the generation
            strategy needs to be updated with `min_arms_observed` observations for
            a given generation step before proceeding to the next one.
        random_seed: Fixed random seed for the Sobol generator.
        winsorize_botorch_model: Whether to apply the winsorization transform
            prior to applying other transforms for fitting the BoTorch model.
        winsorization_limits: Bounds for winsorization, if winsorizing, expressed
            as percentile. Usually only the upper winsorization trim is used when
            minimizing, and only the lower when maximizing.
        no_bayesian_optimization: If True, Bayesian optimization generation
            strategy will not be suggested and quasi-random strategy will be used.
    """
    # If there are more discrete choices than continuous parameters, Sobol
    # will do better than GP+EI.
    if not no_bayesian_optimization and _should_use_gp(search_space=search_space):
        # Ensure that number of arms per model is divisible by batch size.
        sobol_arms = max(5, len(search_space.parameters))
        if arms_per_trial != 1:  # pragma: no cover
            # If using batches, ensure that initialization sample is divisible by
            # the batch size.
            sobol_arms = ceil(sobol_arms / arms_per_trial) * arms_per_trial
        gs = GenerationStrategy(
            steps=[
                _make_sobol_step(
                    num_arms=sobol_arms,
                    enforce_num_arms=enforce_sequential_optimization,
                    seed=random_seed,
                ),
                _make_botorch_step(
                    recommended_max_parallelism=3,
                    winsorize=winsorize_botorch_model,
                    winsorization_limits=winsorization_limits,
                ),
            ]
        )
        logger.info(
            f"Using Bayesian Optimization generation strategy: {gs}. Iterations "
            f"after {sobol_arms} will take longer to generate due to model-fitting."
        )
        return gs

    logger.info(f"Using Sobol generation strategy.")
    return GenerationStrategy(steps=[_make_sobol_step(seed=random_seed)])
コード例 #9
0
 def test_factorial_thompson_strategy(self, mock_update, mock_gen,
                                      mock_discrete):
     exp = get_branin_experiment()
     factorial_thompson_generation_strategy = GenerationStrategy(steps=[
         GenerationStep(model=Models.FACTORIAL, num_arms=1),
         GenerationStep(model=Models.THOMPSON, num_arms=-1),
     ])
     self.assertEqual(factorial_thompson_generation_strategy.name,
                      "factorial+thompson")
     self.assertEqual(
         factorial_thompson_generation_strategy.generator_changes, [1])
     for i in range(2):
         data = get_data() if i > 0 else None
         factorial_thompson_generation_strategy.gen(experiment=exp,
                                                    new_data=data)
         exp.new_batch_trial().add_arm(Arm(parameters={"x1": i, "x2": i}))
         if i < 1:
             mock_discrete.assert_called()
             args, kwargs = mock_discrete.call_args
             self.assertIsInstance(kwargs.get("model"),
                                   FullFactorialGenerator)
             exp.new_batch_trial()
         else:
             mock_discrete.assert_called()
             args, kwargs = mock_discrete.call_args
             self.assertIsInstance(
                 kwargs.get("model"),
                 (ThompsonSampler, EmpiricalBayesThompsonSampler),
             )
コード例 #10
0
    def test_factorial_thompson_strategy(self, _):
        exp = get_branin_experiment()
        factorial_thompson_generation_strategy = GenerationStrategy(steps=[
            GenerationStep(
                model=Models.FACTORIAL,
                num_trials=1,
                model_kwargs=self.step_model_kwargs,
            ),
            GenerationStep(
                model=Models.THOMPSON,
                num_trials=-1,
                model_kwargs=self.step_model_kwargs,
            ),
        ])
        self.assertEqual(factorial_thompson_generation_strategy.name,
                         "Factorial+Thompson")
        self.assertEqual(
            factorial_thompson_generation_strategy.model_transitions, [1])
        mock_model_bridge = self.mock_discrete_model_bridge.return_value

        # Initial factorial batch.
        exp.new_batch_trial(
            factorial_thompson_generation_strategy.gen(experiment=exp))
        args, kwargs = mock_model_bridge._set_kwargs_to_save.call_args
        self.assertEqual(kwargs.get("model_key"), "Factorial")

        # Subsequent Thompson sampling batch.
        exp.new_batch_trial(
            factorial_thompson_generation_strategy.gen(experiment=exp))
        args, kwargs = mock_model_bridge._set_kwargs_to_save.call_args
        self.assertEqual(kwargs.get("model_key"), "Thompson")
コード例 #11
0
 def test_store_experiment(self):
     exp = get_branin_experiment()
     sobol_generation_strategy = GenerationStrategy(
         steps=[GenerationStep(model=Models.SOBOL, num_arms=5)])
     self.assertIsNone(sobol_generation_strategy._experiment)
     sobol_generation_strategy.gen(exp)
     self.assertIsNotNone(sobol_generation_strategy._experiment)
コード例 #12
0
def generation_strategy_from_json(
        generation_strategy_json: Dict[str, Any],
        experiment: Optional[Experiment] = None) -> GenerationStrategy:
    """Load generation strategy from JSON."""
    steps = object_from_json(generation_strategy_json.pop("steps"))
    gs = GenerationStrategy(steps=steps,
                            name=generation_strategy_json.pop("name"))
    gs._db_id = object_from_json(generation_strategy_json.pop("db_id"))
    gs._experiment = experiment or object_from_json(
        generation_strategy_json.pop("experiment"))
    gs._curr = gs._steps[generation_strategy_json.pop("curr_index")]
    gs._generator_runs = object_from_json(
        generation_strategy_json.pop("generator_runs"))
    if generation_strategy_json.pop(
            "had_initialized_model"):  # pragma: no cover
        # If model in the current step was not directly from the `Models` enum,
        # pass its type to `restore_model_from_generator_run`, which will then
        # attempt to use this type to recreate the model.
        if type(gs._curr.model) != Models:
            models_enum = type(gs._curr.model)
            assert issubclass(models_enum, ModelRegistryBase)
            # pyre-ignore[6]: `models_enum` typing hackiness
            gs._restore_model_from_generator_run(models_enum=models_enum)
            return gs

        gs._restore_model_from_generator_run()
    return gs
コード例 #13
0
 def test_clone_reset(self):
     ftgs = GenerationStrategy(steps=[
         GenerationStep(model=Models.FACTORIAL, num_arms=1),
         GenerationStep(model=Models.THOMPSON, num_arms=2),
     ])
     ftgs._curr = ftgs._steps[1]
     self.assertEqual(ftgs._curr.index, 1)
     self.assertEqual(ftgs.clone_reset()._curr.index, 0)
コード例 #14
0
 def test_custom_callables_for_models(self):
     exp = get_branin_experiment()
     sobol_factory_generation_strategy = GenerationStrategy(
         steps=[GenerationStep(model=get_sobol, num_trials=-1)]
     )
     self.assertFalse(sobol_factory_generation_strategy._uses_registered_models)
     self.assertTrue(sobol_factory_generation_strategy.uses_non_registered_models)
     gr = sobol_factory_generation_strategy.gen(experiment=exp, n=1)
     self.assertEqual(len(gr.arms), 1)
コード例 #15
0
ファイル: test_generation_strategy.py プロジェクト: ekilic/Ax
 def test_max_parallelism_reached(self):
     exp = get_branin_experiment()
     sobol_generation_strategy = GenerationStrategy(steps=[
         GenerationStep(model=Models.SOBOL, num_trials=5, max_parallelism=1)
     ])
     exp.new_trial(generator_run=sobol_generation_strategy.gen(
         experiment=exp)).mark_running(no_runner_required=True)
     with self.assertRaises(MaxParallelismReachedException):
         sobol_generation_strategy.gen(experiment=exp)
コード例 #16
0
 def test_kwargs_passed(self):
     gs = GenerationStrategy(steps=[
         GenerationStep(model=Models.SOBOL,
                        num_arms=1,
                        model_kwargs={"scramble": False})
     ])
     exp = get_branin_experiment()
     gs.gen(exp, exp.fetch_data())
     self.assertFalse(gs._model.model.scramble)
コード例 #17
0
 def test_sobol_GPEI_strategy_batches(self, mock_GPEI_gen, mock_GPEI_update,
                                      mock_GPEI_init):
     exp = get_branin_experiment()
     sobol_GPEI_generation_strategy = GenerationStrategy(
         name="Sobol+GPEI",
         steps=[
             GenerationStep(model=Models.SOBOL, num_arms=5),
             GenerationStep(model=Models.GPEI, num_arms=8),
         ],
     )
     self.assertEqual(sobol_GPEI_generation_strategy.name, "Sobol+GPEI")
     self.assertEqual(sobol_GPEI_generation_strategy.generator_changes, [5])
     exp.new_batch_trial(
         generator_run=sobol_GPEI_generation_strategy.gen(exp, n=2)).run()
     for i in range(1, 8):
         if i == 2:
             with self.assertRaisesRegex(ValueError,
                                         "Cannot generate 2 new"):
                 g = sobol_GPEI_generation_strategy.gen(
                     exp, exp._fetch_trial_data(trial_index=i - 1), n=2)
             g = sobol_GPEI_generation_strategy.gen(
                 exp, exp._fetch_trial_data(trial_index=i - 1))
         elif i == 7:
             # Check completeness error message.
             with self.assertRaisesRegex(ValueError, "Generation strategy"):
                 g = sobol_GPEI_generation_strategy.gen(
                     exp, exp._fetch_trial_data(trial_index=i - 1), n=2)
         else:
             g = sobol_GPEI_generation_strategy.gen(
                 exp, exp._fetch_trial_data(trial_index=i - 1), n=2)
         exp.new_batch_trial(generator_run=g).run()
         if i > 4:
             mock_GPEI_init.assert_called()
     with self.assertRaises(ValueError):
         sobol_GPEI_generation_strategy.gen(exp, exp.fetch_data())
コード例 #18
0
 def test_sobol_GPEI_strategy(self):
     exp = get_branin_experiment()
     sobol_GPEI = GenerationStrategy(
         name="Sobol+GPEI",
         steps=[
             GenerationStep(
                 model=Models.SOBOL,
                 num_trials=5,
                 model_kwargs=self.step_model_kwargs,
             ),
             GenerationStep(model=Models.GPEI,
                            num_trials=2,
                            model_kwargs=self.step_model_kwargs),
         ],
     )
     self.assertEqual(sobol_GPEI.name, "Sobol+GPEI")
     self.assertEqual(sobol_GPEI.model_transitions, [5])
     # exp.new_trial(generator_run=sobol_GPEI.gen(exp)).run()
     for i in range(7):
         g = sobol_GPEI.gen(exp)
         exp.new_trial(generator_run=g).run()
         self.assertEqual(len(sobol_GPEI._generator_runs), i + 1)
         if i > 4:
             self.mock_torch_model_bridge.assert_called()
         else:
             self.assertEqual(g._model_key, "Sobol")
             self.assertEqual(
                 g._model_kwargs,
                 {
                     "seed": None,
                     "deduplicate": False,
                     "init_position": i,
                     "scramble": True,
                     "generated_points": None,
                 },
             )
             self.assertEqual(
                 g._bridge_kwargs,
                 {
                     "optimization_config": None,
                     "status_quo_features": None,
                     "status_quo_name": None,
                     "transform_configs": None,
                     "transforms": Cont_X_trans,
                     "fit_out_of_design": False,
                     "fit_abandoned": False,
                 },
             )
             self.assertEqual(g._model_state_after_gen,
                              {"init_position": i + 1})
     # Check completeness error message when GS should be done.
     with self.assertRaises(GenerationStrategyCompleted):
         g = sobol_GPEI.gen(exp)
コード例 #19
0
ファイル: test_generation_strategy.py プロジェクト: ekilic/Ax
 def test_min_observed(self):
     # We should fail to transition the next model if there is not
     # enough data observed.
     exp = get_branin_experiment(get_branin_experiment())
     gs = GenerationStrategy(steps=[
         GenerationStep(
             model=Models.SOBOL, num_trials=5, min_trials_observed=5),
         GenerationStep(model=Models.GPEI, num_trials=1),
     ])
     self.assertFalse(gs.uses_non_registered_models)
     for _ in range(5):
         exp.new_trial(gs.gen(exp))
     with self.assertRaises(DataRequiredError):
         gs.gen(exp)
コード例 #20
0
 def test_sobol_strategy(self):
     exp = get_branin_experiment()
     sobol_generation_strategy = GenerationStrategy(steps=[
         GenerationStep(
             model=Models.SOBOL,
             num_trials=5,
             max_parallelism=10,
             use_update=False,
             enforce_num_trials=False,
         )
     ])
     for i in range(1, 6):
         sobol_generation_strategy.gen(exp, n=1)
         self.assertEqual(len(sobol_generation_strategy._generator_runs), i)
コード例 #21
0
    def test_current_generator_run_limit(self):
        NUM_INIT_TRIALS = 5
        SECOND_STEP_PARALLELISM = 3
        NUM_ROUNDS = 4
        exp = get_branin_experiment()
        sobol_gs_with_parallelism_limits = GenerationStrategy(steps=[
            GenerationStep(
                model=Models.SOBOL,
                num_trials=NUM_INIT_TRIALS,
                min_trials_observed=3,
            ),
            GenerationStep(
                model=Models.SOBOL,
                num_trials=-1,
                max_parallelism=SECOND_STEP_PARALLELISM,
            ),
        ])
        sobol_gs_with_parallelism_limits._experiment = exp
        could_gen = []
        for _ in range(NUM_ROUNDS):
            (
                num_trials_to_gen,
                opt_complete,
            ) = sobol_gs_with_parallelism_limits.current_generator_run_limit()
            self.assertFalse(opt_complete)
            could_gen.append(num_trials_to_gen)
            trials = []

            for _ in range(num_trials_to_gen):
                gr = sobol_gs_with_parallelism_limits.gen(
                    experiment=exp,
                    pending_observations=get_pending(experiment=exp),
                )
                trials.append(
                    exp.new_trial(gr).mark_running(no_runner_required=True))

            for trial in trials:
                exp.attach_data(get_branin_data(trial_indices=[trial.index]))
                trial.mark_completed()

        # We expect trials from first generation step + trials from remaining rounds in
        # batches limited by parallelism setting in the second step.
        self.assertEqual(
            len(exp.trials),
            NUM_INIT_TRIALS + (NUM_ROUNDS - 1) * SECOND_STEP_PARALLELISM,
        )
        self.assertTrue(all(t.status.is_completed
                            for t in exp.trials.values()))
        self.assertEqual(could_gen, [NUM_INIT_TRIALS] +
                         [SECOND_STEP_PARALLELISM] * (NUM_ROUNDS - 1))
コード例 #22
0
ファイル: dispatch.py プロジェクト: yanpei18345156216/Ax
def choose_generation_strategy(
    search_space: SearchSpace,
    arms_per_trial: int = 1,
    enforce_sequential_optimization: bool = True,
    random_seed: Optional[int] = None,
) -> GenerationStrategy:
    """Select an appropriate generation strategy based on the properties of
    the search space."""
    model_kwargs = {"seed": random_seed} if (random_seed is not None) else None
    num_continuous_parameters, num_discrete_choices = 0, 0
    for parameter in search_space.parameters.values():
        if isinstance(parameter, ChoiceParameter):
            num_discrete_choices += len(parameter.values)
        if isinstance(parameter, RangeParameter):
            num_continuous_parameters += 1
    # If there are more discrete choices than continuous parameters, Sobol
    # will do better than GP+EI.
    if num_continuous_parameters >= num_discrete_choices:
        # Ensure that number of arms per model is divisible by batch size.
        sobol_arms = (
            ceil(max(5, len(search_space.parameters)) / arms_per_trial) *
            arms_per_trial)
        logger.info(
            "Using Bayesian Optimization generation strategy. Iterations after "
            f"{sobol_arms} will take longer to generate due to model-fitting.")
        return GenerationStrategy(
            name="Sobol+GPEI",
            steps=[
                GenerationStep(
                    model=Models.SOBOL,
                    num_arms=sobol_arms,
                    min_arms_observed=ceil(sobol_arms / 2),
                    enforce_num_arms=enforce_sequential_optimization,
                    model_kwargs=model_kwargs,
                ),
                GenerationStep(model=Models.GPEI,
                               num_arms=-1,
                               recommended_max_parallelism=3),
            ],
        )
    else:
        logger.info(f"Using Sobol generation strategy.")
        return GenerationStrategy(
            name="Sobol",
            steps=[
                GenerationStep(model=Models.SOBOL,
                               num_arms=-1,
                               model_kwargs=model_kwargs)
            ],
        )
コード例 #23
0
    def test_equality(self):
        gs1 = GenerationStrategy(steps=[
            GenerationStep(model=Models.SOBOL, num_arms=5),
            GenerationStep(model=Models.GPEI, num_arms=-1),
        ])
        gs2 = GenerationStrategy(steps=[
            GenerationStep(model=Models.SOBOL, num_arms=5),
            GenerationStep(model=Models.GPEI, num_arms=-1),
        ])
        self.assertEqual(gs1, gs2)

        # Clone_reset() doesn't clone exactly, so they won't be equal.
        gs3 = gs1.clone_reset()
        self.assertNotEqual(gs1, gs3)
コード例 #24
0
ファイル: test_generation_strategy.py プロジェクト: ekilic/Ax
 def test_string_representation(self):
     gs1 = GenerationStrategy(steps=[
         GenerationStep(model=Models.SOBOL, num_trials=5),
         GenerationStep(model=Models.GPEI, num_trials=-1),
     ])
     self.assertEqual(
         str(gs1),
         ("GenerationStrategy(name='Sobol+GPEI', steps=[Sobol for 5 trials,"
          " GPEI for subsequent trials])"),
     )
     gs2 = GenerationStrategy(
         steps=[GenerationStep(model=Models.SOBOL, num_trials=-1)])
     self.assertEqual(
         str(gs2),
         ("GenerationStrategy(name='Sobol', steps=[Sobol for all trials])"))
コード例 #25
0
ファイル: test_managed_loop.py プロジェクト: viotemp1/Ax
 def test_annotate_exception(self, _):
     strategy0 = GenerationStrategy(
         name="Sobol",
         steps=[GenerationStep(model=Models.SOBOL, num_trials=-1)])
     loop = OptimizationLoop.with_evaluation_function(
         parameters=[
             {
                 "name": "x1",
                 "type": "range",
                 "bounds": [-5.0, 10.0],
                 "value_type": "float",
                 "log_scale": False,
             },
             {
                 "name": "x2",
                 "type": "range",
                 "bounds": [0.0, 10.0]
             },
         ],
         experiment_name="test",
         objective_name="branin",
         minimize=True,
         evaluation_function=_branin_evaluation_function,
         total_trials=6,
         generation_strategy=strategy0,
     )
     with self.assertRaisesRegex(
             expected_exception=RuntimeError,
             expected_regex="Cholesky errors typically occur",
     ):
         loop.run_trial()
コード例 #26
0
ファイル: test_managed_loop.py プロジェクト: viotemp1/Ax
 def test_custom_gs(self) -> None:
     """Managed loop with custom generation strategy"""
     strategy0 = GenerationStrategy(
         name="Sobol",
         steps=[GenerationStep(model=Models.SOBOL, num_trials=-1)])
     loop = OptimizationLoop.with_evaluation_function(
         parameters=[
             {
                 "name": "x1",
                 "type": "range",
                 "bounds": [-5.0, 10.0],
                 "value_type": "float",
                 "log_scale": False,
             },
             {
                 "name": "x2",
                 "type": "range",
                 "bounds": [0.0, 10.0]
             },
         ],
         experiment_name="test",
         objective_name="branin",
         minimize=True,
         evaluation_function=_branin_evaluation_function,
         total_trials=6,
         generation_strategy=strategy0,
     )
     bp, _ = loop.full_run().get_best_point()
     self.assertIn("x1", bp)
     self.assertIn("x2", bp)
コード例 #27
0
ファイル: save.py プロジェクト: jshuadvd/Ax
def _save_generation_strategy(generation_strategy: GenerationStrategy,
                              encoder: Encoder) -> int:
    # If the generation strategy has not yet generated anything, there will be no
    # experiment set on it.
    if generation_strategy._experiment is None:
        experiment_id = None
    else:
        # Experiment was set on the generation strategy, so need to check whether
        # if has been saved and create a relationship b/w GS and experiment if so.
        experiment_id = _get_experiment_id(
            experiment=generation_strategy._experiment, encoder=encoder)

    gs_sqa = encoder.generation_strategy_to_sqa(
        generation_strategy=generation_strategy, experiment_id=experiment_id)

    with session_scope() as session:
        if generation_strategy._db_id is None:
            session.add(gs_sqa)
            session.flush()  # Ensures generation strategy id is set.
            generation_strategy._db_id = gs_sqa.id
        else:
            gs_sqa_class = encoder.config.class_to_sqa_class[
                GenerationStrategy]
            existing_gs_sqa = session.query(gs_sqa_class).get(
                generation_strategy._db_id)
            existing_gs_sqa.update(gs_sqa)
            # our update logic ignores foreign keys, i.e. fields ending in _id,
            # because we want SQLAlchemy to handle those relationships for us
            # however, generation_strategy.experiment_id is an exception, so we
            # need to update that manually
            existing_gs_sqa.experiment_id = gs_sqa.experiment_id

    return generation_strategy._db_id
コード例 #28
0
ファイル: botorch_methods.py プロジェクト: viotemp1/Ax
def make_basic_generation_strategy(
    name: str,
    acquisition: str,
    num_initial_trials: int = 14,
    surrogate_model_constructor: Callable = singletask_gp_model_constructor,
) -> GenerationStrategy:

    if acquisition not in ACQF_MODEL_MAP:
        acquisition = "Sobol"
        logger.warning(f"{acquisition} is not a supported "
                       "acquisition function. Defaulting to Sobol.")

    return GenerationStrategy(
        name=name,
        steps=[
            GenerationStep(
                model=Models.SOBOL,
                num_trials=num_initial_trials,
                min_trials_observed=num_initial_trials,
            ),
            GenerationStep(
                model=ACQF_MODEL_MAP[acquisition],
                num_trials=-1,
                model_kwargs={
                    "model_constructor": surrogate_model_constructor,
                    "transforms": Cont_X_trans + Y_trans,
                },
            ),
        ],
    )
コード例 #29
0
ファイル: test_managed_loop.py プロジェクト: kjanoudi/Ax
 def test_optimize_graceful_exit_on_exception(self) -> None:
     """Tests optimization as a single call, with exception during
     candidate generation.
     """
     best, vals, exp, model = optimize(
         parameters=[  # pyre-fixme[6]
             {"name": "x1", "type": "range", "bounds": [-10.0, 10.0]},
             {"name": "x2", "type": "range", "bounds": [-10.0, 10.0]},
         ],
         # Booth function.
         evaluation_function=lambda p: (
             (p["x1"] + 2 * p["x2"] - 7) ** 2 + (2 * p["x1"] + p["x2"] - 5) ** 2,
             None,
         ),
         minimize=True,
         total_trials=6,
         generation_strategy=GenerationStrategy(
             name="Sobol", steps=[GenerationStep(model=Models.SOBOL, num_trials=3)]
         ),
     )
     self.assertEqual(len(exp.trials), 3)  # Check that we stopped at 3 trials.
     # All the regular return values should still be present.
     self.assertIn("x1", best)
     self.assertIn("x2", best)
     self.assertIsNotNone(vals)
     self.assertIn("objective", vals[0])
     self.assertIn("objective", vals[1])
     self.assertIn("objective", vals[1]["objective"])
コード例 #30
0
 def test_sobol_GPEI_strategy_keep_generating(self):
     exp = get_branin_experiment()
     sobol_GPEI_generation_strategy = GenerationStrategy(steps=[
         GenerationStep(model=Models.SOBOL, num_arms=5),
         GenerationStep(model=Models.GPEI, num_arms=-1),
     ])
     self.assertEqual(sobol_GPEI_generation_strategy.name, "Sobol+GPEI")
     self.assertEqual(sobol_GPEI_generation_strategy.model_transitions, [5])
     exp.new_trial(
         generator_run=sobol_GPEI_generation_strategy.gen(exp)).run()
     for i in range(1, 15):
         g = sobol_GPEI_generation_strategy.gen(exp, exp.fetch_data())
         exp.new_trial(generator_run=g).run()
         if i > 4:
             self.assertIsInstance(sobol_GPEI_generation_strategy.model,
                                   TorchModelBridge)