Example for using the multi target mode for the objective

Example for using the multi target mode for the objective. It uses a desirability value to handle several targets.

This example assumes some basic familiarity with using BayBE. We thus refer to campaign for a basic example.

Necessary imports for this example

import pandas as pd
from baybe import Campaign
from baybe.objectives import DesirabilityObjective
from baybe.parameters import CategoricalParameter, NumericalDiscreteParameter
from baybe.searchspace import SearchSpace
from baybe.targets import NumericalTarget
from baybe.utils.dataframe import add_fake_measurements

Experiment setup and creating the searchspace

Categorical_1 = CategoricalParameter("Cat_1", values=["22", "33"], encoding="OHE")
Categorical_2 = CategoricalParameter(
    "Cat_2",
    values=["very bad", "bad", "OK", "good", "very good"],
    encoding="INT",
)
Num_disc_1 = NumericalDiscreteParameter(
    "Num_disc_1", values=[1, 2, 3, 4, 6, 8, 10], tolerance=0.3
)
Num_disc_2 = NumericalDiscreteParameter(
    "Num_disc_2", values=[-1, -3, -6, -9], tolerance=0.3
)
parameters = [Categorical_1, Categorical_2, Num_disc_1, Num_disc_2]
searchspace = SearchSpace.from_product(parameters=parameters)

Defining the targets

The multi target mode is handled when creating the objective object. Thus we first need to define the different targets.

This examples has different targets with different modes. The first target is maximized and while the second one is minimized. Note that in this multi target mode, the user must specify bounds for each target.

Target_1 = NumericalTarget(
    name="Target_1", mode="MAX", bounds=(0, 100), transformation="LINEAR"
)
Target_2 = NumericalTarget(
    name="Target_2", mode="MIN", bounds=(0, 100), transformation="LINEAR"
)

For each target it is also possible to specify a target_transform function. A detailed discussion of this functionality can be found at the end of this example.

In this example, define a third target working with the mode MATCH. We furthermore use target_transform="BELL".

Target_3 = NumericalTarget(
    name="Target_3", mode="MATCH", bounds=(45, 55), transformation="BELL"
)

Note that the MATCH mode seeks to have the target at the mean between the two bounds. For example, choosing 95 and 105 will lead the algorithm seeking 100 as the optimal value. Thus, using the bounds, it is possible to control both the match target and the range around this target that is considered viable.

Creating the objective

Now to work with these three targets the objective object must be properly created. The mode is set to DESIRABILITY and the targets are described in a list.

targets = [Target_1, Target_2, Target_3]

As the recommender requires a single function, the different targets need to be combined. Thus, a scalarizer is used to create a single target out of the several targets given. The combine function can either be the mean MEAN or the geometric mean GEOM_MEAN. Per default, GEOM_MEAN is used. Weights for each target can also be specified as a list of floats in the arguments Per default, weights are equally distributed between all targets and are normalized internally. It is thus not necessary to handle normalization or scaling.

objective = DesirabilityObjective(
    targets=targets,
    weights=[20, 20, 60],
    scalarizer="MEAN",
)
print(objective)
Objective
   Type: DesirabilityObjective
   Targets
                    Type      Name  ... Transformation  Weight
      0  NumericalTarget  Target_1  ...         LINEAR    20.0
      1  NumericalTarget  Target_2  ...         LINEAR    20.0
      2  NumericalTarget  Target_3  ...           BELL    60.0
      
      [3 rows x 7 columns]
   Scalarizer: MEAN

Creating and printing the campaign

campaign = Campaign(searchspace=searchspace, objective=objective)
print(campaign)
Campaign
   Meta Data
      Batches done: 0
      Fits done: 0
      Discrete Subspace Meta Data
         Recommended: 0/280
         Measured: 0/280
         Excluded: 0/280
   SearchSpace
      Search Space Type: DISCRETE
      SubspaceDiscrete
         Discrete Parameters
                     Name                        Type  Num_Values

Encoding 0 Cat_1 CategoricalParameter 2 CategoricalEncoding.OHE 1 Cat_2 CategoricalParameter 5 CategoricalEncoding.INT 2 Num_disc_1 NumericalDiscreteParameter 7 None 3 Num_disc_2 NumericalDiscreteParameter 4 None Experimental Representation Cat_1 Cat_2 Num_disc_1 Num_disc_2 0 22 OK 1.0 -9.0 1 22 OK 1.0 -6.0 2 22 OK 1.0 -3.0 .. … … … … 277 33 very good 10.0 -6.0 278 33 very good 10.0 -3.0 279 33 very good 10.0 -1.0

            [280 rows x 4 columns]
         Constraints
            Empty DataFrame
            Columns: []
            Index: []
         Computational Representation
                 Cat_1_22  Cat_1_33  ...  Num_disc_1  Num_disc_2
            0         1.0       0.0  ...         1.0        -9.0
            1         1.0       0.0  ...         1.0        -6.0
            2         1.0       0.0  ...         1.0        -3.0
            ..        ...       ...  ...         ...         ...
            277       0.0       1.0  ...        10.0        -6.0
            278       0.0       1.0  ...        10.0        -3.0
            279       0.0       1.0  ...        10.0        -1.0
            
            [280 rows x 5 columns]
   Objective
      Type: DesirabilityObjective
      Targets
                       Type      Name  ... Transformation  Weight
         0  NumericalTarget  Target_1  ...         LINEAR    20.0
         1  NumericalTarget  Target_2  ...         LINEAR    20.0
         2  NumericalTarget  Target_3  ...           BELL    60.0
         
         [3 rows x 7 columns]
      Scalarizer: MEAN
   TwoPhaseMetaRecommender
      Initial recommender
         RandomRecommender
            Compatibility: SearchSpaceType.HYBRID
      Recommender
         BotorchRecommender
            Surrogate
               GaussianProcessSurrogate
                  Supports Transfer Learning: True
                  Kernel factory: DefaultKernelFactory()
            Acquisition function: qLogExpectedImprovement()
            Compatibility: SearchSpaceType.HYBRID
            Sequential continuous: False
            Hybrid sampler: None
            Sampling percentage: 1.0
      Switch after: 1
      Remain switched: False
      Has switched: False

Performing some iterations

The following loop performs some recommendations and adds fake results. It also prints what happens to internal data.

N_ITERATIONS = 3
for kIter in range(N_ITERATIONS):
    rec = campaign.recommend(batch_size=3)
    add_fake_measurements(rec, campaign.targets)
    campaign.add_measurements(rec)
    desirability = campaign.objective.transform(campaign.measurements, allow_extra=True)

    print(f"\n\n#### ITERATION {kIter+1} ####")
    print("\nRecommended measurements with fake measured results:\n")
    print(rec)
    print("\nInternal measurement database with desirability values:\n")
    print(pd.concat([campaign.measurements, desirability], axis=1))
#### ITERATION 1 ####

Recommended measurements with fake measured results:

    Cat_1      Cat_2  Num_disc_1  Num_disc_2   Target_1   Target_2   Target_3
255    33  very good         1.0        -1.0  81.035560  41.476898  51.412816
250    33   very bad        10.0        -3.0  43.111472  88.093847  51.717550
159    33         OK         6.0        -1.0   6.371019  74.459046  56.214626

Internal measurement database with desirability values:

  Cat_1      Cat_2  Num_disc_1  Num_disc_2   Target_1   Target_2   Target_3  \
0    33  very good         1.0        -1.0  81.035560  41.476898  51.412816   
1    33   very bad        10.0        -3.0  43.111472  88.093847  51.717550   
2    33         OK         6.0        -1.0   6.371019  74.459046  56.214626   

   BatchNr  FitNr  Desirability  
0        1    NaN      0.855637  
1        1    NaN      0.675660  
2        1    NaN      0.340957  




#### ITERATION 2 ####

Recommended measurements with fake measured results:

      Cat_1      Cat_2  Num_disc_1  Num_disc_2   Target_1   Target_2  \
index                                                                  
254      33  very good         1.0        -3.0  13.987205  66.625403   
227      33   very bad         1.0        -1.0  66.281267  25.270305   
267      33  very good         4.0        -1.0   0.760799   3.330948   

        Target_3  
index             
254    56.294032  
227    51.457647  
267    55.761479  

Internal measurement database with desirability values:

  Cat_1      Cat_2  Num_disc_1  Num_disc_2   Target_1   Target_2   Target_3  \
0    33  very good         1.0        -1.0  81.035560  41.476898  51.412816   
1    33   very bad        10.0        -3.0  43.111472  88.093847  51.717550   
2    33         OK         6.0        -1.0   6.371019  74.459046  56.214626   
3    33  very good         1.0        -3.0  13.987205  66.625403  56.294032   
4    33   very bad         1.0        -1.0  66.281267  25.270305  51.457647   
5    33  very good         4.0        -1.0   0.760799   3.330948  55.761479   

   BatchNr  FitNr  Desirability  
0        1    1.0      0.855637  
1        1    1.0      0.675660  
2        1    1.0      0.340957  
3        2    NaN      0.366406  
4        2    NaN      0.857059  
5        2    NaN      0.503766  


#### ITERATION 3 ####

Recommended measurements with fake measured results:

      Cat_1      Cat_2  Num_disc_1  Num_disc_2   Target_1   Target_2  \
index                                                                  
249      33   very bad        10.0        -6.0  99.999529  33.454825   
115      22  very good         1.0        -1.0  45.358466   7.186741   
0        22         OK         1.0        -9.0  67.534761  62.638132   

        Target_3  
index             
249    53.353029  
115    56.559833  
0      54.366232  

Internal measurement database with desirability values:

  Cat_1      Cat_2  Num_disc_1  Num_disc_2   Target_1   Target_2   Target_3  \
0    33  very good         1.0        -1.0  81.035560  41.476898  51.412816   
1    33   very bad        10.0        -3.0  43.111472  88.093847  51.717550   
2    33         OK         6.0        -1.0   6.371019  74.459046  56.214626   
3    33  very good         1.0        -3.0  13.987205  66.625403  56.294032   
4    33   very bad         1.0        -1.0  66.281267  25.270305  51.457647   
5    33  very good         4.0        -1.0   0.760799   3.330948  55.761479   
6    33   very bad        10.0        -6.0  99.999529  33.454825  53.353029   
7    22  very good         1.0        -1.0  45.358466   7.186741  56.559833   
8    22         OK         1.0        -9.0  67.534761  62.638132  54.366232   

   BatchNr  FitNr  Desirability  
0        1    1.0      0.855637  
1        1    1.0      0.675660  
2        1    1.0      0.340957  
3        2    2.0      0.366406  
4        2    2.0      0.857059  
5        2    2.0      0.503766  
6        3    NaN      0.812268  
7        3    NaN      0.530081  
8        3    NaN      0.619585  

Addendum: Description of transformation functions

This function is used to transform target values to the interval [0,1] for MAX/MIN mode. An ascending or decreasing LINEAR function is used per default. This function maps input values in a specified interval [lower, upper] to the interval [0,1]. Outside the specified interval, the function remains constant, that is, 0 or 1.

For the match mode, two functions are available TRIANGULAR and BELL. The TRIANGULAR function is 0 outside a specified interval and linearly increases to 1 from both interval ends, reaching the value 1 at the center of the interval. This function is used per default for MATCH mode. The BELL function is a Gaussian bell curve, specified through the boundary values of the sigma interval, reaching the maximum value of 1 at the interval center.