Source code for PyALAF.optimize_step

"""
This module contains functionality to evaluate the acquisition functions and 
find their optimum using different approaches. The supported approaches are:
- Evaluation on discrete grid
- Evaluation using LBFGS optimizer from Scipy
- Evaluation using PSO optimizer from PySwarms
- Evaluation for single objectives and combined objectives via aggregation functions
"""

# Author: Mirko Fischer
# Date: 12.08.2024
# Version: 0.1
# License: MIT license

import copy
import sys
import os
import warnings

import numpy as np
from scipy.stats.qmc import scale
from scipy.optimize import minimize
from sklearn.linear_model import LinearRegression

from pyswarms.single.global_best import GlobalBestPSO

from PyALAF.acfn_continuous import EI_con, POI_con, UCB_con, IDEAL_con, GSx_con
from PyALAF.acfn_continuous import (
    GSy_con,
    iGS_con,
    QBC_con,
    SGSx_con,
    std_con,
    UIDAL_con,
)
from PyALAF.acfn_continuous_multi import (
    EI_multi,
    POI_multi,
    UCB_multi,
    IDEAL_multi,
    NIPV_multi,
)
from PyALAF.acfn_continuous_multi import GSx_multi, GSy_multi, iGS_multi, QBC_multi
from PyALAF.acfn_continuous_multi import SGSx_multi, std_multi, UIDAL_multi, max_multi
from PyALAF.acfn_discrete import EI, POI, UCB, IDEAL, GSx, GSy, iGS, SGSx, UIDAL

if not sys.warnoptions:
    print("Disabled warnings")
    warnings.simplefilter("ignore")
    os.environ["PYTHONWARNINGS"] = "ignore::ConvergenceWarning"


[docs] def step_discrete( acquisition_function, estimated_observation_y, alpha, mean, std, n_data, data_indices, pool, custom_acfn_input, rng, ): """Evaluating an acquisition function on a discrete grid or for discrete values. This is suited for pool-based learning. Parametersls ---------- acquisition_function : str or callable Name of the acquisition function or a callable. Choose from: ei, poi, ucb, random, std, ideal, uidal, GSx, GSy, iGS, sGSx. QBC must implemented separately. estimated_observation_y : nd_array Values of the objective for already evaluated data. alpha : float Hyperparameter for the acquisition function. mean : nd_array Mean of the prediction for all data points. std : nd_array Mean of the prediction for all data points. n_data : int Number of data points data_indices : nd_array Array with indices of already evaluated data points from a pool of data pool : nd_array Pool of data custom_acfn_input : dict Dictionary that contains which information is used by a custom acquisition function. rng : Numpy Random Number Generator Random Number Generator object from numpy. Returns ------- nd_array The values of the acquisition function for all data points in the pool. Raises ------ Exception Acquisition function is not implemented. """ acquisition = None if acquisition_function == "poi": acquisition = POI( mean, std, opt=np.max(estimated_observation_y), max=True, alpha=alpha ) elif acquisition_function == "ei": acquisition = EI( mean, std, opt=np.max(estimated_observation_y), max=True, alpha=alpha ) elif acquisition_function == "ucb": acquisition = UCB(mean, std, alpha=alpha) elif acquisition_function == "random": acquisition = rng.rand(n_data) elif acquisition_function == "std": acquisition = std elif acquisition_function == "ideal": y_true = np.zeros(len(pool)) y_true[data_indices] = estimated_observation_y acquisition = IDEAL(data_indices, pool, mean, y_true, alpha) elif acquisition_function == "uidal": acquisition = UIDAL(data_indices, pool, std, alpha) elif acquisition_function == "GSx": acquisition = GSx(data_indices, pool) elif acquisition_function == "GSy": acquisition = GSy(mean, estimated_observation_y) elif acquisition_function == "iGS": acquisition = iGS(data_indices, pool, mean, estimated_observation_y) elif acquisition_function == "SGSx": acquisition = SGSx(data_indices, pool, std, alpha) elif callable(acquisition_function): custom_args = {} if "mean" in custom_acfn_input: custom_args["mean"] = mean if "std" in custom_acfn_input: custom_args["std"] = std if "pool" in custom_acfn_input: custom_args["pool"] = pool if "data_indices" in custom_acfn_input: custom_args["data_indices"] = data_indices if "alpha" in custom_acfn_input: custom_args["alpha"] = alpha if "y_true" in custom_acfn_input: custom_args["y_true"] = y_true if "y_est" in custom_acfn_input: custom_args["y_est"] = estimated_observation_y acquisition = acquisition_function(custom_args) else: raise KeyError( 'Acquisition function "{}" not implemented'.format(acquisition_function) ) return acquisition
[docs] def step_continuous( acquisition_function, opt_method, regression_model, estimated_observation_y, estimated_sample_x, custom_acfn_input, alpha, sampler, lim, dimensions, poly_x, n_jobs, pso_options, rng, ): """Evaluating an acquisition function within a continuous intervall. Parameters ---------- acquisition_function : str or callable Name of the acquisition function or a callable. Choose from: ei, poi, ucb, random, std, ideal, uidal, GSx, GSy, iGS, sGSx, qbc opt_method : str Choose from scipy (using lbfgs algorithm) or PSO (using PySwarms). regression_model : scikit-learn model Trained scikit-Learn model estimated_observation_y : nd_array Values of the objective for already evaluated data. estimated_sample_x : nd_array Values of the data points for already evaluated data. custom_acfn_input : dict Dictionary that contains which information is used by a custom acquisition function. alpha : float Hyperparameter for the acquisition function. sampler : LatinHypercube Scipys LatinHypercube object. lim : list Boundaries for model evaluation. dimensions : int Number of dimensions of the features. poly_x : bool Indicates if polynomial features are used. Is a PolynomialFeature object of scikit-learn if Polynomial Features should be used and None otherwise. n_jobs : int Number of jobs for PySwarms. pso_options : dict Options for PySwarms GlobalBestOptimizer. rng : Numpy Random Number Generator Random Number Generator object from numpy. Returns ------- nd_array Feature values for which the acquisition function has its maximum. float Value of the found maximum of the acquisition function. Raises ------ Exception Acquisition function not implemented. Exception Optimization method not implemented. """ cost = None new_x = None if acquisition_function == "random": x0_unscaled = sampler.random(1)[0] x0 = scale(x0_unscaled.reshape(1, -1), *lim).reshape(dimensions) new_x = x0 elif opt_method == "scipy": lim_t = np.array(lim).T x0_unscaled = sampler.random(1)[0] x0 = scale(x0_unscaled.reshape(1, -1), *lim).reshape(dimensions) # Check for the acquisition functions if acquisition_function == "ei": res = minimize( EI_con, x0=x0, args=(regression_model, np.max(estimated_observation_y), alpha), bounds=lim_t, ) elif acquisition_function == "poi": res = minimize( POI_con, x0=x0, args=(regression_model, np.max(estimated_observation_y), alpha), bounds=lim_t, ) elif acquisition_function == "ucb": res = minimize(UCB_con, x0=x0, args=(regression_model, alpha), bounds=lim_t) elif acquisition_function == "ideal": res = minimize( IDEAL_con, x0=x0, args=( estimated_sample_x, regression_model, estimated_observation_y, lim, alpha, poly_x, ), bounds=lim_t, ) elif acquisition_function == "uidal": res = minimize( UIDAL_con, x0=x0, args=(estimated_sample_x, regression_model, alpha), bounds=lim_t, ) elif acquisition_function == "std": res = minimize(std_con, x0=x0, args=(regression_model), bounds=lim_t) elif acquisition_function == "GSx": res = minimize(GSx_con, x0=x0, args=(estimated_sample_x), bounds=lim_t) elif acquisition_function == "GSy": res = minimize( GSy_con, x0=x0, args=(estimated_observation_y, regression_model, poly_x), bounds=lim_t, ) elif acquisition_function == "iGS": res = minimize( iGS_con, x0=x0, args=( estimated_sample_x, estimated_observation_y, regression_model, poly_x, ), bounds=lim_t, ) elif acquisition_function == "SGSx": res = minimize( SGSx_con, x0=x0, args=(estimated_sample_x, regression_model, alpha), bounds=lim_t, ) elif acquisition_function == "qbc": models = [] for _ in range(alpha): train_index = rng.randint( 0, len(estimated_sample_x), len(estimated_sample_x) ) if isinstance(regression_model, LinearRegression): estimated_sample_x_poly = poly_x.transform(estimated_sample_x) regression_model.fit( estimated_sample_x_poly[train_index], estimated_observation_y[train_index], ) else: regression_model.fit( estimated_sample_x[train_index], estimated_observation_y[train_index], ) models.append(copy.deepcopy(regression_model)) res = minimize(QBC_con, x0=x0, args=(models, poly_x), bounds=lim_t) elif callable(acquisition_function): custom_args = [] if "x" in custom_acfn_input: custom_args.append(estimated_sample_x) if "y" in custom_acfn_input: custom_args.append(estimated_observation_y) if "max_y" in custom_acfn_input: custom_args.append(np.max(estimated_observation_y)) if "regression_model" in custom_acfn_input: custom_args.append(regression_model) if "lim" in custom_acfn_input: custom_args.append(lim) if "alpha" in custom_acfn_input: custom_args.append(alpha) if "poly_x" in custom_acfn_input: custom_args.append(poly_x) custom_args = tuple(custom_args) res = minimize(acquisition_function, x0=x0, args=custom_args, bounds=lim_t) else: raise KeyError( 'Acquisition function "{}" not implemented'.format(acquisition_function) ) new_x = res.x cost = res.fun # Simple Particle Swarm Optimization elif opt_method == "PSO": if not isinstance(pso_options, dict): pso_options = { "c1": 0.5, "c2": 0.3, "w": 0.9, "p": dimensions * 10, "i": 200, } else: dict_keys = pso_options.keys() if "c1" not in dict_keys or "c2" not in dict_keys or "w" not in dict_keys: if "p" not in dict_keys or "i" not in dict_keys: raise KeyError("c1, c2, w, p and i keys must be in pso_options.") n_particles = int(pso_options["p"]) n_iters = int(pso_options["i"]) lb = lim[0] ub = lim[1] bounds = [lb, ub] init_pos_unscaled = sampler.random(n_particles) init_pos = scale(init_pos_unscaled, *lim) np.random.seed(rng.randint(0, 1000000)) optimizer = GlobalBestPSO( n_particles=n_particles, dimensions=dimensions, options=pso_options, bounds=bounds, init_pos=init_pos, ) if acquisition_function == "ei": cost, new_x = optimizer.optimize( EI_con, iters=n_iters, verbose=False, n_processes=n_jobs, model=regression_model, opt=np.max(estimated_observation_y), alpha=alpha, ) elif acquisition_function == "poi": cost, new_x = optimizer.optimize( POI_con, iters=n_iters, verbose=False, n_processes=n_jobs, model=regression_model, opt=np.max(estimated_observation_y), alpha=alpha, ) elif acquisition_function == "ucb": cost, new_x = optimizer.optimize( UCB_con, iters=n_iters, verbose=False, n_processes=n_jobs, model=regression_model, alpha=alpha, ) elif acquisition_function == "ideal": cost, new_x = optimizer.optimize( IDEAL_con, iters=n_iters, verbose=False, n_processes=n_jobs, x_samples=estimated_sample_x, model=regression_model, y_true=estimated_observation_y, lim=lim, alpha=alpha, poly_x=poly_x, ) elif acquisition_function == "uidal": cost, new_x = optimizer.optimize( UIDAL_con, iters=n_iters, verbose=False, n_processes=n_jobs, x_samples=estimated_sample_x, model=regression_model, alpha=alpha, ) elif acquisition_function == "std": cost, new_x = optimizer.optimize( std_con, iters=n_iters, verbose=False, n_processes=n_jobs, model=regression_model, ) elif acquisition_function == "GSx": cost, new_x = optimizer.optimize( GSx_con, iters=n_iters, verbose=False, n_processes=n_jobs, x_sample=estimated_sample_x, ) elif acquisition_function == "GSy": cost, new_x = optimizer.optimize( GSy_con, iters=n_iters, verbose=False, n_processes=n_jobs, y_sample=estimated_observation_y, model=regression_model, poly_x=poly_x, ) elif acquisition_function == "iGS": cost, new_x = optimizer.optimize( iGS_con, iters=n_iters, verbose=False, n_processes=n_jobs, x_sample=estimated_sample_x, y_sample=estimated_observation_y, model=regression_model, poly_x=poly_x, ) elif acquisition_function == "SGSx": cost, new_x = optimizer.optimize( SGSx_con, iters=n_iters, verbose=False, n_processes=n_jobs, x_sample=estimated_sample_x, model=regression_model, alpha=alpha, ) elif acquisition_function == "qbc": models = [] for _ in range(alpha): train_index = rng.randint( 0, len(estimated_sample_x), len(estimated_sample_x) ) if isinstance(regression_model, LinearRegression): estimated_sample_x_poly = poly_x.transform(estimated_sample_x) regression_model.fit( estimated_sample_x_poly[train_index], estimated_observation_y[train_index], ) else: regression_model.fit( estimated_sample_x[train_index], estimated_observation_y[train_index], ) models.append(copy.deepcopy(regression_model)) cost, new_x = optimizer.optimize( QBC_con, iters=n_iters, verbose=False, n_processes=n_jobs, models=models, poly_x=poly_x, ) elif callable(acquisition_function): custom_args = {} if "x" in custom_acfn_input: custom_args["x"] = estimated_sample_x if "y" in custom_acfn_input: custom_args["y"] = estimated_observation_y if "max_y" in custom_acfn_input: custom_args["max_y"] = np.max(estimated_observation_y) if "regression_model" in custom_acfn_input: custom_args["regression_model"] = regression_model if "lim" in custom_acfn_input: custom_args["lim"] = lim if "alpha" in custom_acfn_input: custom_args["alpha"] = alpha if "poly_x" in custom_acfn_input: custom_args["poly_x"] = poly_x cost, new_x = optimizer.optimize( acquisition_function, iters=n_iters, verbose=False, n_processes=n_jobs, **custom_args ) else: raise KeyError( 'Acquisition function "{}" not implemented'.format(acquisition_function) ) else: raise KeyError('Optimization method "{}" not implemented'.format(opt_method)) return new_x, cost
[docs] def step_continous_multi( acquisition_function, opt_method, regression_models, aggregation_function, estimated_observation_y, estimated_observation_y_aggregated, estimated_sample_x, custom_acfn_input, alpha, sampler, lim, dimensions, poly_x, n_jobs, pso_options, rng, n_models, **kwargs ): """Evaluating an acquisition function within a continuous intervall with the support for aggregation functions to combine multiple objectives and optimize them together. Parameters ---------- acquisition_function : str or callable Name of the acquisition function or a callable. Choose from: ei, poi, ucb, random, std, ideal, uidal, GSx, GSy, iGS, sGSx, qbc. opt_method : str Choose from scipy (using lbfgs algorithm) or PSO (using PySwarms). regression_models : list of scikit-learn model Trained scikit-Learn models. One is needed for each objective. aggregation_function : callable Function that combines all individual objectives together. estimated_observation_y : nd_array Values of the objective for already evaluated data. estimated_observation_y_aggregated : nd_array Values of the aggregated objective for already evaluated data. estimated_sample_x : nd_array Values of the data points for already evaluated data. custom_acfn_input : dict Dictionary that contains which information is used by a custom acquisition function. alpha : float Hyperparameter for the acquisition function. sampler : LatinHypercube Scipys LatinHypercube object. lim : list Boundaries for model evaluation. dimensions : int Number of dimensions of the features. poly_x : bool Indicates if polynomial features are used. Is a PolynomialFeature object of scikit-learn if Polynomial Features should be used and None otherwise. n_jobs : int Number of jobs for PySwarms. pso_options : dict Options for PySwarms GlobalBestOptimizer. rng : Numpy Random Number Generator Random Number Generator object from numpy. n_models : int Number of objectives and models. Returns ------- nd_array Feature values for which the acquisition function has its maximum. float Value of the found maximum of the acquisition function. Raises ------ Exception Acquisition function not implemented. Exception Optimization method not implemented. """ cost = None new_x = None if acquisition_function == "random": x0_unscaled = sampler.random(1)[0] x0 = scale(x0_unscaled.reshape(1, -1), *lim).reshape(dimensions) new_x = x0 elif opt_method == "scipy": lim_t = np.array(lim).T x0_unscaled = sampler.random(1)[0] x0 = scale(x0_unscaled.reshape(1, -1), *lim).reshape(dimensions) optargs = kwargs.values() # Check for the acquisition functions if acquisition_function == "ei": res = minimize( EI_multi, x0=x0, args=( regression_models, aggregation_function, np.max(estimated_observation_y_aggregated), alpha, True, *optargs, ), bounds=lim_t, ) elif acquisition_function == "poi": res = minimize( POI_multi, x0=x0, args=( regression_models, aggregation_function, np.max(estimated_observation_y_aggregated), alpha, True, *optargs, ), bounds=lim_t, ) elif acquisition_function == "ucb": res = minimize( UCB_multi, x0=x0, args=(regression_models, aggregation_function, alpha, *optargs), bounds=lim_t, ) elif acquisition_function == "max": res = minimize( max_multi, x0=x0, args=(regression_models, aggregation_function, *optargs), bounds=lim_t, ) elif acquisition_function == "ideal": res = minimize( IDEAL_multi, x0=x0, args=( estimated_sample_x, regression_models, estimated_observation_y_aggregated, lim, aggregation_function, alpha, poly_x, *optargs, ), bounds=lim_t, ) elif acquisition_function == "uidal": res = minimize( UIDAL_multi, x0=x0, args=( estimated_sample_x, regression_models, aggregation_function, alpha, *optargs, ), bounds=lim_t, ) elif acquisition_function == "std": res = minimize( std_multi, x0=x0, args=(regression_models, aggregation_function, *optargs), bounds=lim_t, ) elif acquisition_function == "GSx": res = minimize(GSx_multi, x0=x0, args=(estimated_sample_x), bounds=lim_t) elif acquisition_function == "GSy": res = minimize( GSy_multi, x0=x0, args=( estimated_observation_y_aggregated, regression_models, aggregation_function, poly_x, *optargs, ), bounds=lim_t, ) elif acquisition_function == "iGS": res = minimize( iGS_multi, x0=x0, args=( estimated_sample_x, estimated_observation_y_aggregated, regression_models, aggregation_function, poly_x, *optargs, ), bounds=lim_t, ) elif acquisition_function == "SGSx": res = minimize( SGSx_multi, x0=x0, args=( estimated_sample_x, regression_models, aggregation_function, alpha, *optargs, ), bounds=lim_t, ) elif acquisition_function == "nipv": kwargs_opt = copy.copy(kwargs) n_x_int = kwargs_opt.pop("n_x_int", 500) X_int_unscaled = sampler.random(n_x_int) X_int = scale(X_int_unscaled, *lim) res = minimize( NIPV_multi, x0=x0, args=( regression_models, aggregation_function, X_int, *optargs, ), bounds=lim_t, ) elif acquisition_function == "qbc": s_models = [] for i in range(n_models): alpha_models = [] for _ in range(alpha): train_index = rng.randint( 0, len(estimated_sample_x), len(estimated_sample_x) ) if isinstance(regression_models[i], LinearRegression): estimated_sample_x_poly = poly_x.transform(estimated_sample_x) regression_models[i].fit( estimated_sample_x_poly[train_index], estimated_observation_y[i][train_index], ) else: regression_models[i].fit( estimated_sample_x[train_index], estimated_observation_y[i][train_index], ) alpha_models.append(copy.deepcopy(regression_models[i])) s_models.append(alpha_models) res = minimize( QBC_multi, x0=x0, args=(s_models, aggregation_function, poly_x, *optargs), bounds=lim_t, ) elif callable(acquisition_function): custom_args = [] if "x" in custom_acfn_input: custom_args.append(estimated_sample_x) if "y" in custom_acfn_input: custom_args.append(estimated_observation_y_aggregated) if "max_y" in custom_acfn_input: custom_args.append(np.max(estimated_observation_y_aggregated)) if "regression_models" in custom_acfn_input: custom_args.append(regression_models) if "lim" in custom_acfn_input: custom_args.append(lim) if "alpha" in custom_acfn_input: custom_args.append(alpha) if "poly_x" in custom_acfn_input: custom_args.append(poly_x) # Aggregation function is always used and provided as the last argument custom_args.append(aggregation_function) # Provide arguments for the aggregation function for optarg in optargs: custom_args.append(optarg) custom_args = tuple(custom_args) res = minimize(acquisition_function, x0=x0, args=custom_args, bounds=lim_t) else: raise KeyError( 'Acquisition function "{}" not implemented'.format(acquisition_function) ) new_x = res.x cost = res.fun # Simple Particle Swarm Optimization elif opt_method == "PSO": if not isinstance(pso_options, dict): pso_options = { "c1": 0.5, "c2": 0.3, "w": 0.9, "p": dimensions * 10, "i": 200, } else: dict_keys = pso_options.keys() if "c1" not in dict_keys or "c2" not in dict_keys or "w" not in dict_keys: if "p" not in dict_keys or "i" not in dict_keys: raise KeyError("c1, c2, w, p and i keys must be in pso_options.") n_particles = int(pso_options["p"]) n_iters = int(pso_options["i"]) lb = lim[0] ub = lim[1] bounds = [lb, ub] init_pos_unscaled = sampler.random(n_particles) init_pos = scale(init_pos_unscaled, *lim) np.random.seed(rng.randint(0, 1000000)) optimizer = GlobalBestPSO( n_particles=n_particles, dimensions=dimensions, options=pso_options, bounds=bounds, init_pos=init_pos, ) if acquisition_function == "ei": cost, new_x = optimizer.optimize( EI_multi, iters=n_iters, verbose=False, n_processes=n_jobs, model=regression_models, aggregation_function=aggregation_function, opt=np.max(estimated_observation_y_aggregated), alpha=alpha, **kwargs ) elif acquisition_function == "poi": cost, new_x = optimizer.optimize( POI_multi, iters=n_iters, verbose=False, n_processes=n_jobs, model=regression_models, aggregation_function=aggregation_function, opt=np.max(estimated_observation_y_aggregated), alpha=alpha, **kwargs ) elif acquisition_function == "ucb": cost, new_x = optimizer.optimize( UCB_multi, iters=n_iters, verbose=False, n_processes=n_jobs, model=regression_models, aggregation_function=aggregation_function, alpha=alpha, **kwargs ) elif acquisition_function == "max": cost, new_x = optimizer.optimize( max_multi, iters=n_iters, verbose=False, n_processes=n_jobs, model=regression_models, aggregation_function=aggregation_function, **kwargs ) elif acquisition_function == "ideal": cost, new_x = optimizer.optimize( IDEAL_multi, iters=n_iters, verbose=False, n_processes=n_jobs, x_samples=estimated_sample_x, model=regression_models, y_true=estimated_observation_y_aggregated, lim=lim, aggregation_function=aggregation_function, alpha=alpha, poly_x=poly_x, **kwargs ) elif acquisition_function == "uidal": cost, new_x = optimizer.optimize( UIDAL_multi, iters=n_iters, verbose=False, n_processes=n_jobs, x_samples=estimated_sample_x, model=regression_models, aggregation_function=aggregation_function, alpha=alpha, **kwargs ) elif acquisition_function == "std": cost, new_x = optimizer.optimize( std_multi, iters=n_iters, verbose=False, n_processes=n_jobs, model=regression_models, aggregation_function=aggregation_function, **kwargs ) elif acquisition_function == "GSx": cost, new_x = optimizer.optimize( GSx_multi, iters=n_iters, verbose=False, n_processes=n_jobs, x_sample=estimated_sample_x, ) elif acquisition_function == "GSy": cost, new_x = optimizer.optimize( GSy_multi, iters=n_iters, verbose=False, n_processes=n_jobs, y_sample=estimated_observation_y_aggregated, model=regression_models, aggregation_function=aggregation_function, poly_x=poly_x, **kwargs ) elif acquisition_function == "iGS": cost, new_x = optimizer.optimize( iGS_multi, iters=n_iters, verbose=False, n_processes=n_jobs, x_sample=estimated_sample_x, y_sample=estimated_observation_y_aggregated, model=regression_models, aggregation_function=aggregation_function, poly_x=poly_x, **kwargs ) elif acquisition_function == "SGSx": cost, new_x = optimizer.optimize( SGSx_multi, iters=n_iters, verbose=False, n_processes=n_jobs, x_sample=estimated_sample_x, model=regression_models, aggregation_function=aggregation_function, alpha=alpha, **kwargs ) elif acquisition_function == "nipv": kwargs_opt = copy.copy(kwargs) n_x_int = kwargs_opt.pop("n_x_int", 500) X_int_unscaled = sampler.random(n_x_int) X_int = scale(X_int_unscaled, *lim) cost, new_x = optimizer.optimize( NIPV_multi, iters=n_iters, verbose=False, n_processes=n_jobs, model=regression_models, aggregation_function=aggregation_function, X_int=X_int, **kwargs_opt ) elif acquisition_function == "qbc": s_models = [] for i in range(n_models): alpha_models = [] for _ in range(alpha): train_index = rng.randint( 0, len(estimated_sample_x), len(estimated_sample_x) ) if isinstance(regression_models[i], LinearRegression): estimated_sample_x_poly = poly_x.transform(estimated_sample_x) regression_models[i].fit( estimated_sample_x_poly[train_index], estimated_observation_y[i][train_index], ) else: regression_models[i].fit( estimated_sample_x[train_index], estimated_observation_y[i][train_index], ) alpha_models.append(copy.deepcopy(regression_models[i])) s_models.append(alpha_models) cost, new_x = optimizer.optimize( QBC_multi, iters=n_iters, verbose=False, n_processes=n_jobs, models=s_models, aggregation_function=aggregation_function, poly_x=poly_x, **kwargs ) elif callable(acquisition_function): custom_args = {} if "x" in custom_acfn_input: custom_args["x"] = estimated_sample_x if "y" in custom_acfn_input: custom_args["y"] = estimated_observation_y_aggregated if "max_y" in custom_acfn_input: custom_args["max_y"] = np.max(estimated_observation_y_aggregated) if "regression_models" in custom_acfn_input: custom_args["regression_models"] = regression_models if "lim" in custom_acfn_input: custom_args["lim"] = lim if "alpha" in custom_acfn_input: custom_args["alpha"] = alpha if "poly_x" in custom_acfn_input: custom_args["poly_x"] = poly_x cost, new_x = optimizer.optimize( acquisition_function, iters=n_iters, verbose=False, n_processes=n_jobs, aggregation_function=aggregation_function, **custom_args, **kwargs ) else: raise KeyError( 'Acquisition function "{}" not implemented'.format(acquisition_function) ) else: raise KeyError('Optimization method "{}" not implemented'.format(opt_method)) return new_x, cost