def __init__(self, model_config: Point, input_space: Hypergrid, output_space: Hypergrid, logger=None): MultiObjectiveRegressionModel.__init__(self, model_type=type(self), model_config=model_config, input_space=input_space, output_space=output_space) if logger is None: logger = create_logger("MultiObjectiveHomogeneousRandomForest") self.logger = logger # We just need to assert that the model config belongs in homogeneous_random_forest_config_store.parameter_space. # A more elaborate solution might be needed down the road, but for now this simple solution should suffice. # assert model_config in homogeneous_random_forest_config_store.parameter_space self._regressors_by_objective_name = KeyOrderedDict( ordered_keys=self.output_dimension_names, value_type=HomogeneousRandomForestRegressionModel) for output_dimension in output_space.dimensions: random_forest = HomogeneousRandomForestRegressionModel( model_config=model_config, input_space=input_space, output_space=SimpleHypergrid( name=f"{output_dimension.name}_objective", dimensions=[output_dimension]), logger=self.logger) self._regressors_by_objective_name[ output_dimension.name] = random_forest
def __init__(self, designer_config: Point, optimization_problem: OptimizationProblem, surrogate_model: RegressionModel, logger=None): assert designer_config in experiment_designer_config_store.parameter_space if logger is None: logger = create_logger(self.__class__.__name__) self.logger = logger self.config = designer_config self.optimization_problem = optimization_problem self.surrogate_model = surrogate_model self.rng = np.random.Generator(np.random.PCG64()) self.utility_function = ConfidenceBoundUtilityFunction( function_config=self.config. confidence_bound_utility_function_config, surrogate_model=self.surrogate_model, minimize=self.optimization_problem.objectives[0].minimize, logger=self.logger) if self.config.numeric_optimizer_implementation == RandomSearchOptimizer.__name__: self.numeric_optimizer = RandomSearchOptimizer( optimizer_config=self.config.random_search_optimizer_config, optimization_problem=self.optimization_problem, utility_function=self.utility_function, logger=self.logger) elif self.config.numeric_optimizer_implementation == GlowWormSwarmOptimizer.__name__: self.numeric_optimizer = GlowWormSwarmOptimizer( optimizer_config=self.config.glow_worm_swarm_optimizer_config, optimization_problem=self.optimization_problem, utility_function=self.utility_function, logger=self.logger)
def __init__(self, model_config: Point, input_space: Hypergrid, output_space: Hypergrid, logger=None): if logger is None: logger = create_logger("HomogeneousRandomForestRegressionModel") self.logger = logger assert model_config in homogeneous_random_forest_config_store.parameter_space RegressionModel.__init__(self, model_type=type(self), model_config=model_config, input_space=input_space, output_space=output_space, fit_state=HomogeneousRandomForestFitState( input_space=input_space, output_space=output_space)) self._input_space_adapter = HierarchicalToFlatHypergridAdapter( adaptee=self.input_space) self._output_space_adapter = HierarchicalToFlatHypergridAdapter( adaptee=self.output_space) self.target_dimension_names = [ dimension.name for dimension in self._output_space_adapter.dimensions ] assert len(self.target_dimension_names ) == 1, "Single target predictions for now." self._decision_trees = [] self._create_estimators()
def __init__(self, designer_config: ExperimentDesignerConfig, optimization_problem: OptimizationProblem, surrogate_model: RegressionModel, logger=None): if logger is None: logger = create_logger(self.__class__.__name__) self.logger = logger self.config = designer_config self.optimization_problem = optimization_problem self.surrogate_model = surrogate_model self.rng = np.random.Generator(np.random.PCG64()) assert self.config.utility_function_implementation == ConfidenceBoundUtilityFunction.__name__ self.utility_function = ConfidenceBoundUtilityFunction( function_config=ConfidenceBoundUtilityFunctionConfig. create_from_config_point( self.config.confidence_bound_utility_function_config), surrogate_model=self.surrogate_model, minimize=self.optimization_problem.objectives[0].minimize, logger=self.logger) assert self.config.numeric_optimizer_implementation == RandomSearchOptimizer.__name__ self.numeric_optimizer = RandomSearchOptimizer( optimizer_config=RandomSearchOptimizerConfig. create_from_config_point( self.config.random_search_optimizer_config), optimization_problem=self.optimization_problem, utility_function=self.utility_function, logger=self.logger)
def __init__(self, bayesian_optimizer_store: BayesianOptimizerStoreBase, logger=None): self._bayesian_optimizer_store = bayesian_optimizer_store if logger is None: logger = create_logger(self.__class__.__name__) self.logger = logger
def __init__(self, connection_string, logger=None): self.logger = logger if logger is not None else create_logger("ModelsDatabase") self.connection_string = connection_string self.database_connector = DatabaseConnector( connection_string=connection_string, logger=self.logger )
def setUp(self): self.logger = create_logger(self.__class__.__name__) # Start up the gRPC service. # self.server = OptimizerMicroserviceServer(port=50051, num_threads=10) self.server.start() self.optimizer_service_channel = grpc.insecure_channel('localhost:50051') self.bayesian_optimizer_factory = BayesianOptimizerFactory(grpc_channel=self.optimizer_service_channel, logger=self.logger) self.optimizer_monitor = OptimizerMonitor(grpc_channel=self.optimizer_service_channel, logger=self.logger) # Define the optimization problem. # input_space = SimpleHypergrid( name="input", dimensions=[ ContinuousDimension(name='x_1', min=-100, max=100), ContinuousDimension(name='x_2', min=-100, max=100) ] ) output_space = SimpleHypergrid( name="output", dimensions=[ ContinuousDimension(name='y', min=-math.inf, max=math.inf) ] ) self.optimization_problem = OptimizationProblem( parameter_space=input_space, objective_space=output_space, objectives=[Objective(name='y', minimize=True)] )
def __init__(self, model_config: Point, input_space: Hypergrid, output_space: Hypergrid, logger=None): if logger is None: logger = create_logger( "RegressionEnhancedRandomForestRegressionModel") self.logger = logger assert model_config in RegressionEnhancedRandomForestRegressionModelConfig.CONFIG_SPACE RegressionModel.__init__(self, model_type=type(self), model_config=model_config, input_space=input_space, output_space=output_space) self.model_config = model_config # one hot encode categorical input dimensions self.one_hot_encoder_adapter = CategoricalToOneHotEncodedHypergridAdapter( adaptee=input_space, merge_all_categorical_dimensions=True, drop='first') # Explode continuous dimensions to polynomial features up to model config specified monomial degree # am using include_bias to produce constant term (all 1s) column to simplify one hot encoding logic self.polynomial_features_adapter = ContinuousToPolynomialBasisHypergridAdapter( adaptee=self.one_hot_encoder_adapter.target, degree=self.model_config.max_basis_function_degree, include_bias=True, interaction_only=False) self.input_space = input_space self.input_dimension_names = [ dimension.name for dimension in self.input_space.dimensions ] self.output_dimension_names = [ dimension.name for dimension in self.output_space.dimensions ] self.base_regressor_ = None self.random_forest_regressor_ = None self.random_forest_kwargs = None self.root_model_kwargs = None self.detected_feature_indices_ = None self.screening_root_model_coef_ = None self.fit_X_ = None self.partial_hat_matrix_ = None self.base_regressor_standard_error_ = None self.dof_ = None self.variance_estimate_ = None self.root_model_gradient_coef_ = None self.polynomial_features_powers_ = None self.categorical_zero_cols_idx_to_delete_ = None self.scaler_ = StandardScaler() self._trained = False
def __init__(self, grpc_channel=None, logger=None): self.logger = logger if logger is not None else create_logger( "BayesianOptimizerFactory") self._grpc_channel = grpc_channel self._optimizer_service_stub = None if self._grpc_channel is not None: self._optimizer_service_stub = OptimizerServiceStub( channel=self._grpc_channel)
def __init__(self, grpc_channel, logger=None): self.logger = logger if logger is not None else create_logger( "OptimizerMonitor") self._grpc_channel = grpc_channel self._optimizer_monitoring_stub = OptimizerMonitoringServiceStub( channel=self._grpc_channel) self._optimizer_factory = BayesianOptimizerFactory( grpc_channel=self._grpc_channel, logger=self.logger)
def __init__(self, connection_string=None, logger=None): if logger is None: logger = create_logger(logger_name="DatabaseConnector") self.logger = logger self.connection_string = connection_string self.connection = None self.using_default_database = False
def __init__(self, port, num_threads=10, logger=None): self.port = port self.num_threads = num_threads self.started = False self._server = None if logger is None: logger = create_logger("OptimizerMicroserviceServer init") self.logger = logger
def __init__(self): self._optimizers_by_id = dict() self._ordered_ids = [] self._lock_manager = multiprocessing.Manager() self._optimizer_locks_by_optimizer_id = dict() self.logger = create_logger("OptimizerMicroservice") self.logger.info("OptimizerMicroservice init")
def __init__(self, surrogate_model, minimize, logger=None): if logger is None: logger = create_logger(self.__class__.__name__) self.logger = logger self.minimize = minimize self._sign = 1 if not minimize else -1 self.surrogate_model = surrogate_model
def setUpClass(cls): """Sets up all the singletons needed to test the BayesianOptimizer. """ warnings.simplefilter("error") global_values.declare_singletons() global_values.tracer = Tracer(actor_id=cls.__name__, thread_id=0) cls.logger = create_logger(logger_name=cls.__name__)
def __init__(self, model_config: Point, input_space: Hypergrid, output_space: Hypergrid, logger=None): if logger is None: logger = create_logger("DecisionTreeRegressionModel") self.logger = logger assert model_config in decision_tree_config_store.parameter_space RegressionModel.__init__(self, model_type=type(self), model_config=model_config, input_space=input_space, output_space=output_space) self._input_space_adapter = CategoricalToDiscreteHypergridAdapter( adaptee=self.input_space) self.input_dimension_names = [ dimension.name for dimension in self._input_space_adapter.dimensions ] self.target_dimension_names = [ dimension.name for dimension in self.output_space.dimensions ] self.logger.debug( f"Input dimensions: {str(self.input_dimension_names)}; Target dimensions: {str(self.target_dimension_names)}." ) assert len( self.target_dimension_names ) == 1, "For now (and perhaps forever) we only support single target per tree." self._regressor = DecisionTreeRegressor( criterion=self.model_config.criterion, splitter=self.model_config.splitter, max_depth=self.model_config.max_depth if self.model_config.max_depth != 0 else None, min_samples_split=self.model_config.min_samples_split, min_samples_leaf=self.model_config.min_samples_leaf, min_weight_fraction_leaf=self.model_config. min_weight_fraction_leaf, max_features=self.model_config.max_features, random_state=self.model_config.get("random_state", None), max_leaf_nodes=self.model_config.max_leaf_nodes if self.model_config.max_leaf_nodes not in (0, 1) else None, min_impurity_decrease=self.model_config.min_impurity_decrease, ccp_alpha=self.model_config.ccp_alpha) # These are used to compute the variance in predictions self._observations_per_leaf = dict() self._mean_per_leaf = dict() self._mean_variance_per_leaf = dict() self._sample_variance_per_leaf = dict() self._count_per_leaf = dict() self._trained = False
def setup_class(cls) -> None: mlos.global_values.declare_singletons() mlos.global_values.tracer = Tracer(actor_id=cls.__name__, thread_id=0) cls.temp_dir = os.path.join(os.getcwd(), "temp") if not os.path.exists(cls.temp_dir): os.mkdir(cls.temp_dir) cls.logger = create_logger("TestOptimizerEvaluator")
def setUp(self): mlos_globals.init_mlos_global_context() mlos_globals.mlos_global_context.start_clock() self.logger = create_logger('TestSmartCacheWithRemoteOptimizer') self.logger.level = logging.DEBUG # Start up the gRPC service. # self.server = OptimizerMicroserviceServer(port=50051, num_threads=10) self.server.start() self.optimizer_service_grpc_channel = grpc.insecure_channel('localhost:50051') self.bayesian_optimizer_factory = BayesianOptimizerFactory(grpc_channel=self.optimizer_service_grpc_channel, logger=self.logger) self.mlos_agent = MlosAgent( logger=self.logger, communication_channel=mlos_globals.mlos_global_context.communication_channel, shared_config=mlos_globals.mlos_global_context.shared_config, bayesian_optimizer_grpc_channel=self.optimizer_service_grpc_channel ) self.mlos_agent_thread = Thread(target=self.mlos_agent.run) self.mlos_agent_thread.start() global_values.declare_singletons() # TODO: having both globals and global_values is a problem # Let's add the allowed component types self.mlos_agent.add_allowed_component_type(SmartCache) self.mlos_agent.add_allowed_component_type(SmartCacheWorkloadGenerator) self.mlos_agent.set_configuration( component_type=SmartCacheWorkloadGenerator, new_config_values=Point( workload_type='cyclical_key_from_range', cyclical_key_from_range_config=Point( min=0, range_width=2048 ) ) ) # Let's create the workload self.smart_cache_workload = SmartCacheWorkloadGenerator(logger=self.logger) self.optimizer = None self.working_set_size_estimator = WorkingSetSizeEstimator() self.hit_rate_monitor = HitRateMonitor() self.smart_cache_experiment = MlosExperiment( smart_component_types=[SmartCache], telemetry_aggregators=[self.working_set_size_estimator, self.hit_rate_monitor] ) self.optimization_problem = OptimizationProblem( parameter_space=SmartCache.parameter_search_space, objective_space=SimpleHypergrid(name="objectives", dimensions=[ContinuousDimension(name="hit_rate", min=0, max=1)]), objectives=[Objective(name="hit_rate", minimize=False)] )
def __init__(self, model_config: Point, input_space: Hypergrid, output_space: Hypergrid, logger=None): if logger is None: logger = create_logger( "RegressionEnhancedRandomForestRegressionModel") self.logger = logger assert model_config in RegressionEnhancedRandomForestRegressionModelConfig.CONFIG_SPACE RegressionModel.__init__(self, model_type=type(self), model_config=model_config, input_space=input_space, output_space=output_space) self.model_config = model_config # one hot encode categorical input dimensions self.one_hot_encoder_adapter = CategoricalToOneHotEncodedHypergridAdapter( adaptee=input_space, merge_all_categorical_dimensions=True, drop='first') self.input_space = input_space self.input_dimension_names = [ dimension.name for dimension in self.input_space.dimensions ] self.output_dimension_names = [ dimension.name for dimension in self.output_space.dimensions ] self.base_regressor_ = None self.random_forest_regressor_ = None # set up basis feature transform self.polynomial_features_transform_ = \ PolynomialFeatures(degree=self.model_config.max_basis_function_degree) self.random_forest_kwargs = None self.root_model_kwargs = None self.detected_feature_indices_ = None self.screening_root_model_coef_ = None self.fit_X_ = None self.partial_hat_matrix_ = None self.base_regressor_standard_error_ = None self.dof_ = None self.variance_estimate_ = None self.root_model_gradient_coef_ = None self.polynomial_features_powers_ = None self.categorical_zero_cols_idx_to_delete_ = None self.scaler_ = StandardScaler() self._trained = False
def __init__(self, designer_config: Point, optimization_problem: OptimizationProblem, surrogate_model: MultiObjectiveRegressionModel, pareto_frontier: ParetoFrontier, logger=None): assert designer_config in experiment_designer_config_store.parameter_space if logger is None: logger = create_logger(self.__class__.__name__) self.logger = logger self.config: Point = designer_config self.optimization_problem: OptimizationProblem = optimization_problem self.pareto_frontier = pareto_frontier self.surrogate_model: MultiObjectiveRegressionModel = surrogate_model self.rng = np.random.Generator(np.random.PCG64()) if designer_config.utility_function_implementation == ConfidenceBoundUtilityFunction.__name__: self.utility_function = ConfidenceBoundUtilityFunction( function_config=self.config. confidence_bound_utility_function_config, surrogate_model=self.surrogate_model, minimize=self.optimization_problem.objectives[0].minimize, logger=self.logger) elif designer_config.utility_function_implementation == MultiObjectiveProbabilityOfImprovementUtilityFunction.__name__: assert self.pareto_frontier is not None self.utility_function = MultiObjectiveProbabilityOfImprovementUtilityFunction( function_config=self.config. multi_objective_probability_of_improvement_config, pareto_frontier=pareto_frontier, surrogate_model=self.surrogate_model, logger=self.logger) else: assert False numeric_optimizer_config = None if self.config.numeric_optimizer_implementation == RandomSearchOptimizer.__name__: numeric_optimizer_config = self.config.random_search_optimizer_config elif self.config.numeric_optimizer_implementation == GlowWormSwarmOptimizer.__name__: numeric_optimizer_config = self.config.glow_worm_swarm_optimizer_config elif self.config.numeric_optimizer_implementation == RandomNearIncumbentOptimizer.__name__: numeric_optimizer_config = self.config.random_near_incumbent_optimizer_config else: raise NotImplementedError( f"Unknown numeric optimizer implementation: {self.config.numeric_optimizer_config}" ) self.numeric_optimizer = UtilityFunctionOptimizerFactory.create_utility_function_optimizer( utility_function=self.utility_function, optimizer_type_name=self.config.numeric_optimizer_implementation, optimizer_config=numeric_optimizer_config, optimization_problem=self.optimization_problem, pareto_frontier=self.pareto_frontier, logger=self.logger)
def __init__(self, optimizer_config: Point, optimization_problem: OptimizationProblem, utility_function: UtilityFunction, logger=None): if logger is None: logger = create_logger(self.__class__.__name__) self.logger = logger self.optimizer_config = optimizer_config self.optimization_problem = optimization_problem self.utility_function = utility_function
def __init__(self, optimizer_config: RandomSearchOptimizerConfig, optimization_problem: OptimizationProblem, utility_function, logger=None): if logger is None: logger = create_logger(self.__class__.__name__) self.logger = logger self.optimization_problem = optimization_problem self.utility_function = utility_function self.config = optimizer_config
def __init__(self, surrogate_model: MultiObjectiveRegressionModel, minimize: bool, logger=None): if logger is None: logger = create_logger(self.__class__.__name__) self.logger = logger self.minimize = minimize self._sign = 1 if not minimize else -1 self.surrogate_model = surrogate_model
def setup_class(cls): """ Set's up all the objects needed to test the UtilityFunctionOptimizers To test the UtilityFunctionOptimizers we need to first construct: * an objective function for the model to approximate and its corresponding parameter and output spaces * an optimization problem * a regression model, then train it on some random parameters to the objective function * a utility function that utilizes the model * a pareto frontier over the random parameters And only then do we get to test our utility function optimizers. This is a lot of work and a somewhat cleaner approach would be to simply create an instance of the BayesianOptimizer to do all of the above for us, but then we might not be able to test the utility function optimizers as thoroughly as we need to. :return: """ global_values.declare_singletons() global_values.tracer = Tracer(actor_id=cls.__name__, thread_id=0) cls.logger = create_logger("TestUtilityFunctionOptimizers") cls.model_config = multi_objective_pass_through_model_config_store.default cls.model = MultiObjectivePassThroughModelForTesting( model_config=cls.model_config, logger=cls.logger ) cls.objective_function = cls.model.objective_function cls.parameter_space = cls.objective_function.parameter_space cls.objective_space = cls.objective_function.output_space cls.optimization_problem = cls.objective_function.default_optimization_problem cls.utility_function_config = Point(utility_function_name="upper_confidence_bound_on_improvement", alpha=0.05) cls.utility_function = ConfidenceBoundUtilityFunction( function_config=cls.utility_function_config, surrogate_model=cls.model, minimize=cls.optimization_problem.objectives[0].minimize, logger=cls.logger ) # To make the pareto frontier we have to generate some random points. # cls.parameters_df = cls.objective_function.parameter_space.random_dataframe(1000) cls.objectives_df = cls.objective_function.evaluate_dataframe(cls.parameters_df) cls.pareto_frontier = ParetoFrontier( optimization_problem=cls.optimization_problem, objectives_df=cls.objectives_df, parameters_df=cls.parameters_df )
def setUp(self): mlos_globals.init_mlos_global_context() mlos_globals.mlos_global_context.start_clock() self.logger = create_logger('TestSmartCacheWithRemoteOptimizer') self.logger.level = logging.INFO self.mlos_agent = MlosAgent( logger=self.logger, communication_channel=mlos_globals.mlos_global_context. communication_channel, shared_config=mlos_globals.mlos_global_context.shared_config, ) self.mlos_agent_thread = Thread(target=self.mlos_agent.run) self.mlos_agent_thread.start() global_values.declare_singletons( ) # TODO: having both globals and global_values is a problem self.workload_duration_s = 5 # Let's add the allowed component types self.mlos_agent.add_allowed_component_type(SmartCache) self.mlos_agent.add_allowed_component_type(SmartCacheWorkloadGenerator) # Let's create the workload self.smart_cache_workload = SmartCacheWorkloadGenerator( logger=self.logger) self.optimizer = None self.working_set_size_estimator = WorkingSetSizeEstimator() self.cache_config_timer = Timer( timeout_ms=200, observer_callback=self._set_new_cache_configuration) self.smart_cache_experiment = MlosExperiment( smart_component_types=[SmartCache], telemetry_aggregators=[ self.cache_config_timer, self.working_set_size_estimator ]) self.optimization_problem = OptimizationProblem( parameter_space=SmartCache.parameter_search_space, objective_space=SimpleHypergrid(name="objectives", dimensions=[ ContinuousDimension( name="miss_rate", min=0, max=1) ]), context_space=None, # TODO: add working set size estimate objectives=[Objective(name="miss_rate", minimize=True)])
def __init__(self, function_config: Point, surrogate_model: MultiObjectiveRegressionModel, minimize: bool, logger=None): if logger is None: logger = create_logger(self.__class__.__name__) self.logger = logger self.config = function_config self.minimize = minimize self._sign = 1 if not minimize else -1 if self.config.utility_function_name not in ("lower_confidence_bound_on_improvement", "upper_confidence_bound_on_improvement"): raise RuntimeError(f"Invalid utility function name: {self.config.utility_function_name}.") self.surrogate_model: MultiObjectiveRegressionModel = surrogate_model
def __init__(self, function_config: Point, pareto_frontier: ParetoFrontier, surrogate_model: MultiObjectiveRegressionModel, logger=None): if logger is None: logger = create_logger(self.__class__.__name__) self.logger = logger self.config = function_config self.pareto_frontier = pareto_frontier self.surrogate_model: MultiObjectiveRegressionModel = surrogate_model
def __init__(self, model_config: Point, input_space: Hypergrid, output_space: Hypergrid, logger=None): if logger is None: logger = create_logger( "RegressionEnhancedRandomForestRegressionModel") self.logger = logger assert model_config in RegressionEnhancedRandomForestRegressionModelConfig.CONFIG_SPACE RegressionModel.__init__(self, model_type=type(self), model_config=model_config, input_space=input_space, output_space=output_space) self.model_config = model_config self.input_dimension_names = [ dimension.name for dimension in self.input_space.dimensions ] self.output_dimension_names = [ dimension.name for dimension in self.output_space.dimensions ] self.base_regressor_ = None self.random_forest_regressor_ = None # set up basis feature transform self.polynomial_features_transform_ = \ PolynomialFeatures(degree=self.model_config.max_basis_function_degree) self.random_forest_kwargs = None self.root_model_kwargs = None self.detected_feature_indices_ = None self.screening_root_model_coef_ = None self.fit_X_ = None self.partial_hat_matrix_ = None self.base_regressor_standard_error_ = None self.dof_ = None self.variance_estimate_ = None self.root_model_gradient_coef_ = None self.polynomial_features_powers_ = None self.num_dummy_vars_ = None self.num_categorical_dims_ = None self.continuous_dim_col_names_ = None self.categorical_dim_col_names_ = None self.dummy_var_map_ = None self.dummy_var_cols_ = None self.categorical_zero_cols_idx_to_delete_ = None
def setUpClass(cls) -> None: mlos_globals.init_mlos_global_context() cls.logger = create_logger('TestE2EScenarios') cls.logger.level = logging.INFO cls.mlos_agent = MlosAgent( logger=cls.logger, communication_channel=mlos_globals.mlos_global_context. communication_channel, shared_config=mlos_globals.mlos_global_context.shared_config) cls.mlos_agent_thread = Thread(target=cls.mlos_agent.run) cls.mlos_agent_thread.start() mlos_globals.mlos_global_context.start_clock() cls.mlos_agent.add_allowed_component_type(SmartCache) cls.mlos_agent.add_allowed_component_type(SmartCacheWorkloadGenerator)
def __init__(self, optimization_problem: OptimizationProblem, optimizer_config: Point, logger=None): if logger is None: logger = create_logger("BayesianOptimizer") self.logger = logger # Let's initialize the optimizer. # assert len(optimization_problem.objectives ) == 1, "For now this is a single-objective optimizer." OptimizerBase.__init__(self, optimization_problem) assert optimizer_config in bayesian_optimizer_config_store.parameter_space, "Invalid config." self.optimizer_config = optimizer_config # Now let's put together the surrogate model. # assert self.optimizer_config.surrogate_model_implementation == HomogeneousRandomForestRegressionModel.__name__, "TODO: implement more" self.surrogate_model = HomogeneousRandomForestRegressionModel( model_config=self.optimizer_config. homogeneous_random_forest_regression_model_config, input_space=self.optimization_problem. parameter_space, # TODO: change to feature space output_space=self.optimization_problem.objective_space, logger=self.logger) # Now let's put together the experiment designer that will suggest parameters for each experiment. # assert self.optimizer_config.experiment_designer_implementation == ExperimentDesigner.__name__ self.experiment_designer = ExperimentDesigner( designer_config=self.optimizer_config.experiment_designer_config, optimization_problem=self.optimization_problem, surrogate_model=self.surrogate_model, logger=self.logger) self._optimizer_convergence_state = BayesianOptimizerConvergenceState( surrogate_model_fit_state=self.surrogate_model.fit_state) # Also let's make sure we have the dataframes we need for the surrogate model. # TODO: this will need a better home - either a DataSet class or the surrogate model itself. self._feature_values_df = pd.DataFrame(columns=[ dimension.name for dimension in self.optimization_problem.parameter_space.dimensions ]) self._target_values_df = pd.DataFrame(columns=[ dimension.name for dimension in self.optimization_problem.objective_space.dimensions ])