Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add example for surrogate optimizer #1085

Merged
merged 5 commits into from
Apr 27, 2023
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Next Next commit
add example for surrogate optimizer
  • Loading branch information
valer1435 committed Apr 15, 2023
commit 84fd5a60f207c75a6af9a38af3bac7c85a9a4252
47 changes: 47 additions & 0 deletions examples/advanced/surrogate_optimization.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
from functools import partial
from typing import Any

from golem.core.optimisers.meta.surrogate_model import SurrogateModel
from golem.core.optimisers.meta.surrogate_optimizer import SurrogateOptimizer

from examples.simple.time_series_forecasting.api_forecasting import get_ts_data
from fedot.api.main import Fedot
from fedot.core.repository.tasks import Task, TaskTypesEnum, TsForecastingParams


class SingleValueSurrogateModel(SurrogateModel):
def __call__(self, graph, **kwargs: Any):
# example how we can get input data from objective
input_data = kwargs.get('objective').__self__._data_producer.args[0]
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

кажется не должно возникать ситуаций, когда придется настолько лезть в кишки ради данных

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Это нормально при нашем подходе с objective. Но упростил получение данных через поле

return [0]
nicl-nno marked this conversation as resolved.
Show resolved Hide resolved


def run_ts_forecasting_example(dataset='australia', horizon: int = 30, validation_blocks=2, timeout: float = None,
visualization=False, with_tuning=True):
train_data, test_data = get_ts_data(dataset, horizon, validation_blocks)
# init model for the time series forecasting
model = Fedot(problem='ts_forecasting',
task_params=Task(TaskTypesEnum.ts_forecasting,
TsForecastingParams(forecast_length=horizon)).task_params,
timeout=timeout,
n_jobs=-1,
with_tuning=with_tuning,
cv_folds=2, validation_blocks=validation_blocks, preset='fast_train',
optimizer=partial(SurrogateOptimizer, surrogate_model=SingleValueSurrogateModel()))

# run AutoML model design in the same way
pipeline = model.fit(train_data)

# use model to obtain two-step in-sample forecast
in_sample_forecast = model.predict(test_data)
print('Metrics for two-step in-sample forecast: ',
model.get_metrics(metric_names=['rmse', 'mae', 'mape']))

# plot forecasting result
if visualization:
pipeline.show()
model.plot_prediction()


if __name__ == '__main__':
run_ts_forecasting_example(visualization=True, timeout=3)
17 changes: 8 additions & 9 deletions fedot/api/api_utils/api_composer.py
Original file line number Diff line number Diff line change
Expand Up @@ -113,15 +113,14 @@ def compose_pipeline(self, train_data: InputData, initial_assumption: Sequence[P
fitted_assumption: Pipeline) -> Tuple[Pipeline, List[Pipeline], GPComposer]:

gp_composer: GPComposer = (ComposerBuilder(task=self.params.task)
.with_requirements(self.params.composer_requirements)
.with_initial_pipelines(initial_assumption)
.with_optimizer(self.params.get('optimizer'))
.with_optimizer_params(parameters=self.params.optimizer_params,
external_parameters=self.params.get('optimizer_external_params'))
.with_metrics(self.metrics.metric_functions)
.with_cache(self.pipelines_cache, self.preprocessing_cache)
.with_graph_generation_param(graph_generation_params=self.params.graph_generation_params)
.build())
.with_requirements(self.params.composer_requirements)
.with_initial_pipelines(initial_assumption)
.with_optimizer(self.params.get('optimizer'))
.with_optimizer_params(parameters=self.params.optimizer_params)
.with_metrics(self.metrics.metric_functions)
.with_cache(self.pipelines_cache, self.preprocessing_cache)
.with_graph_generation_param(graph_generation_params=self.params.graph_generation_params)
.build())

if self.timer.have_time_for_composing(self.params.get('pop_size'), self.params.n_jobs):
# Launch pipeline structure composition
Expand Down
1 change: 0 additions & 1 deletion fedot/api/api_utils/api_params_repository.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,6 @@ def default_params_for_task(task_type: TaskTypesEnum) -> dict:
early_stopping_iterations=None,
early_stopping_timeout=10,
optimizer=None,
optimizer_external_params=None,
collect_intermediate_metric=False,
max_pipeline_fit_time=None,
initial_assumption=None,
Expand Down
5 changes: 2 additions & 3 deletions fedot/api/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@

from fedot.api.api_utils.api_composer import ApiComposer
from fedot.api.api_utils.api_data import ApiDataProcessor
from fedot.api.api_utils.input_analyser import InputAnalyser
from fedot.api.api_utils.data_definition import FeaturesType, TargetType
from fedot.api.api_utils.input_analyser import InputAnalyser
from fedot.api.api_utils.metrics import ApiMetrics
from fedot.api.api_utils.params import ApiParams
from fedot.api.api_utils.predefined_model import PredefinedModel
Expand Down Expand Up @@ -161,8 +161,7 @@ class Fedot:
:class:`~golem.core.optimisers.optimizer.GraphOptimizer` to specify a custom optimizer.
Default optimizer is :class:`~golem.core.optimisers.genetic.gp_optimizer.EvoGraphOptimizer`.
See the `example \
<https://github.com/aimclub/FEDOT/blob/master/examples/advanced/fedot_based_solutions/external_optimizer.py>`_.
optimizer_external_params (Dict[str, Any]): additional parameters for custom optimizer (if needed).
<https://github.com/aimclub/FEDOT/blob/master/examples/advanced/fedot_based_solutions/external_optimizer.py>`_
"""

def __init__(self,
Expand Down
11 changes: 3 additions & 8 deletions fedot/core/composer/composer_builder.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
import platform
from multiprocessing import set_start_method
from pathlib import Path
from typing import Dict, List, Optional, Sequence, Type, Union
from typing import List, Optional, Sequence, Type, Union

from golem.core.log import LoggerAdapter, default_log
from golem.core.optimisers.genetic.gp_optimizer import EvoGraphOptimizer
from golem.core.optimisers.genetic.gp_params import GPAlgorithmParameters
from fedot.core.pipelines.pipeline_composer_requirements import PipelineComposerRequirements
from golem.core.optimisers.initial_graphs_generator import InitialPopulationGenerator, GenerationFunction
from golem.core.optimisers.optimizer import GraphOptimizer, AlgorithmParameters, GraphGenerationParams
from golem.core.utilities.data_structures import ensure_wrapped_in_sequence
Expand All @@ -17,6 +16,7 @@
from fedot.core.composer.gp_composer.gp_composer import GPComposer
from fedot.core.optimisers.objective.metrics_objective import MetricsObjective
from fedot.core.pipelines.pipeline import Pipeline
from fedot.core.pipelines.pipeline_composer_requirements import PipelineComposerRequirements
from fedot.core.pipelines.pipeline_graph_generation_params import get_pipeline_generation_params
from fedot.core.pipelines.verification import rules_by_task
from fedot.core.repository.operation_types_repository import get_operations_for_task
Expand Down Expand Up @@ -46,7 +46,6 @@ def __init__(self, task: Task):

self.optimizer_cls: Type[GraphOptimizer] = EvoGraphOptimizer # default optimizer class
self.optimizer_parameters: Optional[AlgorithmParameters] = None
self.optimizer_external_parameters: dict = {}

self.composer_cls: Type[Composer] = GPComposer # default composer class
self.composer_requirements: Optional[PipelineComposerRequirements] = None
Expand All @@ -72,12 +71,9 @@ def with_optimizer(self, optimizer_cls: Optional[Type[GraphOptimizer]]):
return self

def with_optimizer_params(self, parameters: Optional[AlgorithmParameters] = None,
external_parameters: Optional[Dict] = None,
dispatcher=None):
if parameters is not None:
self.optimizer_parameters = parameters
if external_parameters is not None:
self.optimizer_external_parameters = external_parameters
if dispatcher is not None:
self.optimizer_parameters = dispatcher
return self
Expand Down Expand Up @@ -157,8 +153,7 @@ def build(self) -> Composer:
initial_graphs=initial_population,
requirements=self.composer_requirements,
graph_generation_params=self.graph_generation_params,
graph_optimizer_params=self.optimizer_parameters,
**self.optimizer_external_parameters)
graph_optimizer_params=self.optimizer_parameters)

composer = self.composer_cls(optimiser,
self.composer_requirements,
Expand Down
2 changes: 0 additions & 2 deletions test/unit/api/test_api_params.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@
from fedot.core.repository.quality_metrics_repository import RegressionMetricsEnum
from fedot.core.repository.tasks import TaskTypesEnum


fedot_params_full = dict(parallelization_mode='populational',
show_progress=True,
max_depth=4,
Expand All @@ -29,7 +28,6 @@
early_stopping_iterations=2,
early_stopping_timeout=None,
optimizer=EvoGraphOptimizer,
optimizer_external_params=dict(),
collect_intermediate_metric=False,
max_pipeline_fit_time=7,
initial_assumption=PipelineBuilder().add_node('lagged').add_node('ridge').build(),
Expand Down
58 changes: 0 additions & 58 deletions test/unit/optimizer/test_external.py

This file was deleted.