Skip to content

Commit

Permalink
Move add_parameter_noise to simulation package
Browse files Browse the repository at this point in the history
  • Loading branch information
AdrianSosic committed Jun 11, 2024
1 parent 39cee78 commit 29b42ca
Show file tree
Hide file tree
Showing 4 changed files with 67 additions and 59 deletions.
2 changes: 1 addition & 1 deletion baybe/simulation/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@
from baybe.campaign import Campaign
from baybe.exceptions import NotEnoughPointsLeftError, NothingToSimulateError
from baybe.simulation.lookup import look_up_targets
from baybe.simulation.utils import add_parameter_noise
from baybe.targets.enum import TargetMode
from baybe.utils.dataframe import add_parameter_noise
from baybe.utils.numerical import DTypeFloatNumpy, closer_element, closest_element
from baybe.utils.random import temporary_seed

Expand Down
61 changes: 61 additions & 0 deletions baybe/simulation/utils.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
"""Simulation utilities."""

from __future__ import annotations

from collections.abc import Iterable
from typing import TYPE_CHECKING, Literal

import numpy as np
import pandas as pd

if TYPE_CHECKING:
from baybe.parameters import Parameter


def add_parameter_noise(
data: pd.DataFrame,
parameters: Iterable[Parameter],
noise_type: Literal["absolute", "relative_percent"] = "absolute",
noise_level: float = 1.0,
) -> None:
"""Apply uniform noise to the parameter values of a recommendation frame.
The noise can be additive or multiplicative.
This can be used to simulate experimental noise or imperfect user input containing
numerical parameter values that differ from the recommendations. Note that the
dataframe is modified in-place, and that no new dataframe is returned.
Args:
data: Output of the ``recommend`` function of a ``Campaign`` object, see
:func:`baybe.campaign.Campaign.recommend`.
parameters: The parameters for which the values shall be corrupted.
noise_type: Defines whether the noise should be additive or multiplicative.
noise_level: Level/magnitude of the noise. Must be provided as numerical value
for noise type ``absolute`` and as percentage for noise type
``relative_percent``.
Raises:
ValueError: If ``noise_type`` is neither ``absolute`` nor
``relative_percent``.
"""
# Validate input
if noise_type not in ("relative_percent", "absolute"):
raise ValueError(
f"Parameter 'noise_type' was {noise_type} but must be either "
"'absolute' or 'relative_percent'."
)

for param in (p for p in parameters if p.is_numeric):
# Add selected noise type
if noise_type == "relative_percent":
data[param.name] *= np.random.uniform(
1.0 - noise_level / 100.0, 1.0 + noise_level / 100.0, len(data)
)
elif noise_type == "absolute":
data[param.name] += np.random.uniform(-noise_level, noise_level, len(data))

# Respect continuous intervals
if param.is_continuous:
data[param.name] = data[param.name].clip(
param.bounds.lower, param.bounds.upper
)
60 changes: 3 additions & 57 deletions baybe/utils/dataframe.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,9 @@
from __future__ import annotations

import logging
from collections.abc import Iterable, Iterator, Sequence
from typing import (
TYPE_CHECKING,
Literal,
overload,
)

import numpy as np
from collections.abc import Iterator, Sequence
from typing import TYPE_CHECKING, overload

import pandas as pd

from baybe.utils.numerical import DTypeFloatNumpy
Expand Down Expand Up @@ -63,55 +58,6 @@ def to_tensor(*dfs: pd.DataFrame) -> Tensor | Iterator[Tensor]:
return out


def add_parameter_noise(
data: pd.DataFrame,
parameters: Iterable[Parameter],
noise_type: Literal["absolute", "relative_percent"] = "absolute",
noise_level: float = 1.0,
) -> None:
"""Apply uniform noise to the parameter values of a recommendation frame.
The noise can be additive or multiplicative.
This can be used to simulate experimental noise or imperfect user input containing
numerical parameter values that differ from the recommendations. Note that the
dataframe is modified in-place, and that no new dataframe is returned.
Args:
data: Output of the ``recommend`` function of a ``Campaign`` object, see
:func:`baybe.campaign.Campaign.recommend`.
parameters: The parameters for which the values shall be corrupted.
noise_type: Defines whether the noise should be additive or multiplicative.
noise_level: Level/magnitude of the noise. Must be provided as numerical value
for noise type ``absolute`` and as percentage for noise type
``relative_percent``.
Raises:
ValueError: If ``noise_type`` is neither ``absolute`` nor
``relative_percent``.
"""
# Validate input
if noise_type not in ("relative_percent", "absolute"):
raise ValueError(
f"Parameter 'noise_type' was {noise_type} but must be either "
"'absolute' or 'relative_percent'."
)

for param in (p for p in parameters if p.is_numeric):
# Add selected noise type
if noise_type == "relative_percent":
data[param.name] *= np.random.uniform(
1.0 - noise_level / 100.0, 1.0 + noise_level / 100.0, len(data)
)
elif noise_type == "absolute":
data[param.name] += np.random.uniform(-noise_level, noise_level, len(data))

# Respect continuous intervals
if param.is_continuous:
data[param.name] = data[param.name].clip(
param.bounds.lower, param.bounds.upper
)


def df_drop_single_value_columns(
df: pd.DataFrame, lst_exclude: list = None
) -> pd.DataFrame:
Expand Down
3 changes: 2 additions & 1 deletion tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@
)
from baybe.recommenders.pure.nonpredictive.sampling import RandomRecommender
from baybe.searchspace import SearchSpace
from baybe.simulation.utils import add_parameter_noise
from baybe.surrogates import _ONNX_INSTALLED, GaussianProcessSurrogate
from baybe.targets import NumericalTarget
from baybe.telemetry import (
Expand All @@ -61,7 +62,7 @@
)
from baybe.utils.basic import hilberts_factory
from baybe.utils.boolean import strtobool
from baybe.utils.dataframe import add_fake_results, add_parameter_noise
from baybe.utils.dataframe import add_fake_results

try:
import baybe.utils.chemistry # noqa: F401 # Tests if chem deps are available
Expand Down

0 comments on commit 29b42ca

Please sign in to comment.