Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor Strategies to Recommenders #146

Merged
merged 18 commits into from
Feb 27, 2024
Merged
Show file tree
Hide file tree
Changes from 17 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,13 +23,24 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Changed
- `Recommender`s now share their core logic via their base class
- Remove progress bars in examples
- Strategies are now called `MetaRecommender`'s and part of the `recommenders.meta`
module
- `Recommender`'s are now called `PureRecommender`'s and part of the `recommenders.pure`
module
- `strategy` keyword of `Campaign` renamed to `recommender`
- `NaiveHybridRecommender` renamed to `NaiveHybridSpaceRecommender`

### Fixed
- Unhandled exception in telemetry when username could not be inferred on Windows
- Metadata is now correctly updated for hybrid spaces
- Unintended deactivation of telemetry due to import problem
- Line wrapping in examples

### Deprecations
- `TwoPhaseStrategy`
- `SequentialStrategy`
- `StreamingSequentialStrategy`

## [0.7.3] - 2024-02-09
### Added
- Copy button for code blocks in documentation
Expand Down
9 changes: 6 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -151,10 +151,13 @@ details, and their configuration settings, see the
of the user guide.

```python
from baybe.strategies import TwoPhaseStrategy
from baybe.recommenders import SequentialGreedyRecommender, FPSRecommender
from baybe.recommenders import (
SequentialGreedyRecommender,
FPSRecommender,
TwoPhaseMetaRecommender,
)

strategy = TwoPhaseStrategy(
strategy = TwoPhaseMetaRecommender(
initial_recommender=FPSRecommender(), # farthest point sampling
recommender=SequentialGreedyRecommender(), # Bayesian model-based optimization
)
Expand Down
2 changes: 1 addition & 1 deletion baybe/acquisition.py
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ class PartialAcquisitionFunction:
pinned_part: Tensor
"""The values that will be attached whenever evaluating the acquisition function."""

pin_discrete: Tensor
pin_discrete: bool
"""A flag for denoting whether ``pinned_part`` corresponds to the discrete
subspace."""

Expand Down
23 changes: 18 additions & 5 deletions baybe/campaign.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,12 @@
from baybe.objective import Objective
from baybe.parameters.base import Parameter
from baybe.recommenders.base import RecommenderProtocol
from baybe.recommenders.meta.sequential import TwoPhaseMetaRecommender
from baybe.searchspace.core import (
SearchSpace,
validate_searchspace_from_config,
)
from baybe.serialization import SerialMixin, converter
from baybe.strategies import TwoPhaseStrategy
from baybe.targets.base import Target
from baybe.telemetry import (
TELEM_LABELS,
Expand All @@ -45,7 +45,7 @@ class Campaign(SerialMixin):
In particular, a campaign:
* Defines the objective of an experimentation process.
* Defines the search space over which the experimental parameter may vary.
* Defines a strategy for traversing the search space.
* Defines a recommender for exploring the search space.
* Records the measurement data collected during the process.
* Records metadata about the progress of the experimentation process.
"""
Expand All @@ -57,8 +57,8 @@ class Campaign(SerialMixin):
objective: Objective = field()
"""The optimization objective."""

strategy: RecommenderProtocol = field(factory=TwoPhaseStrategy)
"""The employed strategy"""
recommender: RecommenderProtocol = field(factory=TwoPhaseMetaRecommender)
"""The employed recommender"""

# Metadata
n_batches_done: int = field(default=0, init=False)
Expand All @@ -82,6 +82,9 @@ class Campaign(SerialMixin):
numerical_measurements_must_be_within_tolerance: bool = field(default=None)
"""Deprecated! Raises an error when used."""

strategy: RecommenderProtocol = field(default=None)
"""Deprecated! Raises an error when used."""

@numerical_measurements_must_be_within_tolerance.validator
def _validate_tolerance_flag(self, _, value) -> None:
"""Raise a DeprecationError if the tolerance flag is used."""
Expand All @@ -92,6 +95,15 @@ def _validate_tolerance_flag(self, _, value) -> None:
f"{self.__class__.__name__}.{Campaign.add_measurements.__name__}."
)

@strategy.validator
def _validate_strategy(self, _, value) -> None:
"""Raise a DeprecationError if the strategy attribute is used."""
if value is not None:
raise DeprecationError(
"Passing 'strategy' to the constructor is deprecated. The attribute "
"has been renamed to 'recommender'."
)

@property
def measurements(self) -> pd.DataFrame:
"""The experimental data added to the Campaign."""
Expand Down Expand Up @@ -275,7 +287,7 @@ def recommend(
self._measurements_exp["FitNr"].fillna(self.n_fits_done, inplace=True)

# Get the recommended search space entries
rec = self.strategy.recommend(
rec = self.recommender.recommend(
self.searchspace,
batch_size,
self._measurements_parameters_comp,
Expand Down Expand Up @@ -306,6 +318,7 @@ def _add_version(dict_: dict) -> dict:
_cattrs_include_init_false=True,
# TODO: Remove once deprecation got expired:
numerical_measurements_must_be_within_tolerance=cattrs.override(omit=True),
strategy=cattrs.override(omit=True),
)
structure_hook = cattrs.gen.make_dict_structure_fn(
Campaign, converter, _cattrs_include_init_false=True
Expand Down
4 changes: 3 additions & 1 deletion baybe/exceptions.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,9 @@ class ModelParamsNotSupportedError(Exception):


class NoRecommendersLeftError(Exception):
"""A recommender is requested by a strategy but there are no recommenders left."""
"""A recommender is requested by a meta recommender but there are no recommenders
left.
"""


class NumericalUnderflowError(Exception):
Expand Down
2 changes: 1 addition & 1 deletion baybe/parameters/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ class DiscreteParameter(Parameter, ABC):

# class variables
encoding: Optional[ParameterEncoding] = field(init=False, default=None)
"""An optional encoding strategy for the parameter."""
"""An optional encoding for the parameter."""

@property
@abstractmethod
Expand Down
23 changes: 18 additions & 5 deletions baybe/recommenders/__init__.py
Original file line number Diff line number Diff line change
@@ -1,20 +1,33 @@
"""BayBE recommenders."""

from baybe.recommenders.bayesian.sequential_greedy import SequentialGreedyRecommender
from baybe.recommenders.naive import NaiveHybridRecommender
from baybe.recommenders.nonpredictive.clustering import (
from baybe.recommenders.meta.sequential import (
SequentialMetaRecommender,
StreamingSequentialMetaRecommender,
TwoPhaseMetaRecommender,
)
from baybe.recommenders.naive import NaiveHybridSpaceRecommender
from baybe.recommenders.pure.bayesian.sequential_greedy import (
SequentialGreedyRecommender,
)
from baybe.recommenders.pure.nonpredictive.clustering import (
GaussianMixtureClusteringRecommender,
KMeansClusteringRecommender,
PAMClusteringRecommender,
)
from baybe.recommenders.nonpredictive.sampling import FPSRecommender, RandomRecommender
from baybe.recommenders.pure.nonpredictive.sampling import (
FPSRecommender,
RandomRecommender,
)

__all__ = [
"FPSRecommender",
"GaussianMixtureClusteringRecommender",
"KMeansClusteringRecommender",
"PAMClusteringRecommender",
"NaiveHybridRecommender",
"NaiveHybridSpaceRecommender",
"RandomRecommender",
"TwoPhaseMetaRecommender",
"SequentialGreedyRecommender",
"SequentialMetaRecommender",
"StreamingSequentialMetaRecommender",
]
Loading