|
23 | 23 | from mlos_core.optimizers.bayesian_optimizers import BaseBayesianOptimizer, SmacOptimizer
|
24 | 24 | from mlos_core.spaces.adapters import SpaceAdapterType
|
25 | 25 |
|
26 |
| -from mlos_core.tests import get_all_concrete_subclasses |
| 26 | +from mlos_core.tests import get_all_concrete_subclasses, SEED |
27 | 27 |
|
28 | 28 |
|
29 | 29 | _LOG = logging.getLogger(__name__)
|
@@ -76,7 +76,7 @@ def objective(x: pd.Series) -> npt.ArrayLike: # pylint: disable=invalid-name
|
76 | 76 | ret: npt.ArrayLike = (6 * x - 2)**2 * np.sin(12 * x - 4)
|
77 | 77 | return ret
|
78 | 78 | # Emukit doesn't allow specifying a random state, so we set the global seed.
|
79 |
| - np.random.seed(42) |
| 79 | + np.random.seed(SEED) |
80 | 80 | optimizer = optimizer_class(parameter_space=configuration_space, **kwargs)
|
81 | 81 |
|
82 | 82 | with pytest.raises(ValueError, match="No observations"):
|
@@ -298,3 +298,69 @@ def test_optimizer_type_defs(optimizer_class: Type[BaseOptimizer]) -> None:
|
298 | 298 | """
|
299 | 299 | optimizer_type_classes = {member.value for member in OptimizerType}
|
300 | 300 | assert optimizer_class in optimizer_type_classes
|
| 301 | + |
| 302 | + |
| 303 | +@pytest.mark.parametrize(('optimizer_type', 'kwargs'), [ |
| 304 | + # Default optimizer |
| 305 | + (None, {}), |
| 306 | + # Enumerate all supported Optimizers |
| 307 | + *[(member, {}) for member in OptimizerType], |
| 308 | + # Optimizer with non-empty kwargs argument |
| 309 | +]) |
| 310 | +def test_mixed_numeric_type_input_space_types(optimizer_type: Optional[OptimizerType], kwargs: Optional[dict]) -> None: |
| 311 | + """ |
| 312 | + Toy problem to test the optimizers with mixed numeric types to ensure that original dtypes are retained. |
| 313 | + """ |
| 314 | + max_iterations = 10 |
| 315 | + if kwargs is None: |
| 316 | + kwargs = {} |
| 317 | + |
| 318 | + def objective(point: pd.DataFrame) -> pd.Series: |
| 319 | + # mix of hyperparameters, optimal is to select the highest possible |
| 320 | + ret: pd.Series = point["x"] + point["y"] |
| 321 | + return ret |
| 322 | + |
| 323 | + input_space = CS.ConfigurationSpace(seed=SEED) |
| 324 | + # add a mix of numeric datatypes |
| 325 | + input_space.add_hyperparameter(CS.UniformIntegerHyperparameter(name='x', lower=0, upper=5)) |
| 326 | + input_space.add_hyperparameter(CS.UniformFloatHyperparameter(name='y', lower=0.0, upper=5.0)) |
| 327 | + |
| 328 | + if optimizer_type is None: |
| 329 | + optimizer = OptimizerFactory.create( |
| 330 | + parameter_space=input_space, |
| 331 | + optimizer_kwargs=kwargs, |
| 332 | + ) |
| 333 | + else: |
| 334 | + optimizer = OptimizerFactory.create( |
| 335 | + parameter_space=input_space, |
| 336 | + optimizer_type=optimizer_type, |
| 337 | + optimizer_kwargs=kwargs, |
| 338 | + ) |
| 339 | + |
| 340 | + with pytest.raises(ValueError, match="No observations"): |
| 341 | + optimizer.get_best_observation() |
| 342 | + |
| 343 | + with pytest.raises(ValueError, match="No observations"): |
| 344 | + optimizer.get_observations() |
| 345 | + |
| 346 | + for _ in range(max_iterations): |
| 347 | + suggestion = optimizer.suggest() |
| 348 | + assert isinstance(suggestion, pd.DataFrame) |
| 349 | + assert (suggestion.columns == ['x', 'y']).all() |
| 350 | + # Check suggestion values are the expected dtype |
| 351 | + assert isinstance(suggestion['x'].iloc[0], np.integer) |
| 352 | + assert isinstance(suggestion['y'].iloc[0], np.floating) |
| 353 | + # Check that suggestion is in the space |
| 354 | + test_configuration = CS.Configuration(optimizer.parameter_space, suggestion.astype('O').iloc[0].to_dict()) |
| 355 | + # Raises an error if outside of configuration space |
| 356 | + test_configuration.is_valid_configuration() |
| 357 | + # Test registering the suggested configuration with a score. |
| 358 | + observation = objective(suggestion) |
| 359 | + assert isinstance(observation, pd.Series) |
| 360 | + optimizer.register(suggestion, observation) |
| 361 | + |
| 362 | + best_observation = optimizer.get_best_observation() |
| 363 | + assert isinstance(best_observation, pd.DataFrame) |
| 364 | + |
| 365 | + all_observations = optimizer.get_observations() |
| 366 | + assert isinstance(all_observations, pd.DataFrame) |
0 commit comments