The CustomSoboStrategy can be used to design custom objectives or objective combinations for optimizations. In this tutorial notebook, it is shown how to use it to optimize a quantity that depends on a combination of an inferred quantity and one of the inputs.
/opt/hostedtoolcache/Python/3.12.14/x64/lib/python3.12/site-packages/torch/jit/_script.py:1491: FutureWarning: `torch.jit.script` is deprecated. Please switch to `torch.compile` or `torch.export`.
warnings.warn(
/opt/hostedtoolcache/Python/3.12.14/x64/lib/python3.12/site-packages/torch/jit/_script.py:1491: FutureWarning: `torch.jit.script` is deprecated. Please switch to `torch.compile` or `torch.export`.
warnings.warn(
Setup the optimization
For the optimization, we want to subtract the inferred quantity by the value of feature x_0.
benchmark = Himmelblau()experiments = benchmark.f(benchmark.domain.inputs.sample(10), return_complete=True)strategy_data = CustomSoboStrategy(domain=benchmark.domain)strategy = strategies.map(strategy_data)# here we find out what is the index of the input feature in the input tensor `X`# in the manipulation function belowfeature2index, _ = strategy.domain.inputs._get_transform_info( strategy.input_preprocessing_specs)feat_idx = feature2index["x_1"][0]# we assign now a torch based function to the strategy which performs the custom manipulation of the objective# the signature has to be understood in the following way:# - samples: the samples to evaluate the objective on, these are the predicted Y/output values of the model(s)# - callables: the botorch callables associated to objectives associated to the features# (have a look at `get_objective_callable` in `bofire/utils/torch_tools.py`)# - weights: the weights associated to the objectives# (have a look here: `_callables_and_weights` in `bofire/utils/torch_tools.py`)# - X: a tensor of input values associated to the output values samples, associated to the Y/output values (`samples`)def f(samples, callables, weights, X): val = torch.tensor(0.0).to(**tkwargs)for c, w inzip(callables, weights): val = val + c(samples, None) * w# here, you have to implement the custom manipulation of the objective# in this example, we subtract the value of the first feature from the objective val = val - X[..., feat_idx]return valstrategy.f = fstrategy.tell(experiments)strategy.ask(1)
/opt/hostedtoolcache/Python/3.12.14/x64/lib/python3.12/site-packages/bofire/utils/torch_tools.py:51: UserWarning: The given NumPy array is not writable, and PyTorch does not support non-writable tensors. This means writing to this tensor will result in undefined behavior. You may want to copy the array to protect its data or make it writable before converting it to a tensor. This type of warning will be suppressed for the rest of this program. (Triggered internally at /__w/pytorch/pytorch/torch/csrc/utils/tensor_numpy.cpp:213.)
return torch.from_numpy(np.ascontiguousarray(df.to_numpy())).to(**tkwargs)
---title: Custom SOBO Strategyjupyter: python3---The `CustomSoboStrategy` can be used to design custom objectives or objective combinations for optimizations. In this tutorial notebook, it is shown how to use it to optimize a quantity that depends on a combination of an inferred quantity and one of the inputs.## Imports```{python}import torchimport bofire.strategies.api as strategiesfrom bofire.benchmarks.api import Himmelblaufrom bofire.data_models.strategies.api import CustomSoboStrategyfrom bofire.utils.torch_tools import tkwargs```## Setup the optimizationFor the optimization, we want to subtract the inferred quantity by the value of feature `x_0`.```{python}benchmark = Himmelblau()experiments = benchmark.f(benchmark.domain.inputs.sample(10), return_complete=True)strategy_data = CustomSoboStrategy(domain=benchmark.domain)strategy = strategies.map(strategy_data)# here we find out what is the index of the input feature in the input tensor `X`# in the manipulation function belowfeature2index, _ = strategy.domain.inputs._get_transform_info( strategy.input_preprocessing_specs)feat_idx = feature2index["x_1"][0]# we assign now a torch based function to the strategy which performs the custom manipulation of the objective# the signature has to be understood in the following way:# - samples: the samples to evaluate the objective on, these are the predicted Y/output values of the model(s)# - callables: the botorch callables associated to objectives associated to the features# (have a look at `get_objective_callable` in `bofire/utils/torch_tools.py`)# - weights: the weights associated to the objectives# (have a look here: `_callables_and_weights` in `bofire/utils/torch_tools.py`)# - X: a tensor of input values associated to the output values samples, associated to the Y/output values (`samples`)def f(samples, callables, weights, X): val = torch.tensor(0.0).to(**tkwargs)for c, w inzip(callables, weights): val = val + c(samples, None) * w# here, you have to implement the custom manipulation of the objective# in this example, we subtract the value of the first feature from the objective val = val - X[..., feat_idx]return valstrategy.f = fstrategy.tell(experiments)strategy.ask(1)```