From 947844caff5e52f26fa15f0c21c6b184f7f78bf6 Mon Sep 17 00:00:00 2001 From: karibbov Date: Sun, 7 Apr 2024 12:41:43 +0200 Subject: [PATCH 1/6] Squashed MF-EI-BO implementation with acq functions and surrogates --- .github/workflows/tests.yaml | 7 +- CITATION.cff | 8 +- README.md | 120 ++- docs/README.md | 35 +- docs/analyse.md | 150 +++- docs/citations.md | 54 ++ docs/contributing/roadmap.md | 34 +- .../tensorboard/tblogger_hparam1.jpg | Bin 0 -> 207727 bytes .../tensorboard/tblogger_hparam2.jpg | Bin 0 -> 321199 bytes .../tensorboard/tblogger_hparam3.jpg | Bin 0 -> 138426 bytes .../doc_images/tensorboard/tblogger_image.jpg | Bin 0 -> 184767 bytes .../tensorboard/tblogger_scalar.jpg | Bin 0 -> 204856 bytes docs/getting_started.md | 101 +++ docs/installation.md | 24 + docs/neps_run.md | 100 +++ .../README.md => docs/optimizers.md | 34 +- docs/parallelization.md | 48 +- docs/pipeline_space.md | 180 ++++ docs/run_pipeline.md | 150 ++++ mkdocs.yml | 21 +- {src/neps => neps}/NOTICE | 0 {src/neps => neps}/__init__.py | 0 {src/neps => neps}/api.py | 228 ++--- neps/metahyper/__init__.py | 2 + {src => neps}/metahyper/_locker.py | 0 {src => neps}/metahyper/api.py | 39 +- {src => neps}/metahyper/example.py | 0 {src => neps}/metahyper/utils.py | 20 +- {src/neps => neps}/optimizers/__init__.py | 0 .../optimizers/base_optimizer.py | 8 +- .../acquisition_functions/__init__.py | 117 +++ .../acquisition_functions/_ehvi.py | 0 .../acquisition_functions/base_acquisition.py | 0 .../acquisition_functions/cost_cooling.py | 0 .../acquisition_functions/ei.py | 0 .../acquisition_functions/mf_ei.py | 430 +++++++++ .../acquisition_functions/mf_pi.py | 447 ++++++++++ .../acquisition_functions/mf_two_step.py | 238 +++++ .../acquisition_functions/mf_ucb.py | 230 +++++ .../acquisition_functions/prior_weighted.py | 0 .../acquisition_functions/ucb.py | 36 +- .../acquisition_samplers/__init__.py | 0 .../acquisition_samplers/base_acq_sampler.py | 0 .../acquisition_samplers/evolution_sampler.py | 0 .../freeze_thaw_sampler.py | 84 +- .../acquisition_samplers/mutation_sampler.py | 0 .../acquisition_samplers/random_sampler.py | 0 .../bayesian_optimization/cost_cooling.py | 3 +- .../bayesian_optimization/kernels/__init__.py | 0 .../kernels/combine_kernels.py | 1 - .../kernels/combine_kernels_hierarchy.py | 0 .../bayesian_optimization/kernels/encoding.py | 0 .../kernels/get_kernels.py | 3 +- .../kernels/grakel_replace/edge_histogram.py | 0 .../kernels/grakel_replace/utils.py | 0 .../grakel_replace/vertex_histogram.py | 0 .../grakel_replace/weisfeiler_lehman.py | 0 .../kernels/graph_kernel.py | 0 .../bayesian_optimization/kernels/utils.py | 0 .../kernels/vectorial_kernels.py | 0 .../kernels/weisfilerlehman.py | 0 .../bayesian_optimization/mf_tpe.py | 3 +- .../bayesian_optimization/models/DPL.py | 834 ++++++++++++++++++ .../bayesian_optimization/models/__init__.py | 22 + .../bayesian_optimization/models/deepGP.py | 94 +- .../bayesian_optimization/models/gp.py | 0 .../models/gp_hierarchy.py | 0 .../bayesian_optimization/optimizer.py | 3 +- .../optimizers/default_searchers/asha.yaml | 0 .../default_searchers/asha_prior.yaml | 0 .../bayesian_optimization.yaml | 0 .../default_searchers/hyperband.yaml | 0 .../optimizers/default_searchers/mobster.yaml | 0 .../optimizers/default_searchers/pibo.yaml | 0 .../default_searchers/priorband.yaml | 0 .../default_searchers/priorband_bo.yaml | 0 .../default_searchers/random_search.yaml | 0 .../regularized_evolution.yaml | 0 .../default_searchers/successive_halving.yaml | 0 .../successive_halving_prior.yaml | 0 .../optimizers/grid_search/optimizer.py | 3 +- {src/neps => neps}/optimizers/info.py | 0 .../optimizers/multi_fidelity/_dyhpo.py | 3 +- .../optimizers/multi_fidelity/dyhpo.py | 94 +- .../optimizers/multi_fidelity/hyperband.py | 3 +- .../optimizers/multi_fidelity/mf_bo.py | 42 +- .../multi_fidelity/promotion_policy.py | 0 .../multi_fidelity/sampling_policy.py | 3 +- .../multi_fidelity/successive_halving.py | 3 +- .../optimizers/multi_fidelity/utils.py | 63 +- .../multi_fidelity_prior/__init__.py | 0 .../multi_fidelity_prior/async_priorband.py | 3 +- .../multi_fidelity_prior/priorband.py | 0 .../optimizers/multi_fidelity_prior/utils.py | 0 .../prototype_optimizer.py | 3 +- .../optimizers/random_search/optimizer.py | 3 +- .../regularized_evolution/optimizer.py | 0 neps/optimizers/utils.py | 30 + {src/neps => neps}/plot/__init__.py | 0 {src/neps => neps}/plot/__main__.py | 0 {src/neps => neps}/plot/plot.py | 0 {src/neps => neps}/plot/plotting.py | 0 {src/neps => neps}/plot/read_results.py | 0 {src/neps => neps}/plot/tensorboard_eval.py | 19 +- neps/py.typed | 0 {src/neps => neps}/search_spaces/__init__.py | 0 .../search_spaces/architecture/api.py | 0 .../search_spaces/architecture/cfg.py | 0 .../cfg_variants/cfg_resolution.py | 0 .../cfg_variants/constrained_cfg.py | 0 .../architecture/core_graph_grammar.py | 0 .../search_spaces/architecture/crossover.py | 0 .../search_spaces/architecture/graph.py | 2 +- .../architecture/graph_grammar.py | 0 .../search_spaces/architecture/mutations.py | 0 .../search_spaces/architecture/primitives.py | 0 .../search_spaces/architecture/topologies.py | 0 .../hyperparameters/categorical.py | 5 +- .../search_spaces/hyperparameters/constant.py | 0 .../search_spaces/hyperparameters/float.py | 3 +- .../search_spaces/hyperparameters/integer.py | 0 .../hyperparameters/numerical.py | 0 {src/neps => neps}/search_spaces/parameter.py | 0 .../search_spaces/search_space.py | 172 +++- neps/search_spaces/yaml_search_space_utils.py | 462 ++++++++++ {src/neps => neps}/status/__main__.py | 0 {src/neps => neps}/status/status.py | 32 +- {src/neps => neps}/utils/common.py | 73 +- {src/neps => neps}/utils/data_loading.py | 9 +- {src/neps => neps}/utils/result_utils.py | 0 neps_examples/README.md | 10 +- .../hpo_usage_example.py | 37 + .../search_space_example.yaml | 26 + .../convenience/neps_tblogger_tutorial.py | 2 +- neps_examples/efficiency/multi_fidelity.py | 5 + ...erarchical_architecture_hierarchical_GP.py | 1 + pyproject.toml | 62 +- src/metahyper/__init__.py | 2 - .../acquisition_functions/__init__.py | 43 - .../acquisition_functions/mf_ei.py | 205 ----- .../bayesian_optimization/models/__init__.py | 16 - src/neps/optimizers/utils.py | 47 - tests/test_metahyper/test_locking.py | 4 +- .../solution_yamls/bo_custom_created.yaml | 5 + .../solution_yamls/bo_neps_decided.yaml | 13 + .../solution_yamls/bo_user_decided.yaml | 29 + .../hyperband_custom_created.yaml | 5 + .../hyperband_neps_decided.yaml | 11 + .../solution_yamls/pibo_neps_decided.yaml | 14 + .../priorband_bo_user_decided.yaml | 23 + .../priorband_neps_decided.yaml | 17 + .../solution_yamls/user_yaml_bo.yaml | 14 + tests/test_neps_api/test_api.py | 130 +++ tests/test_neps_api/test_yaml_api.py | 98 -- .../testing_scripts/baseoptimizer_neps.py | 51 ++ .../default_neps.py} | 55 +- .../testing_scripts/user_yaml_neps.py | 31 + .../testing_yaml/optimizer_test.yaml | 12 + .../config_including_unknown_types.yaml | 20 + .../config_including_wrong_types.yaml | 20 + .../correct_config.yaml | 32 + .../correct_config_including_priors.yml | 22 + .../correct_config_including_types.yaml | 37 + .../inconsistent_types_config.yml | 17 + .../inconsistent_types_config2.yml | 18 + .../incorrect_config.txt | 5 + .../missing_key_config.yml | 15 + .../not_allowed_key_config.yml | 26 + .../test_search_space.py | 159 ++++ 169 files changed, 5423 insertions(+), 854 deletions(-) create mode 100644 docs/citations.md create mode 100644 docs/doc_images/tensorboard/tblogger_hparam1.jpg create mode 100644 docs/doc_images/tensorboard/tblogger_hparam2.jpg create mode 100644 docs/doc_images/tensorboard/tblogger_hparam3.jpg create mode 100644 docs/doc_images/tensorboard/tblogger_image.jpg create mode 100644 docs/doc_images/tensorboard/tblogger_scalar.jpg create mode 100644 docs/installation.md rename src/neps/optimizers/README.md => docs/optimizers.md (81%) rename {src/neps => neps}/NOTICE (100%) rename {src/neps => neps}/__init__.py (100%) rename {src/neps => neps}/api.py (76%) create mode 100644 neps/metahyper/__init__.py rename {src => neps}/metahyper/_locker.py (100%) rename {src => neps}/metahyper/api.py (96%) rename {src => neps}/metahyper/example.py (100%) rename {src => neps}/metahyper/utils.py (88%) rename {src/neps => neps}/optimizers/__init__.py (100%) rename {src/neps => neps}/optimizers/base_optimizer.py (95%) create mode 100644 neps/optimizers/bayesian_optimization/acquisition_functions/__init__.py rename {src/neps => neps}/optimizers/bayesian_optimization/acquisition_functions/_ehvi.py (100%) rename {src/neps => neps}/optimizers/bayesian_optimization/acquisition_functions/base_acquisition.py (100%) rename {src/neps => neps}/optimizers/bayesian_optimization/acquisition_functions/cost_cooling.py (100%) rename {src/neps => neps}/optimizers/bayesian_optimization/acquisition_functions/ei.py (100%) create mode 100644 neps/optimizers/bayesian_optimization/acquisition_functions/mf_ei.py create mode 100644 neps/optimizers/bayesian_optimization/acquisition_functions/mf_pi.py create mode 100644 neps/optimizers/bayesian_optimization/acquisition_functions/mf_two_step.py create mode 100644 neps/optimizers/bayesian_optimization/acquisition_functions/mf_ucb.py rename {src/neps => neps}/optimizers/bayesian_optimization/acquisition_functions/prior_weighted.py (100%) rename {src/neps => neps}/optimizers/bayesian_optimization/acquisition_functions/ucb.py (72%) rename {src/neps => neps}/optimizers/bayesian_optimization/acquisition_samplers/__init__.py (100%) rename {src/neps => neps}/optimizers/bayesian_optimization/acquisition_samplers/base_acq_sampler.py (100%) rename {src/neps => neps}/optimizers/bayesian_optimization/acquisition_samplers/evolution_sampler.py (100%) rename {src/neps => neps}/optimizers/bayesian_optimization/acquisition_samplers/freeze_thaw_sampler.py (71%) rename {src/neps => neps}/optimizers/bayesian_optimization/acquisition_samplers/mutation_sampler.py (100%) rename {src/neps => neps}/optimizers/bayesian_optimization/acquisition_samplers/random_sampler.py (100%) rename {src/neps => neps}/optimizers/bayesian_optimization/cost_cooling.py (99%) rename {src/neps => neps}/optimizers/bayesian_optimization/kernels/__init__.py (100%) rename {src/neps => neps}/optimizers/bayesian_optimization/kernels/combine_kernels.py (99%) rename {src/neps => neps}/optimizers/bayesian_optimization/kernels/combine_kernels_hierarchy.py (100%) rename {src/neps => neps}/optimizers/bayesian_optimization/kernels/encoding.py (100%) rename {src/neps => neps}/optimizers/bayesian_optimization/kernels/get_kernels.py (97%) rename {src/neps => neps}/optimizers/bayesian_optimization/kernels/grakel_replace/edge_histogram.py (100%) rename {src/neps => neps}/optimizers/bayesian_optimization/kernels/grakel_replace/utils.py (100%) rename {src/neps => neps}/optimizers/bayesian_optimization/kernels/grakel_replace/vertex_histogram.py (100%) rename {src/neps => neps}/optimizers/bayesian_optimization/kernels/grakel_replace/weisfeiler_lehman.py (100%) rename {src/neps => neps}/optimizers/bayesian_optimization/kernels/graph_kernel.py (100%) rename {src/neps => neps}/optimizers/bayesian_optimization/kernels/utils.py (100%) rename {src/neps => neps}/optimizers/bayesian_optimization/kernels/vectorial_kernels.py (100%) rename {src/neps => neps}/optimizers/bayesian_optimization/kernels/weisfilerlehman.py (100%) rename {src/neps => neps}/optimizers/bayesian_optimization/mf_tpe.py (99%) create mode 100644 neps/optimizers/bayesian_optimization/models/DPL.py create mode 100755 neps/optimizers/bayesian_optimization/models/__init__.py rename {src/neps => neps}/optimizers/bayesian_optimization/models/deepGP.py (88%) rename {src/neps => neps}/optimizers/bayesian_optimization/models/gp.py (100%) rename {src/neps => neps}/optimizers/bayesian_optimization/models/gp_hierarchy.py (100%) rename {src/neps => neps}/optimizers/bayesian_optimization/optimizer.py (99%) rename {src/neps => neps}/optimizers/default_searchers/asha.yaml (100%) rename {src/neps => neps}/optimizers/default_searchers/asha_prior.yaml (100%) rename {src/neps => neps}/optimizers/default_searchers/bayesian_optimization.yaml (100%) rename {src/neps => neps}/optimizers/default_searchers/hyperband.yaml (100%) rename {src/neps => neps}/optimizers/default_searchers/mobster.yaml (100%) rename {src/neps => neps}/optimizers/default_searchers/pibo.yaml (100%) rename {src/neps => neps}/optimizers/default_searchers/priorband.yaml (100%) rename {src/neps => neps}/optimizers/default_searchers/priorband_bo.yaml (100%) rename {src/neps => neps}/optimizers/default_searchers/random_search.yaml (100%) rename {src/neps => neps}/optimizers/default_searchers/regularized_evolution.yaml (100%) rename {src/neps => neps}/optimizers/default_searchers/successive_halving.yaml (100%) rename {src/neps => neps}/optimizers/default_searchers/successive_halving_prior.yaml (100%) rename {src/neps => neps}/optimizers/grid_search/optimizer.py (96%) rename {src/neps => neps}/optimizers/info.py (100%) rename {src/neps => neps}/optimizers/multi_fidelity/_dyhpo.py (99%) rename {src/neps => neps}/optimizers/multi_fidelity/dyhpo.py (83%) rename {src/neps => neps}/optimizers/multi_fidelity/hyperband.py (99%) rename {src/neps => neps}/optimizers/multi_fidelity/mf_bo.py (90%) rename {src/neps => neps}/optimizers/multi_fidelity/promotion_policy.py (100%) rename {src/neps => neps}/optimizers/multi_fidelity/sampling_policy.py (99%) rename {src/neps => neps}/optimizers/multi_fidelity/successive_halving.py (99%) rename {src/neps => neps}/optimizers/multi_fidelity/utils.py (81%) rename {src/neps => neps}/optimizers/multi_fidelity_prior/__init__.py (100%) rename {src/neps => neps}/optimizers/multi_fidelity_prior/async_priorband.py (99%) rename {src/neps => neps}/optimizers/multi_fidelity_prior/priorband.py (100%) rename {src/neps => neps}/optimizers/multi_fidelity_prior/utils.py (100%) rename {src/neps => neps}/optimizers/multiple_knowledge_sources/prototype_optimizer.py (98%) rename {src/neps => neps}/optimizers/random_search/optimizer.py (96%) rename {src/neps => neps}/optimizers/regularized_evolution/optimizer.py (100%) create mode 100644 neps/optimizers/utils.py rename {src/neps => neps}/plot/__init__.py (100%) rename {src/neps => neps}/plot/__main__.py (100%) rename {src/neps => neps}/plot/plot.py (100%) rename {src/neps => neps}/plot/plotting.py (100%) rename {src/neps => neps}/plot/read_results.py (100%) rename {src/neps => neps}/plot/tensorboard_eval.py (96%) create mode 100644 neps/py.typed rename {src/neps => neps}/search_spaces/__init__.py (100%) rename {src/neps => neps}/search_spaces/architecture/api.py (100%) rename {src/neps => neps}/search_spaces/architecture/cfg.py (100%) rename {src/neps => neps}/search_spaces/architecture/cfg_variants/cfg_resolution.py (100%) rename {src/neps => neps}/search_spaces/architecture/cfg_variants/constrained_cfg.py (100%) rename {src/neps => neps}/search_spaces/architecture/core_graph_grammar.py (100%) rename {src/neps => neps}/search_spaces/architecture/crossover.py (100%) rename {src/neps => neps}/search_spaces/architecture/graph.py (99%) rename {src/neps => neps}/search_spaces/architecture/graph_grammar.py (100%) rename {src/neps => neps}/search_spaces/architecture/mutations.py (100%) rename {src/neps => neps}/search_spaces/architecture/primitives.py (100%) rename {src/neps => neps}/search_spaces/architecture/topologies.py (100%) rename {src/neps => neps}/search_spaces/hyperparameters/categorical.py (98%) rename {src/neps => neps}/search_spaces/hyperparameters/constant.py (100%) rename {src/neps => neps}/search_spaces/hyperparameters/float.py (99%) rename {src/neps => neps}/search_spaces/hyperparameters/integer.py (100%) rename {src/neps => neps}/search_spaces/hyperparameters/numerical.py (100%) rename {src/neps => neps}/search_spaces/parameter.py (100%) rename {src/neps => neps}/search_spaces/search_space.py (71%) create mode 100644 neps/search_spaces/yaml_search_space_utils.py rename {src/neps => neps}/status/__main__.py (100%) rename {src/neps => neps}/status/status.py (93%) rename {src/neps => neps}/utils/common.py (82%) rename {src/neps => neps}/utils/data_loading.py (97%) rename {src/neps => neps}/utils/result_utils.py (100%) create mode 100644 neps_examples/basic_usage/defining_search_space/hpo_usage_example.py create mode 100644 neps_examples/basic_usage/defining_search_space/search_space_example.yaml delete mode 100644 src/metahyper/__init__.py delete mode 100644 src/neps/optimizers/bayesian_optimization/acquisition_functions/__init__.py delete mode 100644 src/neps/optimizers/bayesian_optimization/acquisition_functions/mf_ei.py delete mode 100755 src/neps/optimizers/bayesian_optimization/models/__init__.py delete mode 100644 src/neps/optimizers/utils.py create mode 100644 tests/test_neps_api/solution_yamls/bo_custom_created.yaml create mode 100644 tests/test_neps_api/solution_yamls/bo_neps_decided.yaml create mode 100644 tests/test_neps_api/solution_yamls/bo_user_decided.yaml create mode 100644 tests/test_neps_api/solution_yamls/hyperband_custom_created.yaml create mode 100644 tests/test_neps_api/solution_yamls/hyperband_neps_decided.yaml create mode 100644 tests/test_neps_api/solution_yamls/pibo_neps_decided.yaml create mode 100644 tests/test_neps_api/solution_yamls/priorband_bo_user_decided.yaml create mode 100644 tests/test_neps_api/solution_yamls/priorband_neps_decided.yaml create mode 100644 tests/test_neps_api/solution_yamls/user_yaml_bo.yaml create mode 100644 tests/test_neps_api/test_api.py delete mode 100644 tests/test_neps_api/test_yaml_api.py create mode 100644 tests/test_neps_api/testing_scripts/baseoptimizer_neps.py rename tests/test_neps_api/{examples_test_api.py => testing_scripts/default_neps.py} (67%) create mode 100644 tests/test_neps_api/testing_scripts/user_yaml_neps.py create mode 100644 tests/test_neps_api/testing_yaml/optimizer_test.yaml create mode 100644 tests/test_yaml_search_space/config_including_unknown_types.yaml create mode 100644 tests/test_yaml_search_space/config_including_wrong_types.yaml create mode 100644 tests/test_yaml_search_space/correct_config.yaml create mode 100644 tests/test_yaml_search_space/correct_config_including_priors.yml create mode 100644 tests/test_yaml_search_space/correct_config_including_types.yaml create mode 100644 tests/test_yaml_search_space/inconsistent_types_config.yml create mode 100644 tests/test_yaml_search_space/inconsistent_types_config2.yml create mode 100644 tests/test_yaml_search_space/incorrect_config.txt create mode 100644 tests/test_yaml_search_space/missing_key_config.yml create mode 100644 tests/test_yaml_search_space/not_allowed_key_config.yml create mode 100644 tests/test_yaml_search_space/test_search_space.py diff --git a/.github/workflows/tests.yaml b/.github/workflows/tests.yaml index 95617323..54b648f5 100644 --- a/.github/workflows/tests.yaml +++ b/.github/workflows/tests.yaml @@ -21,9 +21,9 @@ jobs: runs-on: ${{ matrix.os }} steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - - uses: actions/setup-python@v4 + - uses: actions/setup-python@v5 with: python-version: ${{ matrix.python-version }} @@ -41,4 +41,5 @@ jobs: - name: Run pytest timeout-minutes: 15 - run: poetry run pytest -m "all_examples or metahyper or summary_csv" + run: poetry run pytest -m "all_examples or metahyper or neps_api or summary_csv" + diff --git a/CITATION.cff b/CITATION.cff index 8dea2157..fde949e5 100644 --- a/CITATION.cff +++ b/CITATION.cff @@ -13,10 +13,12 @@ authors: given-names: Samir - family-names: Abou Chakra given-names: Tarek - - family-names: Hvarfner - given-names: Carl + - family-names: Rogalla + given-names: Daniel - family-names: Bergman given-names: Eddie + - family-names: Hvarfner + given-names: Carl - family-names: Binxin given-names: Ru - family-names: Kober @@ -26,6 +28,6 @@ authors: - family-names: Hutter given-names: Frank title: "Neural Pipeline Search (NePS)" -version: 0.10.0 +version: 0.11.1 date-released: 2023-10-25 url: "https://github.com/automl/neps" diff --git a/README.md b/README.md index 43687ca4..a83ac11d 100644 --- a/README.md +++ b/README.md @@ -5,23 +5,33 @@ [![License](https://img.shields.io/pypi/l/neural-pipeline-search?color=informational)](LICENSE) [![Tests](https://github.com/automl/neps/actions/workflows/tests.yaml/badge.svg)](https://github.com/automl/neps/actions) -NePS helps deep learning experts to optimize the hyperparameters and/or architecture of their deep learning pipeline with: +Welcome to NePS, a powerful and flexible Python library for hyperparameter optimization (HPO) and neural architecture search (NAS) with its primary goal: enable HPO adoption in practice for deep learners! -- Hyperparameter Optimization (HPO) ([example](neps_examples/basic_usage/hyperparameters.py)) -- Neural Architecture Search (NAS) ([example](neps_examples/basic_usage/architecture.py), [paper](https://openreview.net/forum?id=Ok58hMNXIQ)) -- Joint Architecture and Hyperparameter Search (JAHS) ([example](neps_examples/basic_usage/architecture_and_hyperparameters.py), [paper](https://openreview.net/forum?id=_HLcjaVlqJ)) +NePS houses recently published and some more well-established algorithms that are all capable of being run massively parallel on any distributed setup, with tools to analyze runs, restart runs, etc. -For efficiency and convenience NePS allows you to +Take a look at our [documentation](https://automl.github.io/neps/latest/) and continue following through current README for instructions on how to use NePS! -- Add your intuition as priors for the search ([example HPO](neps_examples/efficiency/expert_priors_for_hyperparameters.py), [example JAHS](neps_examples/experimental/expert_priors_for_architecture_and_hyperparameters.py), [paper](https://openreview.net/forum?id=MMAeCXIa89)) -- Utilize low fidelity (e.g., low epoch) evaluations to focus on promising configurations ([example](neps_examples/efficiency/multi_fidelity.py), [paper](https://openreview.net/forum?id=ds21dwfBBH)) -- Trivially parallelize across machines ([example](neps_examples/efficiency/parallelization.md), [documentation](https://automl.github.io/neps/latest/parallelization/)) -Or [all of the above](neps_examples/efficiency/multi_fidelity_and_expert_priors.py) for maximum efficiency! +## Key Features -### Note +In addition to the common features offered by traditional HPO and NAS libraries, NePS stands out with the following key features: -As indicated with the `v0.x.x` version number, NePS is early stage code and APIs might change in the future. +1. [**Hyperparameter Optimization (HPO) With Prior Knowledge:**](neps_examples/template/priorband_template.py) + - NePS excels in efficiently tuning hyperparameters using algorithms that enable users to make use of their prior knowledge within the search space. This is leveraged by the insights presented in: + - [PriorBand: Practical Hyperparameter Optimization in the Age of Deep Learning](https://arxiv.org/abs/2306.12370) + - [πBO: Augmenting Acquisition Functions with User Beliefs for Bayesian Optimization](https://arxiv.org/abs/2204.11051) + +2. [**Neural Architecture Search (NAS) With Context-free Grammar Search Spaces:**](neps_examples/basic_usage/architecture.py) + - NePS is equipped to handle context-free grammar search spaces, providing advanced capabilities for designing and optimizing architectures. this is leveraged by the insights presented in: + - [Construction of Hierarchical Neural Architecture Search Spaces based on Context-free Grammars](https://arxiv.org/abs/2211.01842) + +3. [**Easy Parallelization and Resumption of Runs:**](docs/parallelization.md) + - NePS simplifies the process of parallelizing optimization tasks both on individual computers and in distributed + computing environments. It also allows users to conveniently resume these optimization tasks after completion to + ensure a seamless and efficient workflow for long-running experiments. + +4. [**Seamless User Code Integration:**](neps_examples/template/) + - NePS's modular design ensures flexibility and extensibility. Integrate NePS effortlessly into existing machine learning workflows. ## Getting Started @@ -33,13 +43,16 @@ Using pip: pip install neural-pipeline-search ``` +> Note: As indicated with the `v0.x.x` version number, NePS is early stage code and APIs might change in the future. + ### 2. Basic Usage Using `neps` always follows the same pattern: - 1. Define a `run_pipeline` function that evaluates architectures/hyperparameters for your problem - 1. Define a search space `pipeline_space` of architectures/hyperparameters - 1. Call `neps.run` to optimize `run_pipeline` over `pipeline_space` +1. Define a `run_pipeline` function capable of evaluating different architectural and/or hyperparameter configurations + for your problem. +2. Define a search space named `pipeline_space` of those Parameters e.g. via a dictionary +3. Call `neps.run` to optimize `run_pipeline` over `pipeline_space` In code, the usage pattern can look like this: @@ -47,53 +60,88 @@ In code, the usage pattern can look like this: import neps import logging -# 1. Define a function that accepts hyperparameters and returns the validation error -def run_pipeline(hyperparameter_a: float, hyperparameter_b: int, architecture_parameter: str): - # create your model + +# 1. Define a function that accepts hyperparameters and computes the validation error +def run_pipeline( + hyperparameter_a: float, hyperparameter_b: int, architecture_parameter: str +) -> dict: + # Create your model model = MyModel(architecture_parameter) - # train and evaluate the model with your training pipeline - validation_error = train_and_eval_model(model, hyperparameter_a, hyperparameter_b) - return validation_error + # Train and evaluate the model with your training pipeline + validation_error, training_error = train_and_eval( + model, hyperparameter_a, hyperparameter_b + ) + + return { # dict or float(validation error) + "loss": validation_error, + "info_dict": { + "training_error": training_error + # + Other metrics + }, + } -# 2. Define a search space of hyperparameters; use the same names as in run_pipeline + +# 2. Define a search space of parameters; use the same names for the parameters as in run_pipeline pipeline_space = dict( hyperparameter_b=neps.IntegerParameter( - lower=1, - upper=100, - is_fidelity=True), # Mark 'is_fidelity' as true for a multi-fidelity approach. + lower=1, upper=42, is_fidelity=True + ), # Mark 'is_fidelity' as true for a multi-fidelity approach. hyperparameter_a=neps.FloatParameter( - lower=0.0, - upper=1.0, - log=True), # If True, the search space is sampled in log space. - architecture_parameter=neps.CategoricalParameter(["option_a", "option_b", "option_c"]), + lower=0.001, upper=0.1, log=True + ), # If True, the search space is sampled in log space. + architecture_parameter=neps.CategoricalParameter( + ["option_a", "option_b", "option_c"] + ), ) -if __name__=="__main__": +if __name__ == "__main__": # 3. Run the NePS optimization logging.basicConfig(level=logging.INFO) neps.run( run_pipeline=run_pipeline, pipeline_space=pipeline_space, - root_directory="path/to/save/results", # Replace with the actual path. + root_directory="path/to/save/results", # Replace with the actual path. max_evaluations_total=100, - searcher="hyperband" # Optional specifies the search strategy, + searcher="hyperband" # Optional specifies the search strategy, # otherwise NePs decides based on your data. ) ``` +## Examples + +Discover how NePS works through these practical examples: +* **[Pipeline Space via YAML](neps_examples/basic_usage/defining_search_space)**: Explore how to define the `pipeline_space` using a + YAML file instead of a dictionary. + +* **[Hyperparameter Optimization (HPO)](neps_examples/basic_usage/hyperparameters.py)**: Learn the essentials of hyperparameter optimization with NePS. + +* **[Architecture Search with Primitives](neps_examples/basic_usage/architecture.py)**: Dive into architecture search using primitives in NePS. + +* **[Multi-Fidelity Optimization](neps_examples/efficiency/multi_fidelity.py)**: Understand how to leverage multi-fidelity optimization for efficient model tuning. + +* **[Utilizing Expert Priors for Hyperparameters](neps_examples/efficiency/expert_priors_for_hyperparameters.py)**: Learn how to incorporate expert priors for more efficient hyperparameter selection. + +* **[Additional NePS Examples](neps_examples/)**: Explore more examples, including various use cases and advanced configurations in NePS. + ## Documentation -For more details and features please have a look at our [documentation](https://automl.github.io/neps/latest/) and [examples](neps_examples) +For more details and features please have a look at our [documentation](https://automl.github.io/neps/latest/) ## Analysing runs See our [documentation on analysing runs](https://automl.github.io/neps/latest/analyse). -## Alternatives - -NePS does not cover your use-case? Have a look at [some alternatives](https://automl.github.io/neps/latest/alternatives). - ## Contributing Please see the [documentation for contributors](https://automl.github.io/neps/latest/contributing/). + +## Citations + +Please consider citing us if you use our tool! + +Refer to our [documentation on citations](https://automl.github.io/neps/latest/citations/). + +## Alternatives + +NePS does not cover your use-case? Have a look at [some alternatives](https://automl.github.io/neps/latest/alternatives). diff --git a/docs/README.md b/docs/README.md index b58e43d6..28f2f0dd 100644 --- a/docs/README.md +++ b/docs/README.md @@ -1,9 +1,32 @@ -# Introduction and Installation +# Neural Pipeline Search (NePS) -## Installation +[![PyPI version](https://img.shields.io/pypi/v/neural-pipeline-search?color=informational)](https://pypi.org/project/neural-pipeline-search/) +[![Python versions](https://img.shields.io/pypi/pyversions/neural-pipeline-search)](https://pypi.org/project/neural-pipeline-search/) +[![License](https://img.shields.io/pypi/l/neural-pipeline-search?color=informational)](LICENSE) +[![Tests](https://github.com/automl/neps/actions/workflows/tests.yaml/badge.svg)](https://github.com/automl/neps/actions) -Using pip +Welcome to NePS, a powerful and flexible Python library for hyperparameter optimization (HPO) and neural architecture search (NAS) with its primary goal: enable HPO adoption in practice for deep learners! -```bash -pip install neural-pipeline-search -``` +NePS houses recently published and some more well-established algorithms that are all capable of being run massively parallel on any distributed setup, with tools to analyze runs, restart runs, etc. + + +## Key Features + +In addition to the common features offered by traditional HPO and NAS libraries, NePS stands out with the following key features: + +1. [**Hyperparameter Optimization (HPO) With Prior Knowledge:**](https://github.com/automl/neps/tree/master/neps_examples/template/priorband_template.py) + - NePS excels in efficiently tuning hyperparameters using algorithms that enable users to make use of their prior knowledge within the search space. This is leveraged by the insights presented in: + - [PriorBand: Practical Hyperparameter Optimization in the Age of Deep Learning](https://arxiv.org/abs/2306.12370) + - [πBO: Augmenting Acquisition Functions with User Beliefs for Bayesian Optimization](https://arxiv.org/abs/2204.11051) + +2. [**Neural Architecture Search (NAS) With Context-free Grammar Search Spaces:**](https://github.com/automl/neps/tree/master/neps_examples/basic_usage/architecture.py) + - NePS is equipped to handle context-free grammar search spaces, providing advanced capabilities for designing and optimizing architectures. this is leveraged by the insights presented in: + - [Construction of Hierarchical Neural Architecture Search Spaces based on Context-free Grammars](https://arxiv.org/abs/2211.01842) + +3. [**Easy Parallelization and Resumption of Runs:**](https://automl.github.io/neps/latest/parallelization) + - NePS simplifies the process of parallelizing optimization tasks both on individual computers and in distributed + computing environments. It also allows users to conveniently resume these optimization tasks after completion to + ensure a seamless and efficient workflow for long-running experiments. + +4. [**Seamless User Code Integration:**](https://github.com/automl/neps/tree/master/neps_examples/template/) + - NePS's modular design ensures flexibility and extensibility. Integrate NePS effortlessly into existing machine learning workflows. diff --git a/docs/analyse.md b/docs/analyse.md index 40d4af7c..cd78a14d 100644 --- a/docs/analyse.md +++ b/docs/analyse.md @@ -17,6 +17,154 @@ ROOT_DIRECTORY ├── best_loss_trajectory.txt └── best_loss_with_config_trajectory.txt ``` +## Summary CSV + +The argument `post_run_summary` in `neps.run` allows for the automatic generation of CSV files after a run is complete. The new root directory after utilizing this argument will look like the following: + +``` +ROOT_DIRECTORY +├── results +│ └── config_1 +│ ├── config.yaml +│ ├── metadata.yaml +│ └── result.yaml +├── summary_csv +│ ├── config_data.csv +│ └── run_status.csv +├── all_losses_and_configs.txt +├── best_loss_trajectory.txt +└── best_loss_with_config_trajectory.txt +``` + +- *`config_data.csv`*: Contains all configuration details in CSV format, ordered by ascending `loss`. Details include configuration hyperparameters, any returned result from the `run_pipeline` function, and metadata information. + +- *`run_status.csv`*: Provides general run details, such as the number of sampled configs, best configs, number of failed configs, best loss, etc. + +## TensorBoard Integration + +### Introduction + +[TensorBoard](https://www.tensorflow.org/tensorboard) serves as a valuable tool for visualizing machine learning experiments, offering the ability to observe losses and metrics throughout the model training process. In NePS, we use this powerful tool to show metrics of configurations during training in addition to comparisons to different hyperparameters used in the search for better diagnosis of the model. + +### The Logging Function + +The `tblogger.log` function is invoked within the model's training loop to facilitate logging of key metrics. + +!!! tip + + The logger function is primarily designed for implementation within the `run_pipeline` function during the training of the neural network. + +- **Signature:** +```python +tblogger.log( + loss: float, + current_epoch: int, + write_config_scalar: bool = False, + write_config_hparam: bool = True, + write_summary_incumbent: bool = False, + extra_data: dict | None = None +) +``` + +- **Parameters:** + - `loss` (float): The loss value to be logged. + - `current_epoch` (int): The current epoch or iteration number. + - `write_config_scalar` (bool, optional): Set to `True` for a live loss trajectory for each configuration. + - `write_config_hparam` (bool, optional): Set to `True` for live parallel coordinate, scatter plot matrix, and table view. + - `write_summary_incumbent` (bool, optional): Set to `True` for a live incumbent trajectory. + - `extra_data` (dict, optional): Additional data to be logged, provided as a dictionary. + +### Extra Custom Logging + +NePS provides dedicated functions for customized logging using the `extra_data` argument. + +!!! note "Custom Logging Instructions" + + Name the dictionary keys as the names of the values you want to log and pass one of the following functions as the values for a successful logging process. + +#### 1- Extra Scalar Logging + +Logs new scalar data during training. Uses `current_epoch` from the log function as its `global_step`. + +- **Signature:** +```python +tblogger.scalar_logging(value: float) +``` +- **Parameters:** + - `value` (float): Any scalar value to be logged at the current epoch of `tblogger.log` function. + +#### 2- Extra Image Logging + +Logs images during training. Images can be resized, randomly selected, and a specified number can be logged at specified intervals. Uses `current_epoch` from the log function as its `global_step`. + +- **Signature:** +```python +tblogger.image_logging( + image: torch.Tensor, + counter: int = 1, + resize_images: list[None | int] | None = None, + random_images: bool = True, + num_images: int = 20, + seed: int | np.random.RandomState | None = None, +) +``` + +- **Parameters:** + - `image` (torch.Tensor): Image tensor to be logged. + - `counter` (int): Log images every counter epochs (i.e., when current_epoch % counter equals 0). + - `resize_images` (list of int, optional): List of integers for image sizes after resizing (default: [32, 32]). + - `random_images` (bool, optional): Images are randomly selected if True (default: True). + - `num_images` (int, optional): Number of images to log (default: 20). + - `seed` (int or np.random.RandomState or None, optional): Seed value or RandomState instance to control randomness and reproducibility (default: None). + +### Logging Example + +For illustration purposes, we have employed a straightforward example involving the tuning of hyperparameters for a model utilized in the classification of the MNIST dataset provided by [torchvision](https://pytorch.org/vision/main/generated/torchvision.datasets.MNIST.html). + +You can find this example [here](https://github.com/automl/neps/blob/master/neps_examples/convenience/neps_tblogger_tutorial.py) + +!!! info "Important" + We have optimized the example for computational efficiency. If you wish to replicate the exact results showcased in the following section, we recommend the following modifications: + + 1- Increase maximum epochs from 2 to 10 + + 2- Set the `write_summary_incumbent` argument to `True` + + 3- Change the searcher from `random_search` to `bayesian_optimization` + + 4- Increase the maximum evaluations before disabling `tblogger` from 2 to 14 + + 5- Increase the maximum evaluations after disabling `tblogger` from 3 to 15 + +### Visualization Results + +The following command will open a local host for TensorBoard visualizations, allowing you to view them either in real-time or after the run is complete. + +```bash +tensorboard --logdir path/to/root_directory +``` + +This image shows visualizations related to scalar values logged during training. Scalars typically include metrics such as loss, incumbent trajectory, a summary of losses for all configurations, and any additional data provided via the `extra_data` argument in the `tblogger.log` function. + +![scalar_loggings](doc_images/tensorboard/tblogger_scalar.jpg) + +This image represents visualizations related to logged images during training. It could include snapshots of input data, model predictions, or any other image-related information. In our case, we use images to depict instances of incorrect predictions made by the model. + +![image_loggings](doc_images/tensorboard/tblogger_image.jpg) + +The following images showcase visualizations related to hyperparameter logging in TensorBoard. These plots include three different views, providing insights into the relationship between different hyperparameters and their impact on the model. + +In the table view, you can explore hyperparameter configurations across five different trials. The table displays various hyperparameter values alongside corresponding evaluation metrics. + +![hparam_loggings1](doc_images/tensorboard/tblogger_hparam1.jpg) + +The parallel coordinate plot offers a holistic perspective on hyperparameter configurations. By presenting multiple hyperparameters simultaneously, this view allows you to observe the interactions between variables, providing insights into their combined influence on the model. + +![hparam_loggings2](doc_images/tensorboard/tblogger_hparam2.jpg) + +The scatter plot matrix view provides an in-depth analysis of pairwise relationships between different hyperparameters. By visualizing correlations and patterns, this view aids in identifying key interactions that may influence the model's performance. + +![hparam_loggings3](doc_images/tensorboard/tblogger_hparam3.jpg) ## Status @@ -38,7 +186,7 @@ To show the status repeatedly, on unix systems you can use watch --interval 30 python -m neps.status ROOT_DIRECTORY ``` -## Visualizations +## CLI commands To generate plots to the root directory, run diff --git a/docs/citations.md b/docs/citations.md new file mode 100644 index 00000000..b697c49f --- /dev/null +++ b/docs/citations.md @@ -0,0 +1,54 @@ +# Citations + +## Citation of The Software + +For citing NePS, please refer to the following: + +### APA Style + +```apa +Stoll, D., Mallik, N., Schrodi, S., Janowski, M., Garibov, S., Abou Chakra, T., Rogalla, D., Bergman, E., Hvarfner, C., Binxin, R., Kober, N., Vallaeys, T., & Hutter, F. (2023). Neural Pipeline Search (NePS) (Version 0.11.0) [Computer software]. https://github.com/automl/neps +``` + +### BibTex Style + +```bibtex +@software{Stoll_Neural_Pipeline_Search_2023, +author = {Stoll, Danny and Mallik, Neeratyoy and Schrodi, Simon and Janowski, Maciej and Garibov, Samir and Abou Chakra, Tarek and Rogalla, Daniel and Bergman, Eddie and Hvarfner, Carl and Binxin, Ru and Kober, Nils and Vallaeys, Théophane and Hutter, Frank}, +month = oct, +title = {{Neural Pipeline Search (NePS)}}, +url = {https://github.com/automl/neps}, +version = {0.11.0}, +year = {2023} +} +``` + +## Citation of Papers + +### PriorBand + +If you have used [PriorBand](https://openreview.net/forum?id=uoiwugtpCH) as the optimizer, please use the bibtex below: + +```bibtex +@inproceedings{mallik2023priorband, +title = {PriorBand: Practical Hyperparameter Optimization in the Age of Deep Learning}, +author = {Neeratyoy Mallik and Eddie Bergman and Carl Hvarfner and Danny Stoll and Maciej Janowski and Marius Lindauer and Luigi Nardi and Frank Hutter}, +year = {2023}, +booktitle = {Thirty-seventh Conference on Neural Information Processing Systems (NeurIPS 2023)}, +keywords = {} +} +``` + +### Hierarchichal NAS with Context-free Grammars + +If you have used the context-free grammar search space and the graph kernels implemented in NePS for the paper [Hierarchical NAS](https://openreview.net/forum?id=Hpt1i5j6wh), please use the bibtex below: + +```bibtex +@inproceedings{schrodi2023hierarchical, +title = {Construction of Hierarchical Neural Architecture Search Spaces based on Context-free Grammars}, +author = {Simon Schrodi and Danny Stoll and Binxin Ru and Rhea Sanjay Sukthanker and Thomas Brox and Frank Hutter}, +year = {2023}, +booktitle = {Thirty-seventh Conference on Neural Information Processing Systems (NeurIPS 2023)}, +keywords = {} +} +``` diff --git a/docs/contributing/roadmap.md b/docs/contributing/roadmap.md index 85007640..a27c3d7d 100644 --- a/docs/contributing/roadmap.md +++ b/docs/contributing/roadmap.md @@ -1,43 +1,33 @@ # Roadmap -## Before 0.10.0 +## Before 0.12.0 ### Features -- Utility to get best HPs and architecture to pass to run_pipeline -- Plot in hours / days, but also show grid corresponding to 1x and 5x etc. - -### Fixes - -- Do not plot log y axis per default - -### Documentation - -- Fill up the core documentation pages - -## Before 0.11.0 - -### Features - -- Evolution as acq sampler +- Allow yaml based input of search space and the target function source to `neps.run` - Generate plot after each evaluation +- Support conditionals in ConfigSpace search space +- Support logging of optimizer state details ### Fixes - Open never closes (talk to Nils) - Deadlock in ASHA-like optimizers (talk to Neeratyoy) +- Extra metahyper sample in [issue 42](https://github.com/automl/neps/issues/42) +- Tighter type check in search space +- Unify MFObservedData class for both Hyperband-like fidelities and one-step fidelities ### Documentation -- Document summary function +- Improved documentation on all basic usage +- Improved README on github that links to the documentations +- Adequate examples targeting different user groups ### Refactoring - Merge GP and hierarchical GP - Merge gpytorch branch - Rethink summary/status API -- Utility to get incumbent losses over time -- Restructure folder structure - Improve placement of \_post_evaluation_hook_function - maintained vs unmaintained optimizers - Read and sample at the same time metahyper @@ -66,9 +56,9 @@ - Print search space upon run - Add comprehensive regression tests to run manually on the cluster on each version release - Utility to generate code for best architecture -- 3.11 support -- Deprecate 3.7 - Core Feature set in terms of research +- Modular plug-and-play of BoTorch acquisition functions +- Exploring gradient-based HPO in the NePS framework ### Fixes diff --git a/docs/doc_images/tensorboard/tblogger_hparam1.jpg b/docs/doc_images/tensorboard/tblogger_hparam1.jpg new file mode 100644 index 0000000000000000000000000000000000000000..19ea6f112b1ce23d1d6f8ea2434598190a960a49 GIT binary patch literal 207727 zcmdpeXIN9+(l$*x0-}Ia6#)@xDufP#B1J$!DI#4!>AeLAy+{-3(o{fHdap_7ND)MO z4OI{Vp@z_sZ*k6fo^#Io{`r1>*SD`r_cqykueD~)+%t2}#Hhzw59z4csELS(=+sp2 z>ktu9K#7P*dnw7mCwjAs7r}|lO-b!3B{=*jUq*s|Uv__B;I8Xr?e1mnYDHw@=;UA} z}qB1{@Tg$%G1{lRz#XkSHx~#QL(bPa$EHF-7BI} z(zkC*-xa^2{NU*=y6#LOqANsd_wPOR&P31n_+1(~C2WuNP4hyo6SpFGqDguXUny07 zE>Kh6v^9QJT;uV;uGqoY)~>qvgsjk`mim*P&>O#J?XeFYNLZB@5ffWc$xOJVrXQY) zb!!Skf&$4Rn{whG-c4WbORtC2ryghTN_B>@n5>^G^CCrJIW%}2-?Ph)OZ`;_4K$Z(_rvI4IVo&0q!*+9bw|mwlfdx@+zio?k;5v!r(jg@W%572 zOwc*{U~o3r*5q-JsH8O4Q(H;D0Xnd%ULMPrGU~vEpR$9Rb{m zVO<9_-gUq>V$RT#DwZRstO!>;MKzG=oaFmd_$Q1O5ocpjy~+sl+tAb~gNR&hu)jHI zh2bbiaFmxp?%I;H6it1rcCcTjrOuYE4TnCh{DpZQI`YkHq1AxZ2E+GB(1roObu|;7 z5wEp^hH5Wa$G(IOg#-U?^$=f@0iy3lxb z)@mT3RMslGu7sa=&0(+=x36xC?$_LM3RbJv6DJ{erY^AIz5KHJ$;WtW%;kA8(_wHA zDUXtzH^`~2o5v{xRnwvrIaT z<=xyY7yG?eOWu9t4vC|NLhv~VxU0W}?jq7dX3$F4 zu1TA10($*0IE`+KiNl*GC_D8XfuPkfakw$Knfz~|L~;Z&etXz+2>XnSWv8zzMjkBB z5}+}m5JxhZ=d)VRm49vGNO-E{2g4Fw+QP_=j5Q}WauNxT^{+*nwBQ{RYGDVA2F1Qi z_*G2ZJPFY>JmaHM;47yWft6lNh<@dkomB2#(XA{$Vn-L@!I7MHiZ2g-%STimH}3RH zmvg%tx9ehDYM)OT3PB$qa6{jvVBj5+)5hO)o{`?|ZS6TznSo5jZKGPIRfX{3LKE4W z=A{YmUtk+5-tMb@^`6O`VW%2+uLy*N{mdKab?V1iNogJ1VgEBldJM^lj1&J883ylg zLaC{RC490T63#>IUm^+{pyjDK%Ed{KmB&A=wSD3KXX>J6)34*J`NH_b0sj3R8_{2E z39c=sH{Roha;I9j%acCB+HI$hJ^LL_GeHv{I9u*G@tth*w2%6SBgbBm_`}{9Ri%FF zwruve=`e)H+o{hInDoGCv;?E&4ee8*{+bc0URoF>3?sNzEyKz4l%C(~&S1V1Q*ZV; z28DnNGV1fYx$j0Bc@HIJDx&&eR5oMeM8P4L<}tD8PpPFHLX*lpVXzk4LAmek#&I?E_i%OpDA5|%H|=q z#q@*nTi=oBy1@%?ObH%JIXpQE%I=3ys;T#MT36h=EfsfmM=A5(`TppwJ12AFXrT06 zoF$pg_5pkniaxno>f7>8pdE2~4WZe(|Lw|c*o8q}g526bi*I~Kq}9Nuxu{B}lmZl- ztkOio730W?IzRNL)GOMP=@bRMh&*MV4(8lm{%8*4@$Sdmc<+5F;X&zjPQlr5rnZUl zxbMMgNq#%3t?c-<8r_rMKSEbd1kJNXDk%OSjc65H2r{wb;XXuU1Gq~;_aK%M_7NG# ztnVjLNqsoM@q`fg%fH~at9UMuJ<<;=f-deYoc&Hchmjz$>3ZI$!nx%o9kIG|uvnot~V93*Dn|!F$4YR z7@L1&QK&%PJoZ@uAj>rx6D=I=jS901(F&+A|Ry*=5g@85M?Am=Mu9 zf^4D6vA)=9@wcQZ_-iU)2cb4vk*OcfXNxn_hAaqJ+7&rHbbMLL)K={6rCQV)(d&5; z^4zt(K_|CJae-o`L^r^3@WQoSlXfs;lGD--*sr&_C?t2e0rnP}(~fwndLw?~3+W)Q z?m~QoQ5_9iRiV2nPc@g`t}cLUK~rYc4%?B!UmF0v-b zr7P4l1)5CMcD?5J&<>(BGf3Bk;O`h1S&V0`HKR~bm-FMNySn@-;zq#fSY1bbvMKEt zZ^i0J`vV^%`fu9eU#0z354*X`o&y<+as$8zZ&sB$;8K^z(O^5nwrgVcIsxL7HILzA zly4?H&XSmJa%itmIM>!{JD8=2EEMy*ca4VMl5Fj*>!7I^iAQ7!o)yiCNDOCS!!mT} zI(AJo{&_4sWNu!qz$1X(ujV$`$MR>Ar*P*wx&bY4R)-Z3iP8qI%tnu(Ut%^}X4uQ0 zADpS=Tw6p`G2u4iYeuTF`#wLFgNzY@f`fgaWzE&Im>=vkkzQgyK+M>QIWlT4cCr$$ zm270H{>?7b@lM`biH~$c`bWpd`jmM(JDYM;Q=DHooiYa1%uA6gR%%n{C{XuS7YGmS zH#k}~KATmqsrC3An2$O=7!*`c_+EJBU+U}X=UP+R(r2&yYAN^PiQTK@sY7jfdY-2M zjK<#i?)T!L#@P(mqsG|g3Aot2n>2Kh1as$ua-aGqjn53SyLulx;8nXwDm+hZaAk#VmtJ!F3WCl+3Ikny_iLH9D_JFmDoI|b3J=<3P619h|ZcWtiF zb=Oa(NCb*6_OWr1#A#&lapqP*yl-!c)>Zdq8eAitHZ63l?~!jGQ$y|ABF-23P@<*C zXxoGJ{$2*5(2ruQxC%xwRPbIWOWwfY$h>;(0dQmYf5TTDcK6vsOT1GQQH3{3z}`>N zlZ|!!K!ul{HY*=38fHmko^Sx?y&HgA6W4jD5Q|x&iM*8=GxCjJ$M} z>UG8ex(f&@`DelS^DoL5q1k@%i!@lx`2B_++{N3cB-L`?E1o zxBR1%+%`L5JLl9wZuS84h%OfeMZ40udd%= zuj&B){sg(-J^?3&4qbSIYRLNeeLGYot`vmA^(DW>T7jh>Ik7NsxZklp)iZkzg1f|> zM3nBz*ig%(zONx6Fy++>n7R0$(0T0^+h0*Xtq85C#S2cPz1ovPIqv`fmb2xAHhM9s z*!rKy312-ed4Q9qeN(%P5r1D*?zZK{8J;jo*~ZdrI~WT_9e-2 z1N63i;*`^Ia8ucCc!x9zAGBwSX&k(u{#ikBDcXj)7bg3j^5S{jCXnr%KbmJ=# zl~eZgD>0Bg%>7=zej>M3%^g`Om$CYdUX0zVJyHQvi1{$(Y>(!gU~Q3RZE+XX7!arq z@MD4=v#HO*Q^&u>f3wZ+OrB|)vx8hg^w|#+^W+L(e=o6k^6+vNKJc(}({j*-{=HJvgw$d&wUE4_7ju$Nt!*;|&lVAi0gF-bAFicb(n z?55&r`O{H`e`T0bB(2=?p&7{7r06c*<%^G{Hw?$3n+9%gP$uL%S?0Z*TX)T_o#iGO zY8C2MXySC^{M7r|*D5C?D|n*J_>W?&SK`gW(fUoz+gt|RgdGnl!WMR!HPIEH^W~tf z5mlPByGgj$HSXn%3L4KydAv1H#68^ELY=*w%y@pl*B*J#X@Ud(P#uIQ$8uga2P)Tg z`7fj^Fxnh+-mC@M8=JE@e{ofT{7z*ov5W4DuSt$|hta6z3CHe0b8OX|Mgntc7mG zN~d2$NWO<#hAb(J*Zbjr5s#71DIEGa;q}I@!d@us;9W2H9MtS(|3sLbuuP~rDXm=^ z2>!!U<4O)bzJAc}UYb&~?yX!+ftN0?{2c$iwR?(;UiAULU z?3Ef%t^8c>SVc|{#w?q*?BzL32WO45Gn@mia%w$yELRYU&xeq=Nq&(ZNm|=$`TmL|E=yG8rlNZ{OyF>99;f=C(vhYwd?V5U zcL55AX#c^hU)2BocuI8r?$!~jQ0uHDcdZ#eel|5VC1;b)8^VajbbR?-KQD{Uyo8%f zMNKc*DKK2?7|%%MbHK=$6Qwbi@0(gUr9}XcDC}0--dFKuayHJKE~Ywukc!akrho+* z)cF|+zQu9eqLYXZTe(6M#9*C!p32mq8@Yab`_6kJ?_Ftja(s5`1>;?T!Dn}zcWN%I z`X3TciLTY&g1Z##(FKT4xzKnq8Xcsw(57aoln&PM9&R%~&ocWk~ZJbf9ZUowH(zXoC;QWKvQ|Kt-C_YJ?z1zajTVACAaTb{Rcs_^9YX^^rB z?25`4uGh8wva6?PO^wLD99Du9pg_dga4E?TXHCB@@^J2vY|ED3PB>)hZbS-!Na^ui zA6lP-TFp9ZilNbuHya)24Vi8lo9ykdf}GXa)9J(NvKY~}{ntkm2=Pl;u0*TMAAP_Y zGHDbC*CCxNkufDFfvcbNsWP!{V1iw}^(6OM9$h=yXD1q;(qlB-qZUvmL{5C+c|0FS zDZ>UUn^}1A2EVJ}SL{2VvP8_V>My0D9?sIB)o@cDW9vO?iJPQrM(yg5kOriSKKxX< zBJ;)s!Tf^%&x;c|l_!|(rLEc}0)9351-Ym{nb!XAM=^be`c1=M;SQG`B$n`<9-z!d z?fxW(8Av2gLz_g$geKV)td|N2-d@zKM~Ea$Xo@ijHa~)yGd0&ks|yaR(cyB|~(Qwmr6#456p8nbSWcp%Ok;X)H*?4aC!0 zx;APv>${}A5hEZ^8|nus{pLAD!nHT3`slgK$W{=OtcU8l?A9{j7Yxy{H0L)LIJEQ_ zpc@<{q_Eh8Syl*42H{B>>5yr9_0)J-B<(`K4UjW$o7 zx9^=TgN-uT35}K#8<|@i?w+uR+Zhnj5d!>+8iGlSe-VMsTUJ|+)lfDkDtz)Vcx5`) zC{x3J#^x-`FB%JeM~_D*Ynfutw+xkbsoEuZ=PJEs4`1#=c}RlC4@{8gFJq~;H6S9o zkMxcGxmvI=#DasGsPAQXz3bI4*~(@ycf7D31Nu>0lO)<^_;&5p{LqQ zy)Y&aUI?t9a_%bC-WsNh^-KEs{o!J7uaX%=C$iE@H$SH>LfD5E;>6C&E$^;+`ldKN z%BX58qY&~um|Z~qOAiamamHrWCcP`6;`IoYvjtigJgb~FB_V64`~WK(f129s$%C6PmF=;F&Likm5*>U8SM(pQ_n|_eC8&?dPOhXb4mv}|Mo%C z#li`Js2~-!fc$$Rf$Rb|3C^>kV(SvStuyx^$@qJxv>;SveNCrvEG1_S1HpWz9Ln6f zrp0z9V)a+8GmRIMoTHBk#waF*71_lMin}B|O8*M!E;SHW|w(E%mZQ2AoPG&f6?td>MoA zV}Y-E`)t?@MX9_7KJU!bl&Zbr^Ts*}a>yzHV?X8=TWbha@RM|TGQmMRg4T_dR^*;G zVD%I5whAabPbm6zXywA$7h^3cCAj5*rvkyGBotAqr~hp#e4^^kN5LLaf3T)&ISQ8u z6GG!^-4yf|fFknx#c)#aLbd0og3b;MCRxFwCn)MiY=H{6XVy%Io6HKzs^s8-ix3ca^&Z=zNA=|rm zRZgWFB^ZqNZ2hv>i$y8Ei*0dK)%q!S?~dk4D}s%a@yO_kU}*16L4C>I8xfw!Q|T8{P}(5Tx1PEYY2@kAUrQx^8XD z=ZKeR&S3sAwk&I5XTy|zdf(5@bP7)vF&%{jg$~3K{U8CZ;XD_Mlg?tw!TtamF_&J; zM|)T1l~&9uWQcOF@pDztuFU)B+F*ZDR4(V9lIzy;ft^tn~Qy$;S}ep&uxfme6~l z!iW3_CWG>;O95C$ZgKrd#UUEoiyX9$AvM8S5t@6l^p5yjcEnOV!PI zUaqzsCZqKqQ|R@yu#rzP2|gk|f`S4b8|az)_H9k4HLpjVVkgQtvA^@{9zY|7Ve#Yd zwJD9aIq-?$*F&H8k6s#=68vT_Sg~~p(8gOiu8h`;Ob3lZL?uSA3Fkj+i|0%GJMY%s zt4tL8#l{z7zn9}DZyn+pssICVqJ~p|lPaZo3%kJOuMBtfCQ`{A3TMJA?RW-D2_Xs3 zbD9I$oevz}pgL@-SHlzDs{w1$GC7|RR?09{_x5MU;#QUbT9wL?J$|qR^ z9kV-hK$iDYA6;#DN$n9J#|cYy6I-utpJ=4|s{-{E0a!Z_^z$WI?R&8Y&1+x1jmZxk zcn>s{QFh()1TM_KGXkR=zzKqaz>}2*f&0u_G<* zdD=P5t}bR5Nv$rAKPDCw#Iq)yL)2~3Q~NI7q-~e6xBaBq^qRbwd8Yh1_Di|hp0^b! zVSvCWjjrkT(Dup%qwAw^`1T>Gaq2Y6imRrP1(2))-hPzU@RYO2mLR~gfC&%-Y-tN% z!S>cfdLEJ$NT^PtR1bbzx0ky_dvfb=PdgI>KNADA6Toe`mLy$m>#KXYS|eQ^G@fSF ztIRp2bz5N?i(V4o>q1U!N;100-o#MA(mOwM*OfBUlarON+zDo2NKx~s`)C%jUN*U8(+dH52*_JX;OPKgNCmsS`33vu@v{PYkgVafIAV~!_4k>ZXua>H zBFC0zcPFAcNV~tUXhWAnG|p)qOX(d4J&r9qFq?GNz;>wdjA)uYz7y;$c%Rm^6pnsKb0U9Matd$6ux@8`O?_?seeKcuc zfKhT|1t&w_Q8XoMVuG|_M+4RFL~RqlM46oCHxWC~YV8(|V-uMrfX$a=hS zHEg($pV3$99s5V276jIL5;p>lwN8xt;|XYt_$2$2#uIqx2FOv` zM`2MwFsvUNBDj^%F_(j>2XFR#SmJ=olq^Dhv zn_k;jW7XhmynvnNm0cHmQ}EO&N7=j@eeVORnyMFs$NIjHKuyIo;to^Fxg%o@_laRP zs`5gncM&R@kreRccsc_Adl{?D@@D0}fAs?J&~0E4Z&J<37nV7jk42FU zXd#sM@)slQmde+Zex^U-Pw#le4C?{1X&&PvfK4Ir4$K$^ja1R>)m=9?wBN|w5j_`K zoD&T@;3Yf453{SKriK7Y8YGVQk?I`q)pc(^>##1iFMGnbY*wT#>{jO1MI%=$zHT2D zC$f^`{f}0dH)a2sDqgJ#5XKh^Zh8Dahhi1 z90)b6LztXBiw{!r#kCr^z`D+Vi+yvAhVKG!Yl;Lrfy23bXPQ1{&LFTd^U(fB0fPXx z)nZJJ?{{n27>tV4shx6E4F}cjRJB_=g}=CS=e6)F*x0O!OM+|GZPfXPf+ME#%e*4dViGhl6WFIu4`LzQ7MkhVsS2;k$Ms{TK0EE+2 zZcU(R;GYLSW;TUN0RtD3(sJ=EvBYdF58Y%2rJm%COOI5GvRCX)mFFwl=*Qzf>BH^~ z79v%jbEO~4Ce#n`V;E=>kEePB6I1%U-@dy{&$X4N~)q*Lmf@Tprt!@z{OXtU7)5ahad4{aj+ z`^^CbSj0TD4Jh`V_lJ!>$lhn?7C>=$yT&%ykf#{02x1<aa*yZknwV1-6AyOgnzQ{iQ{Ny@K>V0&*&m6r*F-C{WX-Tg zm1G7PUwuVQdr}Rdcec*(4`9S{kE^gCsY*f;W<$YTqD2l4>d4%3bV|A!E3WjJ983h% zRzBaq{*&-NRHV|e(w{B*@eT~h-{2a4@UUXcD(!VF$gYzv{=_w8rVeviFC$AplG0KR z|Hbi4EG7>NfJg?YaN645$ErLPP>MA8q16fN31gts-DwFKXa8*}u@;yxm}C%kSlc_E z-|NRo-jRCQBZJqN9>i!ABPtKhNZ?{TWuc}5ps5$phj9zFnD&W=>B4J2Pc0&uK_S~o z+;gSB#W}ZQwrMG>vAh;9@)}+W*KeJel~j101$U8GQCB&M)xZt8+-F7v8x|1bH*?R# zb=Dc+M369fKy(xNTdy~}tJ7^OqT&SCXc_}w&S(#0jx0W5fIPoI?{Z+ZQgntsIPLoH z?C=1}4S7*Rydw@B!Br8@RxlKmVR-H;(Q;GF@ffji=dz zitd=b#VsHLbXXkHXTAGL*lT14?(xp7f0Ex8OEddMhJd%Oa3g?}GW0nRSfsw;6V(k8`-i_`qd%sWm{X?Qu zusyFg1v79I{%{Lo5kkbrJ~iCZP(@nn+n*so>N8MKiRYQ4Pq(a zbFne<9J|CU+Lw(id2)M?SlFZjkUXCbtbl)iwS)_mux)+9KJi~&S38!@9}?gcu6Zih z6fw}8BWri-3>Om+{hP6%y22~#rWBjvSn>!|Cy0O#044OVp(>hRDqgyQYWtglm=2T! zS&(iQ5r>YzMhGL@@(&+c6K5mlH2r-0`yy|jX5pN5|GUj=hjh56tX4v`(LwL9>T^Db zrpLU?jFR63l~&r30%8w@bFrX6Iv2aN?;)9JHad8fd?mKx@gqJ5*Wvl^7Ph3Lk8Y(s@on>&%43ux zq>q0JiYxuEUb&ZC8|VL16F~o9%l{DLwf{f6<*xl-HSaCSOmc!cj?{}axlOJOVGb7T ztOdu0@V`Yy$@bq`eoaU4vT``B3!O5LJ7}7O49Fe4_*KE@lo@c*_b*=J>>Sa$(s0v9 z;F_!Kw>=DUo#XI7dfp2e;_-?{)Uq^=_j9&w|iBRS%4(m;)6T>ruXQ1D>QK zezm z@)q+#`GY3H|8D2xc%aZwHg?x;GwIP#yJ!rX9YM9?*7_^2|5zgwug;&#mO@<%rg4-fA;&1N3VLg@ot7CT)|_s8ydZNB*Z zBcqFyUbeX>S0X@^0%I?&Za8)_{ZAwb#(f+y*{&3}R zZ%CU7n<49S`}OPBnQr}3<266lOOgFXPVf%7gK6a)dH?ZxH~sK(B%-()fj`;QI0ZnHdrv_#gzI}XJWLOz)lkF3Jj)r--U03OhB4QOaBO)?|or=qNZN@l3XFSFd-n~;&Q=`g~_E?DG&%PogL>H*5Etkxn zO5A2L(-(83nd6%5rku3+kAs{dhT$md&$1QHPGii(Z z?!CIzYXM~AzB!!^wsEjPJ16wCq;7#aoQ_>Zl=V7zIS^~MzKKs*!0FNa?%}J!Pv;J1 zytsvoYREp^3n71$DS5Uv4Afy|x1xu%6|%sVr|j*yGYdU$2U8##uW?|fVZPPuF+;kk zKS&3eRxH#jcIJpkO1hZs^ZRnY{IR{~#$*TB);}YKEQF&meT zI^)N4A@mjA+Y7j{OewbuqoptE-(e8P=L7HbOOghHp*aID-?6@KFXOUsKb)Sse`~&N z0uF`z`SXXCTb?6u$_dHYTagAdhLoIkE|^C63IvjRCT+)=2HvXO?Jn-!%AC^}Ap6^h zqO!8L^KB7#Y=>`T`>qKPl{D?BKN@7=tW-Ny*tpCgL$IVS_(`rxxmgPdZQC5!L5*>zws1OHF4?rAqFb)6 zu0$eva_dEvthZlM*4Nh?q+FtpIx~dC^z`n9j_B^59*dtJ?%jG`6$vEd_9s8p73gAx z`yU-5>mTnsL|}&+99>d#0hfx6YU45-8=}rEr9Vq%2&gGFH8rc8@7=K%ZgfCQ!oaRS zJ&fm~@Zxr-NA?4 zy!HnhwJ4Ie85zAm^ZLuo+g8WRd4McdfFhB7@Y(%64RDI+e(n<@Y4_E)qDtN;xNUpz z_{WW=rY4-k*&HCV-aNqA@`0u`o$U0U{UIVFA=c5+`QF`q6+q%=%?!S(U7)X>y$?vY zok#C#0#Oct_dY}hoWA;%r`8%Es8_^FqN8yh8TxG#sJe0renKH)RfRi zB%c$H!eeWRz;^KmAf8F3o$_hEZ=bGrBL**_8hn*hRdtukclE0L;S$ps5Nysg7Rsjl zmtZ*9&kLa8VAdB}2ln>%@&@5U1==e|>!k%wC`6{ms3B2b21JA_K#xyEgnp~%a_YGc zL?IOPT9XoY?(BXzdNJy0cq}C)b%M50Sghz3)}Z#Hzb+^kZHnJXbw`hjU0sr(&F%5$ z=u&&G$DEe&`7(w@aje8RvF8Q`<45m-beO7f0d}?

PreaObxB>SK;B^U12$vL{<@ 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

IFQ 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 literal 0 HcmV?d00001 diff --git a/docs/doc_images/tensorboard/tblogger_hparam2.jpg b/docs/doc_images/tensorboard/tblogger_hparam2.jpg new file mode 100644 index 0000000000000000000000000000000000000000..4341ce4932d7eea36f8dc3d8c9b632539cfa2ed1 GIT binary patch literal 321199 zcmd?QXEPZ^$f3A=_HX#py9wFf_LGC1;{y;x>$zZo2 zcX$6_FJK6g45~#uN&N3gdO_|kAy0w+0uP`1xs#X!1!Uy}4BTA>F^?oN|g6arI@6zLR?+%;s9I=%d^3&_cI-q3++2IUTX$v`sxj z=wlQtb+OHJBF5uj?{iM9l?~Ye~}UT`l8SApH!H0 z9~-&+PnO;_SpSQickK6J691y}|4nuj2dHNIsbYOqg7rQAQ2vfP{HulNpbwbL-6@`o^R)~P!ztT zzV>QyIn~n9HH1<^lV3NZg%*MENTtqEEAvxt#u zY_q(N`3bv;FWvT|VgxZ^f8Aces_<;GM(&0!@;N>5+zYwlkP7(H(wQ3N^7WfQ=n^Q@(q+b+^7i)2JPD`7vxue-32&GuNKK_SyH_ z((%8A*4|OajGrha%K?WDifjezLuQ^ZkC$W?b~S$SYnTij*s#<*P@LzJtMhFx@qFkP z!AsGeEuax3IJcV3%!gCezkwy#r?x&L{+ocy^|qHa;&}K(QnJj7Y(yUpVjtH6Le?R z-s3`#o0N&NN^TaV4d1;l5QyK)E>4ykc2n}wD{llAI1ZPDl=UsEOq>83FSSMAL%f?i zjN4ApHbeZbmS1YNN}KL|?&e6ESNjNI0nPnh*OHe+3H{(aK3Op4$4k_=>rpdyC1d1) z1W4JAu_!e*ag+KhJwL_|$b*9T3suA^k8D;ZV5cn8>NDKJu%P5l~0Y)_U5ngTt&uL<0fWROlw%|I^MfF8L(dI=NE)|(KlLO z7Do8DH8)I%hU}Na)NAgl9OIKJokB0D*e(^0*X}k@hmZRVbmOjo*M-61QoUMl8%n

?Iki%wcg6Lq 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

uC8^SUPf{GN+^0W4wewZ1 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 z

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


-8E|k-Eme|kK<>TfwkptmUJ$z!uzYNf^RrsRGVwK+wJZPnd9EvF*&FKzs^k=rO!jN z&AxhB3*2#k+c;yD*Ge_WmfU@wfX8*mt9#zL#CcXiZgey`HY;~rS^b&ni>Wf1WF6gz zm6|O(eSU98R~mW#i5vxZWJ^?xhnUDm7wFKmlnF3$gmv13HJ`Vu z>j`cz!~!SF(yLI%h_JY?P;`RH=9@z$3Uqq$ew5e+_{~03xG5=WW!9#y*XB5lZ?V+1 zWI6PkJCA9g;exm`ic!bTPysh3JDcm+Ra1(V?J0jnI6~@Dtp?@%aNtbQ>nSgM>)8!C zPjc$6&>~*0%)ec;FS+oRObpK^T@ydeWcL>3qBYn!Z%h2aza)z6BH?7TtbB9F!n!gj z)OhVl*(vYOMLm6aI^D0@Er?>q7CnI#70~WCk;>5ZDz&X z1s7&mkJ7NrYm&yl4~Tgh$}mU=?)jx4x>tARI2RY)4dQcmbx~2**PF#`J`et;K?t#A z@$k$Jou!c>s3j_S*#l-BY=z75#S+8Vj>cZ7M4KeL`2%xt4{rRsd9eVd#V zKm*i@FaJdW^njIz;)S;MuCiFarIEd%nTE9pn)enAK z_WCbBt)-@k;NraI<$cXuoXS7LZyP7S%J_C1&DB|G@0Kc|vG@LMg82C3sVG81lQqki z+E%QxbF-BU>=8-t-U%J7p!c)Fi2B%=23!vUL;zos!oIr@IHv$}6Rsk>)tM4twbZR$ zF=7(2V&&6FBzE@qY@K|+1yFOq0)Sa1+J|?*okD(VN{VhwPeM{sSgZYR{%BIW?op7m zqDOc-v&n7aZMO7>a9~n$!Iw{j;*CZ!P82l_OdqXNYE=3g(qX6G0}79OHudBpqi@x_ zJgLr&AJUW84mdNHx>4RwvXd8a+5HZMpzyO6`tn%A(aEpElAZAxhLhIm0Kwvv%&BH& z$%gFFz8xl0yG<`5T+Lp(mh&t)sWdOntmPghq(_c&?8pqUTw-Lz7x?b) ztWJ^Ee8@9T7~!_W-jZb4doi|MF1Cfi{ec=WqBO4T=)00>Y+U%dWAbT(w{rernasbE zOuOiDO&cAFNKkIa;Hf9!vi;8JHzm^GU_nm#qNVaCvBO)5ml}P_ujCC|AH<{zs4lmz zNaWBRn6Og#(6UAwb8l962U*pX ze0n|nwlM1tv$O11NTh6>QPFm9m5{j{qiB6VyPnD}5L{UQMdT~CzJcN1>jtS$9W8<- zWYPxdYJ#>K8bi9yWS6^dtCs1is;ZEFfq-D!1#3}=X z=Ifg%jich@iZ8jGQBP++UbhMGM%Ih6rU^%u%y!$ul2_Z1uJPUkdOQHz(!RD341`Kq zGqTKoZ}3T3`~la*IODt9Klk-Tf0-jE#A>gX*6zO%S7Nr|Cd8|WPRl>AVXy^W#j$*L z=_Vd6fw$rQ5~$0E#%2I!h0lDs9UuZDzAuT{bwYKD7?_!{vcVi020_6>nTUvJeY7Oo zM3~@TShf@W7Vb@up^GTmIT3J*WidmBWxK58Z~5C}&TXwFMR;mKfrXkh#8REnYP00r z_-d|ezb(W?sm&b-dg(Jc{}>3Z4SyS6iLG~F7{VZ^oy`&tQ0H=d*#D?qZU4vlxhJ*f zwrH}?rQ11z=uvKNE)vB7&TR$W&CSh7&qu%|XXoeVOY4aIx-GUbM9&jln90qW0F;}WN}hzsAXDk5f8Jq}Vh`_YoZ zx2|8PQ&V^CZ|FWM6HK9rSuDQ4#W7@;Vdv+Uc(^yHGHmdBtiy)^Zy^anKd(aV=f@)F zoEeZr*!VU-H`XSgU?=aD{_y!&dzE9~h=^)4F9-ARw)lyYC{M}ny|~L(^730JhH6HB zt1Fd6yb;zu=!1V%v5O`~TAs@0YRduVAZnwr0BE-oq$Yc_W4n0+f#oz5_0lak~CMFLlVQRHGd-sR`B6g_zW z=IKU2BCFJ5v$wYgw+Jw_=9V{vKj}&qO6Z7W*n>TrvTF3NF!o*ks9E-T?$V?tu&H#L z#Pdr8{%qH{j%tv(S;f6qO6sJP^EJLLW=3qf;Z|LwS|1GU0{l__6*(}&fm9LlHu80w zGat(7miPw%T4ijabPzdjFLs?yAeNU&Lh)N(p5a)j8N7!U0s+rs4&^L4T5uxSnQJEi zkHYhlJw~&N-x~`tx?s4O*8IA1;$S2{JLh}UPSAoE5^dF6SKihpWnHyEj5NsszZGDd zYI*Lof~)(W!@4~0L<^P6xTu?(TfmZnq9PCx34DC6*se|%*nL)@9Ts_5L=>Y&1ytL!vr0k&6+o0DGtUu-5xQEm$ z=GpQuFI?x&6mYDI5Q-b7Fi^z|Z zqu>dFd0M%`dhH!Xcb#toqZ-Rr6_uSWAB&G1!H>ZPgt;vvTQo0^2C9%8w%>L)lf> z8*Js^QvP>n=+9p$kc<|dFOmF{(PkZUGlcbA_gK|eHEg<~srqjd+GEJmP95`c(MqUI zsLV~sIHaV|WJ=9J4t?>CBDPBZ##(#Wji)v};#TE)980O0cuNIQX)HaxGv9XBZ7QuX zFlMr54JJt+-7L$&KxwsJqOr46U+gv<(zJP=C)IDrEuT?an+T~?8v*mfhtuGS$pD3^86Q5>15?0p<8 z-{9Z0ywTRV4y&v3!zc+YGe%0&9q+~#+tT%@VN?&9dp={|zi5kIa=#)G4|M#ri~;9} zSQ~2J_lyJmTQRNOb1}l5MJ1bucE+=Eega9Jk39LR5B+pRM6A0yGrmV))k(=4nn|I_ zNUp7Vwi<|9S^uO?SsyhCdJ?ey!cF}JI&JmENPPN3Fpfe341jdgI9caWtWl86n}9N` z?E*LSh|YVj&hdOsI(5H~j!k-If{QcYM?F1jvq@S0ZDR?Shrw++XS%fpbLZ3t@{hy< ztvyP&9|mV=d%RFt=;1bN_hz$Y#8k7I3g@CnGqJxD-vFZSyZ*$mG0PcUv*sXMKKJ=D z`-}5f8=g5+m#wGQuB#OoG{XT73YR1v_<}4zux9|;2SLr*W(@`|F8%$M8Y(+5^o58R zK;u0^kiczrXRbXWyXvHCNsYZ~*6z2aOb)v6Zyet7=^zofA@|0_1Q3!NPFt*Z@4f{> zCDQV=H-8dV#AfwcVTq1b|DQiizypQgo6m3v{~ZA}wYTaLD#sbwC@J}`P@EL5s%d;I zX3WY8j({b5-05eb(#nb=bi<}>jXoRnY*c+Gp)S$}f)Vpn#yUo{0~J0Ui+xYY6-uhr z9j9(sY_{P~9@>g_-WIrWSrY-NbYJZ@?yVHKpkG)$M&NMk=661k6tT#h-n|n+E`p0< zF?QTr)jwp`KM)AfROmQkXnyTu_Qh``BlNiTyR#FX$OA5}NC-rc!qkL+-9H`d?aloG z+s8ML(sG%Ay$uxhFGz|x0K4rs%7)$Rl!*S*xAVxGhHn!icsdKxU{ZEa@SkXcnStnj zf2vV5(w2Ic<&W52Vt;xr%Sa80nmTEC)P3%Z+pWf}dOf06mIkBS{Wp_-=68qxT{-9) zuOUGc54N<&9d4O)Z_h{^zR-WIHL?m$i>0QYOayp&W5A~VHZk$g%q4_~+PxkD9WGB2 zR*m_x399~XyVCiwlU#eOVI2?F)#9}@#KvMPi7t5IW;M^9UtBPnJy4<(Gkm^DnDGWaT1oc;zojm@ET*Bxzy-};30H2WRyEt>4?3=5YF+gqr`zbvyx zZY8N@4Gqs#7`7Knj4xw_*tI-pDqhPFVthBsY$Wj&UyRbFZOi$`j~@_N=-An}zD5*i zRegqVQUWO_SRFlNVYv^KZY1U&mJ@KEPhchO?ClxOwgj0RVEii^0)^sw}~j zGfW4hI1_&SGh6GzLs^A(;Lys%N*#aD-&(Pdz$9(xRVzYT#|q1Id+oN*)2%O8cuVh1 zYm$s|a+b--1v%B8p${)EzFhq9uX;Azkdj)(3bB>M72_%|WOMfO|GteVvhBF{2qdlL zT}7=5MEAwf)Yd3a6^oG1S_rXKe^$7(1tD4RVt;@ki4K+_;M1=aD5939_}%;8dG-3e z^KFW?uk%mW5E>R4G7_C(ucR9m=DK|Gse&B&NNtK;TPLaSGW+zX{Qt!?yocu7Tu@B6 zW%#8&^yI&MX}obvE{!)4I)P6trEkZ1B_}Ugrg7~>fvOIfU~GGr@lc`xQ5Jp@9H!Vb z!j#H2#F@I@ClB7eODcMZgNbPXb(xmOMj6We`}gq)2_1jCRb_wfiw&+D$9QUOhzms5 z!{2kRN43fr*w}C2dv%Hd9P}L+3S3M*L&L)k-H(Sk^cqnV*8z+B0PqWlrBy~1G$Htk zqhUqW5RkY(MtNRZA0M}Im^UP=-ydV&bV$I_;`^Y+DKVvFsI?@{XD()KYunB^oy*Qy zU@P-$Doe|c>$FGUZe?_g z993b^O8C%wfi4ZFOUn~0?N;s5BD$~3))G!mMGGnT={EU4_@7!-j1A1UI~4cV%RWmi z`(H=M_|eR>=V+3m1vz56O8&GBAA5@uhcbAn?awc&vQkk@91+7|*9F1Guq{WKlQKb@ zNkVPZk_Tey3{huK&mq&LbIY4YpCTjYh$uJ>ZVnmZ-E;KIT{#|=Y(Po}y}1IXPGhwUjieTUkn&S+?CKSQ=fL ztfdUjL>|x#pA3rr6IruIFEF27BoCBqlro;X?%(<+AAWk3hm$c{!?BzF?HP>`o%^4{ z#>OGy&P#8;&ji={VyGn5bVF7eX@`2^6cu?i@*k1LR@u;$f1<0K&DyFr)Rsbag2{b{DwN**Q!pypZwfZk4+rzEP1P^uZO-QXY^`oZ;ETt#KwSpbeu zlf-sA_-A0kmn9cB8&n6!@l7NoI_Gsc4d$TVzbi|)ybVh!D7W1S&J!IUvV%S_me&AbC zk%$$uagu_|pU}zaX+15rVaD)nW5phC7X?o0wU@HX1P&_-)Ek3;|Jtq< zRJap4>w0WFzDKw4ld|7w;hHo?%FvLvmV>FF{Z8aJjbTJW$Yiu-Svj%06^|k~)pVSH zxRrCHly-D4#IMn5O@mj9ZQl)*Z#J@jzaYe8p=+V@wTKmY)^ zO>3;rO^-2-b6y)GDQ)N$yIVWOpmn+L$xCUloYOrfS{RYH7&MqUICiD(=r%GGF&AP! zWvD=GJSG`7FH6tO)}=^$h{?(z_zItrG8C~P+T?W^EEgN`W(DHL{_~Jtf zd(8#6bnxUC>#|+WDI{Yo#6mGNbw7V!Da@$N@BI2YqorauHlvnckb-qW?F@nsYf{IUcDW?l8u z=waT5u7yYtaeG%BopUN}4cN51GwPsTgjyjeEbO2~2i916dQZKwjD*BZn}!Pjb1zAp zoSX=GEA(@X2Pd?3Tw2;5 z9o1}^9x4_0eKTXB;6f`aB}CDF&bYkKmywRmQke9AvjEp@&(7>NToA=af3Wo{5b~m; z*H%_m#sStWm&6|p@b9^;Ek(c%fUaZ+w3U3w48SS$`t|GX>t!V+B~YScft$KO-X0JN z-U9iK@fg$YUF82AXzZ0v-IR9qlGk~!rJ8YgP49UQ-Ouyz+s>p>8A|1OTpIFFi{@U* zS&!O(ouk)Y{gMUO;PK0|wvAh^uQa>yFox9x?~c$+4`&o<>T__cZR-oy&0@+0;JVFb zQ33#czb(mGew!l`!_Tkt^ZnFTx2U~@iN%dH9ao3 zdN6Epc7@AdyUUj>3kcK-hZS?`4HXp?yR!|eJT_KhEZG>g2T<2*F0BOS=7Mo<;(?pO ztC#mAn=kV_`Wo}3b>_=kYJ`eC0t8!9Fugy>GZY-2jXewT^SMu-Uh0wBdYh(KrN&u* zNB`6IUYFdyfHO+!(BE_(9z%*plqmA=QmCIiEA#2CH{t79uvdEZswL&>+{F8^BqeEo z2aM~XXntL3ON&(T+C?rofn*MtwgVYqlcpJ4y$Xa;VKu&(@&8&Td(sD~M;Pc97Mkkr z&lF!YKY(x%h?RgjuBI|WB(QFBueZp>dMxNNO;Y7G&=Lzj;{PXxq>fmTc0GB>#>@U7 z^V6HMq)Q2t?P{+2)8NI|CAG8v8$U5GJ3O`sc1X$1<$hdN@Z&KlHn5onh&?B)kDfEv zl2cG9YQDiK4{#@PKhS4#`#H+6a19?Hzc16di(&CkwBVQnf70>U8JEkZmg4#cJmIG* zDz6#odt^knZ;Q2+ds$VpSW_o#V`ILIU6svG|r9 zb{T@#KYAd z@EpT#=2YH}EVxcvNl~eai?!PYBS=`eXkh2Vx~1?lnWi}W2;m|WkQEF?*$%&QPs)(} zo;{}wC-*34&7k<@xg{jU%ez-G|E3p{zAPt*7fhzbOiy0npdYn013bWw1AuI(yeZFqZ%STDNi)q`!kQS#A zQuD8iE^k&;=dGl4TT$qMa3D*5uSK;`s{=AC=m!nKr-8kmiE;QO#87)WISuL*7l^+5+sRan zC6&|vOWv5vrnPlOPNwl=LcrL_+Z|Kd!%B(EXr9EaCF-x$B#YZ#B&5IafY;Vb~aD4k+)z&Z^-UwZ#g zHdHNbm^5$6RKA`eqB#IB!z@0V3OvN_K(4*U?Gw-}>gWipfSgXZ#BV?=(X^=>Eb%(t z)`#kkl+!>Wrnf)t^wiz^axdlRSJl|rNv}^2usl7^Ytv1hs4(mLw~EG z{CI2rvV=AD=SA}uJzJOai+eqjEm`!*iqE#0_Q(9OX}Op?v;B04)ZIpnmRDC%`belG z#anM9G_Y*{S9BiC-gv#RuyDS}+py!v1>Sn&cI{MOv$H*f_%d>tz%mgD=gX9hai2Y! zaG`il9!ICxNME1t&4UG0Gc~=t4ZWQ=l5qdczPzoky{T>WxH?`#xN6zp++)Sx ztOUjt6KuYhS`45UIC!dM!m#4n$>`77aRUxgq#R($<6!`zc^ddX56nTRfR@Y;6A#!S z(6;H#9Vcjg{6HTjWNhy6HA$5DR1FJ@ii*OA7%lN?B~sHXR_9Nm@id@@hXEXx8=#FV z?1>asSH~l)EiAIv9QoZK8UOnBuDh1=h|c-ISa3}t8n2?_MIIg(zmN9N$givW_g&?s z%EL%S7t5`Leb^6AaCr58_nwjQX!RaJ2yaJU-) z7ETxroh`xuGz2Fi9 zDRZKNNx+$Af$E<>e`;0#vT2rwe*gYG{K%&G4oPfd?rg+sm2=Jo)=a_bof+J{J9 zK?J}fwVVc3vTLQY%*eyS!p2?a!jeZ!QoQ{8P1pahJdf%00|gGG(0?J}xvZ>gh4Ce3 zzlvl+9XQaYKxcRH+t{WyOX#}hZ!vTT+Z$7ppv|1xmlotQ+kO# z6dgVHOiol_=+PCjEDjSA8B42MTr_5DIJbv!faxHB@y$jJ+q`XTd|H39NKsU^ibcY< zerQm}wcuO>4Bm0uW}M^^kgC4r=L;I~V$inuErkZxNo9N*fjdC#^lDmme!~e9WL(Bb zkdRb3<#TAB#>K_GdGp3K*-`HKb6OS_>^dDqFsHqNh7A-#aKaRO`V^(_w6v?%Z4Z3L zjR4vP0)N2DKz8KEkJD~R?{3_B1cbx)A3i{jC()$x6xa!IoQD2Olp7J(VxbEOmd1RM zJ}|EcyRScD^m_P5!Jjju<(fqII;{`2#b9pej-_+xXh5w&uY}a`LyG>CH*A{z(6i!> z#E_PG^iZ!$?;WFh7zn)Brg+ZQkJ zLH^1#@#u=>%(g0-QijPAqz7ItCS1EZWde!VYxfkUhs0C3m!VAgY0CY>WlIM>!!tR# zeM0RB5_czlD&XuMpPcAFih~f`@|-z9I*eS>%S#AMq_fh}-i3yS;+pIu5rR<5q8x5b z^$zR$$U{#Sl5d?40~Z$;&^rK#WGRV=$G>+u!`!)NBQ;nyQLEU;`gG}|s+!n-7M{i0 zyYejomlqsco!t*b*VJ0Oa45cKXQrK;&A_OVd^2d_b|aird@W;LdCT31eo1-)HL54? z={WnDHyf-dD8T>v+2XOzM{vAHrn5;dlRGV&^=H=5-|k8i5BOGCm<3>$+*~H)PbiKj zG(UKKf7B#JQYi{otyzOylayaL3E4K@%N~0*s{iS!65+jj_l}!sE~kT#teF@c_aMku zl$Df3;iChvaDINC!){h0*>x79w_ewC2NlLURp~%of+u>qRSaG~>#>M$sN*%}`R#rV?#UOx`}Am~lfk zbo$-O5JiQB#;w6bzW%?(?}!ERXtN!zI`YHQ5o}dA_4>2pDmVO`{Q_oShS z8QDseD;_yFI`|la)x6pj8SL1=J%HV3LwgWLVvtYVWy-4^xN}eJ=h361qq8kv4^zNW zgm&Nb^v@44Y!Cn}3;X3hTIBW-Y3`MhmBq@;%+yI)1Bsl^b^9)8%dcL&g1zT4&2{_Y z(|~%%uN5oaO>G4~3+1y#srUFK=|N%g%bl{d1`VN~i44-iWR+qs4u<(MGWy@Yx22~~ ztxP0!C{fZ-hOucVQm7p(tSxWZkv2e2T5Q%ja57Dl9ZTPga%Ru;o+-)wh=EiQWl$dV94Y&vp%y9+v;Yb`;5G>eb) zxV~TacyBR{ofU3&r0Al58zIoZ8Yol< z0i-r{-diokCAX=lx}zAC1&duK-2xy&RHl#wqc^|sy>}y1IJ{0B!78$=@!bs=os0VN1uh?X z*PpI3s}^X${e~N~w6t~mqnNtxCR_K~;)I*bEG~?WfAQRC3zS&*M$LZm61`vBrzrn$ z%o&IBmugjcFu};HXjA~KJQAWpF&Wp}ZBYYCQD#2V4G;DoHh=9~nRw zqj7Kq<37K)&zCGLtWQ3govZ4#TtpC5hXw5=z;F%JbX5*ZNTRf&bafn;$s>owF5HOG z5)(WuVivva>7P_RzYZKu2Ruj6K2*oZnwv9;oc2c?&qpf80xlH=&Yh(=ljIfKtJPI= zVm7V7LGuIiz0o-MT@g`BeAZ5{&t-|))D@OpqNd$mwl>~gLS=g&WdSptMFscm2};G+ zdi`eM#2W?LwXuzlEou!|V|0FZDT-u@U^7&vr(J8XLZE=OoUWnq9fu4z7q_B;X4t!e zswT~4X}^5Qxdv8A5eT}Dw-I*G=B%#fFH*O)t%X7hs@4HLJR@MB)I#FZro{D8##|xSy@Tl3)v=FOeYfehUCyHp1PWv zK14pDa)dQ9Ut0v2_WehXe#k10i>=)-um+EoDenYWJf~kHD8i&5DkBlxGfjTTR+W}x zza-!~;Z*E7-6OaN(HxdbUej%HphJmAD@nhKh<0*77R*aAG_MBJdCD6wvTVIbLU3oB zK+3S2m}zE_mGj-cRtdwG3q+(?_QedDJI{XOuVRINBpN@#t}8i6`G{}L#I_hlEB+$F ziBKs~AzAiW<0CKrlFN%N?_wsI{V>>XP9lau0QDd;mvWUT$Exd)0JCY{;x`>edNAs)tiwh_fJ+z0x z-G$#%eMurXJ@K!%2p`|^*Xy>5f4IXSx*%VwA`9%<#6(I+FP&AFAXB&t_4NE}W7i*` zEmDhQp)NMYi1^=+wL1!bP8vGt>oo#I5|1ZPt==N61F}+D|n!Y5i z;?5mg9CCCRDu~wzZ9N&8i~Rre*uENF=_+sUF5ZNbH|y%yt*yzfjs7^uQT0VDgp>n` z_05nyamb&c!bNTXq8##NO!YE6Q47J^57_ zMcwQdvw_%?nSlD|t2f_S^KRkNguhe^FepxC7Y=5=hpA?|Ce9cU>+lPA;|!NPKFdv; zJxReNW)t;c@cZVO?O-x&f1RXJ#K_1qW8eiEu@~=^LnFO}vr`Hb#mw z+Ity&m*e*iE25RPze2Ip{|}1FLc3l`n_@ja}NEHlA_zseHQ(vhD&{rpHP z4)VZKw3^NiWeofttd!r4T5j&2Ls=~$DOv2iq0x)OEkB_C-+ZD8K;B?U!JrcitFfqm ze@mk4`3XWGTbcEpC62)k(RNv#G}-IP+e(kb5`8uWH2e*qLo51!(x`(!NH{gSd;KWG z)9T~;Y2V5oLn`xv8#!;sZL!tcS1_;^w=>}~GSlN;g^UThyH4N5);GZJ}fiV`4TQ zPys+f`5vg5L*Ro9bk>gDg-&E-f|Ymw!Gk0vEG0=L0DW)IN6`;k&d`A{N^$YFe5y77 z1o!eXQq3z?=_(6lZLz1-r<1tIbua(*MOI(lb!H&LX=_vcr-h!~nhp%R)yS{UqI;a$ zhgE?0r&QN#b!jO8;dM$)9iNr-m#P5Pvuxh`UPxVu;JmIeK|uNm)2Y4Ur%?Rq9QjWr ziNh#%d={tcwjOjMO;C$E7k2Y?%ze0E*439!*DPMj&8=!UvM!+HEiv0tLNz(eNIi);K&4E&Xw++=r_ELT|Dehu3zemBhmUPjDNhsCE|gFEL>pwhqvciYhuIBCVqdP<_AQfDmSJcwd( zKg?r{`Yk8!ALUmAC*mR51f->Nzrtw9OF9-o8Gu*pz@%_)5juIFV2jsEF6mu(H_JV|QW^fQ?ol0TE98WRWe8l{uU zUa4fRjEta}ZY=gi8x$cn=W4ey_v5gn}cQJ_0ev^-%A#LKr9oeP1X^Hp0G2i&D@PHm5&KZ_E!CLZI*mA>rj~ zMjKM(32=pMtioIhyu$y=Kadv`tKEpGsTCkdAP2nJ>;6__+CyRyN+XgCvT{lN&sVCd zZCl<)0=>wg8_rmH>VBE`n0;*WYD`(^uL%O?fSUKH=6nyF&2l*iTVf+}XG zPaMz9c-S<)?eVZyGZdK$8ab&CF`>iy;pfw5&jPa#K9|}HUu}FBmf??ZE0-qo?pC#; z3%+MH>&vICNJyAbnP_z_DLkd(ERIe>?VRDh?_wMmhE@fx$;<2hlRkK$V`^^BEctQB=vEzaaxa_uaxz053o+((xfPz> zcYVIjA3yu0MebtK`0%mPZ>xf9IGZ%(zS7+dZD}$ls3LL#GSujR?ytTJGG7^DV z*Q}v|4zCquUs760BY#BMKa~u-QcPU^ctefPYeYpB*@0167!3~!dXgjLAPqC}5HEF# zAsvN~>LDm?TA(}bx!1jn5E48YvnaYvMm9>f#Lmn-2TIr4Cxdti z?BO{tv~uf-)xiWWm_4K9vu(6U0VScl%;UOQdpH$x>bGQKWaL+_N}eF~=`V{jIdv9dsR(L$d;1>@hfP@QiThXsc0g1ILj(vG>p}9# zf^l!(q9iJ057$FJ36b-1t>Lnh0O&Opg3RuU(n^Gk`#N{y#p?C-%n_{avPm+oM!i>` znOpqs^(`2<8`h~=x;;b3t;!1K;;>kGnLpS5A$RuKb1^P5&P5tgt72&7mRKH}ik+Df zDu*|SVD0VMNlAOO-T-ss3!|8sDL<8`vrUAE#A%h~1I5QLscrv)xM^qo3l|aKqk&+0 zuJ$1zJNt4lfb4)KH>=ot^_84}i+d|gPp^p~?^x4Oxovi&TDVYbLEblsf}(aZst|#P zr2kWJ=jV2wLv04>lY9Bx+?-v_M0Nqe$c8iMcY+9L;y{^yFvj-{F24L5-aG_|V8`#@ zV7LHt7yLFRht6*x@`X}9`TXnGGw2L>CWRx_y0vj@Ug)=hTEbN?<_9u)HImDrL zfuWa&2KlmM0jh2i?uRG0TJ@#Xlsg$nw8u^ShRExZe|lSmWN6A8{N0~Vu#-!23smo6w@!&;I}fGxnI%`Ln^m4i#0Ms2EFqP%7|R@2H8`~-`~N1MSM;4-H)3;7<@^8 zd=!d1n4F^d8Ha6w{@nQb(t)5GwQ#!!gNg4OGw=`~xNlJUEd8Sz@Awh|PoFghGLsDXPbHd%>NZYR}%6W&+{}3GmL;q-V zVzR8`jlr*vv?Cjb1j)nW<6X$(ZB5AIP_N9n+vFFlXITB+Z?Dz+oF!G|siE5$^XCQE z0lW4-E$ut#j2v&EAO~!EUculm)Z=H}=@T%t`+N%x2McR&t@=|`l!UrEY4X5`{J{A5 zI&Yo}On-ykm$32pd5seTf5(qVKW*VlFO!_W?+y5l`pPFbGXUW=V277m83 ze*q*R5v$kTAx}T+-hrvwxt|8b9Hrgey2z14P*t@*8#*~X=ACeiblGsOaf9i0xR12* zd5gi9k1J87brME-i_Hg_WMpM;Bn2b)6)PofyV9PmgT4KEa6`L6u{w0|4?>b0dY&-U zAr2(goojU2Hac!JTJl7ur1&%m#>dAa8~U|tI21gfoq>#^5Aa7%AcBBEVo-r#WMwr1 zp$fU*;9$k2{8;X8lA(xqPA++%U9QNf^S{1r=gc5_e8N~3|#DrXR&+q<> z;!?7RZ#Ry`&{8WaNlQjO*9maB61w3s-&rf9+KLto`JD^*o;*2;+T~Ma zlU__SBZpgp`}>YImdKkAwm(sk7dfCOW)EQw$?}DMDiT=#S(a_4qTzxSuG1l>0@`wtU#W`^@h&5-<2T3Rjbm+!&(+eYphwY;Lqfl-Wp^pkp%GLog* z_t_msHg}EXNW0tSwg?HtD5sJ_mJFV6mz_JQxVl=Oc3$iH=JA?4ESf|oFtdBr$OV+VKsW&XDGJA~O-Y6g$uAKz5;w8<*Gdavi<6dDpTS2nD(SI7=K zJWC{6h=&{czOWz!RJfLkbWuab{R~J+@?1M&Z5_<`va-Xo0AfK$6iEKm7=3` zRv%40%!+x$T2J?u45Poq zEVwNaK`qL8V!e{1JuKm=e1&2>D3l-H7W|2hvtq?MGmoi)m}F1;Bayo}cbLm9JgFU5 z4o}_ivA@0y^tg(SEE<8)7S5KLk~sCd;=nkvsXw8Is&#Ti!w%a zDslTRqMOwhUHHe5F0!QhU2X&o(ZyzM3yJJ!5 z76hbpkx*JdK)M8^yGsEv|o0 zna%l#nA-98+=Cvrhc5)y0-1fo89(s;dpuR#%y60eYOG{E{`=ewS<0lFQ zvgy5>0bb>)H_LGg!ZsR0(_Nk|cNaIBwmFXz{+=|Ott$EYA@W1iS=xoy*GI371v1v? zd=skQJ<|W}ve!_$dXHv^mfrVPfFF}8O7Tj4r$Sf5@mi(XY{%;lG9}alz3%G*3QHq~ zEj*;8?#4Au-=-IhT!P-9bCnn?`z;%{8%&g994X_z$+IXUpf2)xvW9gb%$>CHF3Yt6 z9YyNt+ITTNRDKr@1|GoOO+ZcE^P}9-9fS*K(6uwSuvkoX>|a<(vOV5ZK8FAD)%)B9 zE*lZC;@DU+bUd0rSxJc?Ok{&14T%)GG$w;$!A#q17&UYUyW;6Xbm$uU`H0X6FluMg}hkY&2SOZdi^rKU|CzmLbd0ueUO-xEW_=VWyuCxv-Wjc$f z-a9!(6T2-5aTN$_pjM~@kd3;_<0;UFz&#FM(6B%GeuwC4{mJZ7MiAXCKE6^p2T(Vx zfXniv$XOTBNPdtPl>pC)Ty1E*iYP)p;z9T9*-HzH{h~s3%UZ08nj&I{)`)1RbGmG` zS}V~#_&J=K(k!#$U_yuPzwo&O9pQC*-sn?5$Dwb|iQ3WD29=s7IMBUN%El_&{#XxP z+)jwZ@m0+T70OEoF4=M~1{Q*wUknX=9cHcd3>1ph?qO5jvUV9^!BTzgH2y}Yv>-G% z{pF&hMCsSv!)-Jh!R*U61OCOEkv}J+aaOjtO)3jLuf?`8ahHF5AiA>MHNd%d@8PCR z&RllR!QfzqyjDGx89~Jtl9W~asB4MK%7(enP?u|5CCLuyG)#sFm+S5+x4Q?v_Tyz& zI+LL~7h7*Ms*h5VZX`cny?NxODelCQ{q?S`ydYJAs)~dSflCO*=&-~ZbDCdIVD1+R zBn=0unyvuvQM(4ALvKGmt2DSEzJL)D%Es;b*S|HG6qDV0sT(1abKmb`J_ChCCkW#{ z=)zh;+}R5~g4J+uDC9ta;7dH7`x@`fkYrd}G{P2i!xVdgx&;xVo) zeDmhb2-~p$KmRGXy|rsY>i?{MhliCPq5ye%db%WTQ><6-1_!ic%A4~TQC4ca)?fUk zJYvae$lDP5H3kj6*@7F_Kw1KoIjV>+C%c=wqR%vIBe)+|!YStM^>6ay_qUOE?;J{n zhI~_tj{Gqkmf6z7N@+4dJCmwWJ=yznS|?dXC#?L}L{lCV9ABE5kq#Y53TIwo)n{v> zv=LS#gCvzNQrr2UH+8Oj_KBnB^1iUqulgHtYRp(CZl{NJ2N&4&rjC{w<5XUPqit0) z9NoQ=L;UhmZS#Bc+fjaGW5O1O`ynr0DegssOwEvo;uJJYgK0#rOPrdt>+e*NRUT z+NY<}r&Aae2QK8u2S4n1?o`>Gm#$@)sarm0c>Qnqr$pbC#`dF^g|+S=jicsIW5%NU z_9^xEYNY|;y30YDV}FyT-gfv)GHlQkedNIeC+OcKO-_z?`vIW$WUxcO&E#;Wc4B6G z*WNr~jgZ7bCkqXP&=FE*gpC^%cyN7#5cJNS0Ep{Xqv^Q0xcWu7Hq=-`njvO%?Owgf zfZExQ05UCxnL-Kx&YaLsA3r9SrLQ{)BMM)kTQjvMpC_wwqU1dPi%;{|@Phm=txc)# z2?{RR2`SbPPr^rg{(N1xqqVinv&dc>1THC8j5QjM4lOc?ylOqE@hOAz63HMo!sHTA zFm~`R)VGq7{8*MlI-{sc!esp;fSm!E1kF{JsHQF8{sWA*C29K_H*RAd`=aeRg?!{C za_*Ig%k!bB>G*5`!2@ZdTT2@oHDb&|&cFFj4%iR1qU56kV^Mi-GxS^Ce_D&##p5}i z>Jgq(>?ZCmSxcv(4KHMPvK?-@zGgr%yDi}K&gh{|~*S$D_cp4%6#LLWz0C?or~8SRO1 z!Bx&bX|-4Zh-zxH;hK@r`=gOwDJeEQ zr0BrJg3Yo$vST#jgymKhE6X(BqG96%y`UIjyh(siXz!fc1N5Yw1Fa=Rk=!E`l=!C| ztu;Dcq6SEBHY{xAODE%>sY!MbraAk!wc+Aw3ff3on}1W*!wY%Meh+2FV7{nXN4B;) z3xVtKbwB{nAm&SuXTqZsef;mguLNBnZKZc?x7NnR#l2XQd9YtJUaTM4W^{kuE0Gu> zj)RA2zbGp!i}J1sCI~`0#B!ik-osVfTa0uL?tUWh@{Sr8KQC>s12pcmP=DcT#rI$h3%ygcUwCulwh<#JFin~ zOP|<>j*e0U$$ccY<5Rjd;Wv-&d5M}(FeH+_yExY7xDevTUnMN;=Y$e&UdE%hAMQ7Z zXt zx1J*AS)ot8eEXT2+HSu7Wp}MOXkC&7tZ(u2AA-IF46cn6Kf9uGMgFaotexriLq>V5 zsCeAo0444$I_+fLuids8TVlAmZ}efn&Rl>{EvIFL|2BL4dWEvy<_I$)|A0(p@%P2W zSZo*6Mh^L-V@-QMNg+|-tAF+SY2J(cN6d ze|8Pzh(5-yXGm;6Urn9TTI1xnq0m809KGf3z%faihjjV8jV?44 zS6M)Urf|Z@Q12;WO=fzMeAS5R(@hKBSbC&yYHH0nSsm%-}wxC3jALpx3gAiV9vXBbhom z>?tzCnm(nbuIE*fMCEgE%;iBd!!|+F6gS0rlgAb&#mJ&at`&@{(RgRtzC>R48tv73 z8sbHGtnv%tI`6kr&yN`%R=I-L-ov&Wz)o=7cw613}U9_~Q=)HE4K^znv6Y~_* zYtS8pjy^*91-~`ISL-%#4Iv#12ghO30(-xr+=1;kgF{j@mtp|}r(-NcjMbkMWN|U3 zCC`y2ErS6!Lj)q3xD2v28YxuQ$z`Qr$2Srk{h>boA*!SM=7a2|78b?1->@UOIi;`< zwxm`0!yjaS{Nk}FiE|fH7amJ8)3gK29W7o~(bFMaM5I+3m2ECsy+ue8wIk@cRl~HH z^c#aGe@V_s_<3^divC)7h>^4n*Y|(5*3dM0&G2HyJpbnDqrw6Vj3|9%%>ypBIZ`ph zuL&ejvCqO0poV0$-zPf=y`iL`Ap=rK=59B8@h)V+K|p131cfxB6f#z%+e54*x*%rT z6U!+I+=SMS4p&(^2n!&mr*r>FXlr%4yMTy}Jh!WZAVRW-M&vG#k4mkl1cpaOkO!Sp zKwm^eMYX|sMaK$H6nu?T#1}J;Vpd{eW)7;|X-I-!#|zrsqS|fY3aiOxTb~2!9ea@f zuL92F$a0;dUyp8tK~|LBb39RIA@64;;xc~4+fYIGsN6UIGRX*F2(L%7ckQT{6>dDl zFJDl6((IOw`smT-V~oF55x#e^QoMw$B4H7~I9gYcP$m+to`+|s;o9-AB7 zYH0TAt>XFB9t+Q5>tue{=(o(eK%bH+zMYnh3N)51V>t(*Qw>=xizFNM)CtY()t{)& z8LrB5*csPXf*ToBIM2Q#2}KPL_A>dT#3=->uO&6X(~cT(q5h{peFOB$AOHccZ8P|d zAIr+#FaYHmH2SXMS1+J=z6_;^OxTm3Q`|aiAO`lmKA(e~Du`(OBH7#9`=HHNKo|yJ z06$-&_;|%z6gpA}t&pU&^ggKiGFh;oE#Bd6<>!5V%nM(xxuqqt+VgpGO5WleQ@N?I zqUWZ~tIR@ajv-1RD|ck*=x!eXE+DTq>ca$sW1kd3(&?;cK`IY2i22PI7OKuqS|BY* z6({H;lkL>lOi)%G=w1u~HBm?maPA?qomSK7{aOYyQ@S!bjc#iCES?r@ z6XcEayN!oDTPX7FkFq9_KvjO?CQjI5J?cBI_4xZQVI{p&GrHf~cuqIwcp1LitZt2} zjSBGnn6bClDL2D+{`X>%Z+Oe}sVS4iGt&0qu@cN}aqpq#+iscv#3grri4ui99K6kB z`veg>l}dufiY_t;TAcepycn9u4ph?ydox1l0FW?ZYU)sgHbUp_-Ma|I>^FF^CL6rZ zc_W9MQ=o?ZXS@1dpZGF!9#(k&%1QG{v|nm3aX(mDqSFBV7!+W;07DU0v>70a{HQF0 zGO_dM)a779IBc_g7jk=h(=%sxQVYkV@tabHH5aKQV&AG_*zIxXaQw(f1DPA}vzv8D zWHtkjJBBgt)?7{Oys8P+eo7G+)0Pz^Qgrdq+I)Vd!Mj?1PO%5w532?rzH|Dj zXBzWFL=s4Lkhk(kpVvJ2FK2~7Dqp@f#Z^T`nHJBsmzI7&>1(Nf&7kF=^OcwdiG?n0 zcC!&u*%!=dZ=x@eRQ*(}hgb}f%2=}+WC(q;lQ0Y9!!NDX<1cYQBY!R6(%&9hJHmNKWnrjY0Kd2>aSd4n8>yeutgeW>KyJmV40go&FHGE<=BfHp();-+ z7;a*GBgOTrX(}q_lwyfDdtx(Ee%8mY(Jk~p-VnIwKHkm}^E$X5?pe$|l*)~j1hK}Y z)PS>#FA0?n?zFtedNg0vQ%`?#eRx@UAgw|aGO`|CO+*y`)fhvegHn!!12GI}y@#8Z zl+?e&-{$U;tYS+_bmvdfo`-sI0R*>L{<@ZhdO(H)S8inX%U@HKkr1mx49`Oq4lQ0# zW;hMsvekx{5u2+j{ZX}~q$B|$;j0-NGdSkJ&H}F^q!3h8vQADNW{=(k1|swv$%@QL zg0}6;4p8Hl&LV_{7N|Rv*4;x&-z^%(Ex8X@bx>0odcQ7?r}_3VV9ld(@>(pU$JL(b z*>Y@H*f;1-vO@0(dL;&DAQ8f&Z5|P%Yg=yCc^7)ym>?wYE6@EDYB}t#QuK-!4mOW5 zN1(O8`x=`kCdPe<0mkiljIw0g%*q?TBS-H?R|>nlt>EcZd!To<HOvAy>X1tb=hX+d*wB@$6TIp@@$zxwZe0Za3TsHf95w!PmQA3T_?2w(Z<+FLxY zgmCIdImHS6!b9@O()wa(2;C*=W4R_}4NFFpXgO4h>=m)y|Hu;AH-)bJxx z^jrC#CfNIRAd~c%VQ8EnH#Fpz!$2Ks;fLTJFqNjI$n)E2!8QU$T-_+TGDA*!N?jk* z_;#(`@F~N?=BkN11~Yu@9sfm6Gc|#sHQ35SmqyyZPf0!cZb}~qk*3b$Fi8IMQ*!Ip zot6{IVb$WjL(&0POT1OcJhfDYp9ao8nW{j$^vp%giE7OLWcV2x;rS@vV&cP?Il}Z; zer4-HK?9R;^!52OsH!4G^~ZAM93kDhINo?Yu9GKpxtrA_fhGE0O;KoQWi#9spYxaW zFVFeva@VU?LyC^ReLnNqyq?+bKzea2Kq%pidZ)wSKzG|_`XzI@k3pr^&OuV*sSKQi zjuY|jgb&Rht*5?VxMv7Tj<{V8nAFe)puUvUeWNNhPgl#l(lCp+UA?Bb^NSReSNJ(TLks(c9`$2q06MAu13-*Zim!oanw#ynG|?=?x^5guG6}1dP${f z7kg%d{sp&8nNY>$HD3V1tDih&yI%bxJ|)zAD}>u&zlL{2>Pp_n!8YXYqjt>B;d{9` zmd*{sf9Uzpjh|DtFA_ccxAe`ttbDfn1*sMGt{1{4vPFDREC4?P{2-_k8{H!5eR}!w zEmmrM9v8#`Yp-JO>!hD^scew3`>v03BhsAvEje!0h$ulhJ39fIVeWBnxX= zdVEUh$4Q}wucB#*n!^^2rt3Y<+IISSO^&3<390V5r>>LeE*u-4{BH9(`FsCal;w93_i=D;^)G)ua3;^&9?>* z$HvXSj~M+=3(ysfL*tKe_ssv~MoKE|CzrcidUZmB_y7Dvu+wNNL{&znNo?*R&zG^c zdi&lcz0||9GnH_Pc*W_`dsgjJ@}RX19fDlpxj!+N64S5Jfp6xmDXDLGE6dwTnQvh& zHOao(O<$Nfe&evdSF2)iiKO$r zfp+da`44l=r--H(!ItytV)eyd9l2dJ@b6s_jlds0(`RYd>!Ul4PadK8Dk^4g<-b`< zc8vdGL%aQt8|VE5cp0G{Y~0KK@V;ovY(n%K_6%;-ao<;CC?VhBduesqS|L6fG|?9x zFg8luJ9Rl>qRck5YeSTJga<_KIhW1U7fDHf<>%tEyLod6jj7?B3sEK=RA8EZ$x0y? z`ZP&T~a40y1a5l+mO-wUO-usHpP_k9M0@I4gwhy`)0zmxNP zyWO*m4GC(nY9=d{l8q;7+fVkYu_D`B4Y|HK-jQ-tRBkJs5<3uXHw2M*+@7(~qvt_d zdUbcSrI>kp*4w_LZLf4@>g9V0XaOIx>}w-5g@})4m&8sfI<~CqIgK@La>4g!pA~&B z?9hC^O ziISWFe|1&Hw3~lELx6eCiOVHUR$Ju~`;O&pQ_uaI{RFp8#Z+~-DqWcGeBl)peK?6Z zRL(DDI1H~K5fRd$wSeg5xgl5QzxI{0gT`krBG36u(eL(U!E2A`42a512k#k3qo?UR zJQ?hz7AMveRnOD7=Qf@vwJ?isgAb`%a0J`U0cNAB;;Q^f=hV900hSzlxq*;s$1`Ku z5dB_WFCh(|tNU7Tf^HO4tx)w&PEyF>Bc&(xR(%+8yY(Q*D(T+0$(tbc#{7?OjX9*4 znDO?;iRWy2QA_J-910{SIjb6^LCVydQ<5Y;RD^_IyaLwn6#rJ(jI^}(EEg8sejhif zy+hI33>$k_JjPd&eIVb zxb|f6q8cqCRIwM{)_13FH}`k7=62Ytq}JOSG=9;Ss&Km4=EHj)NDjCfCH9_eKE#Wf z_beVOR2v0RU-OR*l__D8wK*o12u|%5ax}G@DP)6DC!QSQizp!F2tLl;KHx&3GBva{ zuebf`6i28%%9Geqfd)-8#qfW}tFvl`xhuvk5b?gUw1iU{pq=yKbhF$eEw848&Y39H z%4^Z&b(Dus#pic>iT^)P*SL~9!{N?f5yZ5w)*VsS4E0X z=y2(?c=p#na2uX?zOjqB===qFSb&hO&G$Y&PoEC4%awyiQWgJyG$x?lpC|<_n$tEY z51C%`7{#9PpdUFwUathlqqE-xPL51e%HPp063JNK z`}D@=E+xn(uL#mj0@kX6@YK?Uwi^8M?sDJ0jko~%^5mI{1_opV6Oaatj0al^;^naF zJ4BN{G!16QKK$e+PsMX}c~WhB?cwIw;S0inLRp++Sj{~y3%!1X{5s9pt~s0 zJcJp3I|gAXDAK#`gB;;cfu26fRJ`fAcz#iR>|g;$qh?P$uUOuo zH-pL>IB-2Ov?kmgluP2SSDUU7+y|M1?EaDk=OtG^Ebb)#!nm8DD#g zbw8=X>QS`(@B99?Oxwt%3G}PW3-WRYq1rAxOqRO_izX4awPFr?#6Fv=jhB2Lk!;J* zj5fV$Kj)qBifj3+T660)CN=mT%^FakyGd@FDD-|$F4pNqVv3E9H7CR7xG@X2EiMI4 zmCD_!VxBl7xpNmm7AcORH(sWSZdJuil*zE7f%VxdomaIS>lJ|hkpYy-DMiNeg zHHqh!V<_Q*{-&b+LlUS#N}|GR4aYF3u$P{Q7;%R+87_+K7|@H=ApZKQQM_u=83Oli zqzed?n9LL05^EA{d8SIz?t4h+8W)|O-ykQJH`AZlD#K#_%oxEU>Er**Kd)eXN%pwq*Va{LT@2J;kZBP zQ$lWJj1nDA&}0VJf)F~ch3;pz?P!y*7mO?sW6z8Ji@eO=^|#Crk+mOT;H3u!c^X4k zW2%gQOvfILN%sd4J!`Hw?drdC5nH>445QC25T7_Rf2Q1xD;5xec5=T2#_H4PaoZ{3dcicinp5Wc3nPjpZu#uC&)V4krs5tKYIdZbT~Tx8$#0f1Y^0xhlMkrkjAz!|M*JZiCyL%EWvs{M3xsvwYh97}h;CJxfBSf}Y0t=5 zjvgj0%K9Y!m^_0f)z?x~vx}KLteNIx;0Tb&(nv_=g^fBIUUcB8r?}GbZqHjv(X!;( z%=`A&W+@=iY46SNDZ!sf$S(zS*~s*GuiG3J+Ha#VJuBOWeW0EnDW93q zOc^C0aFAxqn|Tcg9!%AzkUf*V0Rx?~-_QN}8~Y}s$1NkFa3AOjom7GNp~|dppU5nz zXM>tIHtwvAE;#%qe0NmtoV>fswL815WmjHnOvI^IH{)gZ|Fzs&F<|3d8W}QH_Ai^) zHsi5_k`j=|_d}DqyH8zZu@dffko(2i=mg|6RW@?|{>nq8aD;gChIA90+GV*HfrLzdBjwEO&D+NB0?uTx0!sGv2 z_iX&*zGj1cU5?rF7{aJ5eOTp1^K0#A%azB6+b!f`b~zygGZ{~wRSSzya~3!kWr37% zeG0?TzQNVCj*&SshS-Ouj9h&>q`9hq!$(zf?LkLnb%NmU6EiDaU8GWM(Nfb4i@@S9 z`SB#%`VJis*GMG4lx;qEOJUKZrWyQWB3Op+y)HkILXfAN>}idH+(qiG+2uvsy*-FF z+>DC?u0*dck-u7xA(_I=s7!XWO*5juv8x9T$dF3Ra$O58u~do35qZ;vuKsiXj0|f- znT0nj@JiU?T373-#-SNq*6N*2zP~qFktQ9@r8|vlalq#L9hr=XLzPdcgxrJ_pQX1lj*scb96j^F~qH3lk{Z#e(^D9f#MvlJuWBjFKRFB zIhuya9Oe>pDted=d!KoLdL+}>JdywX_orgTcHphey!@+{gItgKbA&HODdM(tOM3M# z+YxcQ6hcX7=6j3}ubC;6=Oc+5(eDYwWO65ai?OkXV#cZ?wA_TW)P%B87-x+Os0B)l zj>BKcmgw#ms%MjuF33LK4b^VAj2#HVW8C0KTC#KuvR~_w-uVHV8|rHIzkg+^5l#1n zK+RCc`^;z5B>Ya_Qj&XL)!VmDc%linsa8N;3Ul%+sc7MC41P<@zN~BdC=Cv5NOORI z{09Sq*yU@ei5AS`mmW#M&5=f_xSHY;7xSrKWz}So&XPl#NfO4HBx_$xA(FeFx|Z+X zuc;Hacl*z3LR4b^#CwUiACE35OuBt%`mJ#*W@A-uS+o*(JS)@0YPGI;mbvF^AB2v( zGzQ2Vp@P&@vhpjiB&8!-lhg1Y#uvt3c{|$Wd`y>;&P=zPOFxU}cl6`4ZY*(jo{04h z8Fn~zt#0x&?o`gUK1V-UppHe{Ce@0$6SdBp>J`>g?eGtUxYy~^>r1c=9A2FiYFD~w zeXxcuD$EcNLpYCRWo6^MAT38^M8cUh<3?6b8}d6a4sZj$>yvy7Yn|-RetD7E?yJ5d zn317IZzBg4oiv4og^Me@r$`S&!~Y#hrr5BkD|ztAgr_WbSu+O%H!hRMyUfO6z_=12fZ~o1q=mzeazbB&B$<1sh;3jcINI3n2hL*Pl z+LaO3Qx!0-QX_R&D5%zyHg9_&_mA^X4b zR8>WZdq*HPkux+j0g%-qF>eoJ^8zVriUT zCJ|4&i`GIZ+TnWj3HxFUyYd<>h417Hi@{4mj80ta+DrcY#M8J2@KubAzbYo<8~1#0 z1m>3a+f!VIH!#p|eRsh=adQ)F;BNoAQ_t(VkRYyzCYD!RUK`-@4 zpXo|;^cU_ss7OH>fvb+G$0D|h?V`;o?`IM%J#%aNzaI3r)R{#JW(U4ey$*eD1zCZ? zpW~(-B)%LM8%sn^zB=CR{Cx-x^Lr$1A7nrX=zJ`2~cl!m} zOCZ}ta$89-19FYvvj3oX76VMBQA6kJ7c)2Ie5vcY=RBYTHf1bF^18WAW?) zGz!kOn&QGL&`khH4Bm{))e*lZo8wEr7tEeK-M!Ol{FzP0zI;1V1A@FK^pf0hB6e>p zRAahYPjzeUl0A#`|7(}1&@?s5Ro9b{Y}fA+{-17wV1^C)9+UG;6g@rlynRLsZ!&K= zOgRZ5ef|RGQ1HL=S48z3wyz- z5|7k#yignCw9?^fVZd^{NNnR2S{i$uwq7L_NxF91A%m9oRJfIzt*SQH}LRsNZow?IJ+ zTrt`+{eS*k(yccOMTPLC_6kRE8Xq1#HlrL86F0YdBfuwkG^ng6p7|`FAae<{V~~vx z;kmLtdbZbk(r))<^t?1@Y;14uone4QlkcQ1Ml8tOE6Ye`ekJXFHm4e3WZXOGmK~)N z?a&w^T}koPNJ6@B`TppY9E4k(MtI~N;7OT{H!bDO{~Y{*SciCwB%HZY?6uKxeL}JB z96~hC)mK@+sLQ4IRr6_5VjZuU3L9VO!OQpdv~Vq{Zw%UA(}&c6=n3J)f>tkr=>ft? zyV}bsl5m>)ME*^FJ*?)znbGfzGl6pabmb&Vsu@!46--v3PRl&(ggP8qt#f z-Nv=^V@tVeTl8fvQ_bw>c2ju_*$bmc+N<6>0c)cF1x>yb3@`XIk3!m3eYoXn@g`Pb z@R%10A7X(q1}trewSi7C-STd1AcAu#mU-ERAE+7C)q1!-66sL@G8K5sBSI=Q+}x^8 z2ArK61UKk?PBTshfTVRtKp+-cn)c(mg{}^<;0$dgR{8=8A3R^%zfZs7&z9HJ6s8yC zbgrA{%VPNo6vmzl0vhN-eD+M9xf}21eh^c4$SDDtfID*JkX*eaKh&1yW$#BPk9pLfu8|BC$Q)V zZSCBabcI@4$sN#ASr@_^6lkyDBTkyLd!BzsH0`fA+r}HGwm*veDj}$$7A57|bZe=@ zC<_Pubw}+Or#hW$Z5Li7=3{Yq8eTsNayfnz5U>kcvPC-~3K#@q+!4`cQ&|ecqO94| zd;I)JfOM?}e-q%7jM3;`BIROn89C~2rRbOA7C&0W41cOt= z<<~!OH^bl(^r$YUf}p=+8Wzjk<%3xEPPy96=>lJ}+MkL;1IGlZt$Lr;-= zWP(fot>|kP3la%IUL(Wy(8PT6sNw8gY_h1j;;DTHS2OCv&^(9bas3f~!`J%L${HOQ zZ{OnBjtKKli22U+G)Qn0xV}JjG48oJz{<^y(8~c=;5`g7Qr6K416~pg-9kK&KneqG z<`ZYIaIt1Q2Ww0#&KH99OrUG-=kjNL$>2;?Mad9%x zrw51+v*lPp1}GZA?S$ZTxoj;04`UGk7!cYtTG~mV=DX!YeOh0q_;KNRBq>=&<{@H7 zdwLa9X&5HpHhz4IoO@>1BIl<^9@F?J!S5~y{fEz9#*6!t4k5;a1()guiJL)}6^MKw zP!|KYErb#Wa23G#h1X36yCQH;H?}S9!MUmibH~$Xq;QC=D`!?xK4H5}J&=(~`4Jcl zydXSUi+V?IkRKu8P~Hsyh~s_}20a1j?*Q!rUR_$~FRp;#{pXMjJ(^Z%i{XRbal*eL z1GZXQd4{~y05&!SB%^CN?XUmPA zRUOP|E4uyR5t;Sh5fMp3AOMD>$cHLz^+BlyRz2`cyaD`E1Xw9~JPys_Q`Fu$0hEG@ zipuGZ?{!b6RA@Yp;SE4>K>OL_Xrm3N6z(v`W}@7Z96SZ&XlQ6TYP*H``B|_N5bz}g zPYS_~3+1W_2ERG{DZt@H5Kydt@FUPTE<3Xdpkf6ik6daoK?=jrx{19Ol||Oh>MSv7 zTiEn89;pZNbY7C#@kRd*n@8IpvACk(jOqu&$^#Kv^AW{4pM^Ggo$D8sD{wL05=t3U z_{6SWuzPi%oqaRDBRVeb0KOgykL4JLfYrn|@TVX!<<$@i*KwvF?C&GF9S+IBHhfa+ z2xF!YG+Lx-haOHuVo*8jfsNR`s-WoTj$ubAL_fvpEe4Y784P7gAt4?Zup_E^js5wC z5@l(o=C{T#D_jdVc`C-S5m8I7&2YIO>Mh0iNuJqf z@t=p_jo~I~?)BV%^|-jD0T+A8jFHhT!W`rJp(&FkS9Jh^f=GYDtCQX^@grSvigI%e!7K|n zhoMGaU)#EplK1d^cY)XIX$179<=T9jA^?gYalGU3X@IQL+?&d%SGvB85#X z9k*J@lTkS3f}IhqeDXxElbE{aFqtM#skGGiPiflgKkYbu)R-9OR*M+jEN{GWqPOl% zoy({MmE=fmA1)Bx*d_k)e-6QrC*WXG3s?zl+jH0L-T-3MKZ1hfa4&;y0Z3$sS%tH; zcnAUC@%Bt8NSX8UHmV|>IYL2z{gyd39qxh9HVJS-B79@;t9QkZ=dO+g5fJ247|lq5 z1M13n5SHaEDe3*!_7Wal^)6Uwz|L7d51XJ0g7Sxbc8LX5W5M3si%PLO0S=VfwA#n|$q2T;cqO-|faJbY*z)ee(T%Z3zkM5*7>znm`Ybd3ia4^z}!th5&aX=12j8?fq>TNLD%k@5{>0en58s z!nt?gGj5PlKF-MHEZ!_Pn$=Kz2$ zVsRfJ5`sFx2<)!2_U1K3p4j7X!L*y)HRPvyA}hOyaH)X^>0@T*;%6Hl3DnR#K``id z%5=3_gexLb% zTq9y!9|E(2Qi!(M+bjS3c+0c5xu9tC=kjt1R8v5lgIY%RAx9~#9}=ZUpj0iHw4w-? zcGB(Gav2#OmVk#0EDCTJrsr7<{@SevKUVd6c2eCYdr?)h?Mb<=Z^+tM=_dUuL5!K}oS{qms5I7xkml##!)dWxYMOVkiiG zHxzK|bQ(B?vmhvtgS#X)HkLRU%2OO$4dpMVDy(%AWFF#DGu1*L55B47cwXpbH0CPp zs79HdQywQD!OJ8`-QJL>WY*TVZ8gK1)(QX90*D0^{T}76U=x)Gl?iGvfC=|!T)l+d zc-p(i?*H(R6teIZOQZ_4;Yt5f3Hc)j(z=msfBy2@DWe>uVV(LT!^+b(NHFsmF!}pI z7hd9_5ln-%SkOH33Dk3Z{eJk76x?zUxTRek=FCcPe}nf{8Uj`Q405e0L3%)@$k4e5 z#OeD``oTaO1j8DKexQ@}Ed9u7X5l_)OSgxJ|1PSc0??-yJPGFc$xl4k-zHsNf) zR};hxH~ty1Sq+aSi53Xd(~!8K>hdc+7kd`tuM(fXl39E{yss<1BTbGzr%7jgeQxLL zZ}jE|r|AlkXV<@G%-l$hjxlz3dXKF<7;dhI6IdW22VxIc6TT9=x-vMx(!O~hVDY8;InSif4IGp=OM9iZ1bVVn zp^{QFz1{_^aRr5YMk+)Cl{UCfTnu0NBk%tE5NY=16xk!iWWUtHv7cWop6?zSnG^Sw zx;NIHQo7|2%MAikGm}dOQad3aJVCgmy11mPqx0qE2ou7{-@H8wNO8n$iSKO3rY~L? zF1Efkp!eMoifDm@gyQOYLPTGzl1o5K8-80R!T@L;5_Ev%;86dyEQANO2v8@!A(#S5 zBIr|s{rvnK9J6k5zchc1jrFC!10zg|+Wk>aEQQMw`o5)olXl`WEShuerJq z9aqf|{9CJj`AsK>slv44f)vR87e8X=3PsRWGvWv&9^c&9NfG>;0rknJZlP77CD`6r zHY>4{Pg0JgeBa)$niI6Y(~~(N?deIemMzL~#HGsC7V5h5T0?ZUx`$`pdi0(7S3l<3 zJ4fhNIOe$I{v~vLg^70pZ?tUB24-|F5=lv-;#FE=nE7W!^I66PwacijJwxk!ZyKYr zv2;HIX2P~YjWS>YAQXY_6^w?@$%x*f%0$wU8Ub;y$OU@=JmO(g_hf|{?3d8#MBR|8 z>kiwH@bK^^O3fnerW?FHt7>Z>>6=6#2KYi%0)v^EnV|xh3}sf6U$yQNtI+>gSv5|n ztQ^!uLc-D03k;kU)-=ECxw)xa7M+kL(ic!HU7TC8$u5L9rAet7dR*BaOGoj62EQom z03KU@eYIZ*{vm8WJldXkG)?|0oDX$3VpYeq#Xs6lWenY@JF9@tx4>Rwuk_geJx83e ztQE&8a~sARWZO>xAOF#C!%5Qj+iKb}u(k3+n-hJDdReR|)xnaIeS?)!B}$6i90xRo>Y)$=v5>5|{4ncJW_1lJDlfmMm?q9i={MlIp4xh2Zh6W0UEv*!2Ui%pfaa30zg-zF0 zac!2N+fWr#RbLIo(!CRZeD6V83~4Ig##7};T4Ka9SshY?9vS}ao$$xf8tld#4jaXn zltMGUpRR~*g{!aDd3AnRlq&f|CQ^aPfcvOSHt_!5-U?FBYmLWEYy2z9>H;nmHvZ(8E`hB<93(a9hS97eid~v!`_L`yPLS(EWpY$tf!i&_bk@b*r z%ZQK=B2r(uOl1~0L!2SyFGtX|3M-=dx=nc~<`)(i5(#yNL}5}uci*F|p>!A(*1QLZ z&vZ4m_wn(;aM{j-w_ei0;cl50=ZB~$dtltkr-{>2g`>l@nm;@)`B-5yeP~{Uo}P!S zIOew>5>B-jvk<%9QjV2QlPc!87<*70 zzgvk2ssDRtjh2YLjcStZt@ZT2W6Z!SG-fRQk@xr2Q!)9cK0}vbRW6Nl>Rrm$^0uEpP3*`-o>HcEbX;8t3E2H(0-T5^ zLN~K3?hRz2Vb?WYZw)KC$>)qTjgM=P$UT0{QtEscsdL!@T#La*FhAzm?9Ke~&HQML zp09(ON5GF`xrZOI^bZh%OWkc}Y63wadI1r&X1&Kf$cxZ4G&JBBSJl*H!r46CZNVob zB@F}$9XUG-vC6pc>M|+&;f7Xub9yLwMt%-$@mm4jFI!ez+YVZEay5lWEgIIz?IYFh z@y|c@w44y#?Ej(WO(uj`npgj~G`v|C3|c3=1H}B4lwsJ@f36=>d1--<3HVYalz4bY z(YOpBZ#C1KBY=MkiX5$&;o!tU|=bs$D^JOrhinyeFP%#fR3(Z2XNyM zfMFo(HFvJy%>MqD?kR1ZHR};{|Na#JSGih-<=J(P=1d>)R?<|h>yYOf>MDlE?Z0pC zmCs_@t&ICx$8nube*YxB4^_J1vZp0*F(Xcr$F6p(#9)-KO68_gv~8O#kvj>I&GOXTIr*l;x*9>00Dei5|P6f={isu5HfX__pI`092m4=UM~HVi+80gU z>lS?9J9Er`@7{b-Q?)RrwMOeiDjc`!-f6P(JiZ-kTilca9o_$5lBh0|`TQz&STiLD zLpJ4JwnVuhQK1Nbm0S)NynzG66mxjTG4=KJGrsg5i1w#Fhy;N4;_xRqI~NypB$%3x z`QZA3Po7CN(1qr~!rEGJxg~q!NQr1{oB1&R<$XscE8lYkk`d=MKV;uav?62@kF-uT z6N4qtWK8<9A^9QuS88*&E>5@_8uZw1`LwoB4~LQm80&p%7V5{WFZ(614NKWc{D03{ z>c?6e$%kVHgRA7TItmS}f!!ILSfhkT$&@cYN7DrPzAz0osu8dz?=*FC!8IqYQh-L`r}R;Xg=5&N*V9zk*%-=5PEHQPM<}&I#{lPf$QsMcaF5ffn`FXjiYeq}t#gatZ5b+)jFY#4 ztFy0Ke_WKtkrxH}D%#~n?!3=$3cEFf>hn(4ZY);XakLyp!B5w^;#b!@LU0 z_|@=1(_gQ|Ph?~Ing6_wA6dH{Ceb!8#^0ZOwqw?i&Lk1o@ac3GQXfco|E9g)JfN>( zCUfGZrKJhU%kw9gFKO<6QmJ!0;qp1zL(XE?X>HnYnvceM*ntv>P1WOt!pqKzH~u~E zE7y3s*aunO-4z9zUvu;!o8y6191O_k7ni)eY*`rHqwaA z88=rgv&yl_I>|$U26T5(gau%}^tl9rsQ)-({|#Of)kqt4D0yoWJ?|_wrFu z*%|>Podz#Tn5XhdFV2wS3kM?fa@zVqiUf1Rkm?&QD#~I3Kg*@xpp)y!micj}`{SO- z;bN%r4q4+IE8<{GH_|(6+vJO;d_=mgKcF=AtYdD?Mpf(x`5F0+eSl1C?2+v^UtIKz zJ~8DgM|W#2iSd9rS1e-$Jf3okKwoG8ugx_+5ET_2%#^~0a`AMdFFmA$LY~JQP(cU+9`wZ6ye2B_ z@@EUK>EBroZy>ci&Tyha1Sx;Ee@IpKHU8_}3_F@UH*)5)#&0~hm$78Ia)3NUNp?TM z;Epj$Ew;U6l*G)fFsY`2KIL9$T%3DRp&o|f3p8_V*POcsUw$wnjeIb&*Z#z@>42M< z`eJCOxRFPQk2v(kja?I4x}>Dgxw<+YW&yG|4i{mK)@EO?*RLrY7xwad*uUkopVX>m zDF1U;W%_t>e4HFGb}z_0k37V@LhI0BEovvMrn`UIulCdKigNd^9~~XF0UohObijb; zTVEe8R;ZEtkf>&CpkmG=m~aKfMI@4Kqmgx|(v-s1oK zgM^HXj4+tl%+|d{R0SZ%{8Cw29OL!1w6w{dM!;qo5xSC`*XeM{7#RF>0|kW_3furn zrrG*Y?ysI-xW7Xu@p$Cv!W+(|n4CKnY zcLLPp|Az9J6x!*?#R3DCCjXDEw~Whb{ho(!It`?|6qN1`1w{n`32Bf}KoDu9k?s-+ zNdb{==`KNOq`N^nlu(3cZO`xf=K1{Jc@*(*?`yAXt(jRfB6QNfv0HRCYiMIHsU-Mf z7(l(Kzi0cFmuf$@N;tKCpN3(pz&)4o+$EIT+-sK8`b_B#0A&YN9!_{G~VW-H2-47e|#}s#E(u^ z?&9Kqty@xZlb2cMfnx15tMD78rK_m6+i&AB`jo6LQ-+OG3{Y_eeA~`@8N~F2?d+*B zQyABxo18tQYkYQlozwkZt@}-juKp}>hm?3zwR}z2Gd>CDJya>#+yxlQJ5F9x_pdoo@QN(fM0D$=WAVjGaEIVv?-B_dMI zC7GR_U8#Hq&Y*k8$K(;fFyv3?B}TpFK}Cd7V&t1F60xxF%yu+yPi?a1S}amrRw&{` zF$*`*JxdvFR$TIz#lUIXSj0N?)yCfK`uLzghTToo5u8#Gj~hUWS=$lh9HML?agkX- zfTXXl4-n;uJ+T)iCcdywxd3l9X=1j43Jh(~jEXp{U)|c;LXnWARK1+=0h}6m9qmrX!}uuc7U<#6(Bcg#4l=ubEm$`WQ6ypapmfuo5R1*35UWk{i0&h>vTQg};)0 z#}Z>?^X$4qp>F8n!MgbwB?)E~Ur3Ze&G~>d4}>0yvqk4}NX1lUY;A9s+OH`sID=dK zW473=O7>BU3S2@$lI@(CQj`0+g_0FIoUnTCA320yaCCG8%jnX6CUEWusf7puAGjfv zy5_RHx@rtYpE6sJ$r07P(&02WIW=YC7Tr1lKyq{nXDYLfz%Gd7S~@%L2Z0j?nMFnI zusv=rA$Bu-Tm8oiY4o>ym_|Brn8j!rA;F zXSd)&2RpXopI^lAxCsNTf`nHA<6yfv%85*);GJ(iRz&;K$_j2S??~x$ipIvqc@d@I zFKJhY+(&duj~}L2DYCoKh z!o{})oSOMuqa?}@$Qwk|gK&E^Vh*@#{b`+mKI52~nE@Y)2|z*zkQaMkx`uBRoo`Rq z#*+a2HK;eP=vCVQgt6NR7X}O4I-RH;CcW1g?`WZJAZRwy0d%i++NMf%+Yuccs{;v_ zJH+5*B*e#)PgYumf~%|gi5nhCpPDu}*CS=Q+^pXiOq4rTzx`Yv#6Wgk;h(jcZ$_)% z|3aOyTNoL61)h;V@MC!X&aAB2@+)`#UC-Z~7*+&%3S5pOil0enWm-v^-lg){EiXe0 z#STa=yvzsvVDeo~Pt~~UNsGd)X4NtL>>7MyJNnx%{hS8VmZ@T_i zMeptV;O*JjbuF3vM{)7pkotzwYE63z=BaqfzU%%d}$f2dDkA#P=MKV=k8DDZ3 z7PVoBMgz|#&wi1YRKeJo$^-h^>q%PUPF(e@eamaI*KEnF>~MU%+!YLv5j0ssW%R}a zPMA>9klDfER#$(2C*q>_;RA!p!n^0%&Mqzs>w}qy$KKU6Ah86f6vMZ6famCN+ieIO zjU<=amxwGi>0E?^18<*SVPRnuYa0*Lnv#kN|Lkm5Xtl87p6AB$Gh*K6By|fVbM>0J z7XA+BdB0fcPq02Uf@ex0YWLCn#v;stC9q#EzcSR|_WHBM2!3}wH*(+tVNcv-rq&UH z6Q~+5&fVO9|Hy`6@e9P%X>1=Fz-``>DoKqP^#a`u-@z5};{saSXMGX?<+~8AfCTvH z)!1QyzqSmNEdTzxni@tPo~yu)UP}=+ZpTIb5c+h|^WUWSSU?4gD%#eWW30X~EZwGQO817yoWO#vt1bq|)b3_CM;nstW z4_d9yd*c8E(h#=28=n>7=Dq^H%IzR@@V{bhy?f1UpN|j&s;4`!>oOd01%ZI01$Nh? z;^G1Tp_Xv{i3>7|_0d9VslPwf7D_uK={vzd#K=VLfa}hcD^~y}QNH;Yt}hdC5CNIy zZOGvRkSPi_t3Q7hn67ms0FhEVU`l?6uXm<{0Y)+A%)ra#h+DIL){MHzZ9vjN4r5kN zOL}Tq9_=noB3|w!rpvMwj~ug|;;W$VPJy}p1OZZyFz)-;igg^q9UZJJ71&~U zv*Mly{HvuFu`cnIfFuKxr~az$;=qO`5L}#r8IldM8ZSX3=Qg+tukJU=CN_OpJVr&$ z*uauo}8Q*PFLHuh77aTMF7zn#@%>= zj!1`|@lnQc>SDuRgFF#gwpe_2Sq~47g`J%UFgBGIv0o*8)9Q4Mm{rLyHkS0@ko|a9 z;a{L@r}8s9Dz+Y;h%BYwGF|IaV;_N+!0=)!Kr`6JF;yhOV2 zrC)nU77w9Q&vvvV6!)N_QFlJct|{s6qNuO47kZ4rOwdqYzXxKB?9D;}8BbwDZQ1?~{#ztmUz zdN(4?>zoqg5B|Qs7(luQK%v6dpMc~$Kgcl4)M6D@fDZ^z?zUEc0)M7`xbzWN7v=*j z;Fo+5}FxU84uYoOuJ1DaA>!)hVWL^gK zay%lebLX;MwwCcr-S~XbmYNOzY#$GxV{|>*!ovx@hvjy(b*ti%G%9Dr0=Xq&oNiss zg$sEJ!X-yG9FP|Rbb7(HyahTH_?)_x1qXt7jJ=w%Aq`FLGX$On{`r`k1dW0!>sa`j zl8wJcb&(Dt;0k@j9basOS;HkDXoF*-wed3MEht2Sb=V*h7;=yCuyj!}ksdfWIO*fM zv4^kb8pEM}lFfNtNV>bb8(LXi%2L%Xc#x9HmC8&^Miu~9EFv5kZ-TwxUmN}q3@2+c zSd;^oEK+*mgJe6az_<+s)dr?ZmCbZ00?ASyR8XcdP{`oT5`zbKeFwZ8`|uW;z);q@ zv^!H52tI;6$)dy-6;wz&0VTq=tV`n3zj<2KgJpvGdV*6cvA_5W5n|tH1IzvUlLK~r z*A;u;;ZR1Ib2t(55E^8>f8{4YfW;BYOGGqIOM&}!$))h^v|a)YZHqk(MFSe@!++qf z(frfE!ILC0j9fd>0J-}nbNv0cU)f&Vv;8B~DkEdlec>okZ#dh#B`|bX_8{&Et=Z?NY$iCA1z$;F@5mP2ene{dD}*47&8an~M&TXxKa_f0k-A6m0pA z^eM(e=GIt7;=$cPDMc*U7-%x0iZCTA@~35X^!X z5Ye@3KJWy<*+mAZk!O5&n4)i|KW-*%_s{yD7U0VlZ0Kg9bRAkjZu}v{DtXL0SWZus z>kHwp7WRIemRSu06Mq8*Xg9S=jjKBj(Q0`ymxFZDs3T3+M-&U-Z#X@oz(u)7o03UM1a9DNm>{(g~NU(kTr1 z`b?%Xf);X*<`}uTi`zS&KYKP09Ust}5^!5)Q#JkQE8}qY@Zfbnu>nCiISkP^q?EG1 zFF=lqEJ%rLp&PLyXi&z)#x{naZUm3w(yM;FvBbyEUkcuONCe!x3mr0cbY4@XyVbvB zQ*6+I-(XKnY+LzmbSZr1O@W@)?lfM)qdg5h@4{ueu%aTKnwpk(ZALD0#hcnwNXTWT=S<@uhM=tXY6hZ$bK+taIsx$HO5}AAnYk}Gs z3~i`+g$~FqmY_B!NO_1sCEJHnTFS=RDefsmisCsvWeB6x8E?#b@HhsrV_O(NptRw2#&bXY0(w4})d$MW zl)>u>wX?G$V=E~tN(mP^dUqKz8X*TT&GR=N;N_V@egD86!7!7GAfa<~`ug7@t@GNQ z{kD(q*SRHymdraD(nkiOp?Emt9$35@qX5N4HTOS8+jIW_{jmB^0>=s+p;V(G@vg6n zd!)9@s>J2SGyH&;XBFpf3-8dp@t&$oFPHOu;^}D^Cf7b=jgf$Qp-1zms7NcmiI_!P zEnK<^u3Z4y_TVlzo~?I5j6k9O&d<-kf%g(Q)Nu6!&~+a^lA7bJp3a+i@(P* zJ^lT~)1zq|-Ap1P6v$l%XDAf1JCXl{n3&s;Pl3?4i|u$Q|2oI#eA-!!O7!&fKtiO0 z?X8WY<2`uD&pGV zhI}znof78w?&zo}1{!t}d?c!u8+#ut{93GeQBTxIrlR66GCV^H)@8N{uVt_(F^ z8`gMG+!}rz;ACohpnWCa@w3~GIT4p4;dQrG8zpE#%D6P%YSnBwAefgWtqEQ_A zn^vD-M^hS4nvrXEMNWyD3fHf}M8*j4D0Im!;JSrO-^jKJq#@shIT0SO!NMh6z=v=z zT_TlY<6j!==)i)X?+&m-5j3JcAbv1`V}Ovia0=%)H+8dQFdjR5-GoD=p`iiMH|Vf3 z7yw_k1m6|fT8N3lot~b~8BoZ(*J3L&Tu4o#q9PM!rrq=4fq9w#EEzVlXQ`v#^~30^ z{1xWj!I9VY=GIp-I+gH}FH?IECqJ3KZA*ir8ydF&2yW}vVcCQ0*9O1bLY0)3dVf`~ zxOZPJQ$--395p>NV+%ZK`T(%ofRcdS#)H&RF^Bax2p)p6`L*!`p1J#83l1Cv9Qa}O zVBPD8o|aa^x;^ynolp^P zB{IJJ3edTv>(8qlpkM;X7&=rhL&y$40bO#bX)o3KFW0lprxzeJZwBZNt`08!R=5Ep zKt7EFVB&2kO+0WNq{sFHC|Y9Jf?l9ka}69-ebm`H0NL4}Z^0PkF#NA0vZn~RUwux1 zIj_$+das6p^){5L+P_DAC~~9A4?a4N^%sM@#BaFH(n3%wBD~}N`MJzX<0+wmO3O>9 zy;CwT-$SCtjgE!d+8>|Yl~r%rbgv28M5`Fmza~4ht;2e9B1!XV?6QgVbaSRoB6D|H zLC(#`X~Pzdg%v7s-75kY(Zl#RIv4u0Q+*^@e zk$lZTxMGsUUn>PoOig7%H-jK!@{+rd(A@#Giaq4VFIR`%Sz2)8Pk=~V0!mkim{6CRaxMUD_VB*+^|?TQP{6s_0=EtsSRP zxwLLoU$IygQyc`q6E+{&whXZGHP_GPF8^%TeG`{)5)#wY9&F6{qhmZ%Av@e!#&^Jbp%0KZ zE9A?BfV>L76Db{_VF!#Sk(sPHdbT0G+C?pBU-cFtS|LM&NvXXOONT-*?*ny#^O?l% z$-)4sj{1Q!^c{L9rM!ZFdS{Uz1q#$VXI7AeAHrCf;mOwErUa)ibW8^=`l zTn`IRci%SN1?q`Q?GJ3ym6BuX5tPD^fvoG~ zv7My>%ns-tTp$5A8v$$UNfgWF61&vkFW_{aeg=d8?Fg;_CMhWnqkfIrUK;}Yjo zg0-Ecy|##Cf);$blS4vJ3A7zP-mLsGnEviQu}mWKe|XvPFH+;MLEIO1=!8-Rs|hVZ z;b?^m#^%#A)e?v9_xueUsj)7LuPtODvN0j&7O z)iXAZ;ri(`MAGcEWNM#IF7eZ9(h$hGQWL zJ623=@LH#BN!hiFDc}_}Tt10{W}&y2lk6$nU2yBjOZLNE3}a1zMn0)AC=rM}6p<>{ zYL)CViyM$@FlLr&J?-^uI1YK%K;t0bBOpkd;;=x;*!u>kYiQvCwu83aP=JatRvsE( zLo+iN>2V%dzBtlW0YMi8Zpc7BIUzO%MS%As7GIcApdU9+RdQisW={Y9gDnLaJJ?4K zf}(1jM6ARnd8H+PVB>gwRp=78#3JJF*`PLJ;017vyFzLyhnI} zoL(2zgHoyO}@Vv>!vuh3rnq-8X|uix^LUXc0*OXY0w4p;+cuVprr{pYqV`Hyb@5Xk$6^)yvjCh1Oj zhdiGx({>L`$f~blTM-__Ua{9-0)U$l+#oqQ8No$?xjlpC-~?oZjPc#(e#-AU}YI8U6OH4?=T*e!bdxp9$i=zi~jOinV8@4t!2=qnj z{?Io|lZ9da1@lfS`*M=unt_m@e(4H&&#I29HO9uj(|?Yv84&qM>r3>(Sx1>xh3j*r(|al-|D6kO`JZaut7 zv9`7*oBchuPFIU9c5z{;!vHnEzK)w&YL~PH7QZ|&E`DP*h(L0BzZ5^j%}v19eD$kF z^Fx1wYSKTD;A30|j9QSL+yZ!RXm9NP&!2ukR=6JTghK@DRY1Esq3+NB_@TYzVlDtX zt}Kw*aurZowj&pDadFs8o`-e94qyp@q_J+En0T)d{MOXUtmm1Zyl~4ij(R*I7j^91 zOoFh3z?I~ORAOY!tdV@Egx59+I@OC&4IT|EcX3~wfPhDWp48t;O3IM#wNP}{$J@JW zI5EDG*Wde>D`fqk9H*WnmAz=h)MvhRA}>m5U?oh;(z|3_jOlFM-xNC2!3T=HK>u`W zC!siO%r`F6Au+wZ9W2Vq_2k69{FRlC$&!q{k(q-*`XE-*+EQPBCtpuNAGyp@zb^Cb zaC|10nxr!V6}c94h>vw}Kccymn3c`p60>D{Sy1GjQ}-1Dw_g~}&J5HMI^+_nLx0W^ zKY>i2h=`G<`x)P7cxR?3>Y&}p(EbcCpifz1D1|y3DKz2!#>IMEI8VJ*FhNpj#|d4Z zo%jpTV%#Z4hd$;3KM{~t0Eig@rArblCt75uGIZE*gJT|Qn)JgKf=VQ}+T(=}M*)~ie~gIRWwrnoj-?WPa?R4x z5)iUSBB0CJJ38X3x>2r_?c3DUWRskjsAFbQ4XSc-Qa3OGi85tiXD0xJ?H{N;4jjz@ z04gwpFXTcWUtZ2H7eNzD5_&2xeSX4R-_Q`9miCm{1;ifJ)goZ~Kn)Lo#2Dxj-=rk! z$tvqeg#PaCCXoL7GseaM?v8z!IGKcmDqH&n!CyQ_JrCdGF@f2T*2@z&^kwz7unXF(hU@tX~x~j^{Nr=5g zi0{*Gyuf2-6~13us@OO%B`khrqeRw_pB|4__A!d(?!70up{@FVaC6Xm=lK8AHWo$e z1-}O}6(-^$J>J(mDH1MaIh=MXa7Q@*$cn#vObCfWXn#~|_W=5Wy#WIHEK=)jkQ+eS znaWF$8-NswYkyz4XeRFoJMb{LrBJzL3N_+gFEf60F<;-^N32*>6(#zYAZHLz;jF8m zKfevY0_2eT0U(|U%0z@>6vs7LK0>3j^9)jp!(smmHTdv0F2fXH@;7 zLM)AV4Da85!y` zw$Ovx*w{3~W{}?%pe>ABG`ZrLnVB&l{Xu36z}S0AN=mu>&JY(2X881>#sJg%=wq$Q zLcb`)c61HeDMdZ#rJ(s|usDRgv_}v>*j(8~$PXVbjPHOX-VXY;GeeCKYQT6`*gpiq z8`g6fXr9(O;LW)oUP4Dlzl){${!svka*&x0k4*fD)X6*sXb77oU9Ju#Jg+{-&I+%o zcrO1DQ^O_Yn~1M~dL;|-R^?x=5dBhB#;o8u22jUFFdrS=ETM=-L+w`Lw;qTS&1=gA z-Re*7Y>8(Xb95y&wko+dN_ps}lq(skRVN->8{lm;01Cm9>q2C4y-7DFCdLU#KoyWUXzg4uOC)Q3I>X5&ILt2S!~C*ZEf#QHn`1m zI2rKDF>AQFEbI|*4_xAv$?H-p?iBL!vP~cRif59M5jEIO&;Sa^xXSd$(~VeP9)q7^ zd6`U$w5xGfrIp|T4I-PoR6-Q-pJdYCFZ+FgpuZ7?v$M0|w|BP&e&CDW7ZDX*fbaqY zNFRW~%3)&|4=A~NfO`PH$&&mBq+Rpil2UY3Kg$ZYF{nwnscHmaG=os_1@Ksq0b+9y z^ihuz1@Hivy2hEREHB>*T-0686!_4|8>*0PuS6b@R|`-feJW!m;P!mFXC)j2!FPRN zCk?+83Y2Eucv4J^FW9)?bxQP`00q|JM6O#_Rn-Y14nGt4N>GO}bY?uEVC+??JoFr| zRJ^InIzY`Hfg6&l`hhZ(U{G!^5A#gvapCpUN)! zam}CO&l|nhljEOO;l;Jw*$k`S)LGElVY^qRs8>-$nX78_QU*PY3pP7O(q%;^8^qOV zG{3#~i+bz4>2T6JMh-&LinjHwFj!Y{zHT+y@qny(*6XJ~9}~?>gN3=w`bXFvbwU)5 z`%EGMxBj5V@>q5Y+|)@VSPKv!Zlr4X^rc7{1@|tX@`j)i>+(9gK+s5d6yvas2$zI6 z=;K20b0MSS0%5IN#ui_{R7Btiz|~9LPwn<1Ux$Ly1mXN3MUEXILIB$S0F!pBD1zU9 zxZ`VRVuJC4_+oOlH} zX#>2=_+EF3hP3ntxyWd%;``D1$EFooRO_60RNn|UeLCQyB-8yI$m|!D$Hz+;px;QC znUr+Z%YodOkivb1I%pJY@-3Iz8kt0cmc!W`dv|l@@7=MX=X`__VSYtc zx+;2fwBaT5hSh^KPi5HJmGe7HpFSecausVabc)0Qys#u(X~=%l$Rv(!G{q%Zk$Y1uXQj*cBrF9veeSZPFTJ`De% z1=)!+1cC8_NDUJU%R9HF^_Q@M|4;if+Q zV2t1lLw=A+2cly+lFETd@5;<|Wc2cPF5RDFaNgXgn*UL>?;|ugJ!(M8(20@n zCg|kB*`0Bbt2RJL&lRG;$5%2lMQwFR-FMkchAM-hkc`^H19(ao0+gJva9B`S!M=={ z?C?W16f9kI5u4E8ccy4)h~l?p%HY)L7`qs!7>?0w9OH{e~2BCx`<0{me+}-v0g_ zP?N*{JOLEs`n^^HL@Gtbq4nm)_fHG&%~HLgvm7nZ#;~@wPW-NbOZ4J*H{klvxWc*~ zsU`2bs3_E~ol_+2mHls757J4B4!)`QwlG+DBY#|@XRzaMvZJ zs%2^Rhp5?Uv3KQVtsAPV@x(F@o;+8$?kvTIugmGQ_*GT4d1CzbTsr5nFcS(D_77Ux zci*D@_-)g3mIVX*!qbB8=an#-t(flw-Unlt8u(WX2fl=_=M2tIy+QFr&MEV`N_y`7 zY&U}i>G}D`7;eFMFLZo9>zplabDs5}-lRWQAZ+raO*DPH{%e?eufm$)Srzk}PH}0) zqN1DYGX%1pzjHOx#J{qTRi+e1*;m-y!OvbP{WyhR|N1$ZbAUmiMF@=0w{N3h20{>W zP#1Wwxje{Hh34FtV7+?@o~N1F8rzDol~p+OE70K}Bs{h+8ciqQB{D$yUcdfP!-L8m||oI?fJ1jPcpjOV_~ru<|1*7DwA6W6DEXJ`DM$JPk!MghwUjNU>+UcwuuLt%B(&+H?Ul~baIq6$;l_I3DRy5 z4}*B?4$wA$F=$!WnL%`DRA_!aJHR|Z1?CPY;NBwrzuFy!Fde!Cognk%&^<5qLb#3& z*sQ!&YOWJ2fdZ?O5Arqd;&9q{Am$Yz8cZQG23Ac$4RkYB9v&Io_48mz(;Q69dUvfi zO`1N2MNvjaM<=#XNM>WIv3;yrzK8vfM;5X?8)u81%gynI^gZR9jz-?TuXt{>KjuQO zs=67+%J;}WxVo+NM6U)tCXF?Wv)A6^Mvcq(1PjTA7>AQQ?8#PmeWx+>KE80z9!(Rz z$JIHXb93F-=dNu>IJL-h5pD9N0M)+hA5YDb(jwE`-J7+}B;ac1UEX-ItU141{Y44E z4_01uEiEy)yt|B=C&i~g$Jlds7IAR=DalhN#}Rt+z=8Z?Ax+d~xOVvKA+ZeXE9Hdq z|EswB5?9{$Oh@!q8=zD-T+*@fFLjcl`>0Qz;;iGN#|u)ka&<4>*e+t=o$GmwN$vcshU_` zBoc-fK-nYAd$1FzH_`3Xp3pcoYUn`Z}#D1IMjiQRhU{%1q^!Bh$-jkuJh?-{L2 z#d-bh1-+$naxR9g(={Wfx*<(xeLWhv1%;OuqjWk3<(|ZH_O}PrS?()ekui}c?s@v4xt|G)L+L)8{f8Zsq%Q;#@weLxAHXJNZkN(R1{}P= zyG-8s`Ifnb>99x#5_%(R>qroXv;Z&-s~OlR*y&h6P%&umL2MH$@BZ8$Xks=GB^UE- z-rTS`YsI_d9ndlP6Hx4=#>(uhV>IxkC-XnlkG7{VmHc+KBW!lITK(fD8l&HET&9zg z)&S5?pvx}JIzLZ%y+R{pHAeY%x|J!PLlg@Kh$COFRPS7}se9iwC!r48i8!5(}}Hmg)baEp=7JK4ndeJ(CqE1Lvg7Oe&K^ED{k zcW4NEKmMEl^A6(~LhA@5&i_ozZ(i!1Z#i-MbL9HdGH(YwB?zJpA6&nq|L?kI1nltO7^`5-{)%ec#g~v^IDqO#>Urf~Pp5%OU z-(O1Om;CyX7&nT~Z@`WG?$ztKK2~F2Cc8I^Rt!kT%A}p1YijD%<-cywJT9t(tl*#` zrV)Iy+fhuI54a)6^6SS(pHdJ1FpI>b`(3|I^VWT?Skr(zm3!^|X`f9(vPpRV65~Z9fDtg*F@(e;k6p&2VK}qQz7wcaWo}Y`1e&(_; zW#1h!$aDaU&cPjiH+Y?urB1ISGQ^ADV@<8+MKEq49ydUWzXe(rpj>x7E^@>?$}O9* zHg`1HO9pq4764f`cJ?-7#2{(+n7+KgPE9H;5>!Tk9q{{8pWAr_xH<}6P(k`56amab z5!c-HxMe#wm$P<59z&rdB+tHj`K{j!r^{YMwL}9HRt&;Unsw63 zmRsdo3GqqYP5oj73I+x|uV(7s3nCecah&RDi-I{<&B|^G3QGL2@#~Oama{o0e>%U* z;y-&gEmD&&(2$Fx`SF-Dvke0yotG;Wx%K4T+iU%($Wm{!V~z#s-%?k@W<=)4BvgL$ zRFIkROM-EigCp$`wMBanQ9W1=8u@;LA^J*E%OR-fu9=q|`(EA7y0Ml9UxouYWKeob z6519%KoyuUE*{(LupK7<3y70R`Gk^a{KFU)tiwH5<;JFg!J1?XI%(dd-gj|v*i+C5 zoA0N7x&LRR*wgXbDeUA~7O&JF_E{cxlIkb4^rtpo3`7p7zB0Qn{Z;1|I&I7~RCkQp zW6v{Q5*~_#-Cwu))7s!UtDuLpV$FH=e_Lqdjg7}Jw5f4+TE^X(ZS-BE!FW9U<$XbA zag)gkchU1c-Qp_C%L=QKzV>S7p^=(S^$!^2F80%PGNTWLUOgM>_mo?Xe~P`dI;1M~ zt!qA@!R@PM;O1k-J^^+xSxv}fQFNAzxW0MVFYX|E%>U3YugqcC`4Jd4Tz-f4K~8Q_ zS#jZ0gPUzCFBlZIlQc}>s zpj%M7Az$T&qWz>Y{0G6x`}_a<~2 z_;k`QhOUFcKnfz?UJ8|)4>AF4>oWP&_o~e2K+x+lLa~$H^!b@*CknLc}$TwY2h+g0PMf6MiB#$p`Vw>hIl00-DURUz%@jLTf zA?&Cx8y2aeme-ESmp>5cREk)v=$ML4S$9NhDZ6W>k0qObyvb5ELwBK`8zM6bE^zvK zVWZ2F1K>C*t)`m5GUXY>Wx8TjMXS3G)@s@_IRlm`sYEdhwXae=_fApfru?4wsT|`C zyyInX8yv@jR^h68FJfz4A_*V|y!(;b@@2V5 z3?v{V2h;Zbyta#XLBKqs@*|k5=*HSyy~`m4W=ovywZU-|M>K=r{RoHmQ)!nXFQd%) z(D!ECK$FVIZ?U(VYK}efFb$-N6#%2ZYXGLi|KdwQ_yn1cr4y1z5czDGm!F@Tlk*`X z!w1T4guJqYEgbF9;-~!})yKm`2Q~7C7gQh+G*A2jzXLLf%Rse(N#N03+5^aE$%eg; zlKwK#o*P4bseT5rlPvuF{4Y%rsef>2sQAvl_iYAeSw&d=hflXtk_&8YLF6U!GHn)l zu|Q0m%7ge@zN%gbF#H3`QTO8+7{~9?+82z5pjFk@iXq;6fE)XOrQ0a&v9165ON*sO z242pe7j-)&(I>vr-+424EEBrJ9XqcWmA+my-gnGwQG?V7tEP_DU#F)={92qfHCo3z zpU%(rwy&q!KjZ5eIm_c<{r-I_Rj>`+yRT{08KW6A9}UbcNQr) z=votrj~tBi$vK+OTX2j@1HQ(*udur@^Md#@@2^XDi++?ELfmF?E8bTF9o@$oSQ7c$&IN*J{F;Dy0H z=B(1rGsf$tkw1VK6#Y#gIJR#e*E@oCpne8I+&BSRf$O)fO3?y@dQrrbV z$$MD(0rTGGZKt%MgGiar>I!{L5I7$OM>5rAl@f7?kx*>>@N0LD9;|OIEZ9H>GPraD z9%dc53BuKR0CX~@$?Iub95BK(1PlXNyv+Xo5Dq+`p z_`#_=s2mKO7yRe@p}6G~6-m9~f^TaC4Sb7s2b>B(DS~5BV0kG|=jn5bgPBY@ zWhu`2#r(lfRYa^u*v_BcxpN}bSW$7tE*OjFxLuW9dX?6y_jx?6+Pa6)u7Rn?-kmD8 zpIv_#Z0)D$9S@Jo&gP3pKY?VEwR#KjYrv1^F^A;VXcv(l_aW*Dc3|Aez1aNYSHQsNdAjK!gIe&fUJ>kLWS;1hZXdOpPBlMj}XxN4TKHU8dUC*wAt*{T9}JY)kF zB->LruH=tEn(T6VpiH?K(AwP~GOh;OUSx$#?bD+LpkY>Fr{{y$#rf@}o|&mvb>TTV zIfnaHw~EI?+ZN`5*vM(4Y1}HT3mRke9E9 zcmxpkn#YgbY=3Y3{FGaTFr866Z~>q2oPw5rLyE9D=E;+RXI<*yp-bD$x?xCU&U*Q{ zmL9*UUq`BgNVVH(pfgTjQ3^>_U=ZWXVTxGH|frt9=*F@5{lbY zP*7o(<^Ms_l(sfBq;+_h_IisU>1y@^v{3^)ylB`yBJ&br4XkqeIly`=B|#wkN@t3H zX&%199WHaK#E}qbPSUZOwXz>w2}Wk~!Y3~7Yi&lEXE>U}QS)(|O5l5`B<9Xp1#8oM zaNOtT%dTdt*{{ukJ8?Uyrd|tZdnf8$_#w|7>Ob$ZuB%j3R0s+mlELG+q0XX|+yz&G zgEJPCKPhOw07ix##Yj-8y@dw$wuS~7kW`)92bl{{)9>bX;eqWed{>sfwCceJ%LXPu60l0Xf?w%*{2Cd5Sy{4j=D&{b zKI%azA>N$o7#@FymgbEmJGa=|aOl`quvvFtNXoLdz(V9-xAa`2`08R$e1*fUw7%5v z?LWI{j|IXnlpZd`Rj{8Fm-n^k>0rMpt>$mE-m5zq}D)&pbP5P`hnS7eBN6qE;LEiz=h0WO( zumEL+l=s?sHXKD-F^3=|?*NvF5VL>N&=0Sws6iULWe6Bb+M2T0Z(RdP4{93tK+=V%Y6@W2ZbJtISVy7ZyEC8tz!fd!tEnAxbK zwtB3!-65}l-x1gG@pgCnDC<1d29`o$%#`Gj_Cne2{4Sh^>5m|XC@Oo)4##rOzdt;zY5|!A_y<}`t zMU#=O2`ypk%b_@nOWIK>y;7m~vU_SH#dqstlB^p=$5X-X1g|RQM;~ExqNsfdZN
Xpv4}3JSxq!_13pVYz+q?ZSjK@Y<+$pf`I-(VAK%;IVRcX7w(Mc~gdf-y z5b6X+MrN0ly{)g8K$<;}%~S9gHb0Cnt(th*xfPuH?w!Ms4ELM11w(MhMKJilwiXbI zB0Da5d8%Lt4}z?2p!LDnLiES^4_Jn(2Or+E(|#{(Ltu7cI!S|tBM>S=L!qvzsRri0 z(3$5J7qdb<_`PD4pgs;msYmHvl(}a#D8Uar(!WUKp6GqBH`O1@vo$jU{+Z-4Nl|#n z5H};EpLy1s44$>RT`fs>kx$IR0u#Jz4*&582O-Z8E$6hl8Y73Tdqa3KDKnW&eG)LBvWZgYG3S9^0b?^K7qvE_M3yovsa?}CKS>Hn ziE*zUu38%L_79|QMfcM%-eq0lrKmRVyevfp$+Xe$-@^Q7K+hkr={f$*@-L2wjUd@e zP8X~K5i^$ZF|P>M;id62BK4w6q^{vA*yo4gPrt_sRp}Fx-+%Gq7B>)c3tf4_A#?pt z)zos+_ya|)8ytK7Ftz_M92OV_Ox&?MuH;14-`|~-I$urW_rss3&Nu9F0}^$R;V=hp zKPNbNSl^vj)a#b^-d zzeb=~zsKWVk5kq>vbB&Vc^cy}NQlif@@xz~ueD_Xs+yPmbi*wCGmoG+EhXpbr6q-% zUe;IBe!Xq_YnmX^C5)BJg$_OaXwK`*`V9MN;A&yuRuC>1CtGV;G7VXzPR-j2wNHj> zS<~!F+%ca@SCj2aUd_>ky=bGVmO11K-Xv@^J|a=%re=8}L7b zjxBZ8fd1$Sd#mx&`}b64dm7h}#J_x=q#9mnX%5q`y(?bawNbhR_5+0JNtlJyjb^_{ z34FHAtvN>K0*<(aJ1Dy%Cua5^Zhjnk$+Fo=zfVX_Mpm^m+ndKIyZ&R-_1-I6Q$9sbJ4%=JNBzX&Q2|w+zh7@F(qy58?h?Z>cYC91`zv zdObE(Wvp;X-}g5gx`f-{Q%48`WW0Mn#u&f}=-qjCTVO(68+s$zgJzk z=e4QJztw5WL6bBXT{~-y5G3%EwDVeA(;yyW{Tyei=pQ})?NrQk*pbk-CV2e7Lu>1A z0)?Kw&E8|&LCNi)u;ujD))KAdwKQV#J(btJPmK1ZpAjx^v58lRQ~B^J&=Y4J`FxMg z+YvByahIryjmr?6h`YP*e3JH#WL5pikND*Ep_h5zzU?oSF0WvjB(^kf-@Etn$0z?; zm`Kl9?0G^u!)vOqqP%q25+PXR^z>bY?dFHR=I41!E6GiM9Xm87SCgbwvmwb%#^E}p z$A1qZBWZm8x0RM#&Z*KsnAr30j%RI~_nALGsx+-QFwg5rhOgz^G&auZ|Ars>xAdv> z`P^G+6|a`9l9MMJG=zc`El2!GbmE+%sSlmx z--aF`5`dIw5;uTF;ry(#=pE6oiwg);ZxsnfInP@_KYaFSbl8Lof3E+abw`7Z>1gv^Y2!Cevc9=; zoc{S1BiqeNs{%@?WXz@uOi6$9nl5JWMt}H_=M!c4w1(ca6+y$%?Ki^Mm+tT5l#q~r zaF)y&bV6@%T~tsu>-)32nX>r8er`jYhc)2Ujsy8`=lu;$hyPxHb&?K)q~3rLixKfl zj3`lhDakk+Oz(v0RNRYo(BA$SSU|ZTv>5n zx8eDaz5qXpNKMY|H_CDmgxo(9A5Fu(-Pg5KqgVX!`-x2}Nmw7%Bb;vDVUfWCjk6cI zIfH|G^)HCgvi|hE{6&2x(RjE}!ghP*8`ZVxhre%t{3v54CC=DdMg|=^aByj^%6sbW zE&;pA&p`CtKwEDS3%)gM{a5)3eapb5D*t`Fe7i$ zU}}9O({JSitSQgP){4w?<<2m%;;p_2a}Wp5o+<^IKuVt`01EupALcejFq z(jg(8n+E9y5kVwXlnwz2>F!QxknWQ12C2KY=lst5-kJN)Ju}XnKT!65o^PzRK1EyT z>I-K^25l!KpSpYexo&_~8smjc{!^#}<8_p12hou~-Rzdw>Br?gimk*7Y{Ez|^`B5y ze2ZX5okxoZR8>-nTCrb+EmV|r?TRod+f}<)uUJ!GF;1vycE{e7wHG+Xp?N8QSVJNIovLw#W0bwhR-$k-F6rHriYIP*Gh z-_y=5RX#^jom=PifYgi3F#*#OP8k80)(0<@7eJ&5c|tb~fS82<=k@G%F?*0@v#8I# z?2$lr_Arq1*?@K(DXaZKrfq_OJYPgQcCG77Ftl3NHO(7-f2};#XiUlwRC9<-Ep)xs z)|M3<*v~=-;e#^qDk7r);{pi6=+|mo{M(ALwu8_x2L*r)(Om&a>ECI#n$it z+%X|hE9QQMIOC~Iw4Qet8w63@LpV7Lqy7Z4Yz}S7SWPhBXJ@K+{3gDTZx=tv_5i-Y z#!3+ZIGC@ELO%!SO|u8+B>esTVM?2@x@rc4iEBAqq50}pxcUfJEBrR0VqS-ryES85wlNH2R?5@nZF7v8g$ znTcI_HjAj#s(lBb6=x>bKbQIgspfDM!`tbqY{W!!TT9vp2Bz7uPYguINTaU%&#_xVpQ0$ z+3EVkz}ao0DO$sd+q~5{oyMd7k{~`&ENX8x(={!<^4av%`#wtg8)c4eKVRcmr6OCb z?m2iCP${+n(ZZ*LHx!19h28vt(C&cYPa8LRi?i;9a*h4f?j-Ud9 zkr3KlC)ie4cR2k40AmAvB%&w23nDe%O0C_&LPIW_##x}KB%>gkc99=Dy0Hl=nFtb zVR2&Ol@4!x%GXRZcocuE{w@01I@Xm}vC+E6i*CY@!LPY1CB^;AC+}p!FzTmApO^P` z>cRR0*EdIO;OBE90wP6=jT))lM}OR_KJ#6Fc5UxM5i7@a;Fx!S^27Dp_)$lLsy}IP zorACiD~(^Mt+!mMy+6iaFazh$D4bK2Z^^_@*m zr-epJo&X$6zv%XD&;Sh`vY3Ef_~gZln_v$EF((vz?lA3k2bLRf-rm3vyXI_H>Tqki z2i_lm8BIK|MAKj(0SCeS7a^qz>}LujTxJB%;2IwU(SI3f_ayRq9&)%uT@T#jS zu^dXZ_30e`8MKDgm%>iO#P7G}HB?*4=;)-gfAp~l*gRTY*~_=6LkW^8xuLY-$lTMD zHlS~sYCKHzPiZUWLzY~KVPJ%6_VoJ2ml_j5$~Gom_-Lk~DvN&!izKA5F#ij~T~B_b z(Rq{VsqxTe?F!&#x~$i|WSh2*V3a4`-ri2j$Or`chrF0}V7dWQOiUBaLq`xg&`gjO z!^{t4$KL0sM`2*V)4w9PX(6ku{3AQNd1=r0yu6^`c4(^@xSem0z`sD3<)FwN!*px_ z3|SH^z5GRZ%)u~Ih2Md6NktTbiO^uiUVi!B9}^gy*Qay=iPWZY^4MLNo}PXgw8YzG z+SRTK%F55g#KbhFZvQ=i@c9SUWGwm;skx3e*zsQRh_?oHyH{5WCyAWUGM3P>7ijdP z-V(L9cGSTlM723qQbb{m5!{z)f1p3f?^nKB&TY*T&G+(Y-sV`>YB}-h*G*F6u*vSX zpKlK=%kMn9dHuMsv3|^DkM*at$(4t0)r=d{cMZZ~P+nHXB`hr{Oa)_B|F8D`<~$J@ zh}qYPfV%aGLK%%nLV?xUMeI*4>*)ZdL2`@J|EuLtGT6uR<7dTHCrp8R_BdYTER&E=I27ix zQc{xD)wlVNrLjbMI+7bKtYDS$T;}1gZB~EFP{XjjlAYgc&ORH>|5Zk&}~qSD_>doK`=e#Ggz%M{gehQ9aW zBPY?!(PhLVZcX9io2=;-NUianHpD@zQ&jYyJD8D^f^_lil<%xdjkpfo+ntN-gFCj} zdwTf-Hy9uOVnMZqqC04;dSuPE9KZ>ji&&HLaSq58A%;?}DS|L&%4^FlWpHMe&Q+MF_c7xj}P zYgZm)61H#!`igu{S%IKu(PfLi0g1-39?J`kLe<;`4(Hd%@;4V@m^ZDTv>Bb*5OOKj z^0;NF94{DH2rii_JMwx|>S5V^L9#TLk}^gX9@QbEANsQs#=By0ZlIM4kYGN1WZO1X zO}@J5J4KKix^#+-QfI%7f@VzU9seRdpDq2-_^gT^Me$OXN{lcICIIbefx9dzjLhg;ARj)+P`u zD!sB>_{ttRjJGN90zX5w>tnC&N^1+t7jLyD@5*o*}xv0X;hi;VRGHFTRvv}EQuWc zSDZ^qC^@-El#Rj~=V7_ZfHvz7H)2kr!)F$$1zu@^l}|4|hy*Alw))~hzuX<%Dd zbLWOLlL20v_Q}Qg%i^}DLm?E-Ey0+98n(7-TqbyJG6CL6<|G5Xb(yB7dcN8^3BsCr z1~-bu4LF1<-xJy`8qhJKLF*X#KIz9X#fmQH94Y@7zRTnHQ*@4!vQmV(3x0?_dRj*E zDs-v33(-fw-PJPeM>>i%0= z1C?7fZqn-junkk;Q#I{qx@{CsfFo)BAtX9V>ggqV-uz%yzrND(v(ZZeo0D0_f;02% z<2L5i#YTSP)VqNhyADs-TKJ7wiIzV#y{qwvUZJi?LIT(jx%^-xUciYN;DoMyyd-mW z6LCr#L9uU#KRXq#3Fcqwt#)#?3JFin&vq4YetE>h?j|0(cqS)ew9r(T|C{joytj#f zNYCWp#?b?z_`QtG6EWoA*n~u`P_2wfBq2@)V|B7E&S|O*lse=VJrGL<9Sa2qKUbqB z^979%1vOs9Nq0naJF3Xpn~vU%#WnJIO=F7Cvm!a`S9GcE*N*=ji3JAS{}}o6#O<*6 z-c~=Ii&?vl%?3_(0UqB-yT|kdpb<%hugYFi4QtxTE^(md zLnj0|njP;$d%xD}-s9tof=U0GXKg1ZGO)YJbfIw5VB7v~rEnn%-Zp8O`wUr?)@$$X zsFkJgYwsH|s%bHtnp&3so}uftR-V2-ci#yU&-dgjm98KAYQMRk`BjIAU|Z76EKlBa zvf?XYgk}S3M|i&e{`Jn3;AxNGVh2VF_J9*NNBOipM)BNXDP?6s*);rwp7+yRt>F1m zto|W5m|9qvvforqQB_$vBO}APydpZ{aN_|UI-UXNuVDnNn5&p!VK2&eCA+;gxYXHW z9)LP6H0?kN5lX^#HMx^B!7tDCxDw*9?O3l@_j?dAKG& zdzKg_tyv5)d_;j$rjD+)T28pQM{aK)Yt45F=1fwu$NIE|PG;L7NWE>4jCuIue>^((gdcGJQaM}aKQ%Qm<@XYF^#(-IJaqs9gTZEoRlaa|y1 z@8irK6akd~dNjfPXQ!kZs>5o_mb+U^4!qxc-JT}(v@%4A$#cqAQFb<;r0>|IO9=CL zhDAt35x9=~4lmD+3Q0BS^WYp4_D!k%{fd2xlNSMrRaLPde9F^nM5`(o{?HpWyk^uK zK!|K;;#^k%tAX20JL89+=)vV%OBvUpHFlX>y?hWQlEwB}i=Oiq2{NqH~ z(b4fYvJ(PwkVq93v4X7;8(%a0df$8v=ZCHkaMsIODEAl9H|hZUuNRWRR;y z3b}DZ69y5|KzKri*We26;~|yPE46_Nao(=N|6$ty_;BZFG#8lNgUMpf( zbE%C{&1sdE4>Uq7Y%6(X7)Pe7FkF0TA-gphMzd#WU)24|k?HHLg@*{=DW$I5o$*hh zx&syGR}*2_E*_SNhI}e8+l~Y(s@?}IZ2s^~)>{f9(yc+Vwei9teI1t+M0TNfWJ0=9 zmBfK7mixRmPAp*+}D#WP3$8 znuJ6|wt(&JMbw`8`uoc>fBpIuj#!TM)O9fAM=Fn*LA>KQU0Vs=5s=ynAyf`{BtARP zfPw(18ClP>CHMUVo_N_3i1Nht|8{`E^fx=HZb z4R*JAaY4o9W|XW*HZlVjRFv?~qUgsvM^ZpOi}>7da@Q-%JVa~oZ=bZt!$p1c(cX+c{o`+}+#(VJ;=ig=9mgmpQDDh0#1=>x1i^_E%a-jnR-QZbT zVjF#p*Z7I*RlgyYwU}aezW90{AIoRTE?f_;p$41pIVMMm6}DzoIu^Qa`sy|3g(zxi zbpdPORgsATYl(3WWw+3gCeSlTMLY%JW}1OCr|;lW;N024QY#IjFXo6$t=(J;zYMN%WLh?8x{>)i;E4l1-&kwIxwwaw7k}2G96Oi<%iVZ#zkknLU5t_Yqge~F z_7F>M(kEwTma#rM9+EmZux;q->YND7X$0`9g%|8&cZ_RJ-p8pqa!$$XXJysND^02` zb4AHNcyKZr&UCy`y^8l=lX0qX;6TxK@S|%V4wpn4y2HQIK6I)Og|9Fp5;eiQl+XXL zylQtKwanRW@8*Bz2w;LzWtD^b+L(s~6{n`w<%s?Gu z1tK2;5aBXSX5=^u=?}Di3M$KZ)mYh#D(&@-@SRsGLoXs4WM8~MT7=P@e-gDmedRK4 z$!NpdpbyEsZR(}60TB{GKdfhXqJnvRNi+{4J0y3~Qj(rM{dT3cvu!r-ML6N+b7mz9 zmL^9r;~bM3xjFlv|%W%H)*UUA!k@u zcPgAIi-Z?%ezp;X#N6yycZ7A((AW-IuAUU5Z{$%&Bs&YP-I+NH{beDeF@>=4AUyVM zP*9NWdWgU#at;R!yF3H@+qaPq9C;S8R1cJ8t$=`$1ePfjEkJfD=EH?c73Sx)$IUEn z^O46JGWyhWU@H;QieOomK`iY^xgAYF5+39iGnGzvcUV`|`<(yLLo&}Fh;J8WYoxF` z`l&h02aim9@Gvft0!7z+=$m9B@tc1;8!r^aCtwP<`G`2*QWG~}akvlnSGI#&G{QdohNR~M)yVD=Rm$6Mv z)34LZcFe^l^&Z$9L@34;NiTKscYjeQ4u4yfH&Ux_VEE!0)zi|i1HA%Sz2;IJN{(g6 zU+$Jp>CPCBjxw%I-xbrMKmmO2#PG}+VLjF9<6C|<%68BBY%a)qfM}tBtzx5j0RKl$ z&f;!|SmArH1f<(ONJQU(3kC{v?U^kl#GotDAF8OT?gi?cU2Xhy zuCA=SfXrV8fdUkO_wT=jfFQ7nmjc^F*3gc4&*&Sc2iNK}Ra)NT+~E1W_<3@%^QoI! zweA&#yPhOOc5<=LhuXg?E(F&$vn!i8_zXtDYson;X3R&8k!x{7HV@%+XVU)X+9#v+l+)^cpz=2(1Lx@-V zr#4pA)6ImO40_Mn1enL58r=2RzXcOrnsozK60mARdQjAlz_%yY94pU;0Xwmly+U3! zkfVSY_@-H(PcPy4*!coHDQ=7-T{6LS4prNlRwp9REA_js(%`(%J6`M|O-E9NOcmee zJCEcL@GO4TNa_U5dWH8pp}q3pg$XdifZE5i}&@Q_3kT=o#sxLJ+2Ak1i~POJAa$NL-MV}v8D}2 z4xo+!aftO0qN5Y+{c<4G{QOVv#U{iBjBGew^?uAz9X;IJTL-}^4ZC^cG1GTBpp|9B zeFKwhI}e3h-p9RLtk0BR2zD!W6A}`hfmXwzT#h&$(wZkCNczdc^<1BxJV0FW{Z3r$&n%9l|7!^NT=QIS{U zb-oq;26+9*Jw|haP4~|eG8t+=uN7r`=l9?=DyLy4)HGFM$v{EbQ`Lhc8mltn=FO`9 zlHLLpfX9LXY z{?r$VN3=`)Yk8JqSKrJX=+e{GMa26#{ywV}VF~>lcBX?z!N6lh{K-e`63zS0*Vb+q zl~yD!%}L#?{ck;02zVfS+B<~fi4cY=wue+}(AcyL;d|f%z4BC2C@YPk7WBnS%3M?B zK=*Pm@g6N}Qy5T>r8sntS$CxD!kp$fKZ1D9%uItrsD_m(8t11!284eRP>VD1a{c(gZdka%a-~`^aw#-PWMDPpWyfHd`c{zlv_J$7bn zgQ}5F?eC*Gd-^{nh<})Rv>lVUl8K3JPXt1GDkoo6^-G4Wl*4f+wU;ElPFr0PUQ!JE z4}=xv#hR`L8^gq9y_e(hUJm%*3%S^;t-pHjgH;-X$(_|2@r#CpXJD|<{wM8vTAl?v z=jQ0RJ$H7hDNJ^P#0?71gT&|A-1fx*+;t&cdVCKr{KjJkhl3Y;yxPn%d-C2{DN^N? zWykN%tF>8HZ4UP~#!Fc)kGw8h!SVa~l!C9bjXs+0Ml9b`_ft!?vkw!RQ&Q3cG(R|A z{@b90XzHs=V)Wg&Oc%N{O`{`;vE+4@A3_?CS|yI#v-#>aQKd~?uKz)M2@Tx#Jpa{6 zvh+YN)0;Wh)xf6JjQk@0(uQe<-t4;n@KAk zKcaQa3|b6q?Afgs_V)WWfvJ{l*X|r`TS_svb{K?B%KB!^9i1Q@41h2v0MPCudisFn zpU;5>29vUdjLe)ls6nyTPQlXD_FzyI6f1qH!$WZ-oWaF~2)*$#HpYwR+LU)6JzV}W z7}b{ammnl2Hvem>r5$6tVkd1M^>J{}Z)1&;8C3$IegcUfL9{e%4E!TQXLoRMPOph? zj0n{Og&0zWBVB!57Cp!zf1p5<)Q?1LXX$9U!5k1U_h&@yk6h&A?|uGhIwA=3#3>4 z40r@D!X1Vsdo!t;U^#Q67 zlsW3|20F2$>AmLaMsN`m70$&*b!uPoWyh(4lTvyvZZ*(EhLYaGR(wjX z?4OaFYuzV35&nBei5WyqG|M(~@HpT1nS3|S)#e3=FG@tjB1+F3n2p$8H-~Be#|5Bh zf4gom=Z7^52L1Qw=srNC$u&GOvJPyXi8>&wz5uT)je{{*u0Ckk$cJju=4Mv`1n(@7T?Gz|M^F?0%>6_=2pkpmiqv!$<=>hF?UAVjQ?a3xn zEj=9>xogjJ1 zV@k=o$fFx|CyQeS?O47S+aaZ@NHnix)S|_NGrnjhGlL#{W%TmL#>SvfJ|I4L_9kO%;30C%`cdLCYOn@vjw{S@>nFFk~C-uplU#BRYd!)LcBucXvJ7BRFC z#T7gV>VnB)29o|a(*%S&g9@jtm?TQmb>~q&WMt8P<*W&hZRLs{@Gv@~;TYx+xb`^z zf3+@sp9~TIQsI)C37#3eKYI12kd*}3aGeqMHKWzJ3`FuVjKikvd*l1|=eMCvj1&5N zaJ_h3%&oSj=-h?VZ9JUX3Rn3NKBldmi+~VC^Zb=Mpz~y`^hd!#Goc>Y*ztpu*32Me z2z$D4^;bt!_4*`{$on?Kq=Eu=#vz!ioOxcdb}Z$p$r)=kGkC`Uiax%sXJ_d{#RRKC68cFY;B9OhWiy zdaj$9{(+S-s|777A?EZ!O=F9*>-m~Xo$8xe>ck~)1*37qn1VmFQ2PXm`diUYO+J9e zWW^w9|Fw4rDHnaQS{a*20#Jk$LON}WVPs^!*fn3Z&{1B=8nN_?T|T69CHUA@s4&C) z71?lsXw0A)wSa*8VZr~cww(pdujAHKa2LY7ITN$T05+CMG|>dj@a*e6$e>1?p12Fc zhypMX%k~F7i1~&ycVQ9%B0E!4R?1>CLe=jn3S$q4;07VuGM#t{u-dSelUC+wTqkk@ z4Nc?Nxs66U(CA1+D3QwJ)GLAZNrBkQv3TL&B!!svCVP0 zrcu?GMwW(9&YI`N`bDJ-%u3M1zo)K7e1Ud(J+YAJeR0CnG07d{md>nLfAmc{My$Zm zn)C3z%#0EJ(BJh96M406yaxC1%^Qzug+BdN!A_78fm8g%3*+DlO=iGJi7ni!wP7Bb zug1vaI+YBmwP&6psHlloPl1ST0{^8Fb8>RNTey-3{*@|(ahWoY5a4&el-|1YQpJx6 zce1y)chM-LG8#N!79!cyqGKbX>+kta;lq7!S2ptP&htdo9alEhFSBw|z7KeK1S2CP zJ`lJH#J!nY+KIz`uS`m>I`nZy_7{>swe0tQcHoH1QUq6mZ)gBdCcFUVF;V0a>{ z`0GO;;s0B^%Eil2%Czn%fQ&?C4Mj$o*_JmTPU9Iv|NL>~ww{tkAP|}Hfk-@T4W+G;a?c2ron-<_WI)|db2an&ZxFLt6GLw&U0== zbUXu406r^lCOBmpEx18%4yNr7n3*@f2v5fVNn@vf8=ucN7t1qH+q4)0D+vZ@`Ri=H7&Tu zZ$ct(+j|cyEOvGh74+3IV-K8Hd2U&6gB4`TQfTp@O%WR}1v@^79$! z-?mpKC8eX^zk2n)B;iLKw5wDURF6en*`pk%Mcz6gSl{7&#(KE4C%AV!5vC!Fb~DUv zb1PP#I4sw*<2~tMNXG&Y8GOKJ2<#Q>a%(Tzp%JEIVxk6|39KI8AqQGTMMY>)_%%ow zaafpw@Ba#5pnZ_W}(bOAVXy$kF@<8+bo(sfOS16f+$#W!^IZ+Nihqufle5C!vPr)A!`*$HF2RL(|OSIJ0+kqsd zWtl&0R{RSxq9JB0r<##Ssu*<|@)42IHMW8(K{epyOfKxM*3s1u0u4}4Ux*tTekXz* zcLAnr#|eiZ#07v2nWs9by?2^FXtlKIaSFdVd|0vstN?cEi-+|y9z`tP`?>P_baS#A zm^jyPjf}(A`!?0f95V8DZ7trGWcP^pnXx6JDQCZNjOv=GvLp*ZQ)i>QGkjc}+;^j* z1ABq)YZH;fp`JLG9e)6)})U|GP>u`>#UX=D&q zo0gZ?J8X(c^|biEnM!)0HOHoy_3K=M0B)>iT>&0rd(<+`AbP=&r3`K37;Z+9W=Td6 z*sSg|3*kC>bUr|tj}Y9bd}mgVI#K4zRT4?UlsdBEe(SDW5mTqi2>gNrI#aBqiY*$C7V z|Bw*Gd`mFoI!vxjydTar*43k8sBn0&PLLTNlY#f%r}@PT5?j0CNHg}G$Bx{maN(TCI=!@GKZl1M{wt zy;(*E$PQb8_2>eD57l!3;{nkLHFGedxzb^+1#%0}Z{AGI%5vnGU2B+qEf37-Ob}{0 z|DUbWO`dA-aB`-`d()nFg5c-_E(d?{R^|Rv;{%i0R9eA@OvJu;T_Z)OB2BLrwNpmt z#vZq0r@&ruTn}jY2J9Z^&Vj+N;kz=5w~3UEdQ%-n#!C;5)k*ilT=CSzDm!3~fmEx) zeex!wVGYEnKjAeXqnXNq_eCP?&I?a=7J93JkZ}-Qf+gjFx|SO^^5p=Q4u%%L^ugI* z1Ym%rZh@`uAi$Y;-H7cD_UMf2Md-EozAZr8-Ycy=4<-q{Uq%BkH4sff`btGZ^BxQi z*+G7W)F^M(UV2h`>?>${94LdEVjJXDN&{c4$iU9l)_EBOv(w2pQ2Zt|iCUUI%FEPO z&|%o|s)6Y)6^mS8c_(7Ct@Gia;-2*KV*77fw%XQb%k&umMgjfa7bAMHmg6R;UvS8O zS{K}}XlvW+psq?d^~N7eWG`8hS{}5^OizF{0fDyS3Bn#lBLI4V5$Z#*AAn_Y`_`>` za1bk&#d`AO38QvZBse!Kk6R`R2Z22=q(-Y(CnY8QEd>maVJ04N;NpS2tL6j`Pjbdr zEHBU`jFd5Jih|LkXDRYt6}ZPnX-HN2)LAdOHd}m%8#UrSp#|FWHdA50=taP7OATWc zXV=a7rLKZE7;z!9ZEcJ}p%PyDso59DHsPAiROcnu#y>;47&qOo_*I?Z>oDjlga(on znKKX$b{2AxV1cz38??DFY!kP)=R^Tod9qHe=inmLM9h9T6p~<2-d90!wlSdT5nOFK{)0^P^u~d{`U|MOVg(*G!Mbi%jvICLM@(_$e&KL}!}J z*tJ~v3X_s(t4|PU?#FsewS{|fWk5-6db)pdqTXqg|5{ZXZB%hNI~+&N)x&GQGORfA zV*5#~<%8L$m5c4NaU{nlOTz8)oJBM>?q7yoYkauUR=wrjYQlbq8E-cwNw~+p`r6(u zsa|5y2GiG~5v073!fE1(g+a(Cobhr_#xIb5%E(dVXpGb_(5 z#auz2tbX2e2|)ueK?g`t7c61EgsarH^8s-kU}+lw#PKO9L)u=};^KfUB`Ewz01SgL zwpqZ@1~*k-y=sF5S7cZlAJ7njeWxH&c@I`pA)NE%#U}MtV6jW-zWoILU7t3?ITJM! z9%Ey->{Jy^=C{y%qz>}%JYoAbJy}l)i@{zLHnH$QdeRRaQ`1T;>Y521fR)$jWUuT6h((D6I zFbD8DU(*2!XWjaalSW!UkYJH$-U*mI6dl9v0G_dV-e9#Tx&rZ%%H{RHodH#o3tjC2 zIX~gFZ}In4mtSITSjX=VlLTK^hI05gn^Rvg_uLOSU)^HiF@w`f<(p9C+u}{pRN?2X z-XE*s@Y=+QkrwIo1dIs_9?`Ay6kEDc~b;e6RK9XbHfu zGk7U5D9ErSh_nhY;Kze!ZGbRAfwXgU)VgA?sHXPZ(UH6M;tzw7kx`Mw=&v<5K{HO< z`KfAmuR-NVCB-7Um{O~SR!Sj~8cQ-?8N&;+?_Dj!J3Gs=S$A%{J~`!J7mD*a(44TA zbp5KlZQ*WgsiCSEr2lK4zt2i@aIM^YOS}Cyhgz7b741UfwXN;v`}peXJ76swD^#C0 zfAytuN>)~<`Q{&xXn&Zr%5~i2e+>7c%Tk43?2K4-Ap zKjBoO=+la^>-lmt;jP8JDHmZUQQpGR8SQD}BClPu^w~+AHwief;cxIc8`Y70v2g0q zINvUHvO$e=jo&C|9_$IFDJX~}TF~Y~jOKZJqoOie_PurcrFhK9kJGGuVD0T9harMR zE?S!sn6a_*ZFucNKtRKSEiw)d*%9}z{Nv=cGEu%~8dw$oj{+pU{|LN>q>v{9RGm;r z)LWG%53hlu)>tr?4K&RFfC78R*Vp$97B(+Aj-^Aib}o>PAacy5J?Xu2TJjc4E$i{I zO-oCwxeXY&GX?}N#1Fh=@7WX8c8dvS(KqOG$y#?rMPr|$_H{T8L_r6Gw!9w&dP1LC|M(YklLg9&6Z*5g%}tjgysl{hAe)eUa5<^!E1a ztJkjer1xs*faN*F`XJ5gArA-d_HA2nUu`)E>hkjPQZF)j0!(^fdlfrQL6)Hsk?ZBm zRU%*CougRtm!WfMIYnQ3#!8pyLkIJgVwT$_Yy3YvQPs|Aj;*hs_#FPock0e{{y6vW z5$uJhiNwm!bZp60BP+ilHYQ_=0oibDVLTUTd41GFZypk7>eRLWN*IuCm?L#Clz{db zKA4#xGb`&yU{jlq3%MPBhwIkw!RjWQI%g2dhU5*xC<-ZGfxU)`ikdEyXHP8ms29eI>DbN0Kg(pZEMI^Ds6#Pj=4 z^r~|B)wA8l@*nVLDhKk3iItm93-8MHKdR*G&!op>sk!QbC?Vn?SeVDa_QUtO2;sIQ zIc~%qD=`s{4e%NMOtWi0PJEo~c99x<$p|*RT3(tLP$*F>-CvOeOi+a@cZ_emGih3?Yt z|7nimT~C;A3|iH>^u_$KKB_bh_Y}f${W1X;mkIb}DefvJlv+|MEE>w0Q9<&(5BHMse^{g?T zC}~5Za<5$0n69T_|Mr^KjCZy3U}HQYGp8Z|CQkt3LD&EkL^jhNM{LI3K#ebUQB<*bB3%Tvcw~@NeC~+OX()maLCJG3wRynA6`!;eYRVH~6Zo?%E zR9~-s&mjhG)5+_1jrw0}KCb=Bknb|lsk-i1;~z@XV6_x6^SB*t|9~GMDJ`hgk?mhW z*S}Jx*Z-*9x~!hTsE`5F>pl>3ZhZSABi7++gPy;*ajPKH0I;UsPnZnZrci zyxZ}}QsYO~`1%AyQQh&biN7CEEF-l8dZy=A_06+PJ=#bn~{(*)qAK1yU9N_XBvaRz>Gb=qS>1L|#djmB-RM4xS_kthtGQ4QRVQiK@GHC&$Vf;a zVjyFEGktdM@hP77MzD^+9glC7l8Xtx5!EK>*{8fSBO)s#>Sb^sA%9Sgi+k$lgQP5BVB|E=^R_pkt zqglz<*ExsTvBa$THWEFGri;s1>a&uYVdS$>QonJje#po<+w4flPa)>Cg;3BW|1+nL zvfmn7_`3mfrPdNm0oCgQ)=u@tPRLLK8rvlDKLmA3FE}aTdm7vsDS3k;zW96FWvP2P zFaSlK9A_#xAgRh)$0}AJqL3kYARz}tzP*V)s)@r>B}_g}o8PmD7|x>$UsuLO?Yy8R z+$7uy$h^(C`8DQi96y_GH@VJtnr;Pd4{GZTx34tgLTSyE&yUHJaB7}@`e8#Utf)+w z+$w4JzEL4Fs?v+VNQg98{N=$qVv6SB!`BVOO>`s-5LFQ_@ zEGNE?QYM6YV~g#4Yu8&Cf0nHlhi~ZPe6%@VfMuwld7rQ=x+Wa*X;8SVUb?M9x{@(kh8 z<&K1kwkw^darx~WVNH3JmK(4GDVfwZEXUbRhMDR1NyiVU_s!^$hA5i8UTD^Vu`0uufuRhdx`T-@H;=h&tJYYLAZO16ifAY52l9?-$907!h9>) zg`PTmUAg}Nf3%(E_)p8hn=v$}!=$V#CFZ^6B}D@0(Wkzuos`6_xs)4YfU)thm3RJT zav*keK=^ufyEVKg<;rP%gnyKhmh3tq$dmRxPk(zR!?7o3NY8p&@FD(#J`n|pv_@C`_lj*b_<7D~Kr zS*ndCIrYSsAZxYr2kpLA!Mn_WKo=%vS&e6zJw3+S_MD+9Dft}tzA4yMd@uTPDK6m# z4(DuaSQ7=PnP;yOhGyoUMLN2R_NA7TcZnrDRfx!Z-j3yKry=sT6*I+_ zh^HtV?F1`fQhs|{6lfKJg!)oB+r}{$DuhRm#K*h4x>8_(J(Ov?2Evrz(3y`p!v4bv zEuSw|2CNh)#A_T}DB$(C^3Q?vJ1pp*c~8>pGWojGMS|+`YA+AjZ^c5U`k8&&^;K*v zIu`4X<~OODPIPx?F5gJ-%w0;whbRrZkK^ZJ-Asf)o@#w1ef{V3ENQ*EGa&;)WoMHd zq`^_6jMWvm{KagNpJX&rM>{|6+plkoyER_}ldOe7RRhx*zM5eI;=RQezEdzxS-xD$ zg=vfLA-90Flk|4Lk9yB#!7&?wu_C=0ToF!3vpK(G5yRIQ~_23S1gvv~*d7$cgYaPmNaElT-{HTlu zv@HQVm3N)l{MOpArnVY`y0OofdeRDv8CfE}ZT#g{mg3y-rKAS;RW)ggi7fg@SY+{LxmM`qI+lwhoiCCFt^Q%;CRkvHOavHuIeBCsPY|fDPdj48Y zWw&|ARvQd*5QR~|_%_K`&QyVVVMNy@UJ`~OLP8hV9gxOHTf2o$_3=MM!<#OkJw$SA zu&P?RXL$U?p{`Pv@a0j)y+K2LQG5GpEr3kBdGK?he-{f`wtC5vrM%iKmqGoLt@(jT zSUZr;Q6K??uzICo(6|i;z05V})NsmkZ~7_TU1VxYi^0RF(_PEXE-$2#Od3LA@Z>$t zL*SG4~0tDm!}{5+qAtfFMrDJ(TAL7Yd))OxUKVj{NXvl?S^Z7d}V@TpH{O} z5GB?fD%Y3Uzer}7AI;5lH_UwUO7#M24!wYUi6x#g$ zc?(Pdf8cd3VwS*dI7C6&rM#%qTsfEF-W#6rVu8#(3^=YN zpXhZ`&sXW^TDkY}w8b{kJMjB$!frAmHYC*$HM`ynN zGA8S#h=`vNLf?8^C6F#da^@}Snf>_zNsqqDZh(e0weE>6+#sK&mQUwH%f9z&Fboq! z=$#mam1NU@^ZS#`V0TH8*WAMXPr(@-d5y|#duyF}lV3_py5>(dTDb~@9f7=>?FLSn zSBn<}zk`hoxJt-EmINrKkoXR$o!|+|7D=>zgP_k}n*_Dy;J*4RSppXv3$-=~DJW!~ zacN;HDk_eYSdzh*^E>DokSu!8D1a6Q*$S7JmxG^i9tcGsq!+2rhDSOaqJu=4hI6PP z^^$U$0v^$7P(U@3sGnPXcn2bNsE7hlllz`S_7*baFI4C-vIM3D=A&R#0R1R4!kJwO~`Ay|4^RUfFp1{8;y&u3Aua1@y&0>9lD=DzT5 zrQFmVV1|dBH-Z`fw8ZKx%}dBhEijp1Dj&EWtn^D@)QEC^4tQfY=45y2QSx=opVzkM zRovd80V+x8-GhK?D!Ecjs_6VfYPJ!aa<3sYtr-b#>Yn$cag_o4u2z$!xDlY8?p$0(fSv*Kh?NgE6kWGKw}(`2loVh&Inj1SL4q-W#$kW1je+nYPM; z#0%E;Kt~mD-~RvON@ai;fF4n3O%QG-vFyNVsJa3FB6(vCPDn^F8|m*0hOyU_t2a`N z-oU%Fv67OKG5~-5^~p-4MZOKBO8!cfAp<@fpb$&&8TD2NVBS&q9$1{QAa&t>P6^Xr zAWs7#)6(FJSq}Z<^1u&#XoMhX_9ImDVz@$05MI>;e~AyQ^@HuKWLpu1dhAii%=opP zN@yaRcPA8R`Hv*yLi_}J`QEPC=b!-lo`BF>B1T5l`MTYM``z3!VCuuN@=_?-Rd4|Z zB8v%o{xB!*)hQ%@I{nqJfW0Y;zxahfWy1LZ%C*JL7S{!%v0(y2L{k&Kb+*O6W(<90 zQt#4I0$gsB<{3phy;Oj+;TdOp*myKU%0~99dBV)HGuuDR8jtWZ&FKIIRS_j7h&ZLN zYbshA+MF!1R8E_p`a&Qnh=|0nDY5t?IW=~ap}KzYuJ*RRxx&^k1{T&saF#*#%TQB% zGmGDXH(ZyN;MtA@MnR1S;hR2=osjC}3?5M6#P{RK9i_r?qaDd+f(b+v#8ZK%=j~9z zU37@yIvlfxK`Iit8q*h~diREd_7Ls*brX+eh(inQLNw04W(D5~nEW?Ee#|l?ivm13 z9B<(Qc8O73<|>1}Q2UoJQP!LvYC!qigakZ+Me47eOCv0N@ugL{bj;~wcL7G@aY#3p znWd#xFcwz>A_(wJb*HLaf=JksD5oglcurdR+1dFU(rgyslh*h2$OSGfEPMjz22d&! zVPay=XXe)E|NKY=C)1EQC3g&V=3qN4@bW*anZ=;*qybyu&Q9rA*)*bBknS8qrX}D% zd8%j9a2_DzD^0B*Hu2RV+U{T29!b+nq%{1@aWKCu%^Rj(?g*T`@=Q-U?@WkTlv5|a z`2#P;q&cxzF8a3tHOg>%Byzsf2M{ClRB)U z`HYe{k%3`Y|BySIm0W0@E3NeRkVab;Li-1vF+&ea#P-Ez&t8U@k;QOCZ>BNNpA>$; zc@glwkj{*dV0iK6hz!(*<)B`221p!mrS0e_w~}Fao5SGiYnNRSWjR{l3!$7Jg+2a& z^CdbudV0kF_9!S{Ve=8c0TXAWVE63&oQ{?j8LWi-a}Ve#I$r0>r}dHGvjEp6ik#ri zbwJsu03d)nv$w=jBi?!LCZ+2#ReMK=oQtLhU-iv08xOwEkB?<<;zJ>9{B6Ry9IZO=i}glA@Y!)U)}B3fyIvu zNpW#B$fx_h@nKXmBV!kQX#s|K0qEWeY<}oGV5KVw$a>4Ltk$g! z6h%P=L8Mz0kPbmQlvGlr8$r6eK?OuWKtZ}eK)R$$36TcrZt3n2&X}&X*LR(B{_U+x z<$dQf$1}z~?sy0elx+}jDqHXM2jvKSp;s2%aYXtj&QK3ixht%RGIAg27nTa7+53)> z`+6;CQ#*-Cme5vM<@oyDn)NWYA+BUyR8^gkfLWYR>lnSA;i#He{Hx3fu9i*5CEEsKyj*p?{@F*U9}n) z_P|t=0(il1-@d(*=?THFG3*9tz-%O^qN37rTTUN`^%ZykzrBu2iwH46pbhoO$8@Ba z1|;z}8CCPCsi-cMw1~2cT)Skp-|O?4|L1-2+;od)w`6w{z+5xwd;7XQ^7yV`?|UG82WhsXMvwaqH0ZXOXpW}5OKV^&%^}L zFJ3Re7}^6WiN{XsePp5g=@TBjpihCs!Nin1sX_qlP9z7zfsvshyMEKP47mg;SQZfk z`2nYk1NOZ6wFjdlp|!tb%`4!YMlu(`jb#QJ`A5ptZ%StDD!-EU099x%BhE@6s1f51 zeXyFi1IOdnjf%oTHVZCN_=A1=-e;sbDk@Hc zm2eBV;cIe(h7p(wz#H10dXo9up3-K!dnw}ZON(9ume7KkYvpR@H0O*p)|@I%s}jZa-nG9WwqOw>s4?^` zf@ZW#U*V|5IMdpl@qFz^L0yAeulQ(LYBs>^DWZln5dbVZS^U76VY$2V50G_KsWp%w z*Z&bN^S7nuuKV9E6;!Y@1~nHIH7TjsW!trU{>n-4*6*Q5nCz3o;u}9&Xxy47CrU7O zL&!(V%pTYxOPJ3+)Fh89Q$As1*R11{;tP{_OX~S(_vx{LOS=@ZNrY88tQ~aj6_SJj zJ~cI!1lKg&P|_OZRP)FNA+n4FVjA2GW<^l4qM%z) zs;*C^yMm6s3pLuT2taEBZ|@6@&JtdyHKOtfCsH7`U!LCW7B&Vn!FXQ~*_ucj(+nIJ zNs6V&A61v~IXUTJ;AOVNi`6E^nQhxYhQ(wy_uJZ=6hY*|lc$%k5<0^3Fz}bkJ$TDp zLL)n|&;c0eZL`Xh$(+j&1FmT7;Cwggt?uufmTuq?)r^gRl}M9xPjkAsim^AdX39=k_w?a=&BaL z9;UBs-%Zf_xLp@a9`m;~pcX1CmvZ$$Q1yEX!C1IX5(WJxw*Q+PFJodIp3fn>5oqLZXw#(xNOu}v^%MNvDgTD z#@TVDReft{9@yF0k@YM@PCPO%b!o;|1qxeI^oyMqvp8WDOyEf3;^18R23H{vsgg=P z1rt2TlqTY@E)C|z9q4wG_9K@LtgAergdnUHNYYVbq%OCfswu?bl};K&{(%_o4!xXD{EDZPR$ZEb z&_?zs9oh~WQa7+-WFTcTsjaC=aic_t?h6hF-^KE)O_pksKemUP8X@m&9B8jL78z)C z5RkUNVy)kM{8r?ZqV1N(j#vT1k0L{HF{LMx^1!@9zHi`?>Lwof|A89w68cm~JyM7Z zss{eSUy{9ze&P=#00!(Xp>0V0^5xnq;6BGfticvI37{(HcscTEm$qDjKZf%P{34=& ztiS>Mv;xvWps6732Ne6a;Ig?3>#p4nj&77KC=Wvmf;b2#;XTmYsvNeh>Pvx)Ln6tF z65VM8-Eplxtn$B`l@9U}<_xSvNL%ipu*JxLW8?r|D46tH)g2pI;%|e{?HG0-*RZjL z7og>tqQ}yeFws2pp>CGk_npVicABcYN)!Fyz`eQd`i)c>ig^&sD$d~N(Mvmdvpgt$ zXv4^fBAh~92ZvYlxkP@&PIB&`R|9KIB_gchF8w6r%Md3Tku^lXVoz#@V#S>&%G$#nj@mEE(zE z%aQrFx}Kau_*Jh~d~e4j(61A==UO1thzms3HkDe4t^s5U4~#m9EbHkNGd_fcy#ZXF zl@%gX+7MMAc-Xwojt~T~Y_8O!%zF$B*`sqP8S+V8Fyqld>=7_-;PM<_{aw<&pbyp& z|0aMTwoyPmhD;o%JWX+=Uz1e^XaQa@ogy&(kfBu!ZUL_!Kw)b10ZeH6-P^V*GqUc) z=dffW;i?oRE$a$wA~Gy=Bvl6mn94x?Y%`ZDgm<+h%cEw0|v3cPkR=ll1SU$?qDb7UyK;m_!^wU)Zk zydxB3|Lye$!6RoULg$2Z7FyjufSp2;l6}z3UbTxRjH}X7EP1v`fIhK9NKL^oe1abk zoUw_&8~@!odrnGPnwZ;4D|mT_M@uNO9hsv#YEzn$6CZ0`aNo81d@xUd+v^5`4IiA-tYr7{Xm;fk=d5%j5l^P z&ZZFSX{NlBo5=#{VHK&=zeEmBctGH^RSUNt)XK>ZuAD^OBd?Gz#U8#CV9fQG<*DRw z38l~mrk{rDrhJWopSqNCJTtxtl8B#k_>1$%DQ1XUJ`atV9{e z;)?gmiAGa)y<5w8)yp4=@C`08QUTTlDReyRNR&8pyx1Wr> zs=LB;s&IPpDcVJ1;pK-l>uvEi*+gv(jHIGx{yys0wV$=Ml}7KU>YQ-4;!t%+-fvU^*bH3n1BZPJH-6x`eZ{^*KpO zEn(%~IBE5lGf}G#p;OAr^0rMe3)_+`Qp{F8@$u4*$m;{tBq*$?-;7GOw;Hi8viuxH zWB8q|YLo1t<=gj?qv|q@I7eS1vcCUkC_4$CD@R0Z;}4nTA;pxo!_~JF^{#7qY(kt( z+yMYh^ClbE-Y*cb-l94G#KgGsLZY+rNAjIEG|W4CBM+FlXlUOm@ba!592$R%A35W( zx%OLD6XlswG!AaJ&xk2m;ZKXFGnx|03vr2rY5bpZn#p?Cse0a+237a0nhXTKW>ghn zrs%*=Em}BUxIHQS?u;^9V<87CqDWg;zu}ynCt`GB6M+SuoDUEn^_vYyb?WLdWtK&1 zX3B*iZGxRzff}&*^HgRBX+wqWvO1+^!tJwILf^l~1kQs59Og?%+Bz`hoAo~`}nUl|=)^X7}X6>Mrcb%{vuMs0rb zqeR`3+ZW0?UqRJi3wjhKsT9@tMv9AB943Vg|5n(&pPxo83n9ky9`ff4|9!r!mT{W2 zUVz7hEx#Xz5?3cmNlA5O4{JVuK8wG5cvzrZbU3di*Odl9I#@^9k6D&qf*_I(WX=V` z`O2r9TMf=2VsNPZ?#VH}{H&sK9tR@Ba~|XQDeT|V*(olfiVD{z9 z%r%9n6J}kx^p-ETnrEg`Qi&l(lr4*EJ!75vv~vP&4v=QZ4@ z1!^!sKu_vzmb2DsRSu_>v_K8+4K&dSAwJNlWM{()2bYX2cfr;!XK8fa&W-|6PGC;0tyvV8lw4Z+m5xE%7jv`59VE8hCKsbikYoe9hWx|b z8@BnU9*66DT;4uu&oBA=tnN%+{gkZ}{VLDixGZsIN&#dz3>|V9$HG;V^NLJ2(&{~A zC>E?=vWUOd8sybaYO=4)78P8LPI86HZBDH%+8v`OfRsDMK`~JS( zaNPvn@_wC+E+@y+1r^#RS3<{@^!2&=C@o*Ry)Oien|=P|yT2bgxry{Y{by+Fya%3D zMGD(#uKUwhKuGe>iy!`%A@Gj20}@L?+f|?jA`aM+JS1?p$d>6h^U=xyj(Rh3&Ia6K+%GPGsfqh*MA}n>X!2hEu%n4UW4ZBt zENh%x%ZCJh^|0u7u$DsE^Ydd`>GdIXUQd0VY4Ed)nMrEpH5F_9%4!S7QJE$y8qH?1 z$mo2aM9&YS#Xl8dpQH{qwHG`K<{}Id*j)t3%r|>pU()ry8Tfp{)R*V}!WE-ic27~n z>s9_#e;HNMS^GoMz3y^Z`QsEZTwFmO#dv>9z~41`crB7yoKaJAh9{{+&&qnJp$vIG zPvqr==kN;>nFxYZS!&((8=$3gc@Gq4{UUH^%4`O(!)L@I-<|@lZC$UN?rjd0t>kr6 zJf%nefejME!o>@l^|w-EZhS>oteDhZ8bDuug7I|wg+!`Y!QyX-t#y4*#!kW4RNT%Y znwkA+WqqxIGQjfe{~G`-(|W>>fL3pGJ9r5qaU$>?Jtqfn6oMz#+x;<)EN zi4^c)2dkerzn|H#x;{w8-?tGDU#;>~R^z|8W5txc?E6alVj9gDq&ths4DEW+drL zxU*YO9sJCPblmgGYGH*5v8rwA<0x=hzJv*Q)CpKzFqM$v<7Xzat3px~WV^3FOml`= z9gq^!F?jpV&dxOIk!d_1Hp(mej?=ky@>ESDeamFyb1tvBKAW=h6Z~-gz^es>)YXV{ z>sOMVTRu~h-_vT%;Irjc1=}{xM%Ikj)VWP z4sj*&c=VT8C5B5#Led5!@z?d&sOb7dYH+v*Hmt$aGBos1V}u_9t^dLZQ_BuvQBj$- zK<3JxUfey}dB(+d*|uU*-vmT`sHfCyySzB7lpK6kG>N-AaL+ z4eO)vRT2ce24dl_10W}SDQYggl{%xXtJaWyoRpw8pt+zrcT1}o)f4fZK9a*Qze2-5 zf&DW^gY@ThDS(E0qoIkSX#M$U-$n1A4L}9zE3NR4?tOg#JAfwgBjK#6H9r3ea8opWd>gBiHEyRvWakv7arYApR2kZd5hb9QhKIR8$@S za=(s`i>qk)UA16n&VjG?MmM(b8Qb^o-v`PfSQr>mp^{=!3TXv(#y$)xEG!gWAA=== zMlImN*?$sYn^Uk30V`A14N=n#mF3Cy;?;5VAA@>$>xHtFCL=diJT zO6(RH0}=t3tt1VaixfzGm5FA1tf@=}13GNW=vi2P!{GsS=Z80MF2gO; zyX=7YZ7%IA?>gVOaRYH!LfEL?<&xKILn?XeuZeCvM!^%ms^rBr5rm7o;K$bx+A3=c zjsC9;CKB_qYK}nN_yDa7AGrAA+n|-w5w!Wncwi=jIUz4F96f71lO?lRaGIwh30JM} z7i@9{%d`7s;i_v3drFgT(?T*7X`b;jGnhIh8AW}#sgM7q+m8RU(+&GOlKi;$*QP0z z7*fn;VeB6S?ZDE5-Ddg`OU3kM;HhD7uA>(Y&D({ahyN1fixJa%9)<)-sBp}@mSTsxL882;>tD_2y`LkLh><6oHc zGN7bXgJxItfaB0@{Mn6sx1d6dg+9v*FYs0={+h#%X=Xm1+~FeKYBOP&aX(I>z8`_& zO|*?Cav37`%l*Xr^#7*?J!}?~dY9)H3cj%Ke(WyN@MY@VSP7=_pbLDyDq8a;8`b>W zd047!aQW!B+~ma%s!jWepQp4DT}=ce zHb8hpRYSQikCs`s0~1spP;|s(3k4QaTMQ`fc06PVA_mEqX0CvxX81*E`@A@G2z}R3 z-{=#tF;DF-Ik1SSSsB8%DmY)7p#JA60NU4=pOJ+MPGwo5A0A|yh`)yCSK4cRZ0A+8 zBh^7qk3t84WYZ5jX%zy=V2MHBE6=%-SueGF^@qgV#_h%(Szg23+EpH%6)<|HOmI+# zsa@tiP=BvV@Q_L4TTKN|;Rr~^_8hRTqMh88r6SQv)MdfpMhh=L6KlCb__ z_beWdIG{>!CTmPp3dV_Gy-Fo2^u^BG-R?}Nxd;}WT&((dDEn?#^wA>}aLz|eIXzDt zV4BUDVEzBd?OtXdYQdraSs%mt?_<;J>H`i-YG&_^AOH<^0zY{;<1r zBs)ly{jM%#tGoDvgO|Whkyd{-;a$~ zB#BT66G?K!a%6{47l8ByL} z9Q9tlYav)=s;jESK-o;)(`9tgckIg(QRhda#%0}Crd%81et4h5x#te1KeoB8`{@Cu zTH!ai40^vPi7zzg87RmE5-^TFlNkGjCDZ|J1Igfss)^iOm=5!?<7v^`y7xSORW%pz zeX@dP0ARa1BvZB-HXw*SIeh3(2zc1v-`|(?Ifggxq8ouz)ME}U6355KHOSq8?*;U* zM{w6B-utgK?DnTg;l>fFf#Vs1pnc? z!Y{VK)3oJFfM{uG)nL~uq423MY3WK(vk0u%RzFFDL=5g>;H&@x-G9Og7&#z)0Ky8G z=U$XJcG2omi8a0}Qn_8>@bNF1{Nxpi!c1ME6wI{b_18}G>meIW` z=A~pziBahOPI?s&nf(lYpw(L*UaU>Hy2u!xe%sz$drBKFo+|Q=<{*8L1-{7SUZ>>yP^lEa!_oHi45zf?TYd%88jcQ3|80 z7fWfO#gGiG()>$Rg7RB-ZtS0(T{O4X{s$cZX1xQ_>+LYTx4K9k*L9)(?T!wq6$#(YJMJOY?W z-uU=rJx{*@vYw-p6P4k`SB$KztN`s-LdfkGt;z?lU%y^>E~IhI)>1=dnShfksyIS} zT-0%c_@=**kISjEnWnAD68VXOxF0MP@mCUF+uP3bw-0$c>0Ljr62O+AmSSwx(=)MP z3Y2apo9j)pSo(GKrrwarQmH*@nHklJlcfsR)I*c(NDqS9=T`KEMQk;fNaDTg7aY#9 z7cu!V{QPq~Z*0Ak!K4pc!sm`rtZTV$vPve9t%jfRHSx7X){#2}Xo@G>m`B{HKK503 zp{#OWh?X)48G40W0AUiC6O>=g1_D{@j@|%py9EtqA3(wFEsm$_2oDnYC0MVBIgAQT zdheov{2yUi!SP3M{PJbrH%**5zQztL2!1DW6+@CGK4pwKX;kwDzY$! zlc~E; zp?q>=X#?zvsBv%jQC8eH-XK2T_KR|*wGci5JMgwJ8tLIub3!DiCf{SCKtf%&98il8 zGTzikSLUwM5}qW==40MJaG3yQDsprZXpl%@Mp#&J+}6JVzc*~~y>69s6^;?mS;E0b z0^w3YSB8AU*5JCUtc?!%?yOrs13%&BRNDB-jz;<2-yS25s!ypd8kgpnOx-*Rur}9d z7bwzhi6~K1#<9|W>{6HH3yMrTM;9RaSfSA(OPeU*gxPHPEZuZdXAq1gP>wa2JT$SVv9Yy;=NJLBv@D7X!49)wJQaDZXEQ(%RSjcvUA zD;+Gv;b|R#Ng+Z*1NM`UMqVT==YR|>4-?;j=V-Zg=!k{WsyT32phPzdS(|FF?_a=S zULGo-g!uEvIgWMWDtQ{s@OnRAn}b&wiGGJc(-rtqu3+F`+M9Z{#JF1}^b{@u#Qz>S zQHX58-$y)%AglE&bkxWn0Sp#NPy}KdB9Dh$xN9h|afNYqYj@WGe#)BDjcSBnW7S%Y z80iDW!U!C?;iuo)+0h48sA{c{fopxYr-z3ch~v)B&t+mck%No_p8C*y>i#a70Fq22 zuqt98-9A%3sczP>o@Bvx;;RO8N=iyRziM$EBt8O3lbrbZwC~fkyMx!a;>JWdp<87HO9b7^;V)59=Ap3i%QSfA?41HyuPt; z-8QYr+@j;1*8np{*jE;x>G2Qko7BFyhEkpnZ4&Li#63TB#55&VDL)UC+0$V&{Y4GK zraTHz=8>d*-1OJy>tHE^^h(ej`oN>UjfXcM zxmNqjHRyTb&_!PPWP^Uu77)<3Vcsl)ou=2>wj>sXfLiL@IG9*nK|^~0fnw7D6W(gBcXxM#Qohhl8=jx-?V@SDY`}*C3ieasixyoVbLe{RLqt^vdRk9 zRj*R%EJnWuz)ym3cM%dO375rBglP&t%rT6lD8t}%0}q2`CmQg*rrlen}lzrlq=#I~yBiC9}{s z+$`|?^eGCb3DMY{H(4z@4cYDW4U<6S@T42CK26_rO!n@MMS7CUXYm}Ef*+Tz@;EGg zIN5~Cak-*%lru)ABTApgm4?!g% z{zF$`b2rKRJO<8ZPAF^r*=;%|S&yY2D#TI?`6LMT02d?*&>7N&rqbcxs4OjTmanRiWQv=a`Nm?=1mvGQaN#%-sOpz{4<5wom^XUzMH%`%03(W(vtw$LJjfdh(N}uw zjb}(oFHZU1p3Iz6Jl)d?`C<6g09wt$F$`%6Wq6ZN(F5xTgH>{x^^3HM1uX3BieryJ zc!IDwkrxe%oUhPvRRsyPn{N%zQqCcO2Z#VwEedGnc}o5Jp&=o(ka7SX^u6GkO)D4w z1O$opzdPs$;X$4gcE&5?`5o;V1_7hDwXLm+?%3;O&op`Kg6+sUJ?X3v>u=z7A&kxl5U)384Fc)ppz!}R7ir9|8`9GAVRzFmm_ zlEd%X=#=WkiSA44pQdc1QGus>jf!`mHP}%_a_0tz4Ij;SADn=lU;CL!!^8RH8M{8A z4*^{1&uUCQa*-nqZgP(y!l7*Rf4Guti${AZTYXr(QTN(Gb35<8C?SOs$5b1?>9eeabMi9?TjsSWGWc+B6U}p>3-Ig;?dAYinFR) zY!(TXftf+M*m>7F0LAKh0z7rY$e*q4?bY*ZkL!1JpR-Um1~Njf4i1DyfYA?7f~~iD zM6vNtiJ-55MiK5F)=>g7G6af30m42Nm<2;sNPwz}P&k19iXKNRmCm%2XNY>95!7K<`F-YPX7m6W_QzCwQ+8&g}+gLYm-V3lhyEYnBuL>*dQaPWu?0GE)f^%n>?)EKs zTRU1Zsb@T|D8|Z)>XaEVulrs1wA7){9V(Dd8dm$|$cN?X&Q5zyx9P_#E#z)J@?&&H zzQL zcL<%)cKd~>p1$=9ola0J_-G}wulEv8!oHMty8)a8j~z$M7P*(d>Ww=e$j&3gF?b8U znA_>}KsUJNFdgZT{5A^>DnQ~z8X&0+I7Z@eEgjC>4R)Gta|VXH65=g(rg_gd1zJ$izP%F1$KTxDmm#uj$Uzs76rLUfWM9T4Qlz*i7H1p zaz@Y`Kn7_ju-N3{d0r2gEr5^H0`#XX7F=^SJV)@qj$srB^eR)M)T}>SIS9_54YIQK z+w_BO0V7x2z+*pia{l~gU>2JN7~-{d2LwWu&CB%t_E}M#TjmOyCAN%1X@n)!$yZX zhVi62AsGRJxw0hJ1^MwrdQ^XFS~u|*hO7L&Rn%@6*?v9ta~gvVt8XW1dNrTb@=bW3 z^&)jZ`^k; zj=7bgXP9+7*u;}-JK`B zPA!qAjNHJu)xdgs#upI=hSOYK* zj=|~&nrw6!*;3%NA;U}!RBre|vS?fhS+t(OadZWZ>oTZ3;N~}mzoh2k{1gQdlzsSc z3xHIFuYm065vc;Gy^(Nda8rXr6rrk<0&`)e=`Z+ZJ$%jrN?QX#sWS05r6c|Gs(xdIk zq(r;DB?Ta^0|R;*n$X|i%7`%A327Go4nNAtogr}cz8l_@a<^gAy^0=nq_%onaz^84 zT8I~$Ms+1-DxlPXY03@)1ADy2{%AVt7h#K+Z{yQy<`{na?!)8ZIUwYzf7g7o26y84 z_0-4nx|fF)Etd7_r7OP#_{&8M@DociT56YY<+3gPNBl3jJNI&N;Ic-!Yhr~5T=G5- zSSQJ~qirgExko5Jt=yPgh7q=2NVD#sWwrQl3FaWeCp*nNO|Ew>E~0P{kF- zZ-0{vA){hvFOo6duVM&Y6$Z=5Ntd~sP!^hy{SXkw>FC}82N{?}eyhoVXodvf-oFj2 zT7-ZCj6oCG4TbEu{^C>^P#zyx-T}0< z2!A&cnVkeTpk9$$G_O4^fEs8qF)@h4+@qP?uFOQY8zAT4->hkbgNHbh!raziR5D}3 zLnP?Nc?zk9kR^oR=is&V0~ina%bH{hwh0A@f*15lAo4?qK!7(b!1r{YmNsK}a{~OD z{a|0*S8A?`Ou*o%-U3z5_MbzOlbR2to7>17ge`P*2MQ(2;Avktt$bn!!tFz_7Z|-^ zRRm_R;E4Jaku27p)_Ey9RCdMCn{WzPZ`Yn-i5I$&XIk+u%J68`z5Om*UpIOSka7{f zOzx({<(l$aHc>H5qHm!^#HVl7n@&lSgkCdH^A7v}xByK)+e->u4$BRGpR_|+h3;L1 zaIH86U$!@YtH{ktX=||hDba5zUwEJ_weNwzZxn*+gk{H-3PEQj3nqHEm;}0}2s#o! z`f6PX0|%`4PeR)=G*o1`K2k zl=l({$nXTr;PxniX@Y=7>nDf^HD1^vPL_oGH_3Pk8@gD1=|~=yKR`9R-Y-nm#azOmhi$#TeSUQ(zc90+m$R+)g{>M9Nz~J; zya{~0`=^_)8%9V-`5c>%hP)iB^*Ohmi7;Id-MkPQmz{|*PDDKOFacbS>u$pC>x;}YJJ%N>x^&T9_<aa~bSec9$iWTeCZDtgcGy4qL1YWG!D~VhbB3=0YuIXw(KmcOcJZuoU4U`TW(0f4> z3&Ni{IJL9Lat?~*Jzm~QneOWLp{OB!gMowC&(taznSF2_A`!s=k%+iCaiO2{wuW`q z-`?xT74YDDO~PBLW}$k)y&uD2ywsP89hh1n2o0EwlvJBCr7m7*dE@uP&aq_2r+XT! zgDEYCx+O+idNM2lI_{59JiShDwxnZG`&OhD2@3^NJ;^NFmBVAR-YPA@gQY8;YEgKt zYimwE192K1*G`yfgxf`2!hc^_gbe6ySZlT}0~$3AcQI_66RB8Oy82!~9P_OO2@DUt z2WdrwJp7J)X!B8>8a`N-6zm7`T5g;USpwxUAt1eh_+9s@OVuT{FE1`zjJ|2#yu%=7 zVZj7#1>(4Z#C9TUO4yG8zcfpymJhJ~moO?I{BRg9bT}~%%4|kLOV@RW<$E*Gk^w6Gruw!C@IEe1ee_s>wWu($MXBz7B*^cM2{<8S}saMTt z@k!-^If+e)v!vdLI8w;&aZ9F@m-iE$I%NJ zbM9=*W|Qd@RPUL**H>p|rXM`B0$0iVXJ-O98MnAUIT$b`HF^Ck9KDCqll;QM=UN7Z z`}LfB3$#qw_PK^bYT{q>vv+m|&+sN4Ouo&;TYe@AmT^!IFO)G^TkH1j&dVts`cy24 zeCm&?7rPmn?vshmhMteGL0+E*Q@K^ZWTQW}J+x|&hbRIg#WgG}VEPNi!|Kbk3pDyq z!1EmFmr;Bc0YJ3nB)JLDQ9|reCv=9;P5EBA+MA)w2y>qapz32~yit-wfD1Sa3w&~a zKWP#XRvXooDA*3_qGf1vQNS0LHGJr$Fx>~uvu(#eRRKjgu;qwHhwLyPK|%qCc9=a~($=2D z-~KO9J`4 z((mvjFZ~Hm)F8($KrEqocn6ljC_pu!W@KE=*72t!)~!zHCgl`2u*Xtsw{~R|JTLb> zASQNMcVdZKV2i2n-kf|Mu|gn%*O}dJd@#eUV51^QL?Cq8+dLUP4G^{2k1zk{P^Wb^ zT!c|I&%q){LU3}d@GOLzuH?+=dFkt2BU8E9NGW4Vy7FBpAy1XMv;Foz$y&yd#yvR@ zQf#6~y$doQcAI1lUJ?ji0vxe_-}NHTZlTTN{CII?O$R~4s!F9vTR_SYs-o#q-34|B z){_EV$4AN0@eAU?+uO({wxpaJm>(A7OW?2y^r|```x~3gV``^MbK;2roY}(y=pFDs zE)`mgJSejmu~RO1{OP@%f|{!)zr!-IneOA#TW(fb(!pmQM!x>lg5J=*Jw+20_or`? zz1PbBae9Nr$AfIkE<9@q@6UoWe0cL$)b9T#HW{+?7`1pWKer(!w#LTPvyEU_@Y;}F zOl*Fbq$SUdnKz-eu?Ss7stMlBG%NDCLGFd9ckKe2N_hT_uRD$AVDeEog-u&tmqRUH zo=T8hrUCG=&A`e0Pd?vB9CRE=SAPJnL?>K;PuSy#DG2>j9VdTqtWUI`c>O`Rr-1mH zdBfQ*RIc@%nwxA>GZzLPrNsl2JE{RyZuy1HdBYwnoSRcT@A=K_#|<$D2{7 zXiuU-XF>__7wTyeCTm@nEJn1ei>F#zkU3h>^>@(y?d%ycC4~f;%uu@qQXr8K<$j`vrgJ zOOif8qK_!B@<>xilZe(b>av=uBQL33dMr{`R|k=jvX=gSelx49K@&8*s?ULU&1pS3 z&Wxq2tBayvQ%g)rxq0BRnWwqDW>e98sRvr<14I0CtVHD;md+A;Rz6i2++j_9hpn(s zU>S@oV4o+F8J>>KAl0(RRO2<4RfeDUc7`4OXV0qoL_RrR)OXZDKF1{pAxylc_%1Fa zRUx|g)R0qRajEy~7mIAefjvDXc!fFt??WpEdoV^uwA&^Om}A^DY&2|p5$Uho;-50W z+fA9V8k(Q{+%Ey#*tM3)(I_nUK9z`~&#C@Ng5fk9aurCpt=0yefeBkaznLB_Lkr&M z<0tToGCDdsS+lT9Pw4I z$14Y)KU1S&5+!%tMSNqx&h|dI^(Ykuh2{Kevxj%&)cAxM+IGqP$MQv1Qg^cmJ8#|NB$+M@8hMl~#4!{bfe%=ok0fu+vCD zGMuGrMA<3s?P;TMP7e`aDsK+oGCgXw$9i;q#ez!Sd)q=-F`ks;@{9xx`JcI z3<4T31#;P}Jw!nqpFrgXHm%i4wn1SS40L+76A~uzl-K9~WD1V`@i2{!3)<`!&Othv zd;VA-={fTKzSv}Xgw9P3sxLe)VvsQvL=C=+3PCGF6#w@uJMu;1=d;*bsrs%XHBXOeq%F;BIM1e{(qLI{vtYwBZq&yRDB|XJ zg5OTO>QEIlxKs)Y6qY%Q^0A3o6u7&pUy@CzLG5UH{(A0A*OmMq z8s7*VNk85qZ3mX?fO-ust;`)^;fuglO9ig?Sm;yS);?TAyr|%!Oi>Q z#;0;2!8DWYt5g0sB1#`@k&gD~F>gF<_m6#qcl6*9+M1rga6H(@{`Y#iMrDPfp_dX$ zNfOtdOPdh#7^}tbkX{~3o2z9__n8kB3f&C{Z1tZjUlS<;fIw^SR(;|A`A=kCnK17b zRoSb{Fbit&l3_V&Ytd;ns^--0j9&|u5VgubU9$*kev|g8e)pUl9WQ^zJxh)3(IK;@ z+EmrUA4e`Vr5fd6B8%bV@1w(CUUV=xxFk<=d23`wbZ@E8{}L)1$}Mo!pKT5@1XGh{Ii*G;7CoGLj``&8so9w&vzwZH)ysuusau>wTl8;>j0-TSc>hX`576;^70Gjf zw5MlrsdT_1E43^c2`o*LNJ~lnCTMESM)VAC;eq=nrVxxG6P6M=^Vbrh1;XcgmT3}8 z7x?XdJUgWtCujTUIiwHo|LHfKd?M7SyX$r7M!SSCjNOD0AuQOS34qQg;@B2|<c#lMe@jpecO^H-~tya~c> z@ly+orH{`U_$AC2t7Q`ek#D3E$2`SgHN;;Sg`Rr&!1!E%K{X%q+um~DQ$BYBR(c#Q zs#wECeW#~;m*0m7c9^EUc7kT3lG+VF?ISv%N4n5;YH{fQ!Jh5w;e9obxS;3eKk~QT z8gK3RH}0YzamxjDUN?b&kOAdT^;+1Q;8gxw6YjbmRgHbUt zuF9=CLp&%R9v=B>1boT`i!NSunoNMgIAC0#q4QIg3^g|Ho81UO7$vU&b{C504XPD= zYrDBQW{bDY*A6P)Imq5I^ct_JsbLgeCV4iX@$GC2P0z8buB)yb{ZvR>3c8F*ENt|s z(!`{IV47Zw1F1o38${NRpJc1#1$G)$f5|P*fyNmA-^ySV1kBWZ@`-05l$4R_z&~Uz90NjK zpe9-Q{QTB;NN5GW0;EmTqTsza*NaWY)AP5~ zZN2(i^{C*;S3Ev*a8}*h{avwVqGnd~>{%CwpVVDOJ<r6Ce?Cv_ zBp_ez_`7VwAqVL_H-A#zIJ-7DBkk-lGO!Nn$twVI2jpWA#H^KSr-(b|7}6Hum976o>x(P)lexn_wO?NVgI-@cJF9|zv6A3@O7$j z8rS=`$0tJP9b^2+v0N%!m1xO{{k0Wq9!>$ADe!X^``>}&`EL2hw&qFESgwwLJ>~BC z!?9(J!iW1;wFtW{lD#kIi4HR0iF{%XPMsMc=&s(E9ph>h?S03%eQ*E^>(RUd@Sg@d zK)gy_IXNs?YO9Q?BRqUs_6GJ8NIEoQdJ_FHuF$excjP-ua-UMLrtFWUxQ@K5x4!_ zpdSUoij$G&jj)7O>ys%X+6n3f@&aY3sW4$8nzMrmF!qFOJAz7GBO}@iupR0@0AK~| z1;q1r-D!}PbEH_@5(LnR@$qDM3p)$-7vz#)nFG_0ta*_5I>rN{CvtKu2lqPDbJ-rL zs6>uAO=s&Yb|!mD5a`seD~$!JG;T$seqP?^?C5Mhn+xr-B)J(%4nP*Y^eYT1hRFXK z%0)d5C9Z*DGdDH{s-{l4|3=8?S&7!oJB@Z)#_gk`B5KN6VT*67-Xxv7UJf24wq~C2 z?j6nVod0@j_9V@I$)%>XuM3M=?2NO^{!)NGV&vK!h;LSH+@0v+>iVKYyNcQvgq-jc z9pe;EVQ9j=b<1XC5%82OuoiF|;fZ9`%`fwL^JZxvhY(0jQ66=vbnyKkyr|Mm@RF1; z;7qj*U``Q5CsE3i8emX{#4ZKO{YJCr^=8WDk^`Dnh)Bn3(G|E;2)DNXPlu8HN1A+V zC&!(g7@f>I&8en}drht}UtX3JRpxmA)hX zME2|P2!heF4;^*3UG5X+T$-+NwPx+v(Mw~6$>G+l!~^GH|KXAZ{3{F-mQ<2SfIW)Y zDrGALq)SK5+Tfi}fx)ki>jFMVAy|*kj*eVlU7k@^Qe2EUu(QUjb+)(PgOm+eq2*x1 z?Ium@!AyWrf3|~hUoQUHX@*Qp0}%5DhP4s|T*H8x3@WVD17`JNU&zXa`aVgT zEf0F+LTR;6o>$!xzTZNgMv5anPU2Jr`zkBPlSe>I=3j6pyC^d%&HI-V{ILxk!07v} z|6YD#0TZzaL9Sy3R-RWKSBw9UFwd;5tTtk&aPU~iQjVs!e4t$U{tm9a%i$A2^ZQ-D z>NUdO+D^Sc08Ul~+(rn209MD9e<26N6b@J{VqhD$yu1vQ9~^S>P5@(ohnaLT4!o6= zUXvc(R7`6KlIV=%Mz)75_n4U0!pyhLI7!~TdE){i-+?+{Ul!_pzl;SYY~YIUR9+qq znjZ)qtiXT*FsytbXE3<}rY^L;h31@lCv(^qECG6!Dg?rurf)`QY{xA-&2l^A_zY~c z>Rx`Oi+!x1HaW}nb)@TMeyIwPpbB9ZiLUczEsh6R4kDYVkUfX z)(Au^pf*rK@5l|rzfr=TEPyp+x68=+DFG=-0qI7%Ly%NKk?v3= zMG+Jb5D;mRZjcsf>5xXH8>Qa$xc52l_s##EZ{GQ4_L3giXR=g?RVG>Q`fhYhF6xV-|{_-~h`qAVriu zUN;743x#axfd^5)D22Rg@c3XA6eM?{VOxi2J{r)5A-r1HF`=gerU3lx-S|FD4UPAJ zp*VKg8~hZbKaY->JANZHu)Kt3sib5%9dOnn`TV(P`UA?XUY7y~*GqI#I(Eeic7r@Z z7(;IxhbycF`S!N_KSg2Zf!2utnl+(xi>J{`FWcrLw8Ds2K)VQtWHW61d!CZ8@J=u= zFlc~TFGSGUz-vc*TLIQG)BPkpo%CfeDNMrn_-gt6|ANPRAq{}@fwmYSY<}w?hIwPL z@8aKXo%vSDPx7$Wv@Eo>s@4X@Ip?ejH5T1;6B03Fub`p%Vfd3iwv8pUszH5|KmWnA zMX$)r6`RosNvb#w3J8@4w`Pdq^xbN{aL3lnyMAeL@eX3c0JLIUJiO2Lg0CFtfIkFW z5QI7nYv2y$#KFcQnAm@VCct5&fCgbQa}4-28-)Z}xw>-j+P+smJ}k}fxW7_TX8dPu zI*dnaB$g-FZoFCzuXuArMC^c%JsP`?{$hjUAZE1cI}zAaJXU&VfD@}j9yT^+*l>R4 zQ+ccS9S7{W;$e07+`~VR;3fcE@M*Nd`fP1&Ei#5`B>?9k%YXQK2YPMPR8$=>9+q^j zKyyQVWgKilkoJb7qT%Xm>iOxrr_KV&H=Ou9Io=Jb=AO_?q4lnP9XI4@a9IC)LwGNy zF)FpE_3j%G0xR{n4R9-0A!zB5eE@J6p;HY7Fp%Hz8wZl@3NH|`E&$f{*JP1csM=Ol zpEnyJ_!S`!LlVWGBUpF?h31-@bfLZ~s27g@aUsfqV<>TUv;Y)|EigLjZwv?kzB9sZ z&ehE&_2JFNA!EQEjJr4na77_rWWWY7S~scp76O8B zI<5D34-9Mf$YDpUCg4DWhmhOG)D1dbr!)&rniy@w0X8vyiecSxf17fSvkolCt_epAXZVlg-_7yU<$L{()d0?)4Y)s4k zDd8r4TCkC_1$ge%TjM?cvt^u zTqI&=WezfHXh1=yrKTaFtWbPrzmu}0$XHj7HJy36ByraL`;V^|FIWiQi(zYf%~vVx zB->}3hW_#K(E~LugS<&PDJg=ZT}@~2YI?3vb_kBRUF~KI{+8JXr@*C<0M!C;AfAAN z8x^+t+aJ0cpcRztoaCjUF8_xM(B}pse{d0^+XWYY$KkwtfK%;w9rj<6Fj%*BM|HBe zr!D@&G|R5y_3iBgm3SZo@FDci%6rpAzufVe?>P&U{u|7$%`N@-XOPr(sA_C@F%RX= zmj|hzpS{v{zzE9dU37;bB{0h$nSWg+al3LiUj5hy7Uh?eS?G3*1|7?fe*Y$+qf-M8 z84i5eqob9#A|M`1I2k#6dU?9cU@I69a8AnVeQoU5isIwLjeCBjPQ&k>ce@cpC}704 z(kt*+z4ViEd%2%l+ZElqTh^2(E}s5Sd2d4QUdBrCs&=5amlr~;{jX^0^8(ypEwI^* zIy>pJf$;!QWWfVzx#RZAdc?6Dxeb9mwhd~I{8QjU0w!=AU+VLszL#{WC3`R!!~C8A zMSbRx^f3f-0$)|D5Cu+6o!z`#OrgY7ogRY!6u?%B-;--cekc4@5uR*C!Kvw8>Ncm&_5mT z&BaxEv|Zo~eUQn4H$FbTx4J?%^&5;Fw6(O-*#gdC=5s`dRF0FQqlv)fdJdpL*NSxM znsVLe6sKw`m}Q1t{7dG+yq*q<#XIovMsb@|MDdtZkULpG=U>>`H3OKd+L?;8i=^Dqh_vwMxR!3N? zz%fI7alI|+DD&R2x6AkDi6@MO=}N`w2(9|mDQiMsaBFcOVePyYUd zpP?}EVW(ny+Kq3W1-I`wLvkGmg@8(irlg{RFsegmP$5oX#7o7ux@JK6n*uVn{yaS{ zXj!2e2;Q4YGO+MVfE>g`<(tr{fKErU4kT=j7I2He*!muPEN$KXb9-*<^;OQ-&YPIt z-Jb{v{$1c^+lQssK9WWg?WET`QPXU{ZU-C4(5m+i6!e-xe!b%vK?Wm@i`9Xl9L!G? zX9)EJ=+05qZYB&7*Fk%tX+0#>h;caj(wJAK3b|8J&Pr?oH2f zqOn3C32dm0o(9lsz%I+k(_3!sb#JKQtXaby8Uet!iCGhihX+@R8$Z@g^$lfbZQah- zr#2&P03O}q9`NYC(;z&$`&fAArvlRv0zQXtQE3bkV zuY%$WlU7Mh=38xGLY)arFh_Cl0SD!8_p1jDO%Pd0wm^3@m@b3i&bG0XBFs+Q-}_tS zg|%MN)Q)=Dm$o!qAju%g=mx)I^pAEuv@pPGXlZGcSR_Lk&|kZM$*z>5!%FL`30{yOKZxUWLe4Y-;o(MdE8?fyZj;a6uPaKmd`vuK%kJLirqz znU4`OS#tO5UG1*nGk*ymu$q6~u9@c&Ez=U&oyKKN#9UouP_ROj+rH}dLED$czA)w z%_j!T=E2hpD8^`UkRJip{0BIUuIBN?vM5%i1G_tS9&F9ZpdiBZ$M;5QDJdzK#quJ? zpyPTsx@uHrPXgueGTck@+V=hFXaLv=gR^j-e23p$7!~wa9rr4C;q!;(I9?NMI*$On zh@_)O47Lz87mzl#_V=@amI_uWbSR)Af|$>K=sh6_Oo2C;-(~%8|Gdq;Qy5y&w4_j^ z-%Vyf{oB9(( z)s0|r@nIb{^~-%}#l7>XKy8Frnl=?#h<3wbtx*LF)Mi)};esnH+(ou0N85<33+xA; z0>XiUnNu0~m{3@30g!BMZx`@C@dW;DmeluQX!8+Ijk~=mb1=4n@F^K=Ws_m3zYcZg z@&d>p77zv~pw?=sVhP~>{+A%$4+8?Uv%q_kfK3Gmmac=VA}EHsF2{m7-rsKg8#BwL z%}|Vcevtk6d(z!?@{*d)@VT~l;kA*e&!e8si5G8Y*DM~>?LW8!MJ6b*CwbB0`fx>W z!P2=Dqh4^vo~&tdOtMb(X{rxnsr;xp1m`0hAXZ6U*;Zs z7*!}f&VrN zN!fsh|AEDl_uCAt{KbJ%i!lqDqQw8uEZWjL|?kvKU(hQtTQ^>l1yp#^_?yY6=B z`w0<#iIkTM9pkS4uky??Ge%(&t}hq*vwPjF{6@9!X!_ODm^Jow?EJF^(E6N6M-#i}63)|8)tNwj7mtdMWI`3$lK48_V#&E3(tW`esXxPn@~=qUUl+ zmtJ>DB@qQmb~i`zu=6|iWWvBjbThSV+1Re84qT?M2b`S9P(Sh6arWs<7;yWPY~h zxvy7<^_A#;AoktM963Hz2Pv9+Bi-FLj-FLD>S%AHBADe7(7P1$!O&DXPIhJaRPq9<8+d&j?*pS@U`>6UnG&Bx($D`4&3fjijupW=+7^4KJ5TxRc&} zta|L?xV)0@_g`%>_jsC&_mkyc*B)%yE-c%hrPUwD#J-!DN1Y|V<{6Jy z$0B25PQ@felOZ9$m7Pb<7)(J-PFxa*g{3W{b(0(CvNZ;Y45s|g!K_d=Jto}TD=*{B zMJ7F#Pf1dygRWd*{&;oe`1j(j*WudNwQ-5kwchGO(?}cEv>O8Grv`;6RMq7A5%XnP zXD>pOZLCCasR2a@4)Z>K_ox2V{dsWsFvuV4-j(>~Sbjy{*w{GJx;X5*jsLte4)Fs% z55~)kPn)1aK%rnZK_tr%y=}Ck7n+y3xd|H2&mg8gQ*_mK?sJ$me7FXFmVq^HnKKtAf5iyVX zkvoizWstN)f{#3^@Z`Iqtqxv=WdDWw^O>0Nv2R|haUB^)KE`Z!B<#AOJE-rik zSxkA@S~QM+dyyOAwXO3Sy=nt{0;fmO@RY1!^*ApIy%#FaYzullL>cC^moh99xsKzS zO6!LQ2DQ9kl<^Eq6Cg%2c*P5jr{&qn?|C(1V0wVwWENzNH^I+s(d`CMbr5qT#O!<2 zF9viOh|HLeHkyN*yY8NAl>m^AfzHwdyAw;{WY?dAtS8{BfkM?zn-?As{CnPo0v`Rs zE8-g^v8480-MHw4VV3%kWv`}X3*UqMF`+zn-9rWsD+T1FXA{Mfdk?$3?9?`U3_qEo zrF_-a0)NVlGQCR%T7iV?lX7#9EO@5XBes8DB{uB1i`CY6cWX3I@xDWYdxld4180tG zaTCf$hcxbCcK>8X0Rb)Y16NNmW;9#fAFNq2TDiKwQYY(htEK}r39JV7-rnV-zQUys zoB*f#N?sQ<8JudGy!uav(#ZLF#iLir%f-q08D!m@eiGNOlL2YFV5?+sP^S)(j^fAO z$wwkKEUqVjmCQn9$8)+;Q1lg;RBDhq0mLeGe)14}q5>C05fchj;J0tOIMJ5p{~SZv zUplIh6dO+dXelFeTW{YUP4xA-D_4&dog@xWMxtJRZ@RdmF#q&abIbI#6B$eB6lqk` zY}+Jzv;Lx|MM}wCJgrlWh)_X$Tkgnn)+?4~_8ene$EIJdUoY98@fmPB_un#L3u()p z=Hr*dvcL>~woU75ZX*3$VD7UALO zl#xeAi{Erj`+wf^DhiF87_b){E4>?gWd!m9ft8J&r*be=F}beAnP3m5Ow^P0J|bnt zE@2%8Pt@4tVB1h0yCSObX+7J#_{q2fqdQ8kNR2I2(0`cs;H{|Zyxp?)%0|QSJzvl@ zZ|&{f0=F4*JglkdX*3jUOQIu7S^l1!tTQ8uDQsuiV3sC6&&@A)f4u)vpdq6bNB^^< zyHU(Yjlj3`t-MCJ{OFAr#DmnBiDl0rJKZB!yQX|BjE2N*b*XE~Q-Bq#5fd}8`cq~0 z&YF?)<|Gx-y-79(57YeiV+Z9V5>n=N!Q?a9N>a&-KO8N{t0^R0gt-atArea#n3dHrp8ZcV$4|%d5=pfKP6P{j|1VI@9~qrmm zq)LG33d+#Fw$~*8l()uP)ID08V|Y!jrOhLsScQGOs(Ew0trx=ht5T2A>gs(fe3?Xu ze~;*W?EZ;;jXC;tRN_MQkL{0%W>*i~nkFx?kGxZ)WhVSCABJuNmA5h|$g-&H0bsl2 z0g|VJf6h)yJ*RjzJ?f_O*>%MqN0!`>vGV-=`Nm0pZrUZYZY;D$k18@}yI0huSQWD8 zg_nZ3xRxp)WoR58)WV2r98VBJw~oQDg$ON9?jtveCq~cHTHdUTiM1c2dDN91 zcy$SJ4FamaCK8Qz1w!R-fb{9fda{XOP9oZ6bQx(_|bK zgX*4V%^q~e9cIyAV!btUm!bn=PtL{F3B1vsEqjj}xcx_VVDtrWePY zOpv|TH*Z~a1AbCYdoJ#8>YGA5_z|Q!mgApnm6Vl9Y*b%y%Yco{;NYN^q2bf{dFwm2 zwsSBNBB2ASu)>8^mruZ#@+WJ&u`3V z;yq4ySDhhGUvDg{bbH`KWc@!?Ic{}TUk7`5yCptJNPzTws!2*Wx+m`_r>ToxKJA;F z8;4qV16YbU?6vyc2M3;y;BE0WO`1{Cd+#O?+CwOJFK7_@+D(sea!VgyK zjZ5C4y5kd-tcw-uu(Ip@AImX?e$&)l1GOD|1X;KXm}qI7!SCg&fHN-HQ1Rq9vfO+*%!p=}Lu| zuU63Sgr%pai}kS&v!K1{R8sfD6M?Jdq}ONM zsRnbyc7=BCnOqE;aBVr%Ng;6bQ-nSdZn83c`ez4;5%3wy=XDst&y-Gwpm$8l%xvSg zDYcTf=Xhg6KgnQ7gH1#q6IK|OMr}i=P~bvFsG019-*86BMHyCshM~BsD_8thbiN2p z%fICj^op}8DyrN^iqJgc=5mQEW&NUtF9YkmR`gZD-0bY<(@MsdjX;H!F|>Y z-e0k%FA3l@z8+t(X)5_ZrP|Al>eKbbNQ!&^>_WdsAA@1)LCGCL>;jh|>&vEFP*7v}Kr4(6Zp8WpzQ&3pR9Uo|kRZ1<35-1;0J@)8eNc>di>-^&ZJ9%)R zNd(r%vyF{eJiNA~p3w^!*5{P?)dScVf+m&EV)5yoqPYTYXK3T z4l(kF(6((bbF>0`Bn~bvIan^wEiJj9;+rAG8%QNjrH8NXov|AvV0~{8Q@n|qaXywR z!z)~T1Kn1rY4pZC@-?c*wOPwpSusD0jI@H%UOLY7qAOjOb8c=94UGFb?`fChR8>(! z%q>h0076+(V?%pJ8;uP-`F_Xp(Z)^+h(dz=IrzV!_2f(LfnPN1#X!&keHBN7%Ju~C z(?qrtNOT&##@4outgbSN-fPF>q_7h$>}RGBclbkXm2^4AhP;?Xe+(_Wx?H3Hm)ZUP zm+2uZu}#Buk@GQA9LGPCY*_-(Nj1B=8Zwfi>la@@bt0YAM(y_OT+3{6L2!3s_x3F} z34cPo3pSkJCk_4|gH@xli*|9ven3n5SiL6Qt_l`ItT=9F-AQe1@$j>@jEumcvzGhW z@8^RxJodA3n4_cA*g|r0a`K0oRJl4V?{!?W61$Iv8pB&Z%IdqUHpSnIT;;#6zlleZ zk_Gv}X$T&E3#gz=oJM)?+_?i#Ix`OsA#?_xZDJ+E0XJD(S^54=0(jU!`2^dTkm80v zcsUxWvS45i8-G_oe!r%QQ^EEI2yWqpv_9TH_q|i30~o;0fEt#Zkm4E+1_u{Ff&tDz zFhqBDb~b@R2MHJKTyg_&_w%o^VrpjfE=G?T3?r);XvvP0^TYNjr=49oRqD^e?>i|z zpVDgm%G_ZYpOOP~_cw_2(V@B+H89W!Kgn6+Fyrov5oiIv?xrTZjha zb?S8TU*;hRjv}-9l11+9litTuEi+zzizwlChCyH;l@8f+=;ZT>F;7M^FbtuY&vi0b z%aOgtyhuq(jW!h9fTjP_^8(L}dpB3(`KavVadJ05jHx0|jTtzph?OvKx{%D&M?VL# zz>Y_YgWMhjl*n8T!9^@mQVj4_wzWlytYF_YGNOUJTQK^029qoqGKm7bojzbcJ2w{u zCV)sb9%3wrL>oij2b*_YZ^_I7oK%e`z^g?L7sc94>@+9ww;pP_KE1gI`bx*jXcWrYc<~NUV6<>ZhYsI2_m#C>QEw|=0 zI*!8!YCg~GmP_$t1!E4pU&7x-fK`NmMV0 z;{0v11qMTX?(eXquSu6knIrt-UPWP+FMQwN@%wZ0@$XNf6%~$Q4VOe_zSY4!c^UgP zL*$DURqMVdjhNBH)ABTM@WlVQWz=tZdyBy`Bnk{MZbDhuhBOISlxKYSpcLf=hGwu2 zrslIm!C&W>AW>u+`irhmXhaY<3F|4x^2>mV0Nw24B>l0K)Sn-jh<^pIMFV$)_<|P$ zUKqMF>#@CFg}@QmbF=|JuX$JEtH$*sT!%G(!h0CKTEB4k2$rjcqC?*BInMWUPHfLu z^MBmxqTN7RF_Ft3uMmv*cB~MXu?sy*2tzKCYU58TVSjtE<>JQv`m9@|k+*B-qW8#^ zzq*_=JJX-7sdse`*|iLARakl|sy=?$FPi{vR%Y>ck_@N5fBTnmK3dV@jLxOeyY?$iCtH_bDNhGLqh>mb`430f~oC0fGRR zA|l{Rg%=lJ19UkM?BchRAbc4cG^UU^d9&`_kB7xahA37vXm+sCfQkgm_l`KxLS3SVt{$9svLSeDcMR=)htbeZ_EwREOd(|x~rMi0XGIjqXoZ`1=a zOd=XIcAw*;`)@vA9~0=;lkTbt>{umeO~=-e)Lp(d&> z&a86kEwgTpD@JQ&ICNbP=FB(LQB3^+(yA5ulk_N3C}PCjxdtxin0WUes~+r zu#9fo1$&qcm11=zo89_87t07FIrR@M+M8?wuYlL>Zgiy+JIi&UM5Q3sxGlcI=x~VlVTi(su+ke;&zrDyV|rQa(`m5%UXKPHRb1 z3H5XGC-Ge0#SKxHYTPka%2K0mTt+{I8!kL8nOOFh3Jed@@BLXK>S?zrrs;o#RGH!@vbf)4+4<`0~j(|I|B#_ zmA-h(Gu#STO&AOi2dko~-5%}_zM z6sFnhB0SXjLucRUo{$Wm)G||)cH_rcS+K`oy=|7`X(*g0kX7>A8SlT=oJ>z9?EB}3 z;X4Y{-uNf9<%;LlQFBkjv zizJ>&shxEc7w6|cNz@!(ipmKW`UAf68it^^QQMTy<@75FmYR!q?RuZ^=yTWP^*i~_ zO3}HFK3!1CBzdEr42R_(bWjjChFC{aeOw$jWn`PdR;BXtJH8rdvzgU#{eqEBot7W& zH)sPm5@Kl5Awu+tLT2uK!A?SPNlD4PC?6j&cvC;lF**{0HuZ|netSm;fUEjOmhKN9 zwg8Jj+t84s9isP8ncM9L+XB=CP@qz?e$ZdK~$ zb=o83;Tul}TWSg4Jtk+KlU8acK5Lg`dr$rT;T(bg&Od2h+*Zs#Di5e!*IY{HCbu4R zc~@25zU|ulQ=E)B^qUA}Z`ALIQr4237KN7XwS{+Z=kDWD_yAlIrvOn&nIH>@H`LLI z&pI+8fzAM^r^*HJGrrf3-$(lI2q?SdYA~SEwK!nG@7?0HB|!ww4!TqjA0Wom^EO}~ z0#>9C6S&^uI&=z4N>K0M=f;ommebyFtBw?K^u>E~j#r+O>G;w|1KVYw{_hM#K~zem z5<}ZsGWA5RhPN7dH|2U9FXpzhuHa~-ol;!AI(9Z25+9uZ+?Id#d*(+Up9ubn57es@ zj|0OS{U6$5H~p!t4dHsAMqcjYV>O%MH(z)0HPh^&_y)=e;?|SJ+-039ro*8IG<53O zHdhu89Vejb#t-~Dz2ukJ;ljuK=faOp0`I=KAt@si?10e1-u=3U4($wV;^GaVEONh^ z*i5!9Hy(h!5$%$;Ht%o`3kc@eHQ$m4oN<{GftC#Z{T9qqXecmxK!p6nfZBv-oZeGf z$Sj|n+dd@etv#+L%rK|O2}ugrnYvpCi;5cu2%kV{0a}GSdK7M8?5N0 zN`SEe64Qti%yb526NycLGk`-#7}jRp44a0h;EIC5_5zo4qVlDn&gy0z)u+1d7*va8 zv;qdky0XEFif@JN=+yRE*0tH$*Ww7aE6X`J)sNn;+tJEjdGm&V&+qc-jX-3g6(Q=|h0%0= z?2bTCp+e9Tt0bp`Hg^w?3l`A_4#Qm-s3--SLbvMY5@#$pFiV<8L#S#x1gy@?%!oXy z2W|dL|8ELV0eGcaybzSEG;--LG9tu@X{0gFZ0;yDuI9^cUr%xn`^+Xe?Grzo`DM zIgD3gk~Gqo;lU*dnprw**_M+Se*MRr>s2$AK}NaCN?UGf-Y!-pv%7J`O%CVZw{vql zZ|AQrhmpv3^4y90St9Bs)sEG`+5Q$kEim?4U9670E5%)SLR|m(7?^P4#MiqVO7)7z zn)nC`^z*NI5-us)_g`@`|w zyw}NK5q;8$FaP_^QKGy0MFo>oFq&8Pv$}{$)H-TC`bdCcGQ?7=_hXw;PQrYfYi1w} z0JnVoBut`l3Q@L3FB1|XY(zvV9Vwi#WUAg5xLk;pJmS zM(%9A1(E6Asl+*nL{`HCOvB_NC=$$-m|PF2zt5DQV-sv`9CQ__K8<55=t~RuJe3h5 zYUjxy9Uj{B-TFBlRnFszfwv|b&VI?hLpEcCs^W>JCM!L-HtCZ$*-GVtp9i~z+6PBGlgAo zx#KQT-#ywNORRrSLga;hpA`+m;9$5H1+3g}VM?qGQaGGfIc>=p$6t9rQ$?XET&wP_ zUVe!|+zV4bhsMA}Av$<4w>#n=crcxp9o}bi?*#wK*GI|;IS+~%{B6;AyCaC_X@!32 zQBzWeD>8Ut!XO91z0DwMA-QzPWP#lUxN9gTaQbUsK^{xipF09HJ3Cp0xTmM50EZPh z0E_#KU$Ca3gjJNlAVP2HIO2 zCj;~X3snbcQHT?Nk=OJvh&?uqmu@EjP3hkS`=H>InPZ@s6iIKsw@Xma*v8ykP1c(v zLYmA6;+1rD^(W!G=&c;D#<1!^Rkb_ zo8=T^t(_hT-Z3&lp^CCFS8c5OH^0(Qr?Pq8JABlUd^n9i%+TSdRG~X@!AaH-R*Gm;vzi+V1xi_`hY&iPEW{nV^$FB$bthZ=1 z7P{@#j7+8HI65 zqHh6?Kfs<2;^&pjOSyR)L zE1>aZrzX(r+YqECh}X-ejKqRm7r@ZUd)sow7OKAD zeh}+>vxHGt^#sg#u^Z;BI|HlHs`$3dYiQS#ulleD4T;SNssGe3yBg(+tb0syC)#EJ zjDc#5cohP}mI#IHZ$&+~m{7Ce_y!thUgYs0XdZAZgKKNWQ8zOO5c~mQ3V~U21lYL& zzXSsi7WuHgHdi{tSX27!2m`?jzc~s)@e2X30Mt@`6b3qakx}j~gmH4U+B60b4iJh( zAo=ptd*f zFPl=@W(ucv`r`fj_mvAEK5&HR9d0fWxkT*GD1xZzT=^Qc@Q%Czfz)r3Z@J{&^mrAU zV-p>5KQfXE71Vop!4FN;1+9kL3fGyt{u-%HnyEeqp8yYG@X(6?QrC+yVf%iej)Td1 z`jPY|mEv;uPU6l~Hus5t`obFZBp94&@b9*tw2sG*y~ybMJo)Xb5H5-Ay3qqJjtxtjQvQ0O6`vWL}Jv_x$OYEqIcE=ZijE zCIDw_NWcmQ43&k62?fIxeBUw(3fS=XFA6|-)mag{dwZ>Llv`avcQ?1Ztp5{FALfdW zANjhz%pi+2U|vx$+^?KuU4O!Ld^q0Hf&u3KFV}{|q5E81)^7-~1trT{zXK!Jl+@H{ z*epk+%BSEOlzY{_1q63*ebRsq{5Js>Z}?Ilg`2x6EV;w6xH5F5#4rJm>b|9(R5kza z%2R@b-tDuO314MQ2HXDDfhrRTE#J=V@mtGXm(@K+{`RLY018RGE--tNYhHezk%5~t zp6)ITWo~;+YdwC&)e28O34DOp*-@tx!OX7t*$v}`J}z@s#y^8cW+ZIGixo9OQgSv! zLIocKZ32CXhhD^a42k`*gxLXEO#wWH;o;!{_p360C9DhwlRpb->*$~t>f?iBWmFVF znbYV+hz)>;`;`zF^Z*Uv0U}oN=%)@0Wa)K&+rSNu+}qp3i`CTB>;PIvYYDs<@MPmW z@tD3>+2Sm011`z)n!vyh!?K830CQm0uocjaGl-=YeXba6Yik4h>sCO#+r|d7Rf~RrNdj8U&o4BkuC{~eCF>+k1nt@@2pvXIakDQCJ49hSijQ`>l=Y zhw)<fD|3`TI5s9!J-^nU zQskMfxqNSsgxdr+{emzq0 zP~zmd8z?C$=iv#;fWDe_lpGTc7OTi_1h(x6I{*Jkf219&+*hicMIo{(E@EZI$zECC=!|;jq2A#w% zBeDk}vc} zXQc94?}uR#Rz+Y`6k{qh?PcB%(t|SgLo=D!bg(_l2x>(I)Czoj{DB-zM&x+Ho)5GG zaEizechogB6yU>#K>?PiBn%8OuxHit@ZCvq(NnHCO2(O?b1&ci#|5gF<9iNZtWIG|@o7rh-aC z)d!^k2Uz$PcjdJJ#{i;*+G_#%sA-^bi~9W$1chKIxFC}O%ew_wbg{4nX4?Dm)mMg? z4?Owp1>fKq%ouZ10-bpw@>)X^*c-b7OB4w$O@iP~q|$)fE-g?`+CjGP{KboqKB;2@ z&IA>S0MOVY8hs#5rPgW4-YcIh5UwizO+oC*&-P*X=z|^?d<-e6f&o`(6uZo^F*#ew z+^(xv`_$Yy8GjzjDHTVov$^+sT_j2T5pf4WpN)eO&Po2*<(P*P4DECzLH_yr)8FWz zpfm_{?it2&oAro`IZI6OFz|kPO6*puXX;Ye1nVy(A`z+{6_|qGgymNZqjU`Li_uYF zg%Sp8`}q(eshhAsL>6A;l$6k(p1*Mdrvy^4eQ5zDEl4S)O?RuHX29_!e7jNtg7}hh z8#utcW;LOucO3%gk+RJO%`R}ew&9oCfL||o*kPjfHl{DZZ&kFF0&ma??o-6i(y&57 zTv|65vYn3ptQHSImsa5NvGSdnXDZ$-;;U+Tlz!`B5YsExfEmI@R&q+Oo^dvztSFdsu+(E-d zjk${vh(191()&Mw2`_v(_<&BL#$L;}s*bS1l8kTv;I${a6{%;te`+Z%GogBUWIc+Q zkuerHK6s2ntNS2Z`YE&x3@=rE95iqmp|ty&q&?@31aP66Kq<)SJ9S4u8~-ly{3yW% z6oLwoJS~V4CWe>w;Q^}?aONNrA_|a27Ew{dPwH}JkT%qU7_Y-fUhJFWH8C$(IkC0;fTBJ^$(J{#HvwQk?&2O zu2t4dwu?bQ!YSvKCr(LitxbnJrJWAtod8`7R$(S8DB;yJ{FlQh>)8GE6Se0bLE+FR zAzYm3s7|+sCDjk_I?w-hib;F(D*RFEhJKDRfV1(b$Lw_M{?wAE)Vq(jYwU zB)E}x+M?|lI=AL2B};I}(~`u`799n7W z;uT6N7DwJ9%sOVN*vKKW|HzGRCi!}QV|f|7Qp~wre{_^3OUfF}H*Xtdqx=}p%~Lt| zk&(vYpMo!{Ppd}5TkDs2cGiWlW5c;y-b51Bie8tceG^+ zjJukyr7yLmuh-0LZBUY(@q76y3#>@2{5&VlhxNk7yf14+z~mipzYfQ zBKIw**pO2I9lB^th$-(Ajhv9gM1yFy8x!k~VN!ySz$SaaXQPY%n{iXpt>O3P=If2+ za4KH&)_I7v(q_EuL|8*c0vyBZwwqV#7*F`u{_Je9zkkFvK|UQ*YJOe=4@$`_y;uU7 z*nywHhxfMQIE6H-XCCLv9nZYr`cvh&NAUc(&*zm9~0A`FQy02byEw7Jmi;Y0UPZ%)>A zA?H6_0Hm=7B`6xS0->h7icn+<^jFpWQiWUruON3ER>NTyvYY#wlqPCI>Lc*zN}YO- z=}XuN^A3DL_KV0ODM=mU?7~tC5i9>ts>kJ?n?AfkPLkA+kON;?0{2%~q(*0C3 zY%eIAGX$v=B-|$36GZTtC#Yb-m4Sdwh>R1m@}3|g9&FHQqu=*h+;v$S`l$u2pM+WJ z-`855$9=TtN+q7bXSwCQD5$3CL#99ChFpXDG==}6XQB;EtZyCp(=<)CCZ%gx-gGTl zjlV3^Udnc5G9a$C=7Y4Gws5GR@AczetduvGd>`5|d$ybZ#tqeFl9Z%J`Y8~EUJ0A| z{~)Bqe*P>A?ZEzT5s3EUf+7E$`x*>qW?PzNtNfo zwh`E75knx=O$CM136rx#vTua&2pm-`G1a91P#R`ul7*g?;WD?mn8IFUQQ;rz0W@Bp zOzypi@~Rz?e;xN{Q8=G)!)X*1Y*YRw-K}LWe?mMyJje<&rNWmpqK(5mgh_WQ_yw^} ziNj%UeAEhKGCtbq_r{lT=Q#iW=pb&eTmVBLGQh=9Uks)oQt1+y*U8_xa|Pxj7#j!y zodDJ4ENu7ZtHEiO0V>|wfs;XbzAh(B(Qsi~!@P@RfI?4@u9FMKrC}iBN0yzaKq03Q zCN?%~;6zgNH3A+vkgZDfWB-p+kvgAzfosm*`H(JD8Kl_mFFrLM9iKYQVQUB=Te&5Z>FLkn;F zPK>h2vx&W-_W|ALS0s?5I?Ml$oDdDSg8#`0$t);X3*P}2;MT!G`)y50)^?bWVu2q6 zr&0M}K`(z8I(Q@vmlcQh2lUr+ES1U(1;}@bk1fPppDiTyCODh^=AhUAS?73AXdPzX8 ztKuwWotPayW{~lLu#lC)^=~G^7{QtA2;Z*Hxa@(Ieikp?H_hi!E#umjULsVsa!M`D zfzA1;Y^v6!);W4^g3Jm3cYKgtYJodXtBQI1b`hQC+~%gm+%}ZRmA*8@-aRkjLieYH zjd33#F#U#`BRwnYRum}dnjOpa50~IR%v~{`6l8F-(4aGUxOU__Yw&jjF@eTc3L=A$ zz%j^hiU6LIC6Fno#UFD+Kp_Y~#*z~jcslr^?o`}yN9Yw}5CNnPBOV+gb=;O$bGke6 zc#PL+44seFBWqhKT8zD^>6A`~t|Kvvb;BT&nQWUFpDV;c7dQ z0oBqr14A_Eq_ybM#M}{26+nv<-YzUHg~13Oxd47~AR}x+xRV;{CzX!WD3~{zTumty z0e5y#S}UM`*sGQ}rOz>8f!!!D!3M|qy@JOD3Op=4JiIIXV0#5O_5zUQP=Sy%LJJ;A zalS{9K+^)3e*_RiC0)OJvEk1zt|)qON?n#9M258Lnzn{Qn z1^6}^Li#OK7v z)9cLCAxZ;y&1_ygu@XBt@IJ#+Qc@fn{Q>6zI^RW*mI9s@GVIv)uul?_H;&NYaL9q5 zCJ@{B0?vGqW)h!@_ZD0q=H5S9AJ9F4F;E8Rhv51FF^tWy6374#DgMwueg~>rQ zdj8i3R<9QAEYW;_Z4kDntdZZ@u2EU~l%h0U3hY9ADlVOi36=JhCPoC&hCvp+l8f_S zadOidyf;i1PqevX>T8@bEDUtoXhL-nZVo)+{}VR{{>-_0G9Zb52eP4f$>98CMID_% zAul>G2m3PIMKR~a0P7vt%5w1XzT$RNQd4UME*~V#XlFXX(lYm4M`Aw1VKw}dCmAYG z1UJclluk|REFN0aP+f!QXZ6sigu%K*>Sz|DZs!ZvScS_a$P#}FEJRxAZIGoRy=I9e z9WilW2ZIj*JZmy(?p=vk#C{U~2W}RHkOpzGO9WnfL2zs^P{0 zAXd3CbPigXDV@A8*3FitPRS?H#+@{ zKj+o`eX|zib);SAiPMpU958|XJ`KxXYU=&W&g*IYiN*Ckq}ZTE0UR!2zO0iHriLMRw9z4R$pVkB#E*Ty*^{D41S3?iXbyE zze_yzoSHmupYj0MRAbn|QJ-PrM#B0Kj7(SpoB`AxSP_M#Lj#KUP z4j2}qA|nI@K&EXV|B#T@1d{NsF2zj0@^Z*YcQHnRLuWtq6Zr1c{rqYzE8(!00a?Eb zbAtlp&rBjr@-UR+aI;GqStW^ROx?C2k_1GYcwz(rnmccCGX^@gBMIrpqh62|^^?{99A=b^tW-?ZzD1P`!iTH% zEfr;Y^($sJHYJcVKCIGMUvQlIyo)`_8tMU!5L)KB$E_cvyBKqY{t`$(JiXSk)BLxc zRtk4w+3n30S{vf5Pj4l*&@^>)Xr`R&l9>ikXfi<_oQqPItrA}W-zUSvjf$GOpe=iT z<-3Ee?FHeX2I_%gBx6XLXe6?epUv%fnV(BV@)ZQFmlHQ-hHtB8Y^2%@bjka*Y$?qb zbZE8OQ~QIoT;c8JNA#?bJ9ee`e0zR`eNf2lyHNM?en0aoidIyc%(buVy-h-MKo1^? zxBt2FWwYxgwvM)U@~Q2s>w|%Ok~Ei?Yr|@0X6+m=k2_diJ>S-D**W8{%&Wd*uN?Xf zK*#<7E}y6%x^g0 zunAkT1OPi>q`>I&3^3=fg}{QF5lE*ZvbYRFuHCxTWwdeSi(0}a8(ou@6j$O6^U)2} zMQsOxO9*Bf&*=qsKL9>LgpC8VM!DKsu$`$FLWX{%Ec-U(O3XSG2%bHwMMgv_RkL{| zKCr7WId{K=XK~r*!b)*|QgFq`PbN2Zbi8pnpR|c3XLk7<)qCqW`JyF*DO)$&1u?3I zzCFWpyEsmg=AN~6celLM(0ZnK>B%vZnPU4V^16QP4hv+PCRe`(u&tJD+*k+|OPzdD zF(IJnpp``9Ao!s5}Cl6+PRHQCQT zYU=+MQp;m_5PhLrr?)Pm>fBjqgE@>r zNIl*gG{Y! z9&0VeaO*teCipF4Jt0yZuc-gLm=j*iuUSS+Z!S#L6&>HEWy_gtq$fBou zrl`IP8CGfg4E~9#+Zs>F55f(5vwiNbYprx`WAk(gMF|%f^9QcJrp|Jye1F^y2y@ymE6KNqcYfDFRBx(NPF?mj*S0RCA$Byk61_P&x`Y|39JB?d0IXnNdF zgxv&}AC6kn>G^A8A-NCUz+h_&0Bypwi7-w_pz9k!(`xh-v7zc}YUL=1hhTpO(*pUg zx)`Y3MD(xU`dfN>dRYwVx9G&irkMB05WgJbGU77AthQvxipUYy;G!W44HCkG?tOq( z_uFTTIv6t&7Kj-Be=@2+PC`V^gBw|mrjAH2t{bvyCk*cO^hifZIdSZ`Jw1O%_x)ca!9l$8;~wbPB7h9+D&IbDa51WXTp_QZ9bfH(bkTS))e#FO4u zh2@!n7`Gq>3E`Oa@*l=qXq0e2HT1G9*@}i)T7<@SKiY-<=YF)5K~L3M{gOKG z#=y(Egz>)O=h18eRNHuXnWglqV;11CeT|U8XAXS`KFDWC2{0J68iFcFWNDLN{%r?x zL?ArXhy>ARdzku(^9PSt_yl*vaX3mM=z9mum^nNmKYHZ!Z1bHep!6Y%ByYn zpKQgm(~+rnbqn);Wq8_~=?&+zB`gf$$khk^hzZb%J!{&rqPcnNo%cEObmrhva zSI=yxa&>+CwmGe}{Diyx``WB0W&=)Cp`05oCKdJj^fq{xybh3_;bndlWo}geKr)H# zV$D=eltkr)pESau)iwxWHva9r3WGb-P_xJYxjIA5rX0{i^KsiTXGd?!>HNb`ru>nzu&OvZR=RV$oY)k8_MA?C78`QXD`M+Kx@7 z-*)e}Q)VR<_qPe1%*qw5Ga}nqsMr#dBIZj;bLc&~1`GPT{CF)@s3{%e0yeELH|0+c zh;IbJU1=*``jePkG}0ma=+8RZQl8!`8B&c}g0NVa8XgT3?<75>xX)!Z$gzCEw7 z8z%Gf?kEq;pXD~3%}kS5`T5p=_lX&2k%x``6P_RaPbC_@d>*}RW!`Z=D`;aPZ zqj^x=Srip-fT?50{U+GdQWiZ&BByhm{e3y3877U)^=^}&X$Qu&9hVgn0a)~YX)~Ge z0`{)}9oCteYdg%hIm`=4VG>ACQTkIVxO729*yMvNzmX1HAAJ? zqPIxzw@re0R7SYuWWTp~(z!X+N51bDJ64jbYFpVgVwCuDZte7wG~IHWyi@A6|2jEG z^*)Nm__oJ^FDVON8p`fwomIOke|3=hehFM-QHMNGMfnKw#>d+-nNR^`S&t3Vi-anm zhlSzDDzZ-k)iTUw9vxl z`r4?8B+gQ(fii1M?{gmTG!5o^0I!%g`1(1&%7drZc=lv>RO2M#39d@3?y*7nH8?o< zKoyjh1a&ELwtzympVVWbn*NC$FSi*3sf$>_j;MgN$bo7;F`xCIBQi z;ix);RKq!n(Xt$`C$|m0>Qr8sMCO#;D|{1(PL?0;i#<;J@dH~_-u;dOBd65A}JzgO2)%O zVIyq8K9`DyhH#nGMkI?KN-4fK*SMFImHEzw;vj(m-~fGghlw|$s{6D`@aBfY&+lFN z^ln*1CWb{TY;4Mcl6Rlv>PxD>xr}tIUOb_G>JF(Qx`({FH*@Q^dh&Cw{ghnz5@*)N zMf%QlGSm9}LyDQ|lS&%JLkgF4^jK)Tr3!Hu2o!}-m#@{G};KMN)3-NVO&`?D}BuZrLb^1@y6JX#uwC399YH>qR zb^q4=-=R+@mPDhZ)3CnY<^0oO#e;#1)_AzxtAWmKcXM`cc+Nz$9u9d`el*KixIOu<}Ee`z>p^Q5!v2 zmBROji(sPVsEr|Pbcd&kA{F8g2?KqnWX$4u9p>)>ODM%NV&mjI#?9>mnyndlR5P%H zUGfH{)4(<|4bJ!FT`6XLp>F zrkOt){KMp{X0xXW+iNr7)dkWpp%2LFTrjH3d!Ce+yTz+3{cyk91}B5S=EBsPtwkYh zYTwtSbM7r`5P=89G(bi2O3c3r=m3!oNhOxPfV@B z(7b-a4zlP;%zz1{FOb%)U!l+~qgK%<0HRWg7SP?pqZ>`vZB(#%I(Gqp03dyjQaV~J zseb6#nKMDCM`niOl2TxaOmqSu&#O4iM?ulQCyTl4SE z!qvyxoka|a_eX9pS3gyVMt;q6)X|eD?Oyx(Zao)%)(LsyHAVxYt!bWkJo}lLTw28} z?!=*YYqxH@M?}zS;9ezxsyEE2{zK^eBJ_$t54-QsYBESG62>+RBG)^erJWk4|KkGG zBcB$iCI;#-i~Z3DK!z^M+;Y6%Ro39Q(A9ODAdb>P*){#CujTnFytsO~8Zw$Wq*?zQ z(ofIVHQU)ZYb)9CrSE!EQ!Ov!yD@j?>XqiX*Drr&)MUm-KVCSy!b_Ks@P^l;+_5fI zaJeOwU5ZK|Q0|bQWYXf}kmfx`H%=WgxM(NQRU~oJf0E;qt0|d0~n`; zvjdh)9~$^$%*X%h!q*u!MbTXW6}3TSDpx>E2&gCoyadodB~7{u6!)`hv)4do zlTcKI8yjL`NPZVrToV`j_PQ#(^xD-t3Z=Tnef#c}NmR?ZJ(X`2!sUi#b;-!eu2TEg z_6FLT2Vs^%DV@I^ zAt8$(#%16%yvEA|?L!*GaGV%~#Wx%W)Y477B3YHgYK+rTfcpHh?V-@-#FlY$b7LPc z;-hQ*a<9T5+^GbV>5S2o3c@bHi(c?UMn)h`c3k7zA%k#CBOSn%NAv=OM_}97XX6GB zY&0;fF4)=%#l~J$Qj!Ak4{1R}#qhVoHER8AM3L_R{|R$;Ha2E)@o)^&P#^-m0O(qF z8?>xfaAq-f`PJlK+EZYXe(ma22<+L=17&D%DJe@UQUSt{iFyeKAMo#STn`-c;q9vR zJLR-N{`|6SGtG*_h|87uupMZQ`R-mFMTL$R(D37+v+h#KFWXCPW`%yHX5E1sk0Rsb z3e&Y+EpAMc*;8=pwN^f4^*G_yq9uC3dhq#pK<4^`$WO>t*&MnW#HGNUUnhB$!RA)Q z$U>d%oS$UefMcmHVlEeh6Ix;Mi@{x(9WAD&)-JQQrR*jQNB`CtN0>r?s| ztUg1&9{~G#vj$E7w2o=z?{ReV8UJ(x+rt8(OLz+CJae@!>*z$9*8F+{2PTBr(XpD= zTo7O&r&dlNoF!oSIWoH-c~5R}qSNl| z9DliYz{XfV+x560<|jfb3LDq{XkW0s?dsIOq~4mK7!{rtdVA|3>4!&$7(QOC&&->l z6MaAS$hXJURKbz_bMX>ZRo7bW6^(%yvA`H{kH|(!>WK}T0oF#!*Zim5Xm=_KzG;2E znJkz2o>vGT(;gieV*SSW035^aMb5~n2zVFSmwo?!69A9Uq21a!IKzlZ073yEUl=*I zU0Ipu;4Z%d_8le*Mm?B9>EcgJ>?O!C;U}UV8#!G$U#hsPFZ>q2%n~Pu)Tax{eB<|G3x4$Lpe>DQzaj%ePv?gXzc|IvDT(swZ$GQ9UmARR|G|dC2N{`D zyj)zi7u`L}eZG`#DLMK1Xr1jN2ZMY{gYyzy>(zTmi`LV|r!IN_3I2%5#pfgxTZ#GW z_S&Op4kE!iA)9ATl{our2ljt(Zd9_Bt#~>x5khMRs0b`kuSQci{5&o^l_WK($we7ZmLa&6mH9dSLWe7~5)z{7fWU9}`hGNqB`N*PBr zqPl23Sq#s(dtNqb-n~zFd1BrsfK8RRbSuwM=4yr1$i@tdHIBxkTzlR&UpYwhs)(Lu z^7Heni%~pEn6GP(0$4Rb#e;o|M)w@nn-RF+Oir_V5h}F65b)x~SMbm;T)*CUW8juR zaB|CCz=KbBGn5CL=9R%X2t5;VXCoQu<*QeliKKuF^76RVPv$Lwr^Z5HH3Gq7@s?-Q z|0(EkqT6b2wpQ6*R`qt;7H5Bkn^rcdMJ4Rf@1QB%`20`!Uj>lS&m7aG*Uk4 zGGeCfN+OzfTW4|~q4t!@#n&w+e7Y2(w}AQaB!6RVg5W7f)eVX$MAf|r4E&Dy0?wj5 z?)4g%_5Il$&W&*n{B#r^k)XZE!H3?>%Zo)+^bp?bbiVjB0(x(suFEjj1%C<4hC-;6 zLa_aux%t$MK5Pc2|9vrEnSj!qKEcTfcXh*{eHqVQ3@bLzCIoTqtT<>>+GMM&%VO{` zd{=CF{fARj1|P*^8m2D;RmY0;ueS=kuClZsIF~{F^tcQ0+G0Y3qB_6nE@+?f8rOR( zMYF2R{%7lHW9wOGhccgkx~PMyp|H4ao|oC*T#}V^m2Az{0S+7^%8li6lk|F!#c@SCCUYZ92zTnG0k8{F0K1}#aZJYd zxuSY7WbAm3)<)+##&d>g6g{b*DI<;l_d$IdtzO_j?;p_J?`AT()3#D8{?<_R0sGII zUTxNF5h3fx=FY{$?wg;c-e6n4@3F65ho`l}juk7$7!&QvJGHzSyXWopNn#T8`^|pJ>?6IIhxLw1Rf#oi zu*8^6)Tn10M6idIpZIePhmc0sU&K0f>H#TW*S7O%GoZBqQp!uNGdzY_a(bI)aXfDT z_AA&2j@tP&fzJ>ZgTH6=zqvy~D0Uzw;zbL~dTDLUo8?K&nSa}Ew;2WE+)TLnkBm#= zu;#u`1FTQJyl+DVIy7Y2q&)!5YsOTvj*oIKVeXW%^C!(PKZf z`8k9VS&mFx##42RmG+fZ{M^vFURx_wTKDPmf6Ert45U#`J&zteq8qb|YcOVGW!>Qh ze7S4tXNSBo?l2;Q!Zuf{Qw0>6{PkrHxDgX{51~+nv#XQmxpHT(9@@QKKQ*&DOdB<3 zT$cF5KP!!L;6-He%&$kzG2@0Nw0z;A!OvMY+R{}dZY>-*%FuJb^2X)u6Woh`yAdth zH-2Z5Ikk6dZMc#owN&=LdxsKbn4!3EJf+F7U`yVWe+sw6FE~Gr{GM0a{f&2Mn9cXY z(!#0mygBI{=4maW<}AvLie*3GSuDr}3XR(k-*67hX`U3~7FKt@Xn6}S_32Zo? z^=k+-Bcr13I3=P2!>O-ow)Rg3Y8PS zREBQJ8-6**!?yu7-^|bEzK3=8jXK@;N|6J9@2@&aJmOjEERM{Mak?~#>r|ux71Wea z_1w=gNV*>P9(@4Rs8tIg_=4&CZYWYAd5%cXS%jHwCa9w*q~fgeyXxKD+7$HXL_maK-^GY&q8tw{moLi$9J$v@eV*kSxrZW{(ja)n5s?Si1@|m2`GMyXy z@+iTxL*o1LeRM-j%7ultXP~9K;l6w~PS@gVM%ugrUo0DI<_>dVGO~@)Wz}rDQ4@Wjl)5vO2@jHZxx zUa9{+>LE#+PwPz>xg>SR%7ztd^=enCzlb}^KScfJScYnv`Jt>Axe}GLN=*l-bgSF< zEUG)$(Fy8@HPGd}lY0E=_<-}(z~Tu(Nxu5sM{DM28J)Du_V1?%D~Z#)8@)4weBDM- zdCO(zwHfC}_@`<}!Z4b$u~0ift=#Jol6vIjB2eL~s& z=)-^KD2bx-;?QS zks;qSXg$khp=hsTVm+Eh5|CH$-&qUH;AUz|t#Qpnqa=E#{wSZb)6@=8QBg!=w)@$Z zdRpg3QS10|aY2#L>c89IfA5BsmF~pyck0pa8862LeIpy}wlIpPbe=2C$ZT&nV2R~8 ze&L3{x<$SADW*l1!~K^O^zTbay*Ry(qDlpN-n!)tuS2VfJ_U80MC(}{L6>>7&onQ& zBxbVKW#ZrV!O#%m7l--LDKAVn!C5HkGE+K}1j6&p;$ajA7A3_ESpa@7T)w==4f~?q z#D;|z8_4y)8%tUmNX|lP-l*_d-)a@VE|yO)W{Y$8HuubQY9`AG`!o}#jY433eLL&; zX_qU}x^mPu9^{Hm8c#XBGXs`Nw3Od!kB;I=(q*Zb1i3bKZP+o?pLl-yUIWebKRLU@ zSK;gc-WItV95*>`GIfei+ln6ak^!XJ>zM#ui)XP#^>jRYz`sL-v%;Z#X4H{y|FL#ul-LT?7N1NZ08MaQO41z`+%+_VUc7^Lh&IXAtp+Xj-2!+Pk44T479A45I5(A`V)mQBz81;gyH&bqM2a z!j>e@9R7E-7(?UojXpGDkqOCB7ba`-#UMX^#}w;wTS?3RcPyZt)Kr1arHr8ES%gm8 zO2@{&dihcUb1@=i-Ej(+LD!UR^~$dTFdJ%UlSbEo23KvYb#6?-!u}NKd&Esn0@f@t zoXgnOy5d@!bJ)G;_`BhDIqL=YT1%)sjqej`XtY}!M*khj0%3v2AG*BuZ|36+Hht?5 z+>mjvhj#>kQb>V`audmb)lgax3JG?K8c`Ad;GX#uAshunY)rJ@o zU{u9x_WK+L`!WFk2o#8ziURolfM5JC64ah)nF$<^NV4;YBvj3xEcz~y5GWrc_85Ej zg1Al8Bj_>Bd%Og7_~?T8jP_yn)0O11#(|K>BPUOKp*~rk4#+1A!>6aGRYAN0B!Nqa z$9~q3$RY%Uf6?5WhiGhrf`S@yj{JQ&+Jlld(`($h<}})6$^oL!a=&lf$~dedYy5+Q z@1j|%agUG{bADsX%<(@p7n#LEhTD zIu;Z_VuIGdcc-yZ&;}F@0{T}FejyyHfXx*I+gTV(v*WP5g~dv|)5yppV0yuC6>bBy zkSqab-qN4{cV=+(usE|+;r;7k0SgnIm$6SlVT_&)@bU8M!<3^Nd>kwjB1=unW$ixd zQqY-tkW2@njm64XI>BKB!bTXh;-2e=@Z)_%!~^HGWx~=mWI89k!>m5p5 zNSfc!XxVOJ&F78&^yvlMZl1ydi6E!qTUZKkUn91yqy|PT(oE}Hg7+*G{BOD=e=p^< z)w|<4(pNcXD)RETBuq8m5FhyGVnXeBn+ng)1Hn~Pva%=l-X`@rpv#uKUEO5Kq0T>= zrPX%-lGi$YZ>5wI&9&BJ5w&+N{g_eLvL{B9_+_k}uTEoGKz(%@-vsJ9@ZO0Ji9t)a zbv2fp9kgb+0PlwmAbb}0&O7w-4U8jZLV=*l5QRHJEANMSQg(M+mD~&Aun-Of##^aB z!{#&AnIDcH#u-7F`w$EwsGq@2OvZo+k@o~K0S;k6D)(TL4#DpQxCc+4DJ(1`@F7qZ zP;Mk6X8}()101La)7N)mKD{7zVE=wRD8;`Is)(xC^{fSp$Z3;z4&hfnXMLro@?rd0 z&tt+RxNyUD*jQ;~VCb$5WlERB;ZD_W5<3jhe-Z>&!ES>^?94&#J0Kk@ipp5 zwLRJbY&Ta|OUeo^{=oyg_q^dV`UagFk;Dz0rm$x!WIhA)zEcS41}e!2_+4}49tQ_f z#s8f!ARoL8<`vcoAjc-<&eOr#n~3EFt3YzAP~7DOU|zXeE|+SS#68^HB7mF`^kLSG zTVG%vMNB?`HZT~Zwk!@shsTPlKo=koeDdbC8H}2t4BNE%`auU#M!q+xu?By~5%%Z) zo6Q_M`i%2tsmxK^HKrd6clm$tm@s!Fvh@^htkX)XYxG#&c|hB!`guFYsKm#*N&O2u z5`{A;4@+sXdTV&{_w!i%s1Rp5Bg?1CVDqAWwgW6cP%zbbLrT|HqSdd;_YU+CC>fTe z+qvs;eh`%t+!y3J54EJ8AaH8A<1oc(ftm!^EO>{BG92~^*P*!KBmaQgky*lroy%APC=VRyr>FOlf!8C1 zFc;nru(PrrhDR_45*2-$4+{&wfkq^>O7?H|48;Q(m9NpVD-psy2O9@;=Qr+760I1j zjXG2tV#~hM%g@eV;qx}GvAg${V&>Q5bFRU=qatlZ1m-nzwlW*vbE=bS?dm)pooOv( zH%=Op70Ir@)4ZQ5>DwaLe)GO{Q`hI4FDE(ff+rPWRP{ut^SR7XB0*%#8Z^uU&WLdb zA_d!_)E2o*m&$2FF~iYGQ@dkz*UE|ysXOQF9Qt7rrNu>J@%!s0s7am1_AJj174kP} zZ1GKZ+f6|s_FnpPhsgjejbr}#5J6@hV2$KJ*r?@5R^05h8kdYsdtSY&`(GqBE7eIGhNZ zG7RgHeB2(Ccj(XMSNFh3{u$9Mw$CeQ*tA$#C@hj^qhG8LPp!?ZGS2HCk}9_nqh=}5VeS2dkjmx=8c%Q3d|oZ6}>K3&n@b9(&%aU8$BHrL)@ zeu&Xw$%9HdX>ziAr$LJfgxSO;$SkF2ylO71tc;{~)uA5i?2d&+@J(*yJ3D>tfnC&X z+(OZnva+&0U}Xxkj9X{p*2^*#z1Pau=>i@D+`-na^%G=JOny6U5#EV&HffsXZ|=<2 z2=b1yg?tU4xIwZk8+%6exA}wUBw6@}#QD5!lI`nlahsD+#>R@q3r1zIf3|NN&QLi) zO<~?;LF*DFzh}=%9=A)ly|U}3ou)H(^IjN}{-jCjSl@Q00_;m&`)6H&>U4im2z;AJ z=Qw40gTG&En2FkH(Pz~vW>5BRvB!1s+eGcB1;sw@H2pC#%@5dYshgA+m6SDA7yH?h(sAT>I~->t!n}EyK6Q&x7xzqyM>LsxR=85q2>YD%IXYfU zeT1w@CcO3DMK@mld(C%jHP^#~nAVpMn0T#fQ2nXbCEYA9+E)@wnBoQa37C9>P=bk@ zNjg396#&j1Ir0eR%T@y)sqZ041cNy6nSWbkUZEnzOc4DMN)Xj*GrxBgeUVU7XLo?_ z#-!ZovtHZ{>zV8plrwId{%E9i1cFcOUvXX076o zhjt2(`agIq82R*xZ!GP>Iz9$65&Cajn8?Z=fNBnI35=sC8~`3#F4IY`MbuGG4*fVg zTDD4lkJ~)b*Z0R#Z&Q)^E)s6Kaw^{KCrpas-aHCPpyZD-J~V2RPeVCk{N_-|ZK>Qz zxlWo0$)itNvOn}F=lEUzgP{<8#);c{1PE030DN3?Sjta-Bj?75a0{dCg$su(fH&3ge2$1!k=? zeZ9S>P|1&H^z2TA!mOTgKj!v`?M3u=4_J;zLH|J*+6>sfKY%X_J2^!<|3DAuc+d1# z`fNm|17m&?`2zc=7GXEjMwTCGErJ>jx;r=QbPs!U?=;SnR63C~W$>=~pKDjIIPWp5 zyLfW%hXN|K{9P9M-8%dGKIya#O?pwt-@o00@Wk@%`+-^&RIGV&pz5hY}Xs7}<* zy%juh;u#1uTjMRfyuI}it+WZ>@+}{T}YU27_x$I8=*ICxX1;|H-dnPaG7En2V|7lqJDMr@rlMpB!)5& zctCgdl_P0UC4_=eG>{`PV{>qob-5jedl)JazOBcOAGZLFjcDwzVB(ItfAHtW{U_Bv z|3;hk{Lq-v6`zQjysDoU=urAV-+ZwDpsQG1VZEe3MqnN<4#OTuQ^7adeyjCNP6vU`9GepSz z5xDQ)1mS1Ri?)qu$KYhCt&!AJ|K*-KOw=Np0mn0d?)e1{3iZEANw27!Y#s4|y z@CR0|T`%LBo#VyDmi;3dNWXB4*BXazZ&KQD%VmK69)x-IvE1)+U|Jnjdaf zI=d1ti4lOCZR_`?L=CH zpscKaN;6!a)1_=q z8t7gYQTu5ccUj?_;%bl77>SiaCXa-YLQjLmWn)(bTD8Ue_xm41tMm67=DU){J`WE> z`-O2Yh3F{leCPY2^>%*X#6Y}Z+eq^Xh@>0&%h=eA4il4%u5Ev~3bE7rCjrY}kJAG{ znb!=^q>52tx)}-G$;0( z|3sCQ$A(9~&+4`$V_}t#{z^SSi5~2&tGTAV{A>DDIo#Y$dXN9m>!vn%#xNYa|1 zmeF&v{o?dY|F=-=id9awfz96Cwl7{#Qy`Y%62#wZrRbAG30MvWKrgXtd0;8=z%vub z5CrjoSmi0sYxcjOZo&?vH}giNpK`Ncv%tO9BGBJtAdYeL>2RE>0>Rc*mOIxs({g~& zJ3-mWWVV;KeBpO6%oq?-)(r~t4%L=fhcIlSXyv$R&w~Kp`e0>q8~p*HO~X??W!W!B zCulOd@xh1>>CX>gHslY56p{aa`qsCtc|a9g9Yu)cXZayM{yECO2h9Lcw|L}7A7@;~aBN(l zz&$z$i;jXW0cPqcFrGVkVA|9TvY8$tn*oA8#=%Iqser?Wdtmc#R~oGd2xQ=CLlB!y za_6oS??UGJ!2&+BsuW|dgw#Za)zsDJNW@`N^#k6hW|kigi^LB89ue#1&LY= z*2sSNy*OdOn8|@6t9i^CK}%;yK;gVLc4ri)6X?~1E*xA$;!~hO`i@Br8DS<(3tcay z!v;7KaqN3Ryb{{p-p;#b?P3284}2u0Z1#-PTmhcoUXu1A=`}WV!GQ}%*i2uSm2g~;awh&c@z4k`JQ;-# zYIfSRM+YbhU9vSE-Wq>~;qC8?*{kz@4T&*t$=8A=T!y@|7cH`E-dr+&xFM$UrzqgA z&-fV3FYfgZeagVydYbO%eMPylsX3c6D#`^XtJd` zzC+I!`Ty;u(JK~OL)s+1HgwsLkB)Ges2{qGQAN9LkJqN+U#N-RHjM-c-)9H^l5mX1 z%no%A2@r(et#^|2kj8~VblU@%4!9%y>nVXB4vUISs=4<3=#8S|*$+@ufGEF-{p8}Mw<T`q&y&zeS9#Kc0WIj-M4?Kkmy z*i4AMW3I9Ir$HUt0Bm4&s8mAWANL#&L=X&qr^yPzw_S}X$_BC@r$T;*uq#N zbT{IBd+BQCg0YfHl(3xwv+_>9LdQJeA+Ow$52&`8q>?a zmwm_`gU=~Y74!qVCyw9FFl$)mzyOM%&VSM^-5rtBEP|M6V%ec+nY0z<)XocO(sJ-Z zbB=68oGcj{i4SHB^!>HvWEB*)O(ujSu!@Lew~A7~&*@W@lY5@Ts;PplOu{zqQNCvG znnZBI3wr15>r`0fK%Zdup1(%b=i6D2G&ZP8%bxRA^ekvNZ-hD>&-^Li1K@vpFv`aQ zVap+n(c-%NzGrvpO(7cC{K)ED4boj4~u25#7$b*|2@JJ4E92 ze#f`oA6z~??30kYq_N|;rkLvwzK!c-_33$Tg72(d=>G+gp2W}_D2+0JBTv#(>SF+@ z*(RSkh|QoJSembGgWoxk9uH14SZ0hatL6YtiI`1@%fT{>tRGTvsLOo!ZdIXcAk2a5 zW*^tj)g%1AG`Bg%DO72kxf%aK**S!DG`+GS@K-MH7V!fS>|@rQNStYixiUOwk5haT zPj-h^lwSsa86KK(isXV%=Fj6kkUJAi2SkQ_p6DaoFr}P`C(k7TEG{-;x%v`*{OgC! z6$~FV(VvJAvyG6vQn>np@{;kAX~c1=d(7dE4KxkZ74lBv`V$IK6Ff<=pZXm3hj!<8 zmygKW&Gay{(v_a6kapWVvhQ2yf}&MQPKWcwyr+ZRFMErf_W^$U#K&bscV&=2o$p1E z4d(8Da7jG32fT(o@vLNmzif{ZwKVR#P1-~mu+fq|^NDq2ZKJ1VCCrau>rP5a(qgfy z16A)WsretBK``G=)i)oLi8tXTAqALa3KsizlGEDGN9CGb%PP)QV1D86ty zsGsfPV*AE?D>XGk?LtphPU84N`+`^!?Mwafg|#I|IFk+4zTH9stBXj7gbo}4Fn2A6 zb2$O;62K-z@xnNnE~HvUA<4we{9J5Yk`#z(f1U$*J*c}_5o-{`Md~`O$Q>EGG6lNmJos%oSr2ZBL0Ig z2$aOlcLgx)DM3qlMcEIV7yV=j&ej_+ZUVPIQK=ukN>gwv;DMDAkv1CnCux;ta^82q zB9pKuAuQl@k|#@r;?Va=Y#v*&fUAM2ZStR2g`3~zBmNRAEARG%AoPqS1hsz5e|t$o~9$` zY&|OdxL(m{4qS!PmL4;_hIBpWjiVTw2iRiSUvp1AE%1E%=Jbu^OkM?9%kd1O(m%s;7}QcdfZx&0WL09E z3ZsIA8S9RUG7Nt^oU&wW&MFNEv;STY@m4h>DF>5yCTH@zAdZ7B{UC`!8HqEv~H>Rj6?t921a|7#kd z&cbJ2$*j@{@smsDBywlYCz;bJEDHo?=upYu`aW0F{e7d8f`vV2xo76^e)50McB!;0 zL;4dyB**#L`{i&#=>dluAA^Ne3VQ$4anoc~)PI7+pX#g{h1ciVg;sHPG zL*vu;l-`6$c*^rWj+Ji4~VN7}Y+ z+m-^t+k!P<85C_%2$YI1MMH>FWqVTpDD;s#$jF382m%Hs?yYfk*@ksTki&b}OUqor zGkflvW37Wyk{I(t-xrjfuELKan|YolcKbXQGwkem^y_!-`h3@#%o~}S{xAi$j8Vn2 zm)H^oI+^S?OV6#wzu$-~HB1;Nlogdv%k5WB`o zqjB0RU*BH-6dQoYC>gHXIs?qt3Nz?93yL+_KNQcNJelmU>AaQR)^Y8E`08XKag-I6 zma5o}qafi$!@OV(>>q=Gcc@9I$MYfcB>V+%3b&^be&$Pbxhjte`*ZazqSeK3wR*eg zOm@1)hB-)m&M-?mq_8=Ed0Vk!Kilw}sG7WsK2^iFS?=tpGv^Ol)rhVy7C-5qZhxNa z5cg8Q&eEu%v3yi|P0@<H6af%@I5iKzDQ0g_cY`{ub>StFog zBYswM1%Xo^!RTk0P%$=A02(TXUj`-AARlDK)@K@1MpsKI5U>ZD0DYF6!no zoz%(ebKg`^tI@EM<~Dp%uz&xoOpQ|BGn>IFZj<}oN2TNqtQTKq|EM2qAdT4-ywrQf zo3eY@9P&EgleXZa5WFDZQc&37fGI_3l!;@X$gPD%Q2;+NV%olk@f{@J$Z94EP4q9s zb%8;55A5JJ{l*SAd}AG!DgiwuSVC{X*unFjg6By9IxLIsqMb;Q#SH8wcpn6@6=&s3 ze}5Tg=XE_NufKceN7;8`q|(i9AQ0S=?;;M*2My3?-F?vILJGe~LFjjGiK!Mt1JnbsPI? zcDTV46cED0lg|r8CKx|1f*6J>jik4)j|Yu7B1qXrv$s;puThk$X2kL)res;=&+XqmvCwPXOx<{LX5i@}(_nMq zHxZ@|ugK;aa{=aZ%fXrEiN&Wv>ouBp_D^n$8|*4n>b7`OyP!GkGS!~LuREX=QlP+e zd|!7tG%dg3vqK2V5&Tj!k_#0zs4MPjtm-LrVq~!I6zlcCnDQQ?R&H`2IAq*t8M6i+(j5u&w-eNvU z2;KlPPJ=nXgVJEZJRiQS6FD=x6&00J=cCJRM`A$*XxW!(W_LZMZ_aZPL1%bKu)}IU zVdz6JgV1&n-sL3n^@}T=8wxNy&t6)g!H_XLJX|G;Ccwy8WV z9QUn}fyw?}@ESW~g8AW&3$N{UFM4Q5uK33toF4QMy4$4b?xx~(#@&mj_s|R#m1}sF z{_dt1G802e*N$@t*yxvbF{AK6{jH|tU$dvzzlgfov-PkxX_0HW`y2PVPTnlR2{-SE z90lAFTmgsGcP!D1dTE`{@Lnr0!hb6ABl>@WrH=Y{v|+Fc)-Px=Po&&A5@CNf0$wmu3i|Cw6fBZ`MC$zaqnTYDQwS(M4cakdZ|~->F4o3^sW=0O0SaZSX(z zXetiJ>~1`7#RP@WwfEN!m%@4g!Ue+n)aE1x^LQifz^V5ap(<98W?sOKR@&N2PH2iyY(92Ls69M$&LHE(Z zEw**8%iw2Gm7U6B*Z7YMaQy7qFmzJMu#wJr<#aS^9w6k!c@Peuafx*3EUutMs`TL z#i^beMitaYU#QoIxwb0)m4puq}znDuywIH-#!3zXcp-V{=E}{TTNTf$YM1 z_l60Re7$PA2?K`D$1pixr2FNVt>h7TYqG5{fINE>ne`npM*7uFZ5yXvxm;B-+1Oud z6~A5(zO7E1a$op8%g^ih>2>jJU^P>hx~l4 z>0P-AkEl;u1O=Ta;)*SMO58ccs(L=`Q?DuU8DaXz;MYW9eB=iqTApzI_dbfN`JE!g znZm|F<19(@j!Y-^E3;J6Nz~0>UHCtgy=7F^+ZH~GiG`@7fTB`LNvD8_bR(TgcXukF z2uKJ5(n#~t(k0T;4bt7+(s%yQeeQpZd+&$)#c{^i+kN1D*P3h2XFgHLKKip0_@{7J zW>O3Yz*btFl|)xp7un9jaH2mtY-J@2WC^4Uz#va{#!qVpXs85CxWGgXCJ>+}O+Zl0 zR_O*}BnnIRE?`6LiTlH62u~D}U9^W0iBv`)X0S!KS>{cEEEpa<#H9@$L0afGpb@)s z>(+DVU!fa;ZxZOvzku!K02$8Zp@!iQ`2<4%1u5xtkjDSMJJVeeEDPfIu-FQI?%s81n@dw? zx-skG%w0r?=KtM3#@U)9Ez)oL{?pTqtOt?}rPw?{OU^!SalXm@Vf2Sfb98@Jc%_ME zb}Qxcsi>>m*4E-2BF1Rl+(yf9EUoSbL9^_c0nKvddQV)PvCu}1>DG}Gd-<49-q&^m zYnQuQVLYCOse@^c>w5X6nF>S2Nxkt#3OOW_6dddM^jD>b`*(0PeK5vi)GQa|iN$@zk65CO{pMY#MN?9@v(>ItD5;zRZh zUUZFao^-lA&3)%}Ub__ldLP2ZXE>q+LQ|m|-U9IOJJ8WV=_a)BGN9|nxG%(YE*AR7z|@_c&@b>P?lfCqR) zc0U%JB1J{Tq&6srv>Y|P&&@b~QD|7B|9s=CJ0BbyR66i0mt;mzN5x0ZRbx%iav2?8 zoR**{htaO8vg2^&rJRWZM`=4glOHSJBdI+-dmmI&!?|<6pKjE@TNIJbbpFF{$E0_~ zV=cO2c88oPY_4E+R5#wBN7b~r;FHqz!-T~x=q4;^sIIB->;J0!#p7t$^R+epjx@{H zsCh}}C^1zO2bm2tsJyMmzc|CEYF@rjy$hW<>=(u=qCbDG0_ui7crd>|1QvKCL{Kq8 zQ30OqIfOwEe5C_2W~Z&KEeCicMnqHLqCh4I7pVBChR0y4g~IwB@Os4fs|_%pTFX{- zSe%H7iIv>0)I$m|z!}4>>Tjo~wPDjp+Ipt(`)DZ8cji`+C5=MeAtC}g<3+^I0Z3gJ zFJD&QyfWYm;&7M^NT44B-!&|VlI+wkpJdOv?5KrH>}pFvSZMc%tL$mT0S;EAlm%A5 zeDe1dJFG^FVCcAmVv16r{p0(EnLi--{a0I)xo!R@(Qn>3o7cbZO#d8D^}25| zYx∨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%0DTUc3Xb;R+0y2lwx5$oI)YJHi_ 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

)-ZTBAxAxvayVil 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 literal 0 HcmV?d00001 diff --git a/docs/doc_images/tensorboard/tblogger_hparam3.jpg b/docs/doc_images/tensorboard/tblogger_hparam3.jpg new file mode 100644 index 0000000000000000000000000000000000000000..af2121f9addde7438f23edd42ed9aa07f1d30e77 GIT binary patch literal 138426 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⪻}Q2 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
^!3uytDmvWxUqbk8;6vrR}K&Mr}B7 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
?{OfJIdJ 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 K$vbrFxBmreDu@gK literal 0 HcmV?d00001 diff --git a/docs/doc_images/tensorboard/tblogger_image.jpg b/docs/doc_images/tensorboard/tblogger_image.jpg new file mode 100644 index 0000000000000000000000000000000000000000..25807197a443ba9391b6537b75ea1c6b05c5abfe GIT binary patch literal 184767 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 P@h0_{*3s-EzxezQE44lB literal 0 HcmV?d00001 diff --git a/docs/doc_images/tensorboard/tblogger_scalar.jpg b/docs/doc_images/tensorboard/tblogger_scalar.jpg new file mode 100644 index 0000000000000000000000000000000000000000..69d421bff9eef6953948ec11f47908faf3cac247 GIT binary patch literal 204856 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∋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 literal 0 HcmV?d00001 diff --git a/docs/getting_started.md b/docs/getting_started.md index e69de29b..7f87e21b 100644 --- a/docs/getting_started.md +++ b/docs/getting_started.md @@ -0,0 +1,101 @@ +# Getting Started + +Getting started with NePS involves a straightforward yet powerful process, centering around its three main components. +This approach ensures flexibility and efficiency in evaluating different architecture and hyperparameter configurations +for your problem. + +## The 3 Main Components +1. **Define a [`run_pipeline`](https://automl.github.io/neps/latest/run_pipeline) Function**: This function is essential +for evaluating different configurations. You'll implement the specific logic for your problem within this function. +For detailed instructions on initializing and effectively using `run_pipeline`, refer to the guide. + +2. **Establish a [`pipeline_space`](https://automl.github.io/neps/latest/pipeline_space)**: Your search space for +defining parameters. You can structure this in various formats, including dictionaries, YAML, or ConfigSpace. +The guide offers insights into defining and configuring your search space. + +3. **Execute with [`neps.run`](https://automl.github.io/neps/latest/neps_run)**: Optimize your `run_pipeline` over +the `pipeline_space` using this function. For a thorough overview of the arguments and their explanations, +check out the detailed documentation. + +By following these steps and utilizing the extensive resources provided in the guides, you can tailor NePS to meet +your specific requirements, ensuring a streamlined and effective optimization process. + +## Basic Usage +In code, the usage pattern can look like this: + +```python +import neps +import logging + + +# 1. Define a function that accepts hyperparameters and computes the validation error +def run_pipeline( + hyperparameter_a: float, hyperparameter_b: int, architecture_parameter: str +) -> dict: + # insert here your own model + model = MyModel(architecture_parameter) + + # insert here your training/evaluation pipeline + validation_error, training_error = train_and_eval( + model, hyperparameter_a, hyperparameter_b + ) + + return { # dict or float(validation error) + "loss": validation_error, + "info_dict": { + "training_error": training_error + # + Other metrics + }, + } + + +# 2. Define a search space of the parameters of interest; ensure that the names are consistent with those defined +# in the run_pipeline function +pipeline_space = dict( + hyperparameter_b=neps.IntegerParameter( + lower=1, upper=42, is_fidelity=True + ), # Mark 'is_fidelity' as true for a multi-fidelity approach. + hyperparameter_a=neps.FloatParameter( + lower=0.001, upper=0.1, log=True + ), # If True, the search space is sampled in log space. + architecture_parameter=neps.CategoricalParameter( + ["option_a", "option_b", "option_c"] + ), +) + +if __name__ == "__main__": + # 3. Run the NePS optimization + logging.basicConfig(level=logging.INFO) + neps.run( + run_pipeline=run_pipeline, + pipeline_space=pipeline_space, + root_directory="path/to/save/results", # Replace with the actual path. + max_evaluations_total=100, + searcher="hyperband" # Optional specifies the search strategy, + # otherwise NePs decides based on your data. + ) +``` + +## Examples + +Discover the features of NePS through these practical examples: + +* **[Hyperparameter Optimization (HPO)]( +https://github.com/automl/neps/blob/master/neps_examples/template/basic_template.py)**: Learn the essentials of +hyperparameter optimization with NePS. + +* **[Architecture Search with Primitives]( +https://github.com/automl/neps/tree/master/neps_examples/basic_usage/architecture.py)**: Dive into architecture search +using primitives in NePS. + +* **[Multi-Fidelity Optimization]( +https://github.com/automl/neps/tree/master/neps_examples/efficiency/multi_fidelity.py)**: Understand how to leverage +multi-fidelity optimization for efficient model tuning. + +* **[Utilizing Expert Priors for Hyperparameters]( +https://github.com/automl/neps/blob/master/neps_examples/template/priorband_template.py)**: +Learn how to incorporate expert priors for more efficient hyperparameter selection. + +* **[Additional NePS Examples]( +https://github.com/automl/neps/tree/master/neps_examples/)**: Explore more examples, including various use cases and +advanced configurations in NePS. diff --git a/docs/installation.md b/docs/installation.md new file mode 100644 index 00000000..90066f37 --- /dev/null +++ b/docs/installation.md @@ -0,0 +1,24 @@ +# Installation + +## Prerequisites + +Ensure you have Python version 3.8, 3.9, 3.10, or 3.11 installed. NePS installation will automatically handle +any additional dependencies via pip. + +## Install from pip + +```bash +pip install neural-pipeline-search +``` +> Note: As indicated with the `v0.x.x` version number, NePS is early stage code and APIs might change in the future. + +## Install from source + +!!! note + We use [poetry](https://python-poetry.org/docs/) to manage dependecies. + +```bash +git clone https://github.com/automl/neps.git +cd neps +poetry install --no-dev +``` diff --git a/docs/neps_run.md b/docs/neps_run.md index e69de29b..886ff91c 100644 --- a/docs/neps_run.md +++ b/docs/neps_run.md @@ -0,0 +1,100 @@ +# Configuring and Running Optimizations + +The `neps.run` function is the core of the NePS optimization process, where the search for the best hyperparameters +and architectures takes place. This document outlines the arguments and options available within this function, +providing a detailed guide to customize the optimization process to your specific needs. + +## Search Strategy +At default NePS intelligently selects the most appropriate search strategy based on your defined configurations in +`pipeline_space`. +The characteristics of your search space, as represented in the `pipeline_space`, play a crucial role in determining +which optimizer NePS will choose. This automatic selection process ensures that the strategy aligns perfectly +with the specific requirements and nuances of your search space, thereby optimizing the effectiveness of the +hyperparameter and/or architecture optimization. You can also manually select a specific or custom optimizer that better +matches your specific needs. For more information, refer [here](https://automl.github.io/neps/latest/optimizers). + +## Arguments + +### Mandatory Arguments +- **`run_pipeline`** (function): The objective function, targeted by NePS for minimization, by evaluation various + configurations. It requires these configurations as input and should return either a dictionary or a sole loss + value as the +output. For correct setup instructions, refer to [here](https://automl.github.io/neps/latest/run_pipeline) +- **`pipeline_space`** (dict | yaml | configspace): This defines the search space for the configurations from which the + optimizer samples. It accepts either a dictionary with the configuration names as keys, a path to a YAML + configuration file, or a configSpace.ConfigurationSpace object. For comprehensive information and examples, + please refer to the detailed guide available [here](https://automl.github.io/neps/latest/pipeline_space) + +- **`root_directory`** (str): The directory path where the information about the optimization and its progress gets + stored. This is also used to synchronize multiple calls to run(.) for parallelization. + +- **Budget**: +To define a budget, provide either or both of the following parameters: + + - **`max_evaluations_total`** (int, default: None): Specifies the total number of evaluations to conduct before + halting the optimization process. + - **`max_cost_total`** (int, default: None): Prevents the initiation of new evaluations once this cost + threshold is surpassed. This requires adding a cost value to the output of the `run_pipeline` function, + for example, return {'loss': loss, 'cost': cost}. For more details, please refer + [here](https://automl.github/io/neps/latest/run_pipeline) + +### Optional Arguments +##### Further Monitoring Options + - **`overwrite_working_directory`** (bool, default: False): When set to True, the working directory + specified by + `root_directory` will be + cleared at the beginning of the run. This is e.g. useful when debugging a `run_pipeline` function. + - **`post_run_summary`** (bool, default: False): When enabled, this option generates a summary CSV file + upon the + completion of the + optimization process. The summary includes details of the optimization procedure, such as the best configuration, + the number of errors occurred, and the final performance metrics. + - **`development_stage_id`** (int | float | str, default: None): An optional identifier used when working with + multiple development stages. Instead of creating new root directories, use this identifier to save the results + of an optimization run in a separate dev_id folder within the root_directory. + - **`task_id`** (int | float | str, default: None): An optional identifier used when the optimization process + involves multiple tasks. This functions similarly to `development_stage_id`, but it creates a folder named + after the task_id instead of dev_id, providing an organized way to separate results for different tasks within + the `root_directory`. +##### Parallelization Setup + - **`max_evaluations_per_run`** (int, default: None): Limits the number of evaluations for this specific call of + `neps.run`. + - **`continue_until_max_evaluation_completed`** (bool, default: False): In parallel setups, pending evaluations + normally count towards max_evaluations_total, halting new ones when this limit is reached. Setting this to + True enables continuous sampling of new evaluations until the total of completed ones meets max_evaluations_total, + optimizing resource use in time-sensitive scenarios. + +For an overview and further resources on how NePS supports parallelization in distributed systems, refer to +the [Parallelization Overview](#parallelization). +##### Handling Errors + - **`loss_value_on_error`** (float, default: None): When set, any error encountered in an evaluated configuration + will not halt the process; instead, the specified loss value will be used for that configuration. + - **`cost_value_on_error`** (float, default: None): Similar to `loss_value_on_error`, but for the cost value. + - **`ignore_errors`** (bool, default: False): If True, errors encountered during the evaluation of configurations + will be ignored, and the optimization will continue. Note: This error configs still count towards + max_evaluations_total. +##### Search Strategy Customization + - **`searcher`** (Literal["bayesian_optimization", "hyperband",..] | BaseOptimizer, default: "default"): Specifies + manually which of the optimization strategy to use. Provide a string identifying one of the built-in + search strategies or an instance of a custom `BaseOptimizer`. + - **`searcher_path`** (Path | str, default: None): A path to a custom searcher implementation. + - **`**searcher_kwargs`**: Additional keyword arguments to be passed to the searcher. + + For more information about the available searchers and how to customize your own, refer +[here](https://automl.github.io/neps/latest/optimizers). +##### Others + - **`pre_load_hooks`** (Iterable, default: None): A list of hook functions to be called before loading results. + +## Parallelization + +`neps.run` can be called multiple times with multiple processes or machines, to parallelize the optimization process. +Ensure that `root_directory` points to a shared location across all instances to synchronize the optimization efforts. +For more information [look here](https://automl.github.io/neps/latest/parallelization) + +## Customization + +The `neps.run` function allows for extensive customization through its arguments, enabling to adapt the +optimization process to the complexities of your specific problems. + +For a deeper understanding of how to use `neps.run` in a practical scenario, take a look at our +[examples and templates](https://github.com/automl/neps/tree/master/neps_examples). diff --git a/src/neps/optimizers/README.md b/docs/optimizers.md similarity index 81% rename from src/neps/optimizers/README.md rename to docs/optimizers.md index 4d2a0a47..c6155ed6 100644 --- a/src/neps/optimizers/README.md +++ b/docs/optimizers.md @@ -1,50 +1,60 @@ ## Optimizer Configuration Options -Before running the optimizer for your AutoML tasks, you have several configuration options to tailor the optimization process to your specific needs. These options allow you to customize the optimizer's behavior according to your preferences and requirements. +Before running the optimizer for your AutoML tasks, you have several configuration options to tailor the optimization +process to your specific needs. These options allow you to customize the optimizer's behavior according to your +preferences and requirements. ### 1. Automatic Optimizer Selection -If you prefer not to specify a particular optimizer for your AutoML task, you can simply pass `default` or `None` for the neps searcher. NePS will automatically choose the best optimizer based on the characteristics of your search space. This provides a hassle-free way to get started quickly. +If you prefer not to specify a particular optimizer for your AutoML task, you can simply pass `"default"` or `None` +for the neps searcher. NePS will automatically choose the best optimizer based on the characteristics of your search +space. This provides a hassle-free way to get started quickly. -The optimizer selection is based on the following characteristics of your search space: +The optimizer selection is based on the following characteristics of your `pipeline_space`: - If it has fidelity: `hyperband` - If it has both fidelity and a prior: `priorband` - If it has a prior: `pibo` - If it has neither: `bayesian_optimization` -For example, running the following format, without specifying a searcher will choose an optimizer depending on the `pipeline_space` passed. +For example, running the following format, without specifying a searcher will choose an optimizer depending on +the `pipeline_space` passed. ```python neps.run( run_pipeline=run_function, pipeline_space=pipeline_space, root_directory="results/", - max_evaluations_total=25, + max_evaluations_total=25, # no searcher specified ) ``` ### 2. Choosing one of NePS Optimizers -We have also prepared some optimizers with specific hyperparameters that we believe can generalize well to most AutoML tasks and use cases. For more details on the available default optimizers and the algorithms that can be called, please refer to the next section on [SearcherConfigs](#Searcher-Configurations). +We have also prepared some optimizers with specific hyperparameters that we believe can generalize well to most AutoML +tasks and use cases. For more details on the available default optimizers and the algorithms that can be called, +please refer to the next section on [SearcherConfigs](#searcher-configurations). ```python neps.run( run_pipeline=run_function, pipeline_space=pipeline_space, root_directory="results/", - max_evaluations_total=25, + max_evaluations_total=25, # searcher specified, along with an argument searcher="bayesian_optimization", initial_design_size=5, ) ``` -For more optimizers, please refer [here](#List-Available-Searchers) . +For more optimizers, please refer [here](#list-available-searchers) . ### 3. Custom Optimizer Configuration via YAML -For users who want more control over the optimizer's hyperparameters, you can create your own YAML configuration file. In this file, you can specify the hyperparameters for your preferred optimizer. To use this custom configuration, provide the path to your YAML file using the `searcher_path` parameter when running the optimizer. The library will then load your custom settings and use them for optimization. +For users who want more control over the optimizer's hyperparameters, you can create your own YAML configuration file. +In this file, you can specify the hyperparameters for your preferred optimizer. To use this custom configuration, +provide the path to your YAML file using the `searcher_path` parameter when running the optimizer. +The library will then load your custom settings and use them for optimization. Here's the format of a custom YAML (`custom_bo.yaml`) configuration using `Bayesian Optimization` as an example: @@ -68,7 +78,7 @@ neps.run( run_pipeline=run_function, pipeline_space=pipeline_space, root_directory="results/", - max_evaluations_total=25, + max_evaluations_total=25, # searcher specified, along with an argument searcher_path = "custom/path/to/directory" # `custom_bo.yaml` should be in `searcher_path` @@ -85,11 +95,11 @@ neps.run( run_pipeline=run_function, pipeline_space=pipeline_space, root_directory="results/", - max_evaluations_total=25, + max_evaluations_total=25, # searcher specified, along with an argument searcher_path = "custom/path/to/directory" # `custom_bo.yaml` should be in `searcher_path` - searcher="custom_bo", + searcher="custom_bo", initial_design_size=5, # overrides value in custom_bo.yaml random_interleave_prob: 0.25 # overrides value in custom_bo.yaml ) diff --git a/docs/parallelization.md b/docs/parallelization.md index ff001186..9a265a40 100644 --- a/docs/parallelization.md +++ b/docs/parallelization.md @@ -1,4 +1,46 @@ -# Parallelization +# Parallelization and Resuming Runs -In order to run a neural pipeline search with multiple processes or multiple machines, simply call `neps.run` multiple times. -All calls to `neps.run` need to use the same `root_directory` on the same filesystem, otherwise there is no synchronization between the `neps.run`'s. +NePS utilizes files as a means of communication for implementing parallelization and resuming runs. As a result, +when `neps.run` is called multiple times with the same `root_directory` in the file system, NePS will automatically +load the optimizer state, allowing seamless parallelization of the run across different processes or machines. +This concept also applies to resuming runs even after termination. + +Example: + +!!! note + The following example assumes all necessary imports are included, in addition to already having defined the [pipeline_space](https://automl.github.io/neps/latest/pipeline_space/) and the [run_pipeline](https://automl.github.io/neps/latest/run_pipeline/) functions. One can apply the same idea on [this](https://github.com/automl/neps/blob/master/neps_examples/basic_usage/hyperparameters.py) example. + +```python +logging.basicConfig(level=logging.INFO) + +# Initial run +neps.run( + run_pipeline=run_pipeline, + pipeline_space=pipeline_space, + root_directory="results/my_example", + max_evaluations_total=5, +) +``` + +After the initial run, NePS will log the following message: + +```bash +INFO:neps:Maximum total evaluations is reached, shutting down +``` + +If you wish to extend the search with more evaluations, simply update the `max_evaluations_total` parameter: + +```python +logging.basicConfig(level=logging.INFO) + + +# Resuming run with increased evaluations +neps.run( + run_pipeline=run_pipeline, + pipeline_space=pipeline_space, + root_directory="results/my_example", + max_evaluations_total=10, +) +``` + +Now, NePS will continue the search, loading the latest information for the searcher. For parallelization, as mentioned above, you can also run this code multiple times on different processes or machines. The file system communication will link them, as long as the `root_directory` has the same location. diff --git a/docs/pipeline_space.md b/docs/pipeline_space.md index e69de29b..ab49a221 100644 --- a/docs/pipeline_space.md +++ b/docs/pipeline_space.md @@ -0,0 +1,180 @@ +# Initializing the Pipeline Space + +In NePS, a pivotal step is the definition of the search space, termed `pipeline_space`. This space can be structured +through various approaches, including a Python dictionary, a YAML file, or ConfigSpace. Each of these methods allows +you to specify a set of parameter types, ranging from Float and Categorical to specialized architecture parameters. +Whether you choose a dictionary, YAML file, or ConfigSpace, your selected method serves as a container or framework +within which these parameters are defined and organized. This section not only guides you through the process of +setting up your `pipeline_space` using these methods but also provides detailed instructions and examples on how to +effectively incorporate various parameter types, ensuring that NePS can utilize them in the optimization process. + + +## Methods for Defining the NePS Pipeline Space +### Option 1: Using a Python Dictionary + +To define the `pipeline_space` using a Python dictionary, follow these steps: + +Create a Python dictionary that specifies the parameters and their respective ranges. For example: + +```python +pipeline_space = { + "learning_rate": neps.FloatParameter(lower=0.00001, upper=0.1, log=True), + "num_epochs": neps.IntegerParameter(lower=3, upper=30, is_fidelity=True), + "optimizer": neps.CategoricalParameter(choices=["adam", "sgd", "rmsprop"]), + "dropout_rate": neps.FloatParameter(value=0.5), +} +``` + +### Option 2: Using a YAML File + +Create a YAML file (e.g., pipeline_space.yaml) with the parameter definitions following this structure. + +```yaml +pipeline_space: # important to start with + learning_rate: + lower: 2e-3 + upper: 0.1 + log: true + + num_epochs: + type: int # or "integer", optional if u want to manually set this + lower: 3 + upper: 30 + is_fidelity: True + + optimizer: + choices: ["adam", "sgd", "rmsprop"] + + dropout_rate: + value: 0.5 +... +``` + +Ensure your YAML file starts with `pipeline_space:`. +This is the root key under which all parameter configurations are defined. + +!!! note "Note" + The various types of parameters displayed in the Dictionary of Option 1 are here automatically determined by the + data. If desired, you have the option to define them manually by providing the argument `type`. For more details, + refer to the section on [Supported Hyperparameter Types](#supported-hyperparameter-types). + + +### Option 3: Using ConfigSpace + +For users familiar with the ConfigSpace library, can also define the `pipeline_space` through +ConfigurationSpace(). + +```python +from configspace import ConfigurationSpace, UniformFloatHyperparameter + +configspace = ConfigurationSpace() +configspace.add_hyperparameter( + UniformFloatHyperparameter("learning_rate", 0.00001, 0.1, log=True) +) +``` + +For additional information on ConfigSpace and its features, please visit the following +[link](https://github.com/automl/ConfigSpace). +## Supported Hyperparameter Types + +### Float/Integer Parameter + +- **Expected Arguments:** + - `lower`: The minimum value of the parameter. + - `upper`: The maximum value of the parameter. + - Accepted values: int or float depending on the specific parameter type one wishes to use. +- **Optional Arguments:** + - `log`: Boolean that indicates if the parameter uses a logarithmic scale (default: False) + - [Details on how YAML interpret Boolean Values](#important-note-on-yaml-data-type-interpretation) + - `is_fidelity`: Boolean that marks the parameter as a fidelity parameter (default: False). + - `default`: Sets a prior central value for the parameter (default: None). + > Note: Currently, if you define a prior for one parameter, you must do so for all your variables. + - `default_confidence`: Specifies the confidence level of the default value, + indicating how strongly the prior + should be considered (default: 'low'). + - Accepted values: 'low', 'medium', or 'high'. + - `type`: Specifies the data type of the parameter. + - Accepted values: 'int', 'integer', or 'float'. + > Note: If type is not specified e notation gets converted to float + + !!! note "YAML Method Specific:" + The type argument, used to specify the data type of parameters as 'int', 'integer', or 'float', + is unique to defining the pipeline_space with a YAML file. This explicit specification of the parameter + type is not required when using a Python dictionary or ConfigSpace, as these methods inherently determine + the data types based on the syntax and structure of the code. + +### Categorical Parameter + +- **Expected Arguments:** + - `choices`: A list of discrete options (int | float | str) that the parameter can take. +- **Optional Arguments:** + - `is_fidelity`: Marks the parameter as a fidelity parameter (default: False). + - [Details on how YAML interpret Boolean Values](#important-note-on-yaml-data-type-interpretation) + - `default`: Sets a prior central value for the parameter (default: None). + > Note: Currently, if you define a prior for one parameter, you must do so for all your variables. + - `default_confidence`: Specifies the confidence level of the default value, + indicating how strongly the prior + should be considered (default: "low"). + - `type`: Specifies the data type of the parameter. + - Accepted values: 'cat' or 'categorical'. + > Note: Yaml Method Specific + +### Constant Parameter + +- **Expected Arguments:** + - `value`: The fixed value (int | float | str) for the parameter. +- **Optional Arguments:** + - `type`: Specifies the data type of the parameter. + - Accepted values: 'const' or 'constant'. + > Note: Yaml Method Specific + - `is_fidelity`: Marks the parameter as a fidelity parameter (default: False). + +### Important Note on YAML Data Type Interpretation + +When working with YAML files, it's essential to understand how the format interprets different data types: + +1. **Strings in Quotes:** + + - Any value enclosed in single (`'`) or double (`"`) quotes is treated as a string. + - Example: `"true"`, `'123'` are read as strings. + +2. **Boolean Interpretation:** + + - Specific unquoted values are interpreted as booleans. This includes: + - `true`, `True`, `TRUE` + - `false`, `False`, `FALSE` + - `on`, `On`, `ON` + - `off`, `Off`, `OFF` + - `yes`, `Yes`, `YES` + - `no`, `No`, `NO` + +3. **Numbers:** + + - Unquoted numeric values are interpreted as integers or floating-point numbers, depending on their format. + - By default, when the 'type' is not specified, any number in scientific notation (e.g., 1e3) is interpreted as a + floating-point number. This interpretation is unique to our system. + +4. **Empty Strings:** + + - An empty string `""` or a key with no value is always treated as `null` in YAML. + +5. **Unquoted Non-Boolean, Non-Numeric Strings:** + + - Unquoted values that don't match boolean patterns or numeric formats are treated as strings. + - Example: `example` is a string. + +Remember to use appropriate quotes and formats to ensure values are interpreted as intended. + +## Supported Architecture parameter Types + +!!! note "Note" + The configuration of `pipeline_space` from a YAML file does not currently support architecture parameter types. +!!! note "Note" + A comprehensive documentation for the Architecture parameter will be available soon. + If you are interested in exploring architecture parameters, you can find detailed + examples and usage in the following resources: + + - [Basic Usage Examples](https://github.com/automl/neps/tree/master/neps_examples/basic_usage) - Basic usage + examples that can help you understand the fundamentals of Architecture parameters. + - [Experimental Examples](https://github.com/automl/neps/tree/master/neps_examples/experimental) - For more advanced + and experimental use cases, including Hierarchical parameters, check out this collection of examples. diff --git a/docs/run_pipeline.md b/docs/run_pipeline.md index e69de29b..fb0e9bed 100644 --- a/docs/run_pipeline.md +++ b/docs/run_pipeline.md @@ -0,0 +1,150 @@ +# The run_pipeline Function + +## Introduction + +The `run_pipeline` function is crucial for NePS. It encapsulates the objective function to be minimized, which could range from a regular equation to a full training and evaluation pipeline for a neural network. + +This function receives the configuration to be utilized from the parameters defined in the search space. Consequently, it executes the same set of instructions or equations based on the provided configuration to minimize the objective function. + +We will show some basic usages and some functionalites this function would require for successful implementation. + +## Types of Returns + +### 1. Single Value + +Assuming the `pipeline_space` was already created (have a look at [pipeline space](https://automl.github.io/neps/latest/pipeline_space/) for more details). A `run_pipeline` function with an objective of minimizing the loss will resemble the following: + +```python +def run_pipeline( + **config, # The hyperparameters to be used in the pipeline +): + element_1 = config["element_1"] + element_2 = config["element_2"] + element_3 = config["element_3"] + + loss = element_1 - element_2 + element_3 + + return loss +``` + +### 2. Dictionary + +In this section, we will outline the special variables that are expected to be returned when the `run_pipeline` function returns a dictionary. + +#### Loss + +One crucial return variable is the `loss`. This metric serves as a fundamental indicator for the optimizer. One option is to return a dictionary with the `loss` as a key, along with other user-chosen metrics. + +!!! note + + Loss can be any value that is to be minimized by the objective function. + +```python +def run_pipeline( + **config, # The hyperparameters to be used in the pipeline +): + + element_1 = config["element_1"] + element_2 = config["element_2"] + element_3 = config["element_3"] + + loss = element_1 - element_2 + element_3 + reverse_loss = -loss + + return { + "loss": loss, + "info_dict": { + "reverse_loss": reverse_loss + ... + } + } +``` + +#### Cost + +Along with the return of the `loss`, the `run_pipeline` function would optionally need to return a `cost` in certain cases. Specifically when the `max_cost_total` parameter is being utilized in the `neps.run` function. + + +!!! note + + `max_cost_total` sums the cost from all returned configuration results and checks whether the maximum allowed cost has been reached (if so, the search will come to an end). + +```python +import neps +import logging + + +def run_pipeline( + **config, # The hyperparameters to be used in the pipeline +): + + element_1 = config["element_1"] + element_2 = config["element_2"] + element_3 = config["element_3"] + + loss = element_1 - element_2 + element_3 + cost = 2 + + return { + "loss": loss, + "cost": cost, + } + +if __name__ == "__main__": + logging.basicConfig(level=logging.INFO) + neps.run( + run_pipeline=run_pipeline, + pipeline_space=pipeline_space, # Assuming the pipeline space is defined + root_directory="results/bo", + max_cost_total=10, + searcher="bayesian_optimization", + ) +``` + +Each evaluation carries a cost of 2. Hence in this example, the Bayesian optimization search is set to perform 5 evaluations. + +## Arguments for Convenience + +NePS also provides the `pipeline_directory` and the `previous_pipeline_directory` as arguments in the `run_pipeline` function for user convenience. + +Regard an example to be run with a multi-fidelity searcher, some checkpointing would be advantageos such that one does not have to train the configuration from scratch when the configuration qualifies to higher fidelity brackets. + +```python +def run_pipeline( + pipeline_directory, # The directory where the config is saved + previous_pipeline_directory, # The directory of the immediate lower fidelity config + **config, # The hyperparameters to be used in the pipeline +): + # Assume element3 is our fidelity element + element_1 = config["element_1"] + element_2 = config["element_2"] + element_3 = config["element_3"] + + # Load any saved checkpoints + checkpoint_name = "checkpoint.pth" + start_element_3 = 0 + + if previous_pipeline_directory is not None: + # Read in state of the model after the previous fidelity rung + checkpoint = torch.load(previous_pipeline_directory / checkpoint_name) + prev_element_3 = checkpoint["element_3"] + else: + prev_element_3 = 0 + + start_element_3 += prev_element_3 + + loss = 0 + for i in range(start_element_3, element_3): + loss += element_1 - element_2 + + torch.save( + { + "element_3": element_3, + }, + pipeline_directory / checkpoint_name, + ) + + return loss +``` + +This could allow the proper navigation to the trained models and further train them on higher fidelities without repeating the entire training process. diff --git a/mkdocs.yml b/mkdocs.yml index 51d4a407..5afc9246 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -1,4 +1,4 @@ -site_name: Neural Pipeline Search +site_name: NePS docs_dir: docs repo_url: https://github.com/automl/neps repo_name: automl/neps @@ -9,6 +9,18 @@ theme: icon: repo: fontawesome/brands/github + palette: + # Palette toggle for light mode + - scheme: default + toggle: + icon: material/weather-night + name: Switch to dark mode + # Palette toggle for dark mode + - scheme: slate + toggle: + icon: material/weather-sunny + name: Switch to light mode + markdown_extensions: - pymdownx.highlight: anchor_linenums: true @@ -16,19 +28,24 @@ markdown_extensions: - pymdownx.snippets - pymdownx.superfences - attr_list + - admonition + - attr_list + - md_in_html extra: version: provider: mike nav: - - Introduction and Installation: 'README.md' + - Installation: 'installation.md' - Getting Started: 'getting_started.md' - The run_pipeline Function: 'run_pipeline.md' - The pipeline_space: 'pipeline_space.md' - The neps.run Function: 'neps_run.md' + - Optimizers: 'optimizers.md' - Analysing Runs: 'analyse.md' - Parallelization: 'parallelization.md' + - Citations: 'citations.md' - Alternatives: 'alternatives.md' - Contributing: - Introduction: "contributing/README.md" diff --git a/src/neps/NOTICE b/neps/NOTICE similarity index 100% rename from src/neps/NOTICE rename to neps/NOTICE diff --git a/src/neps/__init__.py b/neps/__init__.py similarity index 100% rename from src/neps/__init__.py rename to neps/__init__.py diff --git a/src/neps/api.py b/neps/api.py similarity index 76% rename from src/neps/api.py rename to neps/api.py index 24efe7e8..2584fcbe 100644 --- a/src/neps/api.py +++ b/neps/api.py @@ -6,19 +6,21 @@ import logging import warnings from pathlib import Path -from typing import Callable, Literal, List +from typing import Callable, Iterable, Literal import ConfigSpace as CS -import metahyper -from metahyper import instance_from_map - +from .metahyper import instance_from_map, metahyper_run from .optimizers import BaseOptimizer, SearcherMapping from .plot.tensorboard_eval import tblogger from .search_spaces.parameter import Parameter -from .search_spaces.search_space import SearchSpace, pipeline_space_from_configspace +from .search_spaces.search_space import ( + SearchSpace, + pipeline_space_from_configspace, + pipeline_space_from_yaml, +) from .status.status import post_run_csv -from .utils.common import get_searcher_data +from .utils.common import get_searcher_data, get_value from .utils.result_utils import get_loss @@ -95,8 +97,14 @@ def write_loss_and_config(file_handle, loss_, config_id_, config_): def run( run_pipeline: Callable, - pipeline_space: dict[str, Parameter | CS.ConfigurationSpace] | CS.ConfigurationSpace, root_directory: str | Path, + pipeline_space: ( + dict[str, Parameter | CS.ConfigurationSpace] + | str + | Path + | CS.ConfigurationSpace + | None + ) = None, overwrite_working_directory: bool = False, post_run_summary: bool = False, development_stage_id=None, @@ -108,18 +116,20 @@ def run( ignore_errors: bool = False, loss_value_on_error: None | float = None, cost_value_on_error: None | float = None, - pre_load_hooks: List=[], - searcher: Literal[ - "default", - "bayesian_optimization", - "random_search", - "hyperband", - "priorband", - "mobster", - "asha", - "regularized_evolution", - ] - | BaseOptimizer = "default", + pre_load_hooks: Iterable | None = None, + searcher: ( + Literal[ + "default", + "bayesian_optimization", + "random_search", + "hyperband", + "priorband", + "mobster", + "asha", + "regularized_evolution", + ] + | BaseOptimizer + ) = "default", searcher_path: Path | str | None = None, **searcher_kwargs, ) -> None: @@ -169,7 +179,6 @@ def run( Raises: ValueError: If deprecated argument working_directory is used. ValueError: If root_directory is None. - TypeError: If pipeline_space has invalid type. Example: @@ -204,24 +213,35 @@ def run( ) max_cost_total = searcher_kwargs["budget"] del searcher_kwargs["budget"] - + + if pre_load_hooks is None: + pre_load_hooks = [] + logger = logging.getLogger("neps") logger.info(f"Starting neps.run using root directory {root_directory}") - + + # Used to create the yaml holding information about the searcher. + # Also important for testing and debugging the api. + searcher_info = { + "searcher_name": "", + "searcher_alg": "", + "searcher_selection": "", + "neps_decision_tree": True, + "searcher_args": {}, + } + if isinstance(searcher, BaseOptimizer): searcher_instance = searcher - searcher_name = "custom" - searcher_alg = searcher.whoami() - user_defined_searcher = True + searcher_info["searcher_name"] = "baseoptimizer" + searcher_info["searcher_alg"] = searcher.whoami() + searcher_info["searcher_selection"] = "user-instantiation" + searcher_info["neps_decision_tree"] = False else: - ( - searcher_name, - searcher_instance, - searcher_alg, - searcher_config, - searcher_info, - user_defined_searcher + ( + searcher_instance, + searcher_info, ) = _run_args( + searcher_info=searcher_info, pipeline_space=pipeline_space, max_cost_total=max_cost_total, ignore_errors=ignore_errors, @@ -233,52 +253,25 @@ def run( **searcher_kwargs, ) - # Used to create the yaml holding information about the searcher. - # Also important for testing and debugging the api. - searcher_info = { - "searcher_name": searcher_name, - "searcher_alg": searcher_alg, - "user_defined_searcher": user_defined_searcher, - "searcher_args_user_modified": False, - } - - # Check to verify if the target directory contains the history of another optimizer state + # Check to verify if the target directory contains history of another optimizer state # This check is performed only when the `searcher` is built during the run - if isinstance(searcher, BaseOptimizer): + if not isinstance(searcher, (BaseOptimizer, str)): + raise ValueError( + f"Unrecognized `searcher` of type {type(searcher)}. Not str or BaseOptimizer." + ) + elif isinstance(searcher, BaseOptimizer): # This check is not strict when a user-defined neps.optimizer is provided - logger.warn( + logger.warning( "An instantiated optimizer is provided. The safety checks of NePS will be " "skipped. Accurate continuation of runs can no longer be guaranteed!" ) - elif isinstance(searcher, str): - # Updating searcher arguments from searcher_kwargs - for key, value in searcher_kwargs.items(): - if user_defined_searcher: - if key not in searcher_config or searcher_config[key] != value: - searcher_config[key] = value - logger.info( - f"Updating the current searcher argument '{key}'" - f" with the value '{value}'" - ) - else: - logger.info( - f"The searcher argument '{key}' has the same" - f" value '{value}' as default." - ) - searcher_info["searcher_args_user_modified"] = True - else: - # No searcher argument updates when NePS decides the searcher. - logger.info(35 * "=" + "WARNING" + 35 * "=") - logger.info("CHANGING ARGUMENTS ONLY WORK WHEN SEARCHER IS DEFINED") - logger.info( - f"The searcher argument '{key}' will not change to '{value}'" - f" because NePS chose the searcher" - ) - searcher_info["searcher_args_user_modified"] = False - else: - raise ValueError(f"Unrecognized `searcher`. Not str or BaseOptimizer.") - - metahyper.run( + + if task_id is not None: + root_directory = Path(root_directory) / f"task_{task_id}" + if development_stage_id is not None: + root_directory = Path(root_directory) / f"dev_{development_stage_id}" + + metahyper_run( run_pipeline, searcher_instance, searcher_info, @@ -286,8 +279,6 @@ def run( max_evaluations_total=max_evaluations_total, max_evaluations_per_run=max_evaluations_per_run, continue_until_max_evaluation_completed=continue_until_max_evaluation_completed, - development_stage_id=development_stage_id, - task_id=task_id, logger=logger, post_evaluation_hook=_post_evaluation_hook_function( loss_value_on_error, ignore_errors @@ -296,35 +287,52 @@ def run( pre_load_hooks=pre_load_hooks, ) - if post_run_csv: + if post_run_summary: post_run_csv(root_directory, logger) def _run_args( - pipeline_space: dict[str, Parameter | CS.ConfigurationSpace] | CS.ConfigurationSpace, + searcher_info: dict, + pipeline_space: ( + dict[str, Parameter | CS.ConfigurationSpace] + | str + | Path + | CS.ConfigurationSpace + | None + ) = None, max_cost_total: int | float | None = None, ignore_errors: bool = False, loss_value_on_error: None | float = None, cost_value_on_error: None | float = None, logger=None, - searcher: Literal[ - "default", - "bayesian_optimization", - "random_search", - "hyperband", - "priorband", - "mobster", - "asha", - "regularized_evolution", - ] - | BaseOptimizer = "default", + searcher: ( + Literal[ + "default", + "bayesian_optimization", + "random_search", + "hyperband", + "priorband", + "mobster", + "asha", + "regularized_evolution", + ] + | BaseOptimizer + ) = "default", searcher_path: Path | str | None = None, **searcher_kwargs, -) -> None: +) -> tuple[BaseOptimizer, dict]: try: + # Raising an issue if pipeline_space is None + if pipeline_space is None: + raise ValueError( + "The choice of searcher requires a pipeline space to be provided" + ) # Support pipeline space as ConfigurationSpace definition if isinstance(pipeline_space, CS.ConfigurationSpace): pipeline_space = pipeline_space_from_configspace(pipeline_space) + # Support pipeline space as YAML file + elif isinstance(pipeline_space, (str, Path)): + pipeline_space = pipeline_space_from_yaml(pipeline_space) # Support pipeline space as mix of ConfigurationSpace and neps parameters new_pipeline_space: dict[str, Parameter] = dict() @@ -335,21 +343,20 @@ def _run_args( else: new_pipeline_space[key] = value pipeline_space = new_pipeline_space - + # Transform to neps internal representation of the pipeline space pipeline_space = SearchSpace(**pipeline_space) except TypeError as e: message = f"The pipeline_space has invalid type: {type(pipeline_space)}" raise TypeError(message) from e - user_defined_searcher = False - if isinstance(searcher, str) and searcher_path is not None: # The users has their own custom searcher. logging.info("Preparing to run user created searcher") config = get_searcher_data(searcher, searcher_path) - user_defined_searcher = True + searcher_info["searcher_selection"] = "user-yaml" + searcher_info["neps_decision_tree"] = False else: if searcher in ["default", None]: # NePS decides the searcher according to the pipeline space. @@ -361,42 +368,41 @@ def _run_args( if pipeline_space.has_fidelity else "bayesian_optimization" ) + searcher_info["searcher_selection"] = "neps-default" else: # Users choose one of NePS searchers. - user_defined_searcher = True + searcher_info["neps_decision_tree"] = False + searcher_info["searcher_selection"] = "neps-default" # Fetching the searcher data, throws an error when the searcher is not found config = get_searcher_data(searcher) searcher_alg = config["searcher_init"]["algorithm"] - searcher_config = {} if config["searcher_kwargs"] is None else config["searcher_kwargs"] + searcher_config = ( + {} if config["searcher_kwargs"] is None else config["searcher_kwargs"] + ) logger.info(f"Running {searcher} as the searcher") logger.info(f"Algorithm: {searcher_alg}") # Used to create the yaml holding information about the searcher. # Also important for testing and debugging the api. - searcher_info = { - "searcher_name": searcher, - "searcher_alg": searcher_alg, - "user_defined_searcher": user_defined_searcher, - "searcher_args_user_modified": False, - } + searcher_info["searcher_name"] = searcher + searcher_info["searcher_alg"] = searcher_alg # Updating searcher arguments from searcher_kwargs for key, value in searcher_kwargs.items(): - if user_defined_searcher: + if not searcher_info["neps_decision_tree"]: if key not in searcher_config or searcher_config[key] != value: searcher_config[key] = value logger.info( f"Updating the current searcher argument '{key}'" - f" with the value '{value}'" + f" with the value '{get_value(value)}'" ) else: logger.info( f"The searcher argument '{key}' has the same" - f" value '{value}' as default." + f" value '{get_value(value)}' as default." ) - searcher_info["searcher_args_user_modified"] = True else: # No searcher argument updates when NePS decides the searcher. logger.info(35 * "=" + "WARNING" + 35 * "=") @@ -405,7 +411,8 @@ def _run_args( f"The searcher argument '{key}' will not change to '{value}'" f" because NePS chose the searcher" ) - searcher_info["searcher_args_user_modified"] = False + + searcher_info["searcher_args"] = get_value(searcher_config) searcher_config.update( { @@ -414,7 +421,7 @@ def _run_args( "ignore_errors": ignore_errors, } ) - + searcher_instance = instance_from_map( SearcherMapping, searcher_alg, "searcher", as_class=True )( @@ -422,5 +429,8 @@ def _run_args( budget=max_cost_total, # TODO: use max_cost_total everywhere **searcher_config, ) - - return searcher, searcher_instance, searcher_alg, searcher_config, searcher_info, user_defined_searcher + + return ( + searcher_instance, + searcher_info, + ) diff --git a/neps/metahyper/__init__.py b/neps/metahyper/__init__.py new file mode 100644 index 00000000..6e2aa0f7 --- /dev/null +++ b/neps/metahyper/__init__.py @@ -0,0 +1,2 @@ +from .api import ConfigResult, Sampler, read, metahyper_run +from .utils import instance_from_map diff --git a/src/metahyper/_locker.py b/neps/metahyper/_locker.py similarity index 100% rename from src/metahyper/_locker.py rename to neps/metahyper/_locker.py diff --git a/src/metahyper/api.py b/neps/metahyper/api.py similarity index 96% rename from src/metahyper/api.py rename to neps/metahyper/api.py index abcd974e..a868e6c2 100644 --- a/src/metahyper/api.py +++ b/neps/metahyper/api.py @@ -1,5 +1,6 @@ from __future__ import annotations +import os import inspect import logging import shutil @@ -10,7 +11,7 @@ from copy import deepcopy from dataclasses import dataclass from pathlib import Path -from typing import Any, List +from typing import Any, Iterable from ._locker import Locker from .utils import YamlSerializer, find_files, non_empty_file @@ -124,17 +125,14 @@ def _process_sampler_info( thread safety, preventing potential conflicts when multiple threads access the file simultaneously. - Parameters: + Args: - serializer: The YAML serializer object used for loading and dumping data. - sampler_info: The dictionary containing information for the optimizer. - sampler_info_file: The path to the YAML file storing optimizer data if available. - decision_locker: The Locker file to use during multi-thread communication. - logger: An optional logger object for logging messages (default is 'neps'). - Note: - The file-locking mechanism is employed to avoid potential errors in multiple threads. - - The `Locker` class and `YamlSerializer` should be appropriately defined or imported. - - Ensure that potential side effects or dependencies are considered when using this function. """ if logger is None: logger = logging.getLogger("neps") @@ -159,6 +157,9 @@ def _process_sampler_info( else: # If the file is empty or doesn't exist, write the sampler_info serializer.dump(sampler_info, sampler_info_file, sort_keys=False) + except ValueError as ve: + # Handle specific value error + raise ve except Exception as e: raise RuntimeError(f"Error during data saving: {e}") from e finally: @@ -268,9 +269,10 @@ def _check_max_evaluations( max_evaluations, serializer, logger, - continue_until_max_evaluation_completed, + continue_until_max_evaluation_completed ): logger.debug("Checking if max evaluations is reached") + #TODO: maybe not read everything again? previous_results, pending_configs, pending_configs_free = read( optimization_dir, serializer, logger ) @@ -290,16 +292,19 @@ def _sample_config(optimization_dir, sampler, serializer, logger, pre_load_hooks ) base_result_directory = optimization_dir / "results" + logger.debug(f"Previous results: {previous_results}") + logger.debug(f"Pending configs: {pending_configs}") + logger.debug(f"Pending configs: {pending_configs_free}") logger.debug("Sampling a new configuration") - + for hook in pre_load_hooks: # executes operations on the sampler before setting its state # can be used for setting custom constraints on the optimizer state - # for example, can be used to input custom grid of configs, meta learning + # for example, can be used to input custom grid of configs, meta learning # information for surrogate building, any non-stationary auxiliary information sampler = hook(sampler) - + sampler.load_results(previous_results, pending_configs) config, config_id, previous_config_id = sampler.get_config_and_ids() @@ -313,6 +318,9 @@ def _sample_config(optimization_dir, sampler, serializer, logger, pre_load_hooks "communication, but most likely some configs crashed during their execution " "or a jobtime-limit was reached." ) + # write some extra data per configuration if the optimizer has any + # if hasattr(sampler, "evaluation_data"): + # sampler.evaluation_data.write_all(pipeline_directory) if previous_config_id is not None: previous_config_id_file = pipeline_directory / "previous_config.id" @@ -413,7 +421,7 @@ def _evaluate_config( return result, {"time_end": time.time()} -def run( +def metahyper_run( evaluation_fn, sampler: Sampler, sampler_info: dict, @@ -421,22 +429,15 @@ def run( max_evaluations_total=None, max_evaluations_per_run=None, continue_until_max_evaluation_completed=False, - development_stage_id=None, - task_id=None, logger=None, post_evaluation_hook=None, overwrite_optimization_dir=False, - pre_load_hooks: List=[], + pre_load_hooks: Iterable | None = None, ): serializer = YamlSerializer(sampler.load_config) if logger is None: logger = logging.getLogger("metahyper") - if task_id is not None: - optimization_dir = Path(optimization_dir) / f"task_{task_id}" - if development_stage_id is not None: - optimization_dir = Path(optimization_dir) / f"dev_{development_stage_id}" - optimization_dir = Path(optimization_dir) if overwrite_optimization_dir and optimization_dir.exists(): logger.warning("Overwriting working_directory") @@ -451,11 +452,13 @@ def run( decision_lock_file.touch(exist_ok=True) decision_locker = Locker(decision_lock_file, logger.getChild("_locker")) + # Configuring the .optimizer_info.yaml file _process_sampler_info( serializer, sampler_info, sampler_info_file, decision_locker, logger ) evaluations_in_this_run = 0 + while True: if max_evaluations_total is not None and _check_max_evaluations( optimization_dir, diff --git a/src/metahyper/example.py b/neps/metahyper/example.py similarity index 100% rename from src/metahyper/example.py rename to neps/metahyper/example.py diff --git a/src/metahyper/utils.py b/neps/metahyper/utils.py similarity index 88% rename from src/metahyper/utils.py rename to neps/metahyper/utils.py index 72fac45f..fede6adc 100644 --- a/src/metahyper/utils.py +++ b/neps/metahyper/utils.py @@ -48,6 +48,21 @@ def get_data_representation(data: Any): return data +class MissingDependencyError(Exception): + def __init__(self, dep: str, cause: Exception, *args: Any): + super().__init__(dep, cause, *args) + self.dep = dep + self.__cause__ = cause # This is what `raise a from b` does + + def __str__(self) -> str: + return ( + f"Some required dependency-({self.dep}) to use this optional feature is " + f"missing. Please, include neps[experimental] dependency group in your " + f"installation of neps to be able to use all the optional features." + f" Otherwise, just install ({self.dep})" + ) + + class YamlSerializer: SUFFIX = ".yaml" PRE_SERIALIZE = True @@ -97,7 +112,7 @@ def instance_from_map( name: str = "mapping", allow_any: bool = True, as_class: bool = False, - kwargs: dict = None, + kwargs: dict | None = None, ): """Get an instance of an class from a mapping. @@ -140,6 +155,9 @@ def instance_from_map( else: raise ValueError(f"Object {request} invalid key for {name}") + if isinstance(instance, MissingDependencyError): + raise instance + # Check if the request is a class if it is mandatory if (args_dict or as_class) and not is_partial_class(instance): raise ValueError( diff --git a/src/neps/optimizers/__init__.py b/neps/optimizers/__init__.py similarity index 100% rename from src/neps/optimizers/__init__.py rename to neps/optimizers/__init__.py diff --git a/src/neps/optimizers/base_optimizer.py b/neps/optimizers/base_optimizer.py similarity index 95% rename from src/neps/optimizers/base_optimizer.py rename to neps/optimizers/base_optimizer.py index 83381c59..33bd1435 100644 --- a/src/neps/optimizers/base_optimizer.py +++ b/neps/optimizers/base_optimizer.py @@ -5,15 +5,13 @@ from copy import deepcopy from typing import Any -import metahyper -from metahyper.api import ConfigResult - +from ..metahyper.api import ConfigResult, Sampler from ..search_spaces.search_space import SearchSpace from ..utils.common import get_rnd_state, set_rnd_state from ..utils.result_utils import get_cost, get_learning_curve, get_loss -class BaseOptimizer(metahyper.Sampler): +class BaseOptimizer(Sampler): """Base sampler class. Implements all the low-level work.""" def __init__( @@ -62,7 +60,7 @@ def load_state(self, state: Any): # pylint: disable=no-self-use super().load_state(state) def load_config(self, config_dict): - config = deepcopy(self.pipeline_space) + config = self.pipeline_space.copy() config.load_from(config_dict) return config diff --git a/neps/optimizers/bayesian_optimization/acquisition_functions/__init__.py b/neps/optimizers/bayesian_optimization/acquisition_functions/__init__.py new file mode 100644 index 00000000..45380755 --- /dev/null +++ b/neps/optimizers/bayesian_optimization/acquisition_functions/__init__.py @@ -0,0 +1,117 @@ +from __future__ import annotations + +from functools import partial +from typing import Callable + +from .ei import ComprehensiveExpectedImprovement +from .mf_ei import MFEI, MFEI_AtMax, MFEI_Dyna, MFEI_Random +from .mf_pi import MFPI, MFPI_AtMax, MFPI_Dyna, MFPI_Random, MFPI_Random_HiT +from .ucb import UpperConfidenceBound +from .mf_ucb import MF_UCB, MF_UCB_AtMax, MF_UCB_Dyna +from .mf_two_step import MF_TwoStep + + +AcquisitionMapping: dict[str, Callable] = { + "EI": partial( + ComprehensiveExpectedImprovement, + in_fill="best", + augmented_ei=False, + ), + "LogEI": partial( + ComprehensiveExpectedImprovement, + in_fill="best", + augmented_ei=False, + log_ei=True, + ), + # # Uses the augmented EI heuristic and changed the in-fill criterion to the best test location with + # # the highest *posterior mean*, which are preferred when the optimisation is noisy. + "AEI": partial( + ComprehensiveExpectedImprovement, + in_fill="posterior", + augmented_ei=True, + ), + "MFEI": partial( + MFEI, + in_fill="best", + augmented_ei=False, + ), + "MFEI-max": partial( + MFEI_AtMax, + in_fill="best", + augmented_ei=False, + ), + "MFEI-dyna": partial( + MFEI_Dyna, + in_fill="best", + augmented_ei=False, + ), + "MFEI-random": partial( + MFPI_Random, # code has been modified, rerun and use "MFEI-random2"! + in_fill="best", + augmented_ei=False, + ), + "MFEI-random2": partial( + MFEI_Random, + in_fill="best", + augmented_ei=False, + ), + "UCB": partial( + UpperConfidenceBound, + maximize=False, + ), + "MF-UCB": partial( + MF_UCB, + maximize=False, + ), + "MF-UCB-max": partial( + MF_UCB_AtMax, + maximize=False, + ), + "MF-UCB-dyna": partial( + MF_UCB_Dyna, + maximize=False, + ), + "MF_TwoStep": partial( + MF_TwoStep, + maximize=False, + ), + "MFPI": partial( + MFPI, + in_fill="best", + augmented_ei=False, + ), + "MFPI-max": partial( + MFPI_AtMax, + in_fill="best", + augmented_ei=False, + ), + "MFPI-thresh-max": partial( + MFPI_Random, + in_fill="best", + augmented_ei=False, + horizon="max", + threshold="random", + ), + "MFPI-random-horizon": partial( + MFPI_Random, + in_fill="best", + augmented_ei=False, + horizon="random", + threshold="0.0", + ), + "MFPI-dyna": partial( + MFPI_Dyna, + in_fill="best", + augmented_ei=False, + ), + "MFPI-random": partial( + MFPI_Random, + in_fill="best", + augmented_ei=False, + ), + "MFPI-random-hit": partial( + MFPI_Random_HiT, + in_fill="best", + augmented_ei=False, + ) +} diff --git a/src/neps/optimizers/bayesian_optimization/acquisition_functions/_ehvi.py b/neps/optimizers/bayesian_optimization/acquisition_functions/_ehvi.py similarity index 100% rename from src/neps/optimizers/bayesian_optimization/acquisition_functions/_ehvi.py rename to neps/optimizers/bayesian_optimization/acquisition_functions/_ehvi.py diff --git a/src/neps/optimizers/bayesian_optimization/acquisition_functions/base_acquisition.py b/neps/optimizers/bayesian_optimization/acquisition_functions/base_acquisition.py similarity index 100% rename from src/neps/optimizers/bayesian_optimization/acquisition_functions/base_acquisition.py rename to neps/optimizers/bayesian_optimization/acquisition_functions/base_acquisition.py diff --git a/src/neps/optimizers/bayesian_optimization/acquisition_functions/cost_cooling.py b/neps/optimizers/bayesian_optimization/acquisition_functions/cost_cooling.py similarity index 100% rename from src/neps/optimizers/bayesian_optimization/acquisition_functions/cost_cooling.py rename to neps/optimizers/bayesian_optimization/acquisition_functions/cost_cooling.py diff --git a/src/neps/optimizers/bayesian_optimization/acquisition_functions/ei.py b/neps/optimizers/bayesian_optimization/acquisition_functions/ei.py similarity index 100% rename from src/neps/optimizers/bayesian_optimization/acquisition_functions/ei.py rename to neps/optimizers/bayesian_optimization/acquisition_functions/ei.py diff --git a/neps/optimizers/bayesian_optimization/acquisition_functions/mf_ei.py b/neps/optimizers/bayesian_optimization/acquisition_functions/mf_ei.py new file mode 100644 index 00000000..5b059db0 --- /dev/null +++ b/neps/optimizers/bayesian_optimization/acquisition_functions/mf_ei.py @@ -0,0 +1,430 @@ +# type: ignore +from typing import Any, Iterable, Tuple, Union + +import numpy as np +import pandas as pd +import torch +from torch.distributions import Normal + +from ....optimizers.utils import map_real_hyperparameters_from_tabular_ids +from ....search_spaces.search_space import IntegerParameter, SearchSpace +from ...multi_fidelity.utils import MFObservedData +from .base_acquisition import BaseAcquisition +from .ei import ComprehensiveExpectedImprovement + + +class MFStepBase(BaseAcquisition): + """A class holding common operations that can be inherited. + + WARNING: Unsafe use of self attributes, can break if not used correctly. + """ + def set_state( + self, + pipeline_space: SearchSpace, + surrogate_model: Any, + observations: MFObservedData, + b_step: Union[int, float], + **kwargs, + ): + # overload to select incumbent differently through observations + self.pipeline_space = pipeline_space + self.surrogate_model = surrogate_model + self.observations = observations + self.b_step = b_step + return + + def get_budget_level(self, config) -> int: + return int((config.fidelity.value - config.fidelity.lower) / self.b_step) + + + def preprocess_gp(self, x: pd.Series) -> Tuple[pd.Series, torch.Tensor]: + x, inc_list = self.preprocess(x) + return x, inc_list + + def preprocess_deep_gp(self, x: pd.Series) -> Tuple[pd.Series, torch.Tensor]: + x, inc_list = self.preprocess(x) + x_lcs = [] + for idx in x.index: + if idx in self.observations.df.index.levels[0]: + # TODO: Samir, check if `budget_id=None` is okay? + # budget_level = self.get_budget_level(x[idx]) + # extracting the available/observed learning curve + lc = self.observations.extract_learning_curve(idx, budget_id=None) + else: + # initialize a learning curve with a placeholder + # This is later padded accordingly for the Conv1D layer + lc = [] + x_lcs.append(lc) + self.surrogate_model.set_prediction_learning_curves(x_lcs) + return x, inc_list + + def preprocess_pfn(self, x: pd.Series) -> Tuple[torch.Tensor, pd.Series, torch.Tensor]: + """Prepares the configurations for appropriate EI calculation. + + Takes a set of points and computes the budget and incumbent for each point, as + required by the multi-fidelity Expected Improvement acquisition function. + """ + _x, inc_list = self.preprocess(x.copy()) + _x_tok = self.observations.tokenize(_x, as_tensor=True) + len_partial = len(self.observations.seen_config_ids) + z_min = x[0].fidelity.lower + z_max = x[0].fidelity.upper + # converting fidelity to the discrete budget level + # STRICT ASSUMPTION: fidelity is the second dimension + _x_tok[:len_partial, 1] = ( + _x_tok[:len_partial, 1] + self.b_step - z_min + ) / self.b_step + _x_tok[:, 1] = _x_tok[:, 1] / z_max + return _x, _x_tok, inc_list + + +# NOTE: the order of inheritance is important +class MFEI(MFStepBase, ComprehensiveExpectedImprovement): + def __init__( + self, + pipeline_space: SearchSpace, + surrogate_model_name: str = None, + augmented_ei: bool = False, + xi: float = 0.0, + in_fill: str = "best", + inc_normalization: bool = False, + log_ei: bool = False, + ): + super().__init__(augmented_ei, xi, in_fill, log_ei) + self.pipeline_space = pipeline_space + self.surrogate_model_name = surrogate_model_name + self.inc_normalization = inc_normalization + self.surrogate_model = None + self.observations = None + self.b_step = None + + def preprocess_inc_list(self, **kwargs) -> list: + assert "budget_list" in kwargs, "Requires a list of query step for candidate set." + budget_list = kwargs["budget_list"] + performances = self.observations.get_best_performance_for_each_budget() + inc_list = [] + for budget_level in budget_list: + if budget_level in performances.index: + inc = performances[budget_level] + else: + inc = self.observations.get_best_seen_performance() + inc_list.append(inc) + return inc_list + + def preprocess(self, x: pd.Series) -> Tuple[pd.Series, torch.Tensor]: + """Prepares the configurations for appropriate EI calculation. + + Takes a set of points and computes the budget and incumbent for each point, as + required by the multi-fidelity Expected Improvement acquisition function. + """ + budget_list = [] + if self.pipeline_space.has_tabular: + # preprocess tabular space differently + # expected input: IDs pertaining to the tabular data + x = map_real_hyperparameters_from_tabular_ids(x, self.pipeline_space) + indices_to_drop = [] + for i, config in x.items(): + target_fidelity = config.fidelity.lower + if i <= max(self.observations.seen_config_ids): + # IMPORTANT to set the fidelity at which EI will be calculated only for + # the partial configs that have been observed already + target_fidelity = config.fidelity.value + self.b_step + + if np.less_equal(target_fidelity, config.fidelity.upper): + # only consider the configs with fidelity lower than the max fidelity + config.fidelity.value = target_fidelity + budget_list.append(self.get_budget_level(config)) + else: + # if the target_fidelity higher than the max drop the configuration + indices_to_drop.append(i) + else: + config.fidelity.value = target_fidelity + budget_list.append(self.get_budget_level(config)) + + # Drop unused configs + x.drop(labels=indices_to_drop, inplace=True) + + # Collecting incumbent list per configuration + inc_list = self.preprocess_inc_list(budget_list=budget_list) + + return x, torch.Tensor(inc_list) + + def eval(self, x: pd.Series, asscalar: bool = False) -> Tuple[np.ndarray, pd.Series]: + # deepcopy + _x = pd.Series([x.loc[idx].copy() for idx in x.index.values], index=x.index) + if self.surrogate_model_name == "pfn": + _x, _x_tok, inc_list = self.preprocess_pfn( + x.copy() + ) # IMPORTANT change from vanilla-EI + ei = self.eval_pfn_ei(_x_tok, inc_list) + elif self.surrogate_model_name in ["deep_gp", "dpl"]: + _x, inc_list = self.preprocess_deep_gp( + _x + ) # IMPORTANT change from vanilla-EI + ei = self.eval_gp_ei(_x.values.tolist(), inc_list) + elif self.surrogate_model_name == "gp": + _x, inc_list = self.preprocess_gp( + _x + ) # IMPORTANT change from vanilla-EI + ei = self.eval_gp_ei(_x.values.tolist(), inc_list) + else: + raise ValueError( + f"Unrecognized surrogate model name: {self.surrogate_model_name}" + ) + + if self.inc_normalization: + ei = ei / inc_list + + if ei.is_cuda: + ei = ei.cpu() + if len(_x) > 1 and asscalar: + return ei.detach().numpy(), _x + else: + return ei.detach().numpy().item(), _x + + def eval_pfn_ei( + self, x: Iterable, inc_list: Iterable + ) -> Union[np.ndarray, torch.Tensor, float]: + """PFN-EI modified to preprocess samples and accept list of incumbents.""" + ei = self.surrogate_model.get_ei(x.to(self.surrogate_model.device), inc_list) + if len(ei.shape) == 2: + ei = ei.flatten() + return ei + + def eval_gp_ei( + self, x: Iterable, inc_list: Iterable + ) -> Union[np.ndarray, torch.Tensor, float]: + """Vanilla-EI modified to preprocess samples and accept list of incumbents.""" + _x = x.copy() + try: + mu, cov = self.surrogate_model.predict(_x) + except ValueError as e: + raise e + # return -1.0 # in case of error. return ei of -1 + std = torch.sqrt(torch.diag(cov)) + + mu_star = inc_list.to(mu.device) # IMPORTANT change from vanilla-EI + + gauss = Normal(torch.zeros(1, device=mu.device), torch.ones(1, device=mu.device)) + # u = (mu - mu_star - self.xi) / std + # ei = std * updf + (mu - mu_star - self.xi) * ucdf + if self.log_ei: + # we expect that f_min is in log-space + f_min = mu_star - self.xi + v = (f_min - mu) / std + ei = torch.exp(f_min) * gauss.cdf(v) - torch.exp( + 0.5 * torch.diag(cov) + mu + ) * gauss.cdf(v - std) + else: + u = (mu_star - mu - self.xi) / std + ucdf = gauss.cdf(u) + updf = torch.exp(gauss.log_prob(u)) + ei = std * updf + (mu_star - mu - self.xi) * ucdf + # Clip ei if std == 0.0 + # ei = torch.where(torch.isclose(std, torch.tensor(0.0)), 0, ei) + if self.augmented_ei: + sigma_n = self.surrogate_model.likelihood + ei *= 1.0 - torch.sqrt(torch.tensor(sigma_n, device=mu.device)) / torch.sqrt( + sigma_n + torch.diag(cov) + ) + + # Save data for writing + self.mu_star = mu_star.detach().numpy().tolist() + self.mu = mu.detach().numpy().tolist() + self.std = std.detach().numpy().tolist() + return ei + + +class MFEI_AtMax(MFEI): + + def preprocess_inc_list(self, **kwargs) -> list: + assert "len_x" in kwargs, "Requires the length of the candidate set." + len_x = kwargs["len_x"] + # finds global incumbent + inc_value = min(self.observations.get_best_performance_for_each_budget()) + # uses the best seen value as the incumbent in EI computation for all candidates + inc_list = [inc_value] * len_x + return inc_list + + def preprocess(self, x: pd.Series) -> Tuple[pd.Series, torch.Tensor]: + """Prepares the configurations for appropriate EI calculation. + + Takes a set of points and computes the budget and incumbent for each point. + Unlike the base class MFEI, sets the target fidelity to be max budget and the + incumbent choice to be the max seen across history for all candidates. + """ + budget_list = [] + if self.pipeline_space.has_tabular: + # preprocess tabular space differently + # expected input: IDs pertaining to the tabular data + x = map_real_hyperparameters_from_tabular_ids(x, self.pipeline_space) + + indices_to_drop = [] + for i, config in x.items(): + target_fidelity = config.fidelity.upper # change from MFEI + + if config.fidelity.value == target_fidelity: + # if the target_fidelity already reached, drop the configuration + indices_to_drop.append(i) + else: + config.fidelity.value = target_fidelity + budget_list.append(self.get_budget_level(config)) + + # drop unused configs + x.drop(labels=indices_to_drop, inplace=True) + + # create the same incumbent for all candidates + inc_list = self.preprocess_inc_list(len_x=len(x.index.values)) + + return x, torch.Tensor(inc_list) + + +class MFEI_Dyna(MFEI_AtMax): + """ + Computes extrapolation length of curves to maximum fidelity seen. + Uses the global incumbent as the best score in EI computation. + """ + + def preprocess(self, x: pd.Series) -> Tuple[pd.Series, torch.Tensor]: + """Prepares the configurations for appropriate EI calculation. + + Takes a set of points and computes the budget and incumbent for each point. + Unlike the base class MFEI, sets the target fidelity to be max budget and the + incumbent choice to be the max seen across history for all candidates. + """ + if self.pipeline_space.has_tabular: + # preprocess tabular space differently + # expected input: IDs pertaining to the tabular data + x = map_real_hyperparameters_from_tabular_ids(x, self.pipeline_space) + + # find the maximum observed steps per config to obtain the current pseudo_z_max + max_z_level_per_x = self.observations.get_max_observed_fidelity_level_per_config() + pseudo_z_level_max = max_z_level_per_x.max() # highest seen fidelity step so far + # find the fidelity step at which the best seen performance was recorded + z_inc_level = self.observations.get_budget_level_for_best_performance() + # retrieving actual fidelity values from budget level + ## marker 1: the fidelity value at which the best seen performance was recorded + z_inc = self.b_step * z_inc_level + self.pipeline_space.fidelity.lower + ## marker 2: the maximum fidelity value recorded in observation history + pseudo_z_max = self.b_step * pseudo_z_level_max + self.pipeline_space.fidelity.lower + + # TODO: compare with this first draft logic + # def update_fidelity(config): + # ### DO NOT DELETE THIS FUNCTION YET + # # for all configs, set the min(max(current fidelity + step, z_inc), pseudo_z_max) + # ## that is, choose the next highest marker from 1 and 2 + # z_extrapolate = min( + # max(config.fidelity.value + self.b_step, z_inc), + # pseudo_z_max + # ) + # config.fidelity.value = z_extrapolate + # return config + + def update_fidelity(config): + # for all configs, set to pseudo_z_max + ## that is, choose the highest seen fidelity in observation history + z_extrapolate = pseudo_z_max + config.fidelity.value = z_extrapolate + return config + + # collect IDs for partial configurations + _partial_config_ids = (x.index <= max(self.observations.seen_config_ids)) + # filter for configurations that reached max budget + indices_to_drop = [ + _idx + for _idx, _x in x.loc[_partial_config_ids].items() + if _x.fidelity.value == self.pipeline_space.fidelity.upper + ] + # drop unused configs + x.drop(labels=indices_to_drop, inplace=True) + + # set fidelity for all partial configs + x = x.apply(update_fidelity) + + # create the same incumbent for all candidates + inc_list = self.preprocess_inc_list(len_x=len(x.index.values)) + + return x, torch.Tensor(inc_list) + + +class MFEI_Random(MFEI): + + BUDGET = 1000 + + def set_state( + self, + pipeline_space: SearchSpace, + surrogate_model: Any, + observations: MFObservedData, + b_step: Union[int, float], + **kwargs, + ): + # set RNG + self.rng = np.random.RandomState(seed=42) + for i in range(len(observations.completed_runs)): + self.rng.uniform(-4,-1) + self.rng.randint(1,51) + + return super().set_state(pipeline_space, surrogate_model, observations, b_step) + + def sample_horizon(self, steps_passed): + shortest = self.pipeline_space.fidelity.lower + longest = min(self.pipeline_space.fidelity.upper, self.BUDGET - steps_passed) + return self.rng.randint(shortest, longest+1) + + def sample_threshold(self, f_inc): + lu = 10**self.rng.uniform(-4,-1) # % of gap closed + return f_inc * (1 - lu) + + def preprocess(self, x: pd.Series) -> Tuple[pd.Series, torch.Tensor]: + """Prepares the configurations for appropriate EI calculation. + + Takes a set of points and computes the budget and incumbent for each point, as + required by the multi-fidelity Expected Improvement acquisition function. + """ + if self.pipeline_space.has_tabular: + # preprocess tabular space differently + # expected input: IDs pertaining to the tabular data + x = map_real_hyperparameters_from_tabular_ids(x, self.pipeline_space) + + + indices_to_drop = [] + inc_list = [] + + steps_passed = len(self.observations.completed_runs) + print(f"Steps acquired: {steps_passed}") + + # Like EI-AtMax, use the global incumbent as a basis for the EI threshold + inc_value = min(self.observations.get_best_performance_for_each_budget()) + # Extension: Add a random min improvement threshold to encourage high risk high gain + inc_value = self.sample_threshold(inc_value) + print(f"Threshold for EI: {inc_value}") + + # Like MFEI: set fidelities to query using horizon as self.b_step + # Extension: Unlike DyHPO, we sample the horizon randomly over the full range + horizon = self.sample_horizon(steps_passed) + print(f"Horizon for EI: {horizon}") + for i, config in x.items(): + if i <= max(self.observations.seen_config_ids): + current_fidelity = config.fidelity.value + if np.equal(config.fidelity.value, config.fidelity.upper): + # this training run has ended, drop it from future selection + indices_to_drop.append(i) + else: + # a candidate partial training run to continue + target_fidelity = config.fidelity.value + horizon + config.fidelity.value = min(config.fidelity.value + horizon, config.fidelity.upper) # if horizon exceeds max, query at max + inc_list.append(inc_value) + else: + # a candidate new training run that we would need to start + current_fidelity = 0 + config.fidelity.value = horizon + inc_list.append(inc_value) + #print(f"- {x.index.values[i]}: {current_fidelity} --> {config.fidelity.value}") + + # Drop unused configs + x.drop(labels=indices_to_drop, inplace=True) + + assert len(inc_list) == len(x) + + return x, torch.Tensor(inc_list) diff --git a/neps/optimizers/bayesian_optimization/acquisition_functions/mf_pi.py b/neps/optimizers/bayesian_optimization/acquisition_functions/mf_pi.py new file mode 100644 index 00000000..3f02bbc5 --- /dev/null +++ b/neps/optimizers/bayesian_optimization/acquisition_functions/mf_pi.py @@ -0,0 +1,447 @@ +# type: ignore +from pathlib import Path +from typing import Any, Iterable, Tuple, Union + +import numpy as np +import pandas as pd +import torch +from torch.distributions import Normal + +from copy import deepcopy + +from ....optimizers.utils import map_real_hyperparameters_from_tabular_ids +from ....search_spaces.search_space import IntegerParameter, SearchSpace +from ...multi_fidelity.utils import MFObservedData +from .base_acquisition import BaseAcquisition +from .ei import ComprehensiveExpectedImprovement +from ....utils.common import SimpleCSVWriter +from .mf_ei import MFStepBase + +# NOTE: the order of inheritance is important +class MFPI(MFStepBase, ComprehensiveExpectedImprovement): + def __init__( + self, + pipeline_space: SearchSpace, + surrogate_model_name: str = None, + augmented_ei: bool = False, + xi: float = 0.0, + in_fill: str = "best", + log_ei: bool = False, + ): + super().__init__(augmented_ei, xi, in_fill, log_ei) + self.pipeline_space = pipeline_space + self.surrogate_model_name = surrogate_model_name + self.surrogate_model = None + self.observations = None + self.b_step = None + + def preprocess_inc_list(self, **kwargs) -> list: + assert "budget_list" in kwargs, "Requires a list of query step for candidate set." + budget_list = kwargs["budget_list"] + performances = self.observations.get_best_performance_for_each_budget() + inc_list = [] + for budget_level in budget_list: + if budget_level in performances.index: + inc = performances[budget_level] + else: + inc = self.observations.get_best_seen_performance() + inc_list.append(inc) + return inc_list + + def preprocess(self, x: pd.Series) -> Tuple[pd.Series, torch.Tensor]: + """Prepares the configurations for appropriate EI calculation. + + Takes a set of points and computes the budget and incumbent for each point, as + required by the multi-fidelity Expected Improvement acquisition function. + """ + budget_list = [] + if self.pipeline_space.has_tabular: + # preprocess tabular space differently + # expected input: IDs pertaining to the tabular data + x = map_real_hyperparameters_from_tabular_ids(x, self.pipeline_space) + indices_to_drop = [] + for i, config in x.items(): + target_fidelity = config.fidelity.lower + if i <= max(self.observations.seen_config_ids): + # IMPORTANT to set the fidelity at which EI will be calculated only for + # the partial configs that have been observed already + target_fidelity = config.fidelity.value + self.b_step + + if np.less_equal(target_fidelity, config.fidelity.upper): + # only consider the configs with fidelity lower than the max fidelity + config.fidelity.value = target_fidelity + budget_list.append(self.get_budget_level(config)) + else: + # if the target_fidelity higher than the max drop the configuration + indices_to_drop.append(i) + else: + config.fidelity.value = target_fidelity + budget_list.append(self.get_budget_level(config)) + + # Drop unused configs + x.drop(labels=indices_to_drop, inplace=True) + + # Collecting incumbent list per configuration + inc_list = self.preprocess_inc_list(budget_list=budget_list) + + return x, torch.Tensor(inc_list) + + def eval(self, x: pd.Series, asscalar: bool = False) -> Tuple[np.ndarray, pd.Series]: + # deepcopy + _x = pd.Series([x.loc[idx].copy() for idx in x.index.values], index=x.index) + if self.surrogate_model_name == "pfn": + _x, _x_tok, inc_list = self.preprocess_pfn( + x.copy() + ) # IMPORTANT change from vanilla-EI + pi = self.eval_pfn_pi(_x_tok, inc_list) + elif self.surrogate_model_name in ["deep_gp", "dpl"]: + _x, inc_list = self.preprocess_deep_gp( + _x + ) # IMPORTANT change from vanilla-EI + pi = self.eval_gp_pi(_x.values.tolist(), inc_list) + elif self.surrogate_model_name == "gp": + _x, inc_list = self.preprocess_gp( + _x + ) # IMPORTANT change from vanilla-EI + pi = self.eval_gp_pi(_x.values.tolist(), inc_list) + else: + raise ValueError( + f"Unrecognized surrogate model name: {self.surrogate_model_name}" + ) + + if pi.is_cuda: + pi = ei.cpu() + if len(_x) > 1 and asscalar: + return pi.detach().numpy(), _x + else: + return pi.detach().numpy().item(), _x + + def eval_pfn_pi( + self, x: Iterable, inc_list: Iterable + ) -> Union[np.ndarray, torch.Tensor, float]: + """PFN-PI modified to preprocess samples and accept list of incumbents.""" + pi = self.surrogate_model.get_pi(x.to(self.surrogate_model.device), inc_list) + if len(pi.shape) == 2: + pi = pi.flatten() + print(f"Maximum PI: {pi.max()}") + return pi + + def eval_gp_pi( + self, x: Iterable, inc_list: Iterable + ) -> Union[np.ndarray, torch.Tensor, float]: + _x = x.copy() + try: + mu, cov = self.surrogate_model.predict(_x) + except ValueError as e: + raise e + std = torch.sqrt(torch.diag(cov)) + mu_star = inc_list.to(mu.device) + + gauss = Normal(torch.zeros(1, device=mu.device), torch.ones(1, device=mu.device)) + pi = gauss.cdf((mu - mu_star) / (std + 1E-9)) + return pi + + +class MFPI_AtMax(MFPI): + + def preprocess_inc_list(self, **kwargs) -> list: + assert "len_x" in kwargs, "Requires the length of the candidate set." + len_x = kwargs["len_x"] + # finds global incumbent + inc_value = min(self.observations.get_best_performance_for_each_budget()) + # uses the best seen value as the incumbent in EI computation for all candidates + inc_list = [inc_value] * len_x + return inc_list + + def preprocess(self, x: pd.Series) -> Tuple[pd.Series, torch.Tensor]: + """Prepares the configurations for appropriate EI calculation. + + Takes a set of points and computes the budget and incumbent for each point. + Unlike the base class MFPI, sets the target fidelity to be max budget and the + incumbent choice to be the max seen across history for all candidates. + """ + budget_list = [] + if self.pipeline_space.has_tabular: + # preprocess tabular space differently + # expected input: IDs pertaining to the tabular data + x = map_real_hyperparameters_from_tabular_ids(x, self.pipeline_space) + + indices_to_drop = [] + for i, config in x.items(): + target_fidelity = config.fidelity.upper # change from MFEI + + if config.fidelity.value == target_fidelity: + # if the target_fidelity already reached, drop the configuration + indices_to_drop.append(i) + else: + config.fidelity.value = target_fidelity + budget_list.append(self.get_budget_level(config)) + + # drop unused configs + x.drop(labels=indices_to_drop, inplace=True) + + # create the same incumbent for all candidates + inc_list = self.preprocess_inc_list(len_x=len(x.index.values)) + + return x, torch.Tensor(inc_list) + + +class MFPI_Dyna(MFPI_AtMax): + """ + Computes extrapolation length of curves to maximum fidelity seen. + Uses the global incumbent as the best score in EI computation. + """ + + def preprocess(self, x: pd.Series) -> Tuple[pd.Series, torch.Tensor]: + """Prepares the configurations for appropriate EI calculation. + + Takes a set of points and computes the budget and incumbent for each point. + Unlike the base class MFEI, sets the target fidelity to be max budget and the + incumbent choice to be the max seen across history for all candidates. + """ + if self.pipeline_space.has_tabular: + # preprocess tabular space differently + # expected input: IDs pertaining to the tabular data + x = map_real_hyperparameters_from_tabular_ids(x, self.pipeline_space) + + # find the maximum observed steps per config to obtain the current pseudo_z_max + max_z_level_per_x = self.observations.get_max_observed_fidelity_level_per_config() + pseudo_z_level_max = max_z_level_per_x.max() # highest seen fidelity step so far + # find the fidelity step at which the best seen performance was recorded + z_inc_level = self.observations.get_budget_level_for_best_performance() + # retrieving actual fidelity values from budget level + ## marker 1: the fidelity value at which the best seen performance was recorded + z_inc = self.b_step * z_inc_level + self.pipeline_space.fidelity.lower + ## marker 2: the maximum fidelity value recorded in observation history + pseudo_z_max = self.b_step * pseudo_z_level_max + self.pipeline_space.fidelity.lower + + # TODO: compare with this first draft logic + # def update_fidelity(config): + # ### DO NOT DELETE THIS FUNCTION YET + # # for all configs, set the min(max(current fidelity + step, z_inc), pseudo_z_max) + # ## that is, choose the next highest marker from 1 and 2 + # z_extrapolate = min( + # max(config.fidelity.value + self.b_step, z_inc), + # pseudo_z_max + # ) + # config.fidelity.value = z_extrapolate + # return config + + def update_fidelity(config): + # for all configs, set to pseudo_z_max + ## that is, choose the highest seen fidelity in observation history + z_extrapolate = pseudo_z_max + config.fidelity.value = z_extrapolate + return config + + # collect IDs for partial configurations + _partial_config_ids = (x.index <= max(self.observations.seen_config_ids)) + # filter for configurations that reached max budget + indices_to_drop = [ + _idx + for _idx, _x in x.loc[_partial_config_ids].items() + if _x.fidelity.value == self.pipeline_space.fidelity.upper + ] + # drop unused configs + x.drop(labels=indices_to_drop, inplace=True) + + # set fidelity for all partial configs + x = x.apply(update_fidelity) + + # create the same incumbent for all candidates + inc_list = self.preprocess_inc_list(len_x=len(x.index.values)) + + return x, torch.Tensor(inc_list) + + +class MFPI_Random(MFPI): + + BUDGET = 1000 + + def __init__( + self, + pipeline_space: SearchSpace, + horizon: str = "random", + threshold: str = "random", + surrogate_model_name: str = None, + augmented_ei: bool = False, + xi: float = 0.0, + in_fill: str = "best", + log_ei: bool = False, + ): + super().__init__(pipeline_space, surrogate_model_name, augmented_ei, xi, in_fill, log_ei) + self.horizon = horizon + self.threshold = threshold + + + + def set_state( + self, + pipeline_space: SearchSpace, + surrogate_model: Any, + observations: MFObservedData, + b_step: Union[int, float], + **kwargs, + ): + # set RNG + self.rng = np.random.RandomState(seed=42) + for i in range(len(observations.completed_runs)): + self.rng.uniform(-4,-1) + self.rng.randint(1,51) + + return super().set_state(pipeline_space, surrogate_model, observations, b_step) + + def sample_horizon(self, steps_passed): + if self.horizon == 'random': + shortest = self.pipeline_space.fidelity.lower + longest = min(self.pipeline_space.fidelity.upper, self.BUDGET - steps_passed) + return self.rng.randint(shortest, longest+1) + elif self.horizon == 'max': + return min(self.pipeline_space.fidelity.upper, self.BUDGET - steps_passed) + else: + return int(self.horizon) + + def sample_threshold(self, f_inc): + if self.threshold == 'random': + lu = 10**self.rng.uniform(-4,-1) # % of gap closed + else: + lu = float(self.threshold) + return f_inc * (1 - lu) + + def preprocess(self, x: pd.Series) -> Tuple[pd.Series, torch.Tensor]: + """Prepares the configurations for appropriate EI calculation. + + Takes a set of points and computes the budget and incumbent for each point, as + required by the multi-fidelity Expected Improvement acquisition function. + """ + if self.pipeline_space.has_tabular: + # preprocess tabular space differently + # expected input: IDs pertaining to the tabular data + x = map_real_hyperparameters_from_tabular_ids(x, self.pipeline_space) + + + indices_to_drop = [] + inc_list = [] + + steps_passed = len(self.observations.completed_runs) + print(f"Steps acquired: {steps_passed}") + + # Like EI-AtMax, use the global incumbent as a basis for the EI threshold + inc_value = min(self.observations.get_best_performance_for_each_budget()) + # Extension: Add a random min improvement threshold to encourage high risk high gain + t_value = self.sample_threshold(inc_value) + print(f"Threshold for PI: {inc_value - t_value}") + inc_value = t_value + + # Like MFEI: set fidelities to query using horizon as self.b_step + # Extension: Unlike DyHPO, we sample the horizon randomly over the full range + horizon = self.sample_horizon(steps_passed) + print(f"Horizon for PI: {horizon}") + for i, config in x.items(): + if i <= max(self.observations.seen_config_ids): + current_fidelity = config.fidelity.value + if np.equal(config.fidelity.value, config.fidelity.upper): + # this training run has ended, drop it from future selection + indices_to_drop.append(i) + else: + # a candidate partial training run to continue + target_fidelity = config.fidelity.value + horizon + config.fidelity.value = min(config.fidelity.value + horizon, config.fidelity.upper) # if horizon exceeds max, query at max + inc_list.append(inc_value) + else: + # a candidate new training run that we would need to start + current_fidelity = 0 + config.fidelity.value = horizon + inc_list.append(inc_value) + #print(f"- {x.index.values[i]}: {current_fidelity} --> {config.fidelity.value}") + + # Drop unused configs + x.drop(labels=indices_to_drop, inplace=True) + + assert len(inc_list) == len(x) + + return x, torch.Tensor(inc_list) + + +class MFPI_Random_HiT(MFPI): + + BUDGET = 1000 + + def set_state( + self, + pipeline_space: SearchSpace, + surrogate_model: Any, + observations: MFObservedData, + b_step: Union[int, float], + **kwargs, + ): + # set RNG + self.rng = np.random.RandomState(seed=42) + for i in range(len(observations.completed_runs)): + self.rng.uniform(-4,0) + self.rng.randint(1,51) + + return super().set_state(pipeline_space, surrogate_model, observations, b_step) + + def sample_horizon(self, steps_passed): + shortest = self.pipeline_space.fidelity.lower + longest = min(self.pipeline_space.fidelity.upper, self.BUDGET - steps_passed) + return self.rng.randint(shortest, longest+1) + + def sample_threshold(self, f_inc): + lu = 10**self.rng.uniform(-4,0) # % of gap closed + return f_inc * (1 - lu) + + def preprocess(self, x: pd.Series) -> Tuple[pd.Series, torch.Tensor]: + """Prepares the configurations for appropriate EI calculation. + + Takes a set of points and computes the budget and incumbent for each point, as + required by the multi-fidelity Expected Improvement acquisition function. + """ + if self.pipeline_space.has_tabular: + # preprocess tabular space differently + # expected input: IDs pertaining to the tabular data + x = map_real_hyperparameters_from_tabular_ids(x, self.pipeline_space) + + + indices_to_drop = [] + inc_list = [] + + steps_passed = len(self.observations.completed_runs) + print(f"Steps acquired: {steps_passed}") + + # Like EI-AtMax, use the global incumbent as a basis for the EI threshold + inc_value = min(self.observations.get_best_performance_for_each_budget()) + # Extension: Add a random min improvement threshold to encourage high risk high gain + t_value = self.sample_threshold(inc_value) + print(f"Threshold for EI: {inc_value - t_value}") + inc_value = t_value + + # Like MFEI: set fidelities to query using horizon as self.b_step + # Extension: Unlike DyHPO, we sample the horizon randomly over the full range + horizon = self.sample_horizon(steps_passed) + print(f"Horizon for EI: {horizon}") + for i, config in x.items(): + if i <= max(self.observations.seen_config_ids): + current_fidelity = config.fidelity.value + if np.equal(config.fidelity.value, config.fidelity.upper): + # this training run has ended, drop it from future selection + indices_to_drop.append(i) + else: + # a candidate partial training run to continue + target_fidelity = config.fidelity.value + horizon + config.fidelity.value = min(config.fidelity.value + horizon, config.fidelity.upper) # if horizon exceeds max, query at max + inc_list.append(inc_value) + else: + # a candidate new training run that we would need to start + current_fidelity = 0 + config.fidelity.value = horizon + inc_list.append(inc_value) + #print(f"- {x.index.values[i]}: {current_fidelity} --> {config.fidelity.value}") + + # Drop unused configs + x.drop(labels=indices_to_drop, inplace=True) + + assert len(inc_list) == len(x) + + return x, torch.Tensor(inc_list) diff --git a/neps/optimizers/bayesian_optimization/acquisition_functions/mf_two_step.py b/neps/optimizers/bayesian_optimization/acquisition_functions/mf_two_step.py new file mode 100644 index 00000000..3c9b3524 --- /dev/null +++ b/neps/optimizers/bayesian_optimization/acquisition_functions/mf_two_step.py @@ -0,0 +1,238 @@ +import numpy as np +import pandas as pd +from typing import Any, Tuple, Union + +from ....search_spaces.search_space import SearchSpace +from ...multi_fidelity.utils import MFObservedData +from .base_acquisition import BaseAcquisition +from .mf_ei import MFEI, MFEI_Dyna +from .mf_ucb import MF_UCB_Dyna + + +class MF_TwoStep(BaseAcquisition): + """ 2-step acquisition: employs 3 different acquisition calls. + """ + + # HYPER-PARAMETERS: Going with the Freeze-Thaw BO (Swersky et al. 2014) values + N_PARTIAL = 10 + N_NEW = 3 + + def __init__(self, + pipeline_space: SearchSpace, + surrogate_model_name: str = None, + beta: float=1.0, + maximize: bool=False, + augmented_ei: bool = False, + xi: float = 0.0, + in_fill: str = "best", + log_ei: bool = False, + ): + """Upper Confidence Bound (UCB) acquisition function. + + Args: + beta: Controls the balance between exploration and exploitation. + maximize: If True, maximize the given model, else minimize. + DEFAULT=False, assumes minimzation. + """ + super().__init__() + # Acquisition 1: For trimming down partial candidate set + self.acq_partial_filter = MFEI_Dyna_PartialFilter( # defined below + pipeline_space=pipeline_space, + surrogate_model_name=surrogate_model_name, + augmented_ei=augmented_ei, + xi=xi, + in_fill=in_fill, + log_ei=log_ei + ) + # Acquisition 2: For trimming down new candidate set + self.acq_new_filter = MFEI( + pipeline_space=pipeline_space, + surrogate_model_name=surrogate_model_name, + augmented_ei=augmented_ei, + xi=xi, + in_fill=in_fill, + log_ei=log_ei + ) + # Acquisition 3: For final selection of winners from Acquisitions 1 & 2 + self.acq_combined = MF_UCB_Dyna( + pipeline_space=pipeline_space, + surrogate_model_name=surrogate_model_name, + beta=beta, + maximize=maximize + ) + self.pipeline_space = pipeline_space + self.surrogate_model_name = surrogate_model_name + self.surrogate_model = None + self.observations = None + self.b_step = None + + def set_state( + self, + pipeline_space: SearchSpace, + surrogate_model: Any, + observations: MFObservedData, + b_step: Union[int, float], + **kwargs, + ): + # overload to select incumbent differently through observations + self.pipeline_space = pipeline_space + self.surrogate_model = surrogate_model + self.observations = observations + self.b_step = b_step + self.acq_partial_filter.set_state( + self.pipeline_space, + self.surrogate_model, + self.observations, + self.b_step + ) + self.acq_new_filter.set_state( + self.pipeline_space, + self.surrogate_model, + self.observations, + self.b_step + ) + self.acq_combined.set_state( + self.pipeline_space, + self.surrogate_model, + self.observations, + self.b_step + ) + + def eval(self, x: pd.Series, asscalar: bool = False) -> Tuple[np.ndarray, pd.Series]: + # Filter self.N_NEW among the new configuration IDs + # Filter self.N_PARTIAL among the partial configuration IDs + max_seen_id = max(self.observations.seen_config_ids) + total_seen_id = len(self.observations.seen_config_ids) + new_ids = x.index[x.index > max_seen_id].values + partial_ids = x.index[x.index <= max_seen_id].values + + # for new candidate set + acq, _samples = self.acq_new_filter.eval(x, asscalar=True) + acq = pd.Series(acq, index=_samples.index) + # drop partial configurations + acq.loc[_samples.index.values <= max_seen_id] = 0 + # NOTE: setting to 0 works as EI-based AF returns > 0 + # find configs not in top-N_NEW set as per acquisition value, to be dropped + not_top_new_idx = acq.sort_values().index[:-self.N_NEW] # len(acq) - N_NEW + # drop these configurations + acq.loc[not_top_new_idx] = 0 # to ignore in the argmax of the acquisition function + # NOTE: setting to 0 works as EI-based AF returns > 0 + # result of first round of filtering of new candidates + + acq_new_mask = pd.Series({ + idx: val for idx, val in _samples.items() if acq.loc[idx] > 0 + }) + # for partial candidate set + acq, _samples = self.acq_partial_filter.eval(x, asscalar=True) + acq = pd.Series(acq, index=_samples.index) + # weigh the acq value based on max seen for each config + acq = self._weigh_partial_acq_scores(acq=acq) + # drop new configurations + acq.loc[_samples.index.values > max_seen_id] = 0 # to ignore in the argmax of the acquisition function + # find configs not in top-N_NEW set as per acquisition value + _top_n_partial = min(self.N_PARTIAL, total_seen_id) + not_top_new_idx = acq.sort_values().index[:-_top_n_partial] # acq.argsort()[::-1][_top_n_partial:] # sorts in ascending-flips-leaves out top-N_PARTIAL + # drop these configurations + acq.loc[not_top_new_idx] = 0 # to ignore in the argmax of the acquisition function + # NOTE: setting to 0 works as EI-based AF returns > 0 + # result of first round of filtering of partial candidates + acq_partial_mask = pd.Series({ + idx: val for idx, val in _samples.items() if acq.loc[idx] > 0 + }) + + eligible_set = set( + np.concatenate([ + acq_partial_mask.index.values.tolist(), + acq_new_mask.index.values.tolist() + ]) + ) + + # for combined selection + acq, _samples = self.acq_combined.eval(x, asscalar=True) + acq = pd.Series(acq, index=_samples.index) + # applying mask from step-1 to make final selection among (N_NEW + N_PARTIAL) + mask = acq.index.isin(eligible_set) + # NOTE: setting to -np.inf works as MF-UCB here is max.(-LCB) instead of min.(LCB) + acq[~mask] = -np.inf # will be ignored in the argmax of the acquisition function + acq_combined = pd.Series({ + idx: acq.loc[idx] for idx, val in _samples.items() if acq.loc[idx] != -np.inf + }) + # NOTE: setting to -np.inf works as MF-UCB here is max.(-LCB) instead of min.(LCB) + acq_combined = acq_combined.reindex(acq.index, fill_value=-np.inf) + acq = acq_combined.values + + return acq, _samples + + def _weigh_partial_acq_scores(self, acq: pd.Series) -> pd.Series: + # find the best performance per configuration seen + inc_list_partial = self.observations.get_best_performance_per_config() + + # removing any config indicey that have not made it till here + _idx_drop = [_i for _i in inc_list_partial.index if _i not in acq.index] + inc_list_partial.drop(labels=_idx_drop, inplace=True) + + # normalize the scores based on relative best seen performance per config + _inc, _max = inc_list_partial.min(), inc_list_partial.max() + inc_list_partial = ( + (inc_list_partial - _inc) / (_max - _inc) if _inc < _max else inc_list_partial + ) + + # calculate weights per candidate + weights = pd.Series(1 - inc_list_partial, index=inc_list_partial.index) + + # scaling the acquisition score with weights + acq = acq * weights + + return acq + + +class MFEI_PartialFilter(MFEI): + """Custom redefinition of MF-EI with Dynamic extrapolation length to adjust incumbents. + """ + + def preprocess_inc_list(self, **kwargs) -> list: + # the assertion exists to forcibly check the call to the super().preprocess() + # this function overload should only affect the operation inside it + assert "budget_list" in kwargs, "Requires the length of the candidate set." + # we still need this as placeholder for the new candidate set + # in this class we only work on the partial candidate set + inc_list = super().preprocess_inc_list(budget_list=kwargs["budget_list"]) + + n_partial = len(self.observations.seen_config_ids) + + # NOTE: Here we set the incumbent for EI calculation for each config to the + # maximum it has seen, in a bid to get an expected improvement over its previous + # observed score. This could act as a filter to diverging configurations even if + # their overall score relative to the incumbent can be high. + inc_list_partial = self.observations.get_best_performance_per_config() + # updating incumbent for EI computation for the partial configs + inc_list[:n_partial] = inc_list_partial + + return inc_list + + +class MFEI_Dyna_PartialFilter(MFEI_Dyna): + """Custom redefinition of MF-EI with Dynamic extrapolation length to adjust incumbents. + """ + + def preprocess_inc_list(self, **kwargs) -> list: + # the assertion exists to forcibly check the call to the super().preprocess() + # this function overload should only affect the operation inside it + assert "len_x" in kwargs, "Requires the length of the candidate set." + # we still need this as placeholder for the new candidate set + # in this class we only work on the partial candidate set + inc_list = super().preprocess_inc_list(len_x=kwargs["len_x"]) + + n_partial = len(self.observations.seen_config_ids) + + # NOTE: Here we set the incumbent for EI calculation for each config to the + # maximum it has seen, in a bid to get an expected improvement over its previous + # observed score. This could act as a filter to diverging configurations even if + # their overall score relative to the incumbent can be high. + inc_list_partial = self.observations.get_best_performance_per_config() + + # updating incumbent for EI computation for the partial configs + inc_list[:n_partial] = inc_list_partial + + return inc_list + \ No newline at end of file diff --git a/neps/optimizers/bayesian_optimization/acquisition_functions/mf_ucb.py b/neps/optimizers/bayesian_optimization/acquisition_functions/mf_ucb.py new file mode 100644 index 00000000..6bf1dc94 --- /dev/null +++ b/neps/optimizers/bayesian_optimization/acquisition_functions/mf_ucb.py @@ -0,0 +1,230 @@ +from typing import Any, Iterable, Tuple, Union + +import numpy as np +import pandas as pd +import torch + +from ....optimizers.utils import map_real_hyperparameters_from_tabular_ids +from ....search_spaces.search_space import IntegerParameter, SearchSpace +from ...multi_fidelity.utils import MFObservedData +from .mf_ei import MFStepBase +from .ucb import UpperConfidenceBound + + +# NOTE: the order of inheritance is important +class MF_UCB(MFStepBase, UpperConfidenceBound): + def __init__(self, + pipeline_space: SearchSpace, + surrogate_model_name: str = None, + beta: float=1.0, + maximize: bool=False + ): + """Upper Confidence Bound (UCB) acquisition function. + + Args: + beta: Controls the balance between exploration and exploitation. + maximize: If True, maximize the given model, else minimize. + DEFAULT=False, assumes minimzation. + """ + super().__init__(beta, maximize) + self.pipeline_space = pipeline_space + self.surrogate_model_name = surrogate_model_name + self.surrogate_model = None + self.observations = None + self.b_step = None + + def preprocess(self, x: pd.Series) -> Tuple[pd.Series, torch.Tensor]: + """Prepares the configurations for appropriate EI calculation. + + Takes a set of points and computes the budget and incumbent for each point, as + required by the multi-fidelity Expected Improvement acquisition function. + """ + budget_list = [] + if self.pipeline_space.has_tabular: + # preprocess tabular space differently + # expected input: IDs pertaining to the tabular data + x = map_real_hyperparameters_from_tabular_ids(x, self.pipeline_space) + + indices_to_drop = [] + betas = [] + for i, config in x.items(): + target_fidelity = config.fidelity.lower + if i <= max(self.observations.seen_config_ids): + # IMPORTANT to set the fidelity at which EI will be calculated only for + # the partial configs that have been observed already + target_fidelity = config.fidelity.value + self.b_step + if np.less_equal(target_fidelity, config.fidelity.upper): + # only consider the configs with fidelity lower than the max fidelity + config.fidelity.value = target_fidelity + budget_list.append(self.get_budget_level(config)) + # CAN ADAPT BETA PER-SAMPLE HERE + betas.append(self.beta) + else: + # if the target_fidelity higher than the max drop the configuration + indices_to_drop.append(i) + else: + config.fidelity.value = target_fidelity + budget_list.append(self.get_budget_level(config)) + # CAN ADAPT BETA PER-SAMPLE HERE + betas.append(self.beta) + + # Drop unused configs + x.drop(labels=indices_to_drop, inplace=True) + + return x, torch.Tensor(betas) + + def preprocess_gp( + self, x: pd.Series, surrogate_name: str = "gp" + ) -> Tuple[pd.Series, torch.Tensor]: + if surrogate_name == "gp": + x, inc_list = self.preprocess(x) + return x, inc_list + elif surrogate_name in ["deep_gp", "dpl"]: + x, inc_list = self.preprocess(x) + x_lcs = [] + for idx in x.index: + if idx in self.observations.df.index.levels[0]: + # extracting the available/observed learning curve + lc = self.observations.extract_learning_curve(idx, budget_id=None) + else: + # initialize a learning curve with a placeholder + # This is later padded accordingly for the Conv1D layer + lc = [] + x_lcs.append(lc) + self.surrogate_model.set_prediction_learning_curves(x_lcs) + return x, inc_list + else: + raise ValueError( + f"Unrecognized surrogate model name: {surrogate_name}" + ) + + def eval_pfn_ucb( + self, x: Iterable, beta: float=(1-.682)/2 + ) -> Union[np.ndarray, torch.Tensor, float]: + """PFN-UCB modified to preprocess samples and accept list of incumbents.""" + ucb = self.surrogate_model.get_ucb( + x_test=x.to(self.surrogate_model.device), + beta=beta # TODO: extend to have different betas for each candidates in x + ) + if len(ucb.shape) == 2: + ucb = ucb.flatten() + return ucb + + def eval(self, x: pd.Series, asscalar: bool = False) -> Tuple[np.ndarray, pd.Series]: + if self.surrogate_model_name == "pfn": + _x, _x_tok, _ = self.preprocess_pfn( + x.copy() + ) + ucb = self.eval_pfn_ucb(_x_tok) + elif self.surrogate_model_name in ["deep_gp", "gp", "dpl"]: + _x, betas = self.preprocess_gp( + x.copy(), + self.surrogate_model_name + ) + ucb = super().eval(_x.values.tolist(), betas, asscalar) + else: + raise ValueError( + f"Unrecognized surrogate model name: {self.surrogate_model_name}" + ) + + return ucb, _x + + +class MF_UCB_AtMax(MF_UCB): + + def preprocess(self, x: pd.Series) -> Tuple[pd.Series, torch.Tensor]: + """Prepares the configurations for appropriate EI calculation. + + Takes a set of points and computes the budget and incumbent for each point. + Unlike the base class MFEI, sets the target fidelity to be max budget and the + incumbent choice to be the max seen across history for all candidates. + """ + budget_list = [] + if self.pipeline_space.has_tabular: + # preprocess tabular space differently + # expected input: IDs pertaining to the tabular data + x = map_real_hyperparameters_from_tabular_ids(x, self.pipeline_space) + + indices_to_drop = [] + betas = [] + for i, config in x.items(): + target_fidelity = config.fidelity.upper # change from MFEI + + if config.fidelity.value == target_fidelity: + # if the target_fidelity already reached, drop the configuration + indices_to_drop.append(i) + else: + config.fidelity.value = target_fidelity + budget_list.append(self.get_budget_level(config)) + + # CAN ADAPT BETA PER-SAMPLE HERE + betas.append(self.beta) + + # drop unused configs + x.drop(labels=indices_to_drop, inplace=True) + + return x, torch.Tensor(betas) + + +class MF_UCB_Dyna(MF_UCB): + + def preprocess(self, x: pd.Series) -> Tuple[pd.Series, torch.Tensor]: + """Prepares the configurations for appropriate EI calculation. + + Takes a set of points and computes the budget and incumbent for each point. + Unlike the base class MFEI, sets the target fidelity to be max budget and the + incumbent choice to be the max seen across history for all candidates. + """ + if self.pipeline_space.has_tabular: + # preprocess tabular space differently + # expected input: IDs pertaining to the tabular data + x = map_real_hyperparameters_from_tabular_ids(x, self.pipeline_space) + + # find the maximum observed steps per config to obtain the current pseudo_z_max + max_z_level_per_x = self.observations.get_max_observed_fidelity_level_per_config() + pseudo_z_level_max = max_z_level_per_x.max() # highest seen fidelity step so far + # find the fidelity step at which the best seen performance was recorded + z_inc_level = self.observations.get_budget_level_for_best_performance() + # retrieving actual fidelity values from budget level + ## marker 1: the fidelity value at which the best seen performance was recorded + z_inc = self.b_step * z_inc_level + self.pipeline_space.fidelity.lower + ## marker 2: the maximum fidelity value recorded in observation history + pseudo_z_max = self.b_step * pseudo_z_level_max + self.pipeline_space.fidelity.lower + + # TODO: compare with this first draft logic + # def update_fidelity(config): + # ### DO NOT DELETE THIS FUNCTION YET + # # for all configs, set the min(max(current fidelity + step, z_inc), pseudo_z_max) + # ## that is, choose the next highest marker from 1 and 2 + # z_extrapolate = min( + # max(config.fidelity.value + self.b_step, z_inc), + # pseudo_z_max + # ) + # config.fidelity.value = z_extrapolate + # return config + + def update_fidelity(config): + # for all configs, set to pseudo_z_max + ## that is, choose the highest seen fidelity in observation history + z_extrapolate = pseudo_z_max + config.fidelity.value = z_extrapolate + return config + + # collect IDs for partial configurations + _partial_config_ids = (x.index <= max(self.observations.seen_config_ids)) + # filter for configurations that reached max budget + indices_to_drop = [ + _idx + for _idx, _x in x.loc[_partial_config_ids].items() + if _x.fidelity.value == self.pipeline_space.fidelity.upper + ] + # drop unused configs + x.drop(labels=indices_to_drop, inplace=True) + + # set fidelity for all partial configs + x = x.apply(update_fidelity) + + # CAN ADAPT BETA PER-SAMPLE HERE + betas = [self.beta] * len(x) # TODO: have tighter order check to Pd.Series index + + return x, torch.Tensor(betas) diff --git a/src/neps/optimizers/bayesian_optimization/acquisition_functions/prior_weighted.py b/neps/optimizers/bayesian_optimization/acquisition_functions/prior_weighted.py similarity index 100% rename from src/neps/optimizers/bayesian_optimization/acquisition_functions/prior_weighted.py rename to neps/optimizers/bayesian_optimization/acquisition_functions/prior_weighted.py diff --git a/src/neps/optimizers/bayesian_optimization/acquisition_functions/ucb.py b/neps/optimizers/bayesian_optimization/acquisition_functions/ucb.py similarity index 72% rename from src/neps/optimizers/bayesian_optimization/acquisition_functions/ucb.py rename to neps/optimizers/bayesian_optimization/acquisition_functions/ucb.py index adf57266..beba8fa3 100644 --- a/src/neps/optimizers/bayesian_optimization/acquisition_functions/ucb.py +++ b/neps/optimizers/bayesian_optimization/acquisition_functions/ucb.py @@ -1,3 +1,5 @@ +from __future__ import annotations + from typing import Iterable, Union import numpy as np @@ -18,7 +20,7 @@ def __init__(self, beta: float=1.0, maximize: bool=False): super().__init__() self.beta = beta # can be updated as part of the state for dynamism or a schedule self.maximize = maximize - + # to be initialized as part of the state self.surrogate_model = None @@ -30,9 +32,9 @@ def set_state(self, surrogate_model, **kwargs): self.beta = kwargs["beta"] else: self.logger.warning("Beta is a list, not updating beta value!") - + def eval( - self, x: Iterable, asscalar: bool = False + self, x: Iterable, betas: torch.Tensor | None = None, asscalar: bool = False ) -> Union[np.ndarray, torch.Tensor, float]: try: mu, cov = self.surrogate_model.predict(x) @@ -40,21 +42,13 @@ def eval( except ValueError as e: raise e sign = 1 if self.maximize else -1 # LCB is performed if minimize=True - ucb_scores = mu + sign * np.sqrt(self.beta) * std - # if LCB, minimize acquisition, or maximize -acquisition - ucb_scores = ucb_scores.detach().numpy() * sign - - return ucb_scores - - -class MF_UCB(UpperConfidenceBound): - - def preprocess(self, x: Iterable) -> Iterable: - performances = self.observations.get_best_performance_for_each_budget() - pass - - def eval( - self, x: Iterable, asscalar: bool = False - ) -> Union[np.ndarray, torch.Tensor, float]: - x = self.preprocess(x) - return self.eval(x, asscalar=asscalar) + ucb_scores = mu + sign * torch.sqrt(self.beta if betas is None else betas) * std + # if LCB, minimize acquisition, or maximize -acquisition + ucb_scores = ucb_scores * sign + + if ucb_scores.is_cuda: + ucb_scores = ucb_scores.cpu() + if len(x) > 1 and asscalar: + return ucb_scores.detach().numpy() + else: + return ucb_scores.detach().numpy().item() diff --git a/src/neps/optimizers/bayesian_optimization/acquisition_samplers/__init__.py b/neps/optimizers/bayesian_optimization/acquisition_samplers/__init__.py similarity index 100% rename from src/neps/optimizers/bayesian_optimization/acquisition_samplers/__init__.py rename to neps/optimizers/bayesian_optimization/acquisition_samplers/__init__.py diff --git a/src/neps/optimizers/bayesian_optimization/acquisition_samplers/base_acq_sampler.py b/neps/optimizers/bayesian_optimization/acquisition_samplers/base_acq_sampler.py similarity index 100% rename from src/neps/optimizers/bayesian_optimization/acquisition_samplers/base_acq_sampler.py rename to neps/optimizers/bayesian_optimization/acquisition_samplers/base_acq_sampler.py diff --git a/src/neps/optimizers/bayesian_optimization/acquisition_samplers/evolution_sampler.py b/neps/optimizers/bayesian_optimization/acquisition_samplers/evolution_sampler.py similarity index 100% rename from src/neps/optimizers/bayesian_optimization/acquisition_samplers/evolution_sampler.py rename to neps/optimizers/bayesian_optimization/acquisition_samplers/evolution_sampler.py diff --git a/src/neps/optimizers/bayesian_optimization/acquisition_samplers/freeze_thaw_sampler.py b/neps/optimizers/bayesian_optimization/acquisition_samplers/freeze_thaw_sampler.py similarity index 71% rename from src/neps/optimizers/bayesian_optimization/acquisition_samplers/freeze_thaw_sampler.py rename to neps/optimizers/bayesian_optimization/acquisition_samplers/freeze_thaw_sampler.py index abae00b1..1fdb01db 100644 --- a/src/neps/optimizers/bayesian_optimization/acquisition_samplers/freeze_thaw_sampler.py +++ b/neps/optimizers/bayesian_optimization/acquisition_samplers/freeze_thaw_sampler.py @@ -6,6 +6,7 @@ import numpy as np import pandas as pd +import time from ....search_spaces.search_space import SearchSpace from ...multi_fidelity.utils import MFObservedData @@ -13,7 +14,7 @@ class FreezeThawSampler(AcquisitionSampler): - + SAMPLES_TO_DRAW = 100 # number of random samples to draw at lowest fidelity def __init__(self, **kwargs): @@ -106,60 +107,70 @@ def sample( set_new_sample_fidelity: int | float = None, ) -> list(): """Samples a new set and returns the total set of observed + new configs.""" + start = time.time() partial_configs = self.observations.get_partial_configs_at_max_seen() - new_configs = self._sample_new( - index_from=self.observations.next_config_id(), n=n, ignore_fidelity=False - ) - - def __sample_single_new_tabular(index: int): - """ - A function to use in a list comprehension to slightly speed up - the sampling process when self.SAMPLE_TO_DRAW is large - """ - config = self.pipeline_space.sample( - patience=self.patience, user_priors=False, ignore_fidelity=False - ) - config["id"].value = _new_configs[index] - config.fidelity.value = set_new_sample_fidelity - return config + # print("-" * 50) + # print(f"| freeze-thaw:get_partial_at_max_seen(): {time.time()-start:.2f}s") + # print("-" * 50) + _n = n if n is not None else self.SAMPLES_TO_DRAW if self.is_tabular: - _n = n if n is not None else self.SAMPLES_TO_DRAW + # handles tabular data such that the entire unseen set of configs from the + # table is considered to be the new set of candidates _partial_ids = {conf["id"].value for conf in partial_configs} - _all_ids = set(self.pipeline_space.custom_grid_table.index.values) + _all_ids = set(list(self.pipeline_space.custom_grid_table.keys())) # accounting for unseen configs only, samples remaining table if flag is set max_n = len(_all_ids) + 1 if self.sample_full_table else _n _n = min(max_n, len(_all_ids - _partial_ids)) - + + start = time.time() _new_configs = np.random.choice( list(_all_ids - _partial_ids), size=_n, replace=False ) - new_configs = [__sample_single_new_tabular(i) for i in range(_n)] + placeholder_config = self.pipeline_space.sample( + patience=self.patience, user_priors=False, ignore_fidelity=False + ) + _configs = [deepcopy(placeholder_config) for _id in _new_configs] + for _i, val in enumerate(_new_configs): + _configs[_i]["id"].value = val + + # print("-" * 50) + # print(f"| freeze-thaw:sample:new_configs_extraction: {time.time()-start:.2f}s") + # print("-" * 50) new_configs = pd.Series( - new_configs, + _configs, index=np.arange( - len(partial_configs), len(partial_configs) + len(new_configs) + len(partial_configs), len(partial_configs) + len(_new_configs) ), ) + else: + # handles sampling new configurations for continuous spaces + new_configs = self._sample_new( + index_from=self.observations.next_config_id(), n=_n, ignore_fidelity=False + ) + # Continuous benchmarks need to deepcopy individual configs here, + # because in contrast to tabular benchmarks + # they are not reset in every sampling step + partial_configs = pd.Series( + [deepcopy(p_config_) for idx, p_config_ in partial_configs.items()], + index=partial_configs.index + ) - elif set_new_sample_fidelity is not None: + # Updating fidelity values + start = time.time() + if set_new_sample_fidelity is not None: for config in new_configs: config.fidelity.value = set_new_sample_fidelity + # print("-" * 50) + # print(f"| freeze-thaw:sample:new_configs_set_fidelity: {time.time()-start:.2f}s") + # print("-" * 50) - # Deep copy configs for fidelity updates - partial_configs_list = [] - index_list = [] - for idx, config in partial_configs.items(): - _config = deepcopy(config) - partial_configs_list.append(_config) - index_list.append(idx) - - # We build a new series of partial configs to avoid - # incrementing fidelities multiple times due to pass-by-reference - partial_configs = pd.Series(partial_configs_list, index=index_list) - - configs = pd.concat([partial_configs, new_configs]) + start = time.time() + configs = pd.concat([deepcopy(partial_configs), new_configs]) + # print("-" * 50) + # print(f"| freeze-thaw:sample:concat_configs: {time.time()-start:.2f}s") + # print("-" * 50) return configs @@ -180,3 +191,4 @@ def set_state( and self.pipeline_space.custom_grid_table is not None ): self.is_tabular = True + self.set_sample_full_tabular(True) diff --git a/src/neps/optimizers/bayesian_optimization/acquisition_samplers/mutation_sampler.py b/neps/optimizers/bayesian_optimization/acquisition_samplers/mutation_sampler.py similarity index 100% rename from src/neps/optimizers/bayesian_optimization/acquisition_samplers/mutation_sampler.py rename to neps/optimizers/bayesian_optimization/acquisition_samplers/mutation_sampler.py diff --git a/src/neps/optimizers/bayesian_optimization/acquisition_samplers/random_sampler.py b/neps/optimizers/bayesian_optimization/acquisition_samplers/random_sampler.py similarity index 100% rename from src/neps/optimizers/bayesian_optimization/acquisition_samplers/random_sampler.py rename to neps/optimizers/bayesian_optimization/acquisition_samplers/random_sampler.py diff --git a/src/neps/optimizers/bayesian_optimization/cost_cooling.py b/neps/optimizers/bayesian_optimization/cost_cooling.py similarity index 99% rename from src/neps/optimizers/bayesian_optimization/cost_cooling.py rename to neps/optimizers/bayesian_optimization/cost_cooling.py index 7a565ce8..8077dced 100644 --- a/src/neps/optimizers/bayesian_optimization/cost_cooling.py +++ b/neps/optimizers/bayesian_optimization/cost_cooling.py @@ -2,8 +2,7 @@ from typing import Any -from metahyper import ConfigResult, instance_from_map - +from ...metahyper import ConfigResult, instance_from_map from ...optimizers.bayesian_optimization.acquisition_functions.cost_cooling import ( CostCooler, ) diff --git a/src/neps/optimizers/bayesian_optimization/kernels/__init__.py b/neps/optimizers/bayesian_optimization/kernels/__init__.py similarity index 100% rename from src/neps/optimizers/bayesian_optimization/kernels/__init__.py rename to neps/optimizers/bayesian_optimization/kernels/__init__.py diff --git a/src/neps/optimizers/bayesian_optimization/kernels/combine_kernels.py b/neps/optimizers/bayesian_optimization/kernels/combine_kernels.py similarity index 99% rename from src/neps/optimizers/bayesian_optimization/kernels/combine_kernels.py rename to neps/optimizers/bayesian_optimization/kernels/combine_kernels.py index 833602e2..849198ca 100644 --- a/src/neps/optimizers/bayesian_optimization/kernels/combine_kernels.py +++ b/neps/optimizers/bayesian_optimization/kernels/combine_kernels.py @@ -51,7 +51,6 @@ def fit_transform( ): N = len(configs) K = torch.zeros(N, N) if self.combined_by == "sum" else torch.ones(N, N) - gr1, x1 = extract_configs(configs) for i, k in enumerate(self.kernels): diff --git a/src/neps/optimizers/bayesian_optimization/kernels/combine_kernels_hierarchy.py b/neps/optimizers/bayesian_optimization/kernels/combine_kernels_hierarchy.py similarity index 100% rename from src/neps/optimizers/bayesian_optimization/kernels/combine_kernels_hierarchy.py rename to neps/optimizers/bayesian_optimization/kernels/combine_kernels_hierarchy.py diff --git a/src/neps/optimizers/bayesian_optimization/kernels/encoding.py b/neps/optimizers/bayesian_optimization/kernels/encoding.py similarity index 100% rename from src/neps/optimizers/bayesian_optimization/kernels/encoding.py rename to neps/optimizers/bayesian_optimization/kernels/encoding.py diff --git a/src/neps/optimizers/bayesian_optimization/kernels/get_kernels.py b/neps/optimizers/bayesian_optimization/kernels/get_kernels.py similarity index 97% rename from src/neps/optimizers/bayesian_optimization/kernels/get_kernels.py rename to neps/optimizers/bayesian_optimization/kernels/get_kernels.py index acce8d41..eb4069af 100644 --- a/src/neps/optimizers/bayesian_optimization/kernels/get_kernels.py +++ b/neps/optimizers/bayesian_optimization/kernels/get_kernels.py @@ -1,7 +1,6 @@ from __future__ import annotations -from metahyper import instance_from_map - +from ....metahyper import instance_from_map from ....search_spaces.architecture.core_graph_grammar import CoreGraphGrammar from ....search_spaces.hyperparameters.categorical import CategoricalParameter from ....search_spaces.hyperparameters.float import FloatParameter diff --git a/src/neps/optimizers/bayesian_optimization/kernels/grakel_replace/edge_histogram.py b/neps/optimizers/bayesian_optimization/kernels/grakel_replace/edge_histogram.py similarity index 100% rename from src/neps/optimizers/bayesian_optimization/kernels/grakel_replace/edge_histogram.py rename to neps/optimizers/bayesian_optimization/kernels/grakel_replace/edge_histogram.py diff --git a/src/neps/optimizers/bayesian_optimization/kernels/grakel_replace/utils.py b/neps/optimizers/bayesian_optimization/kernels/grakel_replace/utils.py similarity index 100% rename from src/neps/optimizers/bayesian_optimization/kernels/grakel_replace/utils.py rename to neps/optimizers/bayesian_optimization/kernels/grakel_replace/utils.py diff --git a/src/neps/optimizers/bayesian_optimization/kernels/grakel_replace/vertex_histogram.py b/neps/optimizers/bayesian_optimization/kernels/grakel_replace/vertex_histogram.py similarity index 100% rename from src/neps/optimizers/bayesian_optimization/kernels/grakel_replace/vertex_histogram.py rename to neps/optimizers/bayesian_optimization/kernels/grakel_replace/vertex_histogram.py diff --git a/src/neps/optimizers/bayesian_optimization/kernels/grakel_replace/weisfeiler_lehman.py b/neps/optimizers/bayesian_optimization/kernels/grakel_replace/weisfeiler_lehman.py similarity index 100% rename from src/neps/optimizers/bayesian_optimization/kernels/grakel_replace/weisfeiler_lehman.py rename to neps/optimizers/bayesian_optimization/kernels/grakel_replace/weisfeiler_lehman.py diff --git a/src/neps/optimizers/bayesian_optimization/kernels/graph_kernel.py b/neps/optimizers/bayesian_optimization/kernels/graph_kernel.py similarity index 100% rename from src/neps/optimizers/bayesian_optimization/kernels/graph_kernel.py rename to neps/optimizers/bayesian_optimization/kernels/graph_kernel.py diff --git a/src/neps/optimizers/bayesian_optimization/kernels/utils.py b/neps/optimizers/bayesian_optimization/kernels/utils.py similarity index 100% rename from src/neps/optimizers/bayesian_optimization/kernels/utils.py rename to neps/optimizers/bayesian_optimization/kernels/utils.py diff --git a/src/neps/optimizers/bayesian_optimization/kernels/vectorial_kernels.py b/neps/optimizers/bayesian_optimization/kernels/vectorial_kernels.py similarity index 100% rename from src/neps/optimizers/bayesian_optimization/kernels/vectorial_kernels.py rename to neps/optimizers/bayesian_optimization/kernels/vectorial_kernels.py diff --git a/src/neps/optimizers/bayesian_optimization/kernels/weisfilerlehman.py b/neps/optimizers/bayesian_optimization/kernels/weisfilerlehman.py similarity index 100% rename from src/neps/optimizers/bayesian_optimization/kernels/weisfilerlehman.py rename to neps/optimizers/bayesian_optimization/kernels/weisfilerlehman.py diff --git a/src/neps/optimizers/bayesian_optimization/mf_tpe.py b/neps/optimizers/bayesian_optimization/mf_tpe.py similarity index 99% rename from src/neps/optimizers/bayesian_optimization/mf_tpe.py rename to neps/optimizers/bayesian_optimization/mf_tpe.py index eeb37831..f705f9f0 100644 --- a/src/neps/optimizers/bayesian_optimization/mf_tpe.py +++ b/neps/optimizers/bayesian_optimization/mf_tpe.py @@ -9,8 +9,7 @@ from scipy.stats import spearmanr from typing_extensions import Literal -from metahyper import ConfigResult, instance_from_map - +from ...metahyper import ConfigResult, instance_from_map from ...search_spaces import ( CategoricalParameter, ConstantParameter, diff --git a/neps/optimizers/bayesian_optimization/models/DPL.py b/neps/optimizers/bayesian_optimization/models/DPL.py new file mode 100644 index 00000000..82bd78c1 --- /dev/null +++ b/neps/optimizers/bayesian_optimization/models/DPL.py @@ -0,0 +1,834 @@ +from __future__ import annotations + +from copy import deepcopy +import logging +import os +import time +from typing import List, Tuple, Any, Type + +import numpy as np + +from scipy.stats import norm +from pathlib import Path +import torch +import torch.nn as nn + +from neps.search_spaces.search_space import ( + CategoricalParameter, + FloatParameter, + IntegerParameter, + SearchSpace, +) + +from neps.optimizers.multi_fidelity.utils import MFObservedData + + +# TODO: Move to utils +def get_optimizer_losses(root_directory: Path | str) -> list[float]: + all_losses_file = root_directory / "all_losses_and_configs.txt" + + # Read all losses from the file in the order they are explored + losses = [ + float(line[6:]) + for line in all_losses_file.read_text(encoding="utf-8").splitlines() + if "Loss: " in line + ] + return losses + + +def get_best_loss(root_directory: Path | str) -> float: + root_directory = Path(root_directory) + best_loss_fiel = root_directory / "best_loss_trajectory.txt" + + # Get the best seen loss value + best_loss = float(best_loss_fiel.read_text(encoding="utf-8").splitlines()[-1].strip()) + + return best_loss + + +class ConditionedPowerLaw(nn.Module): + + def __init__( + self, + nr_initial_features=10, + nr_units=200, + nr_layers=3, + use_learning_curve: bool = True, + kernel_size: int = 3, + nr_filters: int = 4, + nr_cnn_layers: int = 2, + ): + """ + Args: + nr_initial_features: int + The number of features per example. + nr_units: int + The number of units for every layer. + nr_layers: int + The number of layers for the neural network. + use_learning_curve: bool + If the learning curve should be use in the network. + kernel_size: int + The size of the kernel that is applied in the cnn layer. + nr_filters: int + The number of filters that are used in the cnn layers. + nr_cnn_layers: int + The number of cnn layers to be used. + """ + super(ConditionedPowerLaw, self).__init__() + + self.use_learning_curve = use_learning_curve + self.kernel_size = kernel_size + self.nr_filters = nr_filters + self.nr_cnn_layers = nr_cnn_layers + + self.act_func = torch.nn.LeakyReLU() + self.last_act_func = torch.nn.GLU() + self.tan_func = torch.nn.Tanh() + self.batch_norm = torch.nn.BatchNorm1d + + layers = [] + # adding one since we concatenate the features with the budget + nr_initial_features = nr_initial_features + if self.use_learning_curve: + nr_initial_features = nr_initial_features + nr_filters + + layers.append(nn.Linear(nr_initial_features, nr_units)) + layers.append(self.act_func) + + for i in range(2, nr_layers + 1): + layers.append(nn.Linear(nr_units, nr_units)) + layers.append(self.act_func) + + last_layer = nn.Linear(nr_units, 3) + layers.append(last_layer) + + self.layers = torch.nn.Sequential(*layers) + + cnn_part = [] + if use_learning_curve: + cnn_part.append( + nn.Conv1d( + in_channels=2, + kernel_size=(self.kernel_size,), + out_channels=self.nr_filters, + ), + ) + for i in range(1, self.nr_cnn_layers): + cnn_part.append(self.act_func) + cnn_part.append( + nn.Conv1d( + in_channels=self.nr_filters, + kernel_size=(self.kernel_size,), + out_channels=self.nr_filters, + ), + ), + cnn_part.append(nn.AdaptiveAvgPool1d(1)) + + self.cnn = nn.Sequential(*cnn_part) + + def forward( + self, + x: torch.Tensor, + predict_budgets: torch.Tensor, + evaluated_budgets: torch.Tensor, + learning_curves: torch.Tensor, + ): + """ + Args: + x: torch.Tensor + The examples. + predict_budgets: torch.Tensor + The budgets for which the performance will be predicted for the + hyperparameter configurations. + evaluated_budgets: torch.Tensor + The budgets for which the hyperparameter configurations have been + evaluated so far. + learning_curves: torch.Tensor + The learning curves for the hyperparameter configurations. + """ + # print(x.shape) + # print(learning_curves.shape) + # x = torch.cat((x, torch.unsqueeze(evaluated_budgets, 1)), dim=1) + if self.use_learning_curve: + lc_features = self.cnn(learning_curves) + # print(lc_features.shape) + # revert the output from the cnn into nr_rows x nr_kernels. + lc_features = torch.squeeze(lc_features, 2) + # print(lc_features) + x = torch.cat((x, lc_features), dim=1) + # print(x.shape) + if torch.any(torch.isnan(x)): + raise ValueError("NaN values in input, the network probably diverged") + x = self.layers(x) + alphas = x[:, 0] + betas = x[:, 1] + gammas = x[:, 2] + # print(x) + output = torch.add( + alphas, + torch.mul( + self.last_act_func(torch.cat((betas, betas))), + torch.pow( + predict_budgets, + torch.mul(self.last_act_func(torch.cat((gammas, gammas))), -1) + ) + ), + ) + + return output + + +ModelClass = ConditionedPowerLaw + +MODEL_MAPPING: dict[str, Type[ModelClass]] = {"power_law": ConditionedPowerLaw} + + +class PowerLawSurrogate: + # defaults to be used for functions + # fit params + default_lr = 0.001 + default_batch_size = 64 + default_nr_epochs = 250 + default_refine_epochs = 20 + default_early_stopping = False + default_early_stopping_patience = 10 + + # init params + default_n_initial_full_trainings = 10 + default_n_models = 5 + default_model_config = dict(nr_units=128, + nr_layers=2, + use_learning_curve=False, + kernel_size=3, + nr_filters=4, + nr_cnn_layers=2) + + # fit+predict params + default_padding_type = "zero" + default_budget_normalize = True + default_use_min_budget = False + default_y_normalize = False + + + # Defined in __init__(...) + default_no_improvement_patience = ... + def __init__( + self, + pipeline_space: SearchSpace, + observed_data: MFObservedData | None = None, + logger=None, + surrogate_model_fit_args: dict | None = None, + # IMPORTANT: Checkpointing does not use file locking, + # IMPORTANT: hence, it is not suitable for multiprocessing settings + # IMPORTANT: For parallel runs lock the checkpoint file during the whole training + checkpointing: bool = False, + root_directory: Path | str | None = None, + # IMPORTANT: For parallel runs use a different checkpoint_file name for each + # IMPORTANT: surrogate. This makes sure that parallel runs don't override each + # IMPORTANT: others saved checkpoint. Although they will still have some conflicts due to + # IMPORTANT: global optimizer step tracking + checkpoint_file: Path | str = "surrogate_checkpoint.pth", + refine_epochs: int = default_refine_epochs, + n_initial_full_trainings: int = default_n_initial_full_trainings, + default_model_class: str = "power_law", + default_model_config: dict[str, Any] = default_model_config, + n_models: int = default_n_models, + model_classes: list[str] | None = None, + model_configs: list[dict[str, Any]] | None = None, + refine_batch_size: int | None = None + ): + if pipeline_space.has_tabular: + self.cover_pipeline_space = pipeline_space + self.real_pipeline_space = pipeline_space.raw_tabular_space + else: + self.cover_pipeline_space = pipeline_space + self.real_pipeline_space = pipeline_space + # self.pipeline_space = pipeline_space + + self.observed_data = observed_data + self.__preprocess_search_space(self.real_pipeline_space) + self.seeds = np.random.choice(100, n_models, replace=False) + self.model_configs = [dict( + nr_initial_features=self.input_size, **default_model_config)] * n_models if not model_configs else model_configs + self.model_classes = [MODEL_MAPPING[default_model_class]] * n_models \ + if not model_classes \ + else [MODEL_MAPPING[m_class] for m_class in model_classes] + self.device = "cpu" + self.models: list[ModelClass] = [self.__initialize_model(config, + self.model_classes[ + index], + self.device) + for index, config in + enumerate(self.model_configs)] + + self.checkpointing = checkpointing + self.refine_epochs = refine_epochs + self.refine_batch_size = refine_batch_size + self.n_initial_full_trainings = n_initial_full_trainings + self.default_no_improvement_patience = int(self.max_fidelity + + 0.2 * self.max_fidelity) + + if checkpointing: + assert ( + root_directory is not None + ), "neps root_directory must be provided for the checkpointing" + self.root_dir = Path(os.getcwd(), root_directory) + self.checkpoint_path = Path(os.getcwd(), root_directory, checkpoint_file) + + self.surrogate_model_fit_args = ( + surrogate_model_fit_args if surrogate_model_fit_args is not None else {} + ) + + if self.surrogate_model_fit_args.get("no_improvement_patience", None) is None: + # To replicate how the original DPL implementation handles the + # no_improvement_threshold + self.surrogate_model_fit_args["no_improvement_patience"] = ( + self.default_no_improvement_patience) + + self.categories_array = np.array(self.categories) + + self.best_state = None + self.prediction_learning_curves = None + + self.criterion = torch.nn.L1Loss() + + self.logger = logger or logging.getLogger("neps") + + def __preprocess_search_space(self, pipeline_space: SearchSpace): + self.categories = [] + self.categorical_hps = [] + + parameter_count = 0 + for hp_name, hp in pipeline_space.items(): + # Collect all categories in a list for the encoder + if hp.is_fidelity: + continue # Ignore fidelity + if isinstance(hp, CategoricalParameter): + self.categorical_hps.append(hp_name) + self.categories.extend(hp.choices) + parameter_count += len(hp.choices) + else: + parameter_count += 1 + + # add 1 for budget + self.input_size = parameter_count + self.continuous_params_size = self.input_size - len(self.categories) + self.min_fidelity = pipeline_space.fidelity.lower + self.max_fidelity = pipeline_space.fidelity.upper + + def __encode_config(self, config: SearchSpace) -> np.ndarray: + categorical_encoding = np.zeros_like(self.categories_array, dtype=np.single) + continuous_values = [] + + for hp_name, hp in config.items(): + if hp.is_fidelity: + continue # Ignore fidelity + if hp_name in self.categorical_hps: + label = hp.value + categorical_encoding[np.argwhere(self.categories_array == label)] = 1 + else: + continuous_values.append(hp.normalized().value) + + continuous_encoding = np.array(continuous_values) + + encoding = np.concatenate([categorical_encoding, continuous_encoding]) + return encoding + + def __normalize_budgets(self, + budgets: np.ndarray, + use_min_budget: bool) -> np.ndarray: + min_budget = self.min_fidelity if use_min_budget else 0 + normalized_budgets = (budgets - min_budget) / ( + self.max_fidelity - min_budget + ) + return normalized_budgets + + def __extract_budgets( + self, x_train: list[SearchSpace], + normalized: bool, + use_min_budget: bool + ) -> np.ndarray: + + budgets = np.array([config.fidelity.value for config in x_train], dtype=np.single) + + if normalized: + budgets = self.__normalize_budgets(budgets, use_min_budget) + return budgets + + def __preprocess_learning_curves( + self, learning_curves: list[list[float]], padding_type: str + ) -> np.ndarray: + # Add padding to the learning curves to make them the same size + existing_values_mask = [] + max_length = self.max_fidelity - 1 + + if padding_type == "last": + init_value = self.__get_mean_initial_value() + else: + init_value = 0.0 + + for lc in learning_curves: + if len(lc) == 0: + padding_value = init_value + elif padding_type == "last": + padding_value = lc[-1] + else: + padding_value = 0.0 + + padding_length = int(max_length - len(lc)) + + mask = [1] * len(lc) + [0] * padding_length + existing_values_mask.append(mask) + + lc.extend([padding_value] * padding_length) + # print(learning_curves) + learning_curves = np.array(learning_curves, dtype=np.single) + existing_values_mask = np.array(existing_values_mask, dtype=np.single) + + learning_curves = np.stack((learning_curves, existing_values_mask), axis=1) + + return learning_curves + + def __reset_xy( + self, + x_train: list[SearchSpace], + y_train: list[float], + learning_curves: list[list[float]], + normalize_y: bool = default_y_normalize, + normalize_budget: bool = default_budget_normalize, + use_min_budget: bool = default_use_min_budget, + padding_type: str = default_padding_type + ): + self.normalize_budget = ( # pylint: disable=attribute-defined-outside-init + normalize_budget + ) + self.use_min_budget = ( # pylint: disable=attribute-defined-outside-init + use_min_budget + ) + self.padding_type = ( # pylint: disable=attribute-defined-outside-init + padding_type + ) + self.normalize_y = normalize_y # pylint: disable=attribute-defined-outside-init + + x_train, train_budgets, learning_curves = self._preprocess_input( + x_train, learning_curves, self.normalize_budget, self.use_min_budget, self.padding_type + ) + + y_train = self._preprocess_y(y_train, normalize_y) + + self.x_train = x_train # pylint: disable=attribute-defined-outside-init + self.train_budgets = ( # pylint: disable=attribute-defined-outside-init + train_budgets + ) + self.learning_curves = ( # pylint: disable=attribute-defined-outside-init + learning_curves + ) + self.y_train = y_train # pylint: disable=attribute-defined-outside-init + + def _preprocess_input( + self, + x: list[SearchSpace], + learning_curves: list[list[float]], + normalize_budget: bool, + use_min_budget: bool, + padding_type: str + ) -> [torch.tensor, torch.tensor, torch.tensor]: + budgets = self.__extract_budgets(x, normalize_budget, use_min_budget) + learning_curves = self.__preprocess_learning_curves(learning_curves, padding_type) + + x = np.array([self.__encode_config(config) for config in x], dtype=np.single) + + x = torch.tensor(x).to(device=self.device) + budgets = torch.tensor(budgets).to(device=self.device) + learning_curves = torch.tensor(learning_curves).to(device=self.device) + + return x, budgets, learning_curves + + def _preprocess_y(self, y_train: list[float], + normalize_y: bool) -> torch.tensor: + y_train_array = np.array(y_train, dtype=np.single) + self.min_y = y_train_array.min() # pylint: disable=attribute-defined-outside-init + self.max_y = y_train_array.max() # pylint: disable=attribute-defined-outside-init + if normalize_y: + y_train_array = (y_train_array - self.min_y) / (self.max_y - self.min_y) + y_train_array = torch.tensor(y_train_array).to(device=self.device) + return y_train_array + + def __is_refine(self, no_improvement_patience: int) -> bool: + losses = get_optimizer_losses(self.root_dir) + + best_loss = get_best_loss(self.root_dir) + + total_optimizer_steps = len(losses) + + # Count the non-improvement + non_improvement_steps = 0 + for loss in reversed(losses): + if np.greater(loss, best_loss): + non_improvement_steps += 1 + else: + break + + self.logger.debug(f"No improvement for: {non_improvement_steps} evaulations") + + return ((non_improvement_steps < no_improvement_patience) + and (self.n_initial_full_trainings <= total_optimizer_steps)) + + def fit( + self, + x_train: list[SearchSpace], + y_train: list[float], + learning_curves: list[list[float]], + ): + self._fit(x_train, y_train, learning_curves, **self.surrogate_model_fit_args) + + def _fit(self, + x_train: list[SearchSpace], + y_train: list[float], + learning_curves: list[list[float]], + nr_epochs: int = default_nr_epochs, + batch_size: int = default_batch_size, + early_stopping: bool = default_early_stopping, + early_stopping_patience: int = default_early_stopping_patience, + no_improvement_patience: int = default_no_improvement_patience, + optimizer_args: dict[str, Any] | None = None, + + normalize_y: bool = default_y_normalize, + normalize_budget: bool = default_budget_normalize, + use_min_budget: bool = default_use_min_budget, + padding_type: str = default_padding_type): + + self.__reset_xy( + x_train, + y_train, + learning_curves, + normalize_y=normalize_y, + normalize_budget=normalize_budget, + use_min_budget=use_min_budget, + padding_type=padding_type, + ) + # check when to refine + if self.checkpointing and self.__is_refine(no_improvement_patience) and self.checkpoint_path.exists(): + # self.__initialize_model() + self.load_state() + weight_new_point = True + nr_epochs = self.refine_epochs + batch_size = self.refine_batch_size if self.refine_batch_size else batch_size + else: + weight_new_point = False + + if optimizer_args is None: + optimizer_args = {"lr": self.default_lr} + + for model_index, model in enumerate(self.models): + self._train_a_model(model_index, + self.x_train, + self.train_budgets, + self.y_train, + self.learning_curves, + nr_epochs=nr_epochs, + batch_size=batch_size, + early_stopping_patience=early_stopping_patience, + early_stopping=early_stopping, + weight_new_point=weight_new_point, + optimizer_args=optimizer_args) + + # save model after training if checkpointing + if self.checkpointing: + self.save_state() + + def _train_a_model(self, + model_index: int, + x_train: torch.tensor, + train_budgets: torch.tensor, + y_train: torch.tensor, + learning_curves: torch.tensor, + nr_epochs: int, + batch_size: int, + early_stopping_patience: int, + early_stopping: bool, + weight_new_point: bool, + optimizer_args: dict[str, Any]): + + # Setting seeds will interfere with SearchSpace random sampling + if self.cover_pipeline_space.has_tabular: + seed = self.seeds[model_index] + torch.manual_seed(seed) + np.random.seed(seed) + + model = self.models[model_index] + + optimizer = ( + torch.optim.Adam(**dict({"params": model.parameters()}, **optimizer_args)) + ) + + count_down = early_stopping_patience + best_loss = np.inf + best_state = deepcopy(model.state_dict()) + + model.train() + + if weight_new_point: + new_x, new_b, new_lc, new_y = self.prep_new_point() + else: + new_x, new_b, new_lc, new_y = [torch.tensor([])] * 4 + + for epoch in range(0, nr_epochs): + + if early_stopping and count_down == 0: + self.logger.info( + f"Epoch: {epoch - 1} surrogate training stops due to early " + f"stopping with the patience: {early_stopping_patience} and " + f"the minimum average loss of {best_loss} and " + f"the final average loss of {best_loss}" + ) + model.load_state_dict(best_state) + break + + n_examples_batch = x_train.size(dim=0) + + # get a random permutation for mini-batches + permutation = torch.randperm(n_examples_batch) + + # optimize over mini-batches + total_scaled_loss = 0.0 + for batch_idx, start_index in enumerate( + range(0, n_examples_batch, batch_size) + ): + end_index = start_index + batch_size + if end_index > n_examples_batch: + end_index = n_examples_batch + indices = permutation[start_index:end_index] + batch_x, batch_budget, batch_lc, batch_y = ( + x_train[indices], + train_budgets[indices], + learning_curves[indices], + y_train[indices], + ) + + minibatch_size = end_index - start_index + + if weight_new_point: + batch_x = torch.cat((batch_x, new_x)) + batch_budget = torch.cat((batch_budget, new_b)) + batch_lc = torch.cat((batch_lc, new_lc)) + batch_y = torch.cat((batch_y, new_y)) + + # increase the batchsize + minibatch_size += new_x.shape[0] + + # if only one example in the batch, skip the batch. + # Otherwise, the code will fail because of batchnorm + if minibatch_size <= 1: + continue + + # Zero backprop gradients + optimizer.zero_grad(set_to_none=True) + + outputs = model(batch_x, batch_budget, batch_budget, + batch_lc) + loss = self.criterion(outputs, batch_y) + loss.backward() + optimizer.step() + + total_scaled_loss += (loss.detach().item() * minibatch_size) + + running_loss = total_scaled_loss / n_examples_batch + + if running_loss < best_loss: + best_loss = running_loss + count_down = early_stopping_patience + best_state = deepcopy(model.state_dict()) + elif early_stopping: + self.logger.debug( + f"No improvement over the minimum loss value of {best_loss} " + f"for the past {early_stopping_patience - count_down} epochs " + f"the training will stop in {count_down} epochs" + ) + count_down -= 1 + if early_stopping: + model.load_state_dict(best_state) + return model + + def set_prediction_learning_curves(self, learning_curves: list[list[float]]): + # pylint: disable=attribute-defined-outside-init + self.prediction_learning_curves = learning_curves + # pylint: enable=attribute-defined-outside-init + + def predict( + self, + x: list[SearchSpace], + learning_curves: list[list[float]] | None = None, + real_budgets: list[int | float] | None = None + ) -> [torch.tensor, torch.tensor]: + # Preprocess input + # [print(_x.hp_values()) for _x in x] + if learning_curves is None: + learning_curves = self.prediction_learning_curves + + if real_budgets is None: + # Get the list of budgets the configs are evaluated for + real_budgets = [len(lc) + 1 for lc in learning_curves] + + x_test, prediction_budgets, learning_curves = self._preprocess_input( + x, learning_curves, self.normalize_budget, self.use_min_budget, self.padding_type + ) + # preprocess the list of budgets the configs are evaluated for + real_budgets = np.array(real_budgets, dtype=np.single) + real_budgets = self.__normalize_budgets(real_budgets, + self.use_min_budget) + real_budgets = torch.tensor(real_budgets).to(self.device) + + all_predictions = [] + for model in self.models: + model.eval() + + preds = model(x_test, prediction_budgets, real_budgets, learning_curves) + all_predictions.append(preds.detach().cpu().numpy()) + + means = torch.tensor(np.mean(all_predictions, axis=0)).cpu() + std_predictions = np.std(all_predictions, axis=0) + cov = torch.diag(torch.tensor(np.power(std_predictions, 2))).cpu() + + return means, cov + + def load_state(self, state: dict[str, int | str | dict[str, Any]] | None = None): + # load and save last evaluated config as well + if state is None: + checkpoint = torch.load(self.checkpoint_path) + else: + checkpoint = state + + self.last_point = checkpoint["last_point"] + + for model_index in range(checkpoint["n_models"]): + self.models[model_index].load_state_dict( + checkpoint[f"model_{model_index}_state_dict"]) + self.models[model_index].to(self.device) + + def get_state(self) -> dict[str, int | str | dict[str, Any]]: + n_models = len(self.models) + model_states = {f"model_{model_index}_state_dict": + deepcopy(self.models[model_index].state_dict()) + for model_index in range(n_models)} + + # get last point + last_point = self.get_last_point() + current_state = dict(n_models=n_models, last_point=last_point, **model_states) + + return current_state + + def __config_ids(self) -> list[str]: + # Parallelization issues + all_losses_file = self.root_dir / "all_losses_and_configs.txt" + + if all_losses_file.exists(): + # Read all losses from the file in the order they are explored + config_ids = [ + str(line[11:]) + for line in all_losses_file.read_text(encoding="utf-8").splitlines() + if "Config ID: " in line + ] + else: + config_ids = [] + + return config_ids + + def save_state(self, state: dict[str, int | str | dict[str, Any]] | None = None): + # TODO: save last evaluated config as well + if state is None: + torch.save( + self.get_state(), + self.checkpoint_path, + ) + else: + assert ("last_point" in state and + "n_models" in state), \ + "The state dictionary is not complete" + torch.save( + state, + self.checkpoint_path, + ) + + def get_last_point(self) -> str: + # Only for single worker case + last_config_id = self.__config_ids()[-1] + # For parallel runs + # get the last config_id that's also in self.observed_configs + return last_config_id + + def get_new_points(self) -> [list[SearchSpace], list[list[float]], list[float]]: + # Get points that haven't been trained on before + + config_ids = self.__config_ids() + + if self.last_point: + index = config_ids.index(self.last_point) + 1 + else: + index = len(config_ids) - 1 + + new_config_indices = [tuple(map(int, config_id.split("_"))) for config_id in + config_ids[index:]] + + # Only include the points that exist in the observed data already + # (not a use case for single worker runs) + existing_index_map = self.observed_data.df.index.isin(new_config_indices) + + new_config_df = self.observed_data.df.loc[existing_index_map, :].copy(deep=True) + + new_configs, new_lcs, new_y = self.observed_data.get_training_data_4DyHPO( + new_config_df, self.cover_pipeline_space) + + return new_configs, new_lcs, new_y + + @staticmethod + def __initialize_model(model_params: dict[str, Any], model_class: Type[ModelClass], + device: str) -> ModelClass: + model = model_class(**model_params) + model.to(device) + return model + + def prep_new_point(self) -> [torch.tensor, torch.tensor, torch.tensor, torch.tensor]: + new_point, new_lc, new_y = self.get_new_points() + + new_x, new_b, new_lc = self._preprocess_input(new_point, + new_lc, + self.normalize_budget, + self.use_min_budget, + self.padding_type + ) + new_y = self._preprocess_y(new_y, self.normalize_y) + + return new_x, new_b, new_lc, new_y + + def __get_mean_initial_value(self): + mean = self.observed_data.get_learning_curves().loc[:, 0].mean() + + return mean + + +if __name__ == "__main__": + max_fidelity = 50 + pipe_space = SearchSpace( + float_=FloatParameter(lower=0.0, upper=5.0), + e=IntegerParameter(lower=1, upper=max_fidelity, is_fidelity=True), + ) + + configs = [pipe_space.sample(ignore_fidelity=False) for _ in range(100)] + + y = np.random.random(100).tolist() + + lcs = [ + np.random.random(size=np.random.randint(low=1, high=max_fidelity)).tolist() + for _ in range(100) + ] + + surrogate = PowerLawSurrogate(pipe_space) + + surrogate.fit(x_train=configs, learning_curves=lcs, y_train=y) + + means, stds = surrogate.predict(configs, lcs) + + print(list(zip(means, y))) + print(stds) diff --git a/neps/optimizers/bayesian_optimization/models/__init__.py b/neps/optimizers/bayesian_optimization/models/__init__.py new file mode 100755 index 00000000..3f9bec50 --- /dev/null +++ b/neps/optimizers/bayesian_optimization/models/__init__.py @@ -0,0 +1,22 @@ +from ....metahyper.utils import MissingDependencyError +from .gp import ComprehensiveGP +from .gp_hierarchy import ComprehensiveGPHierarchy +from .DPL import PowerLawSurrogate + +try: + from .deepGP import DeepGP +except ImportError as e: + DeepGP = MissingDependencyError("gpytorch", e) + +try: + from .pfn import PFN_SURROGATE # only if available locally +except ImportError as e: + PFN_SURROGATE = MissingDependencyError("pfn", e) + +SurrogateModelMapping = { + "deep_gp": DeepGP, + "gp": ComprehensiveGP, + "gp_hierarchy": ComprehensiveGPHierarchy, + "dpl": PowerLawSurrogate, + "pfn": PFN_SURROGATE, +} diff --git a/src/neps/optimizers/bayesian_optimization/models/deepGP.py b/neps/optimizers/bayesian_optimization/models/deepGP.py similarity index 88% rename from src/neps/optimizers/bayesian_optimization/models/deepGP.py rename to neps/optimizers/bayesian_optimization/models/deepGP.py index ee47ce70..862f8a6e 100644 --- a/src/neps/optimizers/bayesian_optimization/models/deepGP.py +++ b/neps/optimizers/bayesian_optimization/models/deepGP.py @@ -17,12 +17,11 @@ SearchSpace, ) +def get_optimizer_losses(root_directory: Path | str) -> list[float]: -def count_non_improvement_steps(root_directory: Path | str) -> int: - root_directory = Path(root_directory) all_losses_file = root_directory / "all_losses_and_configs.txt" - best_loss_fiel = root_directory / "best_loss_trajectory.txt" + # Read all losses from the file in the order they are explored losses = [ @@ -30,18 +29,16 @@ def count_non_improvement_steps(root_directory: Path | str) -> int: for line in all_losses_file.read_text(encoding="utf-8").splitlines() if "Loss: " in line ] + return losses + +def get_best_loss(root_directory: Path | str) -> float: + root_directory = Path(root_directory) + best_loss_fiel = root_directory / "best_loss_trajectory.txt" + # Get the best seen loss value best_loss = float(best_loss_fiel.read_text(encoding="utf-8").splitlines()[-1].strip()) - # Count the non-improvement - count = 0 - for loss in reversed(losses): - if np.greater(loss, best_loss): - count += 1 - else: - break - - return count + return best_loss class NeuralFeatureExtractor(nn.Module): @@ -167,13 +164,19 @@ def __init__( # IMPORTANT: hence, it is not suitable for multiprocessing settings checkpointing: bool = False, root_directory: Path | str | None = None, + # IMPORTANT: For parallel runs use a different checkpoint_file name for each + # IMPORTANT: surrogate. This makes sure that parallel runs don't override each + # IMPORTANT: others saved checkpoint. Although they will still have some conflicts due to + # IMPORTANT: global optimizer step tracking checkpoint_file: Path | str = "surrogate_checkpoint.pth", refine_epochs: int = 50, + n_initial_full_trainings: int = 10, **kwargs, # pylint: disable=unused-argument - ): + ): self.surrogate_model_fit_args = ( surrogate_model_fit_args if surrogate_model_fit_args is not None else {} ) + self.n_initial_full_trainings = n_initial_full_trainings self.checkpointing = checkpointing self.refine_epochs = refine_epochs @@ -204,9 +207,17 @@ def __init__( neural_network_args.get("n_layers", 2) ) + if self.surrogate_model_fit_args.get("perf_patience", -1) is None: + # To replicate how the original DyHPO implementation handles the + # no_improvement_threshold + self.surrogate_model_fit_args["perf_patience"] = int(self.max_fidelity + + 0.2 * self.max_fidelity) + # build the neural network self.nn = NeuralFeatureExtractor(self.input_size, **neural_network_args) + self.best_state = None + self.logger = logger or logging.getLogger("neps") def __initialize_gp_model( @@ -237,6 +248,26 @@ def __initialize_gp_model( mll = gpytorch.mlls.ExactMarginalLogLikelihood(likelihood, model).to(self.device) return model, likelihood, mll + def __is_refine(self, perf_patience: int): + losses = get_optimizer_losses(self.root_dir) + + best_loss = get_best_loss(self.root_dir) + + total_optimizer_steps = len(losses) + + # Count the non-improvement + non_improvement_steps = 0 + for loss in reversed(losses): + if np.greater(loss, best_loss): + non_improvement_steps += 1 + else: + break + + self.logger.debug(f"No improvement for: {non_improvement_steps} evaulations") + + return ((non_improvement_steps < perf_patience) + and (self.n_initial_full_trainings <= total_optimizer_steps)) + def __preprocess_search_space(self, pipeline_space: SearchSpace): self.categories = [] self.categorical_hps = [] @@ -258,9 +289,9 @@ def __preprocess_search_space(self, pipeline_space: SearchSpace): self.max_fidelity = pipeline_space.fidelity.upper def __encode_config(self, config: SearchSpace): - categorical_encoding = np.zeros_like(self.categories_array) + categorical_encoding = np.zeros_like(self.categories_array, dtype=np.single) continuous_values = [] - + # print(config.hp_values()) for hp_name, hp in config.items(): if hp.is_fidelity: continue # Ignore fidelity @@ -268,6 +299,7 @@ def __encode_config(self, config: SearchSpace): label = hp.value categorical_encoding[np.argwhere(self.categories_array == label)] = 1 else: + # self.logger.info(f"{hp_name} Value: {hp.value} Normalized {hp.normalized().value}") continuous_values.append(hp.normalized().value) continuous_encoding = np.array(continuous_values) @@ -276,12 +308,16 @@ def __encode_config(self, config: SearchSpace): return encoding def __extract_budgets( - self, x_train: list[SearchSpace], normalized: bool = True + self, x_train: list[SearchSpace], + normalized: bool = True, + use_min_budget: bool = False ) -> np.ndarray: + + min_budget = self.min_fidelity if use_min_budget else 0 budgets = np.array([config.fidelity.value for config in x_train], dtype=np.single) if normalized: - normalized_budgets = (budgets - self.min_fidelity) / ( - self.max_fidelity - self.min_fidelity + normalized_budgets = (budgets - min_budget) / ( + self.max_fidelity - min_budget ) budgets = normalized_budgets return budgets @@ -316,14 +352,18 @@ def __reset_xy( learning_curves: list[list[float]], normalize_y: bool = False, normalize_budget: bool = True, + use_min_budget: bool = False, ): self.normalize_budget = ( # pylint: disable=attribute-defined-outside-init normalize_budget ) + self.use_min_budget = ( # pylint: disable=attribute-defined-outside-init + use_min_budget + ) self.normalize_y = normalize_y # pylint: disable=attribute-defined-outside-init x_train, train_budgets, learning_curves = self._preprocess_input( - x_train, learning_curves, normalize_budget + x_train, learning_curves, normalize_budget, use_min_budget ) y_train = self._preprocess_y(y_train, normalize_y) @@ -342,8 +382,9 @@ def _preprocess_input( x: list[SearchSpace], learning_curves: list[list[float]], normalize_budget: bool = True, + use_min_budget: bool = False ): - budgets = self.__extract_budgets(x, normalize_budget) + budgets = self.__extract_budgets(x, normalize_budget, use_min_budget) learning_curves = self.__preprocess_learning_curves(learning_curves) x = np.array([self.__encode_config(config) for config in x], dtype=np.single) @@ -369,6 +410,7 @@ def fit( y_train: list[float], learning_curves: list[list[float]], ): + self.logger.info(f"FIT ARGS: {self.surrogate_model_fit_args}") self._fit(x_train, y_train, learning_curves, **self.surrogate_model_fit_args) def _fit( @@ -378,6 +420,7 @@ def _fit( learning_curves: list[list[float]], normalize_y: bool = False, normalize_budget: bool = True, + use_min_budget: bool = False, n_epochs: int = 1000, batch_size: int = 64, optimizer_args: dict | None = None, @@ -391,6 +434,7 @@ def _fit( learning_curves, normalize_y=normalize_y, normalize_budget=normalize_budget, + use_min_budget=use_min_budget ) self.model, self.likelihood, self.mll = self.__initialize_gp_model(len(y_train)) self.nn = NeuralFeatureExtractor(self.input_size, **self.nn_args) @@ -399,12 +443,10 @@ def _fit( self.nn.to(self.device) if self.checkpointing and self.checkpoint_path.exists(): - non_improvement_steps = count_non_improvement_steps(self.root_dir) # If checkpointing and patience is not exhausted load a partial model - if non_improvement_steps < perf_patience: + if self.__is_refine(perf_patience): n_epochs = self.refine_epochs self.load_checkpoint() - self.logger.debug(f"No improvement for: {non_improvement_steps} evaulations") self.logger.debug(f"N Epochs for the full training: {n_epochs}") initial_state = self.get_state() @@ -421,7 +463,7 @@ def _fit( patience=patience, ) if self.checkpointing: - self.save_checkpoint() + self.save_checkpoint(self.best_state) except gpytorch.utils.errors.NotPSDError: self.logger.info("Model training failed loading the untrained model") self.load_checkpoint(initial_state) @@ -467,6 +509,7 @@ def __train_model( f"the minimum average loss of {min_avg_loss_val} and " f"the final average loss of {average_loss}" ) + self.load_checkpoint(self.best_state) break n_examples_batch = x_train.size(dim=0) @@ -530,6 +573,7 @@ def __train_model( if average_loss < min_avg_loss_val: min_avg_loss_val = average_loss count_down = patience + self.best_state = self.get_state() elif early_stopping: self.logger.debug( f"No improvement over the minimum loss value of {min_avg_loss_val} " @@ -558,7 +602,7 @@ def predict( if learning_curves is None: learning_curves = self.prediction_learning_curves x_test, test_budgets, learning_curves = self._preprocess_input( - x, learning_curves, self.normalize_budget + x, learning_curves, self.normalize_budget, self.use_min_budget ) self.model.eval() diff --git a/src/neps/optimizers/bayesian_optimization/models/gp.py b/neps/optimizers/bayesian_optimization/models/gp.py similarity index 100% rename from src/neps/optimizers/bayesian_optimization/models/gp.py rename to neps/optimizers/bayesian_optimization/models/gp.py diff --git a/src/neps/optimizers/bayesian_optimization/models/gp_hierarchy.py b/neps/optimizers/bayesian_optimization/models/gp_hierarchy.py similarity index 100% rename from src/neps/optimizers/bayesian_optimization/models/gp_hierarchy.py rename to neps/optimizers/bayesian_optimization/models/gp_hierarchy.py diff --git a/src/neps/optimizers/bayesian_optimization/optimizer.py b/neps/optimizers/bayesian_optimization/optimizer.py similarity index 99% rename from src/neps/optimizers/bayesian_optimization/optimizer.py rename to neps/optimizers/bayesian_optimization/optimizer.py index e598b3df..6c47ac8b 100644 --- a/src/neps/optimizers/bayesian_optimization/optimizer.py +++ b/neps/optimizers/bayesian_optimization/optimizer.py @@ -5,8 +5,7 @@ from typing_extensions import Literal -from metahyper import ConfigResult, instance_from_map - +from ...metahyper import ConfigResult, instance_from_map from ...search_spaces.hyperparameters.categorical import ( CATEGORICAL_CONFIDENCE_SCORES, CategoricalParameter, diff --git a/src/neps/optimizers/default_searchers/asha.yaml b/neps/optimizers/default_searchers/asha.yaml similarity index 100% rename from src/neps/optimizers/default_searchers/asha.yaml rename to neps/optimizers/default_searchers/asha.yaml diff --git a/src/neps/optimizers/default_searchers/asha_prior.yaml b/neps/optimizers/default_searchers/asha_prior.yaml similarity index 100% rename from src/neps/optimizers/default_searchers/asha_prior.yaml rename to neps/optimizers/default_searchers/asha_prior.yaml diff --git a/src/neps/optimizers/default_searchers/bayesian_optimization.yaml b/neps/optimizers/default_searchers/bayesian_optimization.yaml similarity index 100% rename from src/neps/optimizers/default_searchers/bayesian_optimization.yaml rename to neps/optimizers/default_searchers/bayesian_optimization.yaml diff --git a/src/neps/optimizers/default_searchers/hyperband.yaml b/neps/optimizers/default_searchers/hyperband.yaml similarity index 100% rename from src/neps/optimizers/default_searchers/hyperband.yaml rename to neps/optimizers/default_searchers/hyperband.yaml diff --git a/src/neps/optimizers/default_searchers/mobster.yaml b/neps/optimizers/default_searchers/mobster.yaml similarity index 100% rename from src/neps/optimizers/default_searchers/mobster.yaml rename to neps/optimizers/default_searchers/mobster.yaml diff --git a/src/neps/optimizers/default_searchers/pibo.yaml b/neps/optimizers/default_searchers/pibo.yaml similarity index 100% rename from src/neps/optimizers/default_searchers/pibo.yaml rename to neps/optimizers/default_searchers/pibo.yaml diff --git a/src/neps/optimizers/default_searchers/priorband.yaml b/neps/optimizers/default_searchers/priorband.yaml similarity index 100% rename from src/neps/optimizers/default_searchers/priorband.yaml rename to neps/optimizers/default_searchers/priorband.yaml diff --git a/src/neps/optimizers/default_searchers/priorband_bo.yaml b/neps/optimizers/default_searchers/priorband_bo.yaml similarity index 100% rename from src/neps/optimizers/default_searchers/priorband_bo.yaml rename to neps/optimizers/default_searchers/priorband_bo.yaml diff --git a/src/neps/optimizers/default_searchers/random_search.yaml b/neps/optimizers/default_searchers/random_search.yaml similarity index 100% rename from src/neps/optimizers/default_searchers/random_search.yaml rename to neps/optimizers/default_searchers/random_search.yaml diff --git a/src/neps/optimizers/default_searchers/regularized_evolution.yaml b/neps/optimizers/default_searchers/regularized_evolution.yaml similarity index 100% rename from src/neps/optimizers/default_searchers/regularized_evolution.yaml rename to neps/optimizers/default_searchers/regularized_evolution.yaml diff --git a/src/neps/optimizers/default_searchers/successive_halving.yaml b/neps/optimizers/default_searchers/successive_halving.yaml similarity index 100% rename from src/neps/optimizers/default_searchers/successive_halving.yaml rename to neps/optimizers/default_searchers/successive_halving.yaml diff --git a/src/neps/optimizers/default_searchers/successive_halving_prior.yaml b/neps/optimizers/default_searchers/successive_halving_prior.yaml similarity index 100% rename from src/neps/optimizers/default_searchers/successive_halving_prior.yaml rename to neps/optimizers/default_searchers/successive_halving_prior.yaml diff --git a/src/neps/optimizers/grid_search/optimizer.py b/neps/optimizers/grid_search/optimizer.py similarity index 96% rename from src/neps/optimizers/grid_search/optimizer.py rename to neps/optimizers/grid_search/optimizer.py index 1924ec62..1c988926 100644 --- a/src/neps/optimizers/grid_search/optimizer.py +++ b/neps/optimizers/grid_search/optimizer.py @@ -2,8 +2,7 @@ import random -from metahyper.api import ConfigResult - +from ...metahyper import ConfigResult from ...search_spaces.search_space import SearchSpace from ..base_optimizer import BaseOptimizer diff --git a/src/neps/optimizers/info.py b/neps/optimizers/info.py similarity index 100% rename from src/neps/optimizers/info.py rename to neps/optimizers/info.py diff --git a/src/neps/optimizers/multi_fidelity/_dyhpo.py b/neps/optimizers/multi_fidelity/_dyhpo.py similarity index 99% rename from src/neps/optimizers/multi_fidelity/_dyhpo.py rename to neps/optimizers/multi_fidelity/_dyhpo.py index b4d972a1..1c948cea 100644 --- a/src/neps/optimizers/multi_fidelity/_dyhpo.py +++ b/neps/optimizers/multi_fidelity/_dyhpo.py @@ -3,8 +3,7 @@ import numpy as np -from metahyper import ConfigResult - +from ...metahyper import ConfigResult from ...search_spaces.search_space import FloatParameter, IntegerParameter, SearchSpace from ..base_optimizer import BaseOptimizer from ..bayesian_optimization.acquisition_functions.base_acquisition import BaseAcquisition diff --git a/src/neps/optimizers/multi_fidelity/dyhpo.py b/neps/optimizers/multi_fidelity/dyhpo.py similarity index 83% rename from src/neps/optimizers/multi_fidelity/dyhpo.py rename to neps/optimizers/multi_fidelity/dyhpo.py index 75f374b4..5e540bc3 100755 --- a/src/neps/optimizers/multi_fidelity/dyhpo.py +++ b/neps/optimizers/multi_fidelity/dyhpo.py @@ -5,9 +5,12 @@ from typing import Any import numpy as np +import pandas as pd +import time -from metahyper import ConfigResult, instance_from_map +from ...utils.common import EvaluationData, SimpleCSVWriter +from ...metahyper import ConfigResult, instance_from_map from ...search_spaces.search_space import FloatParameter, IntegerParameter, SearchSpace from ..base_optimizer import BaseOptimizer from ..bayesian_optimization.acquisition_functions import AcquisitionMapping @@ -23,6 +26,15 @@ from .utils import MFObservedData +class AcqWriter(SimpleCSVWriter): + def set_data(self, sample_configs: pd.Series, acq_vals: pd.Series): + config_vals = pd.DataFrame([config.hp_values() for config in sample_configs], index=sample_configs.index) + if isinstance(acq_vals, pd.Series): + acq_vals.name = "Acq Value" + self.df = config_vals.join(acq_vals) + self.df = self.df.sort_values(by="Acq Value") + + class MFEIBO(BaseOptimizer): """Base class for MF-BO algorithms that use DyHPO-like acquisition and budgeting.""" @@ -124,7 +136,7 @@ def __init__( self._prep_model_args(self.hp_kernels, self.graph_kernels, pipeline_space) # TODO: Better solution than branching based on the surrogate name is needed - if surrogate_model in ["deep_gp", "gp"]: + if surrogate_model in ["deep_gp", "gp", "dpl"]: model_policy = FreezeThawModel elif surrogate_model == "pfn": model_policy = PFNSurrogate @@ -164,6 +176,8 @@ def __init__( ) self.count = 0 + self.evaluation_data = EvaluationData() + def _prep_model_args(self, hp_kernels, graph_kernels, pipeline_space): if self.surrogate_model_name in ["gp", "gp_hierarchy"]: # setup for GP implemented in NePS @@ -264,7 +278,7 @@ def total_budget_spent(self) -> int | float: return total_budget_spent - def is_init_phase(self, budget_based: bool = True) -> bool: + def is_init_phase(self, budget_based: bool = False) -> bool: if budget_based: # Check if we are still in the initial design phase based on # either the budget spent so far or the number of configurations evaluated @@ -290,11 +304,11 @@ def load_results( previous_results (dict[str, ConfigResult]): [description] pending_evaluations (dict[str, ConfigResult]): [description] """ + start = time.time() self.observed_configs = MFObservedData( columns=["config", "perf", "learning_curves"], index_names=["config_id", "budget_id"], ) - # previous optimization run exists and needs to be loaded self._load_previous_observations(previous_results) self.total_fevals = len(previous_results) + len(pending_evaluations) @@ -306,7 +320,6 @@ def load_results( self.observed_configs.df.sort_index( level=self.observed_configs.df.index.names, inplace=True ) - # TODO: can we do better than keeping a copy of the observed configs? # TODO: can we not hide this in load_results and have something that pops out # more, like a set_state or policy_args @@ -315,6 +328,9 @@ def load_results( init_phase = self.is_init_phase() if not init_phase: self._fit_models() + # print("-" * 50) + # print(f"| Total time for `load_results()`: {time.time()-start:.2f}s") + # print("-" * 50) @classmethod def _get_config_id_split(cls, config_id: str) -> tuple[str, str]: @@ -420,7 +436,7 @@ def get_config_and_ids( # pylint: disable=no-self-use ) config.fidelity.value = self.min_budget _config_id = self.observed_configs.next_config_id() - elif self.is_init_phase(budget_based=True) or self._model_update_failed: + elif self.is_init_phase() or self._model_update_failed: # promote a config randomly if initial design size is satisfied but the # initial design budget has not been exhausted self.logger.info("promoting...") @@ -433,32 +449,84 @@ def get_config_and_ids( # pylint: disable=no-self-use # main acquisition call here after initial design is turned off self.logger.info("acquiring...") # generates candidate samples for acquisition calculation + start = time.time() samples = self.acquisition_sampler.sample( set_new_sample_fidelity=self.pipeline_space.fidelity.lower ) # fidelity values here should be the observations or min. fidelity + # print("-" * 50) + # print(f"| Total time for acq. sampling: {time.time()-start:.2f}s") + # print("-" * 50) + + start = time.time() # calculating acquisition function values for the candidate samples acq, _samples = self.acquisition.eval( # type: ignore[attr-defined] x=samples, asscalar=True ) + acq = pd.Series(acq, index=_samples.index) + + # print("-" * 50) + # print(f"| Total time for acq. eval: {time.time()-start:.2f}s") + # print("-" * 50) # maximizing acquisition function - _idx = np.argsort(acq)[-1] + best_idx = acq.sort_values().index[-1] # extracting the config ID for the selected maximizer - _config_id = samples.index[_samples.index.values[_idx]] + _config_id = best_idx # samples.index[_samples.index.values[_idx]] # `_samples` should have new configs with fidelities set to as required # NOTE: len(samples) need not be equal to len(_samples) as `samples` contain # all (partials + new) configurations obtained from the sampler, but # in `_samples`, configs are removed that have reached maximum epochs allowed # NOTE: `samples` and `_samples` should share the same index values, hence, - # avoid using `.iloc` and work with `.loc` on pandas DataFrame/Series - - # Is this "config = _samples.loc[_config_id]"? + # avoid using `.iloc` and work with `.loc` on these pandas DataFrame/Series + + acq_writer = AcqWriter("Acq_values") + # Writes extra information into Acq_values.csv + # if hasattr(self.acquisition, "mu"): + # # collect prediction learning_curves + # lcs = [] + # # and tabular ids + # tabular_ids = [] + # for idx in _samples.index: + # if self.acquisition_sampler.is_tabular: + # tabular_ids.append(samples[idx]["id"].value) + # if idx in self.observed_configs.df.index.levels[0]: + # # budget_level = self.get_budget_level(_samples[idx]) + # # extracting the available/observed learning curve + # lc = self.observed_configs.extract_learning_curve(idx, budget_id=None) + # else: + # # initialize a learning curve with a placeholder + # # This is later padded accordingly for the Conv1D layer + # lc = [] + # lcs.append(lc) + # + # data = {"Acq Value": acq.values, + # "preds": self.acquisition.mu, + # "incumbents": self.acquisition.mu_star, + # "std": self.acquisition.std, + # "pred_learning_curves": lcs} + # if self.acquisition_sampler.is_tabular: + # data["tabular_ids"] = tabular_ids + # + # acq = pd.DataFrame(data, index=_samples.index) + acq_writer.set_data(_samples, acq) + self.evaluation_data.data_dict["acq"] = acq_writer + + # assigning config hyperparameters config = samples.loc[_config_id] - config.fidelity.value = _samples.loc[_config_id].fidelity.value + # IMPORTANT: setting the fidelity appropriately + + config.fidelity.value = ( + config.fidelity.lower + if best_idx > max(self.observed_configs.seen_config_ids) + else ( + self.get_budget_value( + self.observed_configs.get_max_observed_fidelity_level_per_config().loc[best_idx] + ) + self.step_size # ONE-STEP FIDELITY QUERY + ) + ) # generating correct IDs if _config_id in self.observed_configs.seen_config_ids: config_id = f"{_config_id}_{self.get_budget_level(config)}" previous_config_id = f"{_config_id}_{self.get_budget_level(config) - 1}" else: config_id = f"{self.observed_configs.next_config_id()}_{self.get_budget_level(config)}" - return config.hp_values(), config_id, previous_config_id diff --git a/src/neps/optimizers/multi_fidelity/hyperband.py b/neps/optimizers/multi_fidelity/hyperband.py similarity index 99% rename from src/neps/optimizers/multi_fidelity/hyperband.py rename to neps/optimizers/multi_fidelity/hyperband.py index 4c368bfe..86ff2f5f 100644 --- a/src/neps/optimizers/multi_fidelity/hyperband.py +++ b/neps/optimizers/multi_fidelity/hyperband.py @@ -9,8 +9,7 @@ import numpy as np from typing_extensions import Literal -from metahyper import ConfigResult - +from ...metahyper import ConfigResult from ...search_spaces.search_space import SearchSpace from ..bayesian_optimization.acquisition_functions.base_acquisition import BaseAcquisition from ..bayesian_optimization.acquisition_samplers.base_acq_sampler import ( diff --git a/src/neps/optimizers/multi_fidelity/mf_bo.py b/neps/optimizers/multi_fidelity/mf_bo.py similarity index 90% rename from src/neps/optimizers/multi_fidelity/mf_bo.py rename to neps/optimizers/multi_fidelity/mf_bo.py index 3cf191bd..c825120b 100755 --- a/src/neps/optimizers/multi_fidelity/mf_bo.py +++ b/neps/optimizers/multi_fidelity/mf_bo.py @@ -7,8 +7,7 @@ import pandas as pd import torch -from metahyper import instance_from_map - +from ...metahyper import instance_from_map from ..bayesian_optimization.models import SurrogateModelMapping from ..multi_fidelity.utils import normalize_vectorize_config from ..multi_fidelity_prior.utils import calc_total_resources_spent, update_fidelity @@ -199,6 +198,11 @@ def __init__( ) if self.surrogate_model_name in ["deep_gp", "pfn"]: self.surrogate_model_args.update({"pipeline_space": pipeline_space}) + elif self.surrogate_model_name == "dpl": + self.surrogate_model_args.update( + {"pipeline_space": self.pipeline_space, + "observed_data": self.observed_configs} + ) # instantiate the surrogate model self.surrogate_model = instance_from_map( @@ -234,7 +238,7 @@ def _fantasize_pending(self, train_x, train_y, pending_x): def _fit(self, train_x, train_y, train_lcs): if self.surrogate_model_name in ["gp", "gp_hierarchy"]: self.surrogate_model.fit(train_x, train_y) - elif self.surrogate_model_name in ["deep_gp", "pfn"]: + elif self.surrogate_model_name in ["deep_gp", "pfn", "dpl"]: self.surrogate_model.fit(train_x, train_y, train_lcs) else: # check neps/optimizers/bayesian_optimization/models/__init__.py for options @@ -245,7 +249,7 @@ def _fit(self, train_x, train_y, train_lcs): def _predict(self, test_x, test_lcs): if self.surrogate_model_name in ["gp", "gp_hierarchy"]: return self.surrogate_model.predict(test_x) - elif self.surrogate_model_name in ["deep_gp", "pfn"]: + elif self.surrogate_model_name in ["deep_gp", "pfn", "dpl"]: return self.surrogate_model.predict(test_x, test_lcs) else: # check neps/optimizers/bayesian_optimization/models/__init__.py for options @@ -263,12 +267,29 @@ def set_state( self.surrogate_model_args = ( surrogate_model_args if surrogate_model_args is not None else {} ) + if self.surrogate_model_name == "dpl": + self.surrogate_model_args.update( + {"pipeline_space": self.pipeline_space, + "observed_data": self.observed_configs} + ) + self.surrogate_model = instance_from_map( + SurrogateModelMapping, + self.surrogate_model_name, + name="surrogate model", + kwargs=self.surrogate_model_args, + ) + # only to handle tabular spaces if self.pipeline_space.has_tabular: if self.surrogate_model_name in ["deep_gp", "pfn"]: self.surrogate_model_args.update( {"pipeline_space": self.pipeline_space.raw_tabular_space} ) + elif self.surrogate_model_name == "dpl": + self.surrogate_model_args.update( + {"pipeline_space": self.pipeline_space, + "observed_data": self.observed_configs} + ) # instantiate the surrogate model, again, with the new pipeline space self.surrogate_model = instance_from_map( SurrogateModelMapping, @@ -276,6 +297,17 @@ def set_state( name="surrogate model", kwargs=self.surrogate_model_args, ) + elif self.surrogate_model_name == "dpl": + self.surrogate_model_args.update( + {"pipeline_space": self.pipeline_space, + "observed_data": self.observed_configs} + ) + self.surrogate_model = instance_from_map( + SurrogateModelMapping, + self.surrogate_model_name, + name="surrogate model", + kwargs=self.surrogate_model_args, + ) def update_model(self, train_x=None, train_y=None, pending_x=None, decay_t=None): if train_x is None: @@ -323,6 +355,8 @@ def preprocess_training_set(self): configs, idxs, performances = self.observed_configs.get_tokenized_data( self.observed_configs.df.copy().assign(config=_configs) ) + idxs = idxs.astype(float) + idxs[:, 1] = idxs[:, 1] / _configs[0].fidelity.upper # TODO: account for fantasization self.train_x = torch.Tensor(np.hstack([idxs, configs])).to(device) self.train_y = torch.Tensor(performances).to(device) diff --git a/src/neps/optimizers/multi_fidelity/promotion_policy.py b/neps/optimizers/multi_fidelity/promotion_policy.py similarity index 100% rename from src/neps/optimizers/multi_fidelity/promotion_policy.py rename to neps/optimizers/multi_fidelity/promotion_policy.py diff --git a/src/neps/optimizers/multi_fidelity/sampling_policy.py b/neps/optimizers/multi_fidelity/sampling_policy.py similarity index 99% rename from src/neps/optimizers/multi_fidelity/sampling_policy.py rename to neps/optimizers/multi_fidelity/sampling_policy.py index 5b1a8529..fc8075e4 100644 --- a/src/neps/optimizers/multi_fidelity/sampling_policy.py +++ b/neps/optimizers/multi_fidelity/sampling_policy.py @@ -10,8 +10,7 @@ import pandas as pd import torch -from metahyper import instance_from_map - +from ...metahyper import instance_from_map from ...search_spaces.search_space import SearchSpace from ..bayesian_optimization.acquisition_functions import AcquisitionMapping from ..bayesian_optimization.acquisition_functions.base_acquisition import BaseAcquisition diff --git a/src/neps/optimizers/multi_fidelity/successive_halving.py b/neps/optimizers/multi_fidelity/successive_halving.py similarity index 99% rename from src/neps/optimizers/multi_fidelity/successive_halving.py rename to neps/optimizers/multi_fidelity/successive_halving.py index 54fa09db..a3145dc2 100644 --- a/src/neps/optimizers/multi_fidelity/successive_halving.py +++ b/neps/optimizers/multi_fidelity/successive_halving.py @@ -10,8 +10,7 @@ import pandas as pd from typing_extensions import Literal -from metahyper import ConfigResult - +from ...metahyper import ConfigResult from ...search_spaces.hyperparameters.categorical import ( CATEGORICAL_CONFIDENCE_SCORES, CategoricalParameter, diff --git a/src/neps/optimizers/multi_fidelity/utils.py b/neps/optimizers/multi_fidelity/utils.py similarity index 81% rename from src/neps/optimizers/multi_fidelity/utils.py rename to neps/optimizers/multi_fidelity/utils.py index f1d359a6..80a6a230 100644 --- a/src/neps/optimizers/multi_fidelity/utils.py +++ b/neps/optimizers/multi_fidelity/utils.py @@ -5,8 +5,11 @@ import numpy as np import pandas as pd +import time import torch +from copy import deepcopy + from ...optimizers.utils import map_real_hyperparameters_from_tabular_ids from ...search_spaces.search_space import SearchSpace @@ -55,6 +58,7 @@ class MFObservedData: default_config_col = "config" default_perf_col = "perf" default_lc_col = "learning_curves" + # TODO: deepcopy all the mutable outputs from the dataframe def __init__( self, @@ -79,6 +83,7 @@ def __init__( self.config_idx = index_names[0] self.budget_idx = index_names[1] + self.index_names = index_names index = pd.MultiIndex.from_tuples([], names=index_names) @@ -129,8 +134,9 @@ def add_data( data_list = data if not self.df.index.isin(index_list).any(): - _df = pd.DataFrame(data_list, columns=self.df.columns, index=index_list) - self.df = pd.concat((self.df, _df)) + index = pd.MultiIndex.from_tuples(index_list, names=self.index_names) + _df = pd.DataFrame(data_list, columns=self.df.columns, index=index) + self.df = _df.copy() if self.df.empty else pd.concat((self.df, _df)) elif error: raise ValueError( f"Data with at least one of the given indices already " @@ -178,7 +184,7 @@ def get_incumbents_for_budgets(self, maximize: bool = False): Returns a series object with the best partial configuration for each budget id Note: this will always map the best lowest ID if two configurations - has the same performance at the same fidelity + have the same performance at the same fidelity """ learning_curves = self.get_learning_curves() if maximize: @@ -205,6 +211,16 @@ def get_best_performance_for_each_budget(self, maximize: bool = False): return performance + def get_budget_level_for_best_performance(self, maximize: bool = False) -> int: + """Returns the lowest budget level at which the highest performance was recorded. + """ + perf_per_z = self.get_best_performance_for_each_budget(maximize=maximize) + y_star = self.get_best_seen_performance(maximize=maximize) + # uses the minimum of the budget that see the maximum obseved score + op = max if maximize else min + z_inc = int(op([_z for _z, _y in perf_per_z.items() if _y == y_star])) + return z_inc + def get_best_learning_curve_id(self, maximize: bool = False): """ Returns a single configuration id of the best observed performance @@ -240,7 +256,17 @@ def reduce_to_max_seen_budgets(self): def get_partial_configs_at_max_seen(self): return self.reduce_to_max_seen_budgets()[self.config_col] - def extract_learning_curve(self, config_id: int, budget_id: int) -> list[float]: + def extract_learning_curve( + self, config_id: int, budget_id: int | None = None + ) -> list[float]: + if budget_id is None: + # budget_id only None when predicting + # extract full observed learning curve for prediction pipeline + budget_id = max(self.df.loc[config_id].index.get_level_values("budget_id").values) + 1 + + # For the first epoch we have no learning curve available + if budget_id == 0: + return [] # reduce budget_id to discount the current validation loss # both during training and prediction phase budget_id = max(0, budget_id - 1) @@ -249,11 +275,12 @@ def extract_learning_curve(self, config_id: int, budget_id: int) -> list[float]: else: lcs = self.get_learning_curves() lc = lcs.loc[config_id, :budget_id].values.flatten().tolist() - return lc + return deepcopy(lc) def get_training_data_4DyHPO( self, df: pd.DataFrame, pipeline_space: SearchSpace | None = None ): + start = time.time() configs = [] learning_curves = [] performance = [] @@ -268,8 +295,34 @@ def get_training_data_4DyHPO( configs.append(row[self.config_col]) performance.append(row[self.perf_col]) learning_curves.append(self.extract_learning_curve(config_id, budget_id)) + # print("-" * 50) + # print(f"| Time for `get_training_data_4DyHPO()`: {time.time()-start:.2f}s") + # print("-" * 50) return configs, learning_curves, performance + def get_best_performance_per_config(self, maximize: bool = False) -> pd.Series: + """Returns the best score recorded per config across fidelities seen. + """ + op = np.max if maximize else np.min + perf = ( + self.df + .sort_values("budget_id", ascending=False) # sorts with largest budget first + .groupby("config_id") # retains only config_id + .first() # retrieves the largest budget seen for each config_id + .learning_curves # extracts all values seen till largest budget for a config + .apply(op) # finds the minimum over per-config learning curve + ) + return perf + + def get_max_observed_fidelity_level_per_config(self) -> pd.Series: + """Returns the highest fidelity level recorded per config seen. + """ + max_z_observed = { + _id: self.df.loc[_id,:].index.sort_values()[-1] + for _id in self.df.index.get_level_values("config_id").sort_values() + } + return pd.Series(max_z_observed) + def get_tokenized_data(self, df: pd.DataFrame): idxs = df.index.values idxs = np.array([list(idx) for idx in idxs]) diff --git a/src/neps/optimizers/multi_fidelity_prior/__init__.py b/neps/optimizers/multi_fidelity_prior/__init__.py similarity index 100% rename from src/neps/optimizers/multi_fidelity_prior/__init__.py rename to neps/optimizers/multi_fidelity_prior/__init__.py diff --git a/src/neps/optimizers/multi_fidelity_prior/async_priorband.py b/neps/optimizers/multi_fidelity_prior/async_priorband.py similarity index 99% rename from src/neps/optimizers/multi_fidelity_prior/async_priorband.py rename to neps/optimizers/multi_fidelity_prior/async_priorband.py index 9527c97d..c932d45d 100644 --- a/src/neps/optimizers/multi_fidelity_prior/async_priorband.py +++ b/neps/optimizers/multi_fidelity_prior/async_priorband.py @@ -5,8 +5,7 @@ import numpy as np from typing_extensions import Literal -from metahyper import ConfigResult - +from ...metahyper import ConfigResult from ...search_spaces.search_space import SearchSpace from ..bayesian_optimization.acquisition_functions.base_acquisition import BaseAcquisition from ..bayesian_optimization.acquisition_samplers.base_acq_sampler import ( diff --git a/src/neps/optimizers/multi_fidelity_prior/priorband.py b/neps/optimizers/multi_fidelity_prior/priorband.py similarity index 100% rename from src/neps/optimizers/multi_fidelity_prior/priorband.py rename to neps/optimizers/multi_fidelity_prior/priorband.py diff --git a/src/neps/optimizers/multi_fidelity_prior/utils.py b/neps/optimizers/multi_fidelity_prior/utils.py similarity index 100% rename from src/neps/optimizers/multi_fidelity_prior/utils.py rename to neps/optimizers/multi_fidelity_prior/utils.py diff --git a/src/neps/optimizers/multiple_knowledge_sources/prototype_optimizer.py b/neps/optimizers/multiple_knowledge_sources/prototype_optimizer.py similarity index 98% rename from src/neps/optimizers/multiple_knowledge_sources/prototype_optimizer.py rename to neps/optimizers/multiple_knowledge_sources/prototype_optimizer.py index eb399b06..9ab96b1a 100644 --- a/src/neps/optimizers/multiple_knowledge_sources/prototype_optimizer.py +++ b/neps/optimizers/multiple_knowledge_sources/prototype_optimizer.py @@ -3,8 +3,7 @@ import logging from typing import Any -from metahyper.api import ConfigResult - +from ...metahyper import ConfigResult from ...search_spaces.search_space import SearchSpace from ...utils.data_loading import read_tasks_and_dev_stages_from_disk from .. import BaseOptimizer diff --git a/src/neps/optimizers/random_search/optimizer.py b/neps/optimizers/random_search/optimizer.py similarity index 96% rename from src/neps/optimizers/random_search/optimizer.py rename to neps/optimizers/random_search/optimizer.py index 2d23fe19..4b84838d 100644 --- a/src/neps/optimizers/random_search/optimizer.py +++ b/neps/optimizers/random_search/optimizer.py @@ -1,7 +1,6 @@ from __future__ import annotations -from metahyper.api import ConfigResult - +from ...metahyper import ConfigResult from ...search_spaces.search_space import SearchSpace from ..base_optimizer import BaseOptimizer diff --git a/src/neps/optimizers/regularized_evolution/optimizer.py b/neps/optimizers/regularized_evolution/optimizer.py similarity index 100% rename from src/neps/optimizers/regularized_evolution/optimizer.py rename to neps/optimizers/regularized_evolution/optimizer.py diff --git a/neps/optimizers/utils.py b/neps/optimizers/utils.py new file mode 100644 index 00000000..757dd0b3 --- /dev/null +++ b/neps/optimizers/utils.py @@ -0,0 +1,30 @@ +import pandas as pd + +from ..search_spaces.search_space import SearchSpace + + +def map_real_hyperparameters_from_tabular_ids( + x: pd.Series, pipeline_space: SearchSpace +) -> pd.Series: + """ Maps the tabular IDs to the actual HPs from the pipeline space. + + Args: + x (pd.Series): A pandas series with the tabular IDs. + TODO: Mention expected format of the series. + pipeline_space (SearchSpace): The pipeline space. + + Returns: + pd.Series: A pandas series with the actual HPs. + TODO: Mention expected format of the series. + """ + if len(x) == 0: + return x + # copying hyperparameter configs based on IDs + _x = pd.Series( + [pipeline_space.custom_grid_table[x.loc[idx]["id"].value] for idx in x.index.values], + index=x.index + ) + # setting the passed fidelities for the corresponding IDs + for idx in _x.index.values: + _x.loc[idx].fidelity.value = x.loc[idx].fidelity.value + return _x diff --git a/src/neps/plot/__init__.py b/neps/plot/__init__.py similarity index 100% rename from src/neps/plot/__init__.py rename to neps/plot/__init__.py diff --git a/src/neps/plot/__main__.py b/neps/plot/__main__.py similarity index 100% rename from src/neps/plot/__main__.py rename to neps/plot/__main__.py diff --git a/src/neps/plot/plot.py b/neps/plot/plot.py similarity index 100% rename from src/neps/plot/plot.py rename to neps/plot/plot.py diff --git a/src/neps/plot/plotting.py b/neps/plot/plotting.py similarity index 100% rename from src/neps/plot/plotting.py rename to neps/plot/plotting.py diff --git a/src/neps/plot/read_results.py b/neps/plot/read_results.py similarity index 100% rename from src/neps/plot/read_results.py rename to neps/plot/read_results.py diff --git a/src/neps/plot/tensorboard_eval.py b/neps/plot/tensorboard_eval.py similarity index 96% rename from src/neps/plot/tensorboard_eval.py rename to neps/plot/tensorboard_eval.py index 445406cb..6463563e 100644 --- a/src/neps/plot/tensorboard_eval.py +++ b/neps/plot/tensorboard_eval.py @@ -2,15 +2,22 @@ import math import os +import warnings from pathlib import Path import numpy as np import torch + +# Remove this once we support pytorch > 2.1.0 +# https://github.com/automl/neps/issues/26 +warnings.filterwarnings( + "ignore", category=DeprecationWarning, module="torch.utils.tensorboard" +) + from torch.utils.tensorboard import SummaryWriter from torch.utils.tensorboard.summary import hparams -from metahyper.api import ConfigInRun - +from ..metahyper.api import ConfigInRun from ..status.status import get_summary_dict from ..utils.common import get_initial_directory @@ -306,7 +313,7 @@ def _write_image_config( if resize_images is None: resize_images = [32, 32] - if tblogger.current_epoch and tblogger.current_epoch % counter == 0: + if tblogger.current_epoch >= 0 and tblogger.current_epoch % counter == 0: # Log every multiple of "counter" if num_images > len(image): @@ -473,10 +480,12 @@ def log( loss (float): Current loss value. current_epoch (int): Current epoch of the experiment (used as the global step). - writer_scalar (bool, optional): Displaying the loss or accuracy + writer_config_scalar (bool, optional): Displaying the loss or accuracy curve on tensorboard (default: True) - writer_hparam (bool, optional): Write hyperparameters logging of + writer_config_hparam (bool, optional): Write hyperparameters logging of the configs (default: True). + write_summary_incumbent (bool, optional): Set to `True` for a live + incumbent trajectory. extra_data (dict, optional): Additional experiment data for logging. """ if tblogger.disable_logging: diff --git a/neps/py.typed b/neps/py.typed new file mode 100644 index 00000000..e69de29b diff --git a/src/neps/search_spaces/__init__.py b/neps/search_spaces/__init__.py similarity index 100% rename from src/neps/search_spaces/__init__.py rename to neps/search_spaces/__init__.py diff --git a/src/neps/search_spaces/architecture/api.py b/neps/search_spaces/architecture/api.py similarity index 100% rename from src/neps/search_spaces/architecture/api.py rename to neps/search_spaces/architecture/api.py diff --git a/src/neps/search_spaces/architecture/cfg.py b/neps/search_spaces/architecture/cfg.py similarity index 100% rename from src/neps/search_spaces/architecture/cfg.py rename to neps/search_spaces/architecture/cfg.py diff --git a/src/neps/search_spaces/architecture/cfg_variants/cfg_resolution.py b/neps/search_spaces/architecture/cfg_variants/cfg_resolution.py similarity index 100% rename from src/neps/search_spaces/architecture/cfg_variants/cfg_resolution.py rename to neps/search_spaces/architecture/cfg_variants/cfg_resolution.py diff --git a/src/neps/search_spaces/architecture/cfg_variants/constrained_cfg.py b/neps/search_spaces/architecture/cfg_variants/constrained_cfg.py similarity index 100% rename from src/neps/search_spaces/architecture/cfg_variants/constrained_cfg.py rename to neps/search_spaces/architecture/cfg_variants/constrained_cfg.py diff --git a/src/neps/search_spaces/architecture/core_graph_grammar.py b/neps/search_spaces/architecture/core_graph_grammar.py similarity index 100% rename from src/neps/search_spaces/architecture/core_graph_grammar.py rename to neps/search_spaces/architecture/core_graph_grammar.py diff --git a/src/neps/search_spaces/architecture/crossover.py b/neps/search_spaces/architecture/crossover.py similarity index 100% rename from src/neps/search_spaces/architecture/crossover.py rename to neps/search_spaces/architecture/crossover.py diff --git a/src/neps/search_spaces/architecture/graph.py b/neps/search_spaces/architecture/graph.py similarity index 99% rename from src/neps/search_spaces/architecture/graph.py rename to neps/search_spaces/architecture/graph.py index 35d2ad01..42b2c388 100644 --- a/src/neps/search_spaces/architecture/graph.py +++ b/neps/search_spaces/architecture/graph.py @@ -12,7 +12,7 @@ import networkx as nx import torch from networkx.algorithms.dag import lexicographical_topological_sort -from path import Path +from pathlib import Path from torch import nn from ...utils.common import AttrDict diff --git a/src/neps/search_spaces/architecture/graph_grammar.py b/neps/search_spaces/architecture/graph_grammar.py similarity index 100% rename from src/neps/search_spaces/architecture/graph_grammar.py rename to neps/search_spaces/architecture/graph_grammar.py diff --git a/src/neps/search_spaces/architecture/mutations.py b/neps/search_spaces/architecture/mutations.py similarity index 100% rename from src/neps/search_spaces/architecture/mutations.py rename to neps/search_spaces/architecture/mutations.py diff --git a/src/neps/search_spaces/architecture/primitives.py b/neps/search_spaces/architecture/primitives.py similarity index 100% rename from src/neps/search_spaces/architecture/primitives.py rename to neps/search_spaces/architecture/primitives.py diff --git a/src/neps/search_spaces/architecture/topologies.py b/neps/search_spaces/architecture/topologies.py similarity index 100% rename from src/neps/search_spaces/architecture/topologies.py rename to neps/search_spaces/architecture/topologies.py diff --git a/src/neps/search_spaces/hyperparameters/categorical.py b/neps/search_spaces/hyperparameters/categorical.py similarity index 98% rename from src/neps/search_spaces/hyperparameters/categorical.py rename to neps/search_spaces/hyperparameters/categorical.py index 39547321..6b5674b2 100644 --- a/src/neps/search_spaces/hyperparameters/categorical.py +++ b/neps/search_spaces/hyperparameters/categorical.py @@ -2,11 +2,10 @@ import random from copy import copy, deepcopy -from typing import Iterable +from typing import Iterable, Literal import numpy as np import numpy.typing as npt -from typing_extensions import Literal from ..parameter import Parameter @@ -32,9 +31,7 @@ def __init__( self.upper = default self.default_confidence_score = CATEGORICAL_CONFIDENCE_SCORES[default_confidence] self.has_prior = self.default is not None - self.is_fidelity = is_fidelity - self.choices = list(choices) self.num_choices = len(self.choices) self.probabilities: list[npt.NDArray] = list( diff --git a/src/neps/search_spaces/hyperparameters/constant.py b/neps/search_spaces/hyperparameters/constant.py similarity index 100% rename from src/neps/search_spaces/hyperparameters/constant.py rename to neps/search_spaces/hyperparameters/constant.py diff --git a/src/neps/search_spaces/hyperparameters/float.py b/neps/search_spaces/hyperparameters/float.py similarity index 99% rename from src/neps/search_spaces/hyperparameters/float.py rename to neps/search_spaces/hyperparameters/float.py index c35cafc2..2c8eaeb4 100644 --- a/src/neps/search_spaces/hyperparameters/float.py +++ b/neps/search_spaces/hyperparameters/float.py @@ -2,10 +2,10 @@ import math from copy import deepcopy +from typing import Literal import numpy as np import scipy.stats -from typing_extensions import Literal from .numerical import NumericalParameter @@ -37,7 +37,6 @@ def __init__( if self.lower >= self.upper: raise ValueError("Float parameter: bounds error (lower >= upper).") - self.log = log if self.log: diff --git a/src/neps/search_spaces/hyperparameters/integer.py b/neps/search_spaces/hyperparameters/integer.py similarity index 100% rename from src/neps/search_spaces/hyperparameters/integer.py rename to neps/search_spaces/hyperparameters/integer.py diff --git a/src/neps/search_spaces/hyperparameters/numerical.py b/neps/search_spaces/hyperparameters/numerical.py similarity index 100% rename from src/neps/search_spaces/hyperparameters/numerical.py rename to neps/search_spaces/hyperparameters/numerical.py diff --git a/src/neps/search_spaces/parameter.py b/neps/search_spaces/parameter.py similarity index 100% rename from src/neps/search_spaces/parameter.py rename to neps/search_spaces/parameter.py diff --git a/src/neps/search_spaces/search_space.py b/neps/search_spaces/search_space.py similarity index 71% rename from src/neps/search_spaces/search_space.py rename to neps/search_spaces/search_space.py index 48d0b252..d74fac11 100644 --- a/src/neps/search_spaces/search_space.py +++ b/neps/search_spaces/search_space.py @@ -6,10 +6,12 @@ from collections import OrderedDict from copy import deepcopy from itertools import product +from pathlib import Path import ConfigSpace as CS import numpy as np import pandas as pd +import yaml from ..utils.common import has_instance from . import ( @@ -21,6 +23,10 @@ ) from .architecture.graph import Graph from .parameter import Parameter +from .yaml_search_space_utils import ( + SearchSpaceFromYamlFileError, + deduce_and_validate_param_type, +) def pipeline_space_from_configspace( @@ -61,6 +67,121 @@ def pipeline_space_from_configspace( return pipeline_space +def pipeline_space_from_yaml( + yaml_file_path: str | Path, +) -> dict[ + str, FloatParameter | IntegerParameter | CategoricalParameter | ConstantParameter +]: + """ + Reads configuration details from a YAML file and constructs a pipeline space + dictionary. + + This function extracts parameter configurations from a YAML file, validating and + translating them into corresponding parameter objects. The resulting dictionary + maps parameter names to their respective configuration objects. + + Args: + yaml_file_path (str | Path): Path to the YAML file containing parameter + configurations. + + Returns: + dict: A dictionary where keys are parameter names and values are parameter + objects (like IntegerParameter, FloatParameter, etc.). + + Raises: + SearchSpaceFromYamlFileError: This custom exception is raised if there are issues + with the YAML file's format or contents. It encapsulates underlying exceptions + (KeyError, TypeError, ValueError) that occur during the processing of the YAML + file. This approach localizes error handling, providing clearer context and + diagnostics. The raised exception includes the type of the original error and + a descriptive message. + + Note: + The YAML file should be properly structured with valid keys and values as per the + expected parameter types. The function employs modular validation and type + deduction logic, ensuring each parameter's configuration adheres to expected + formats and constraints. Any deviation results in an appropriately raised error, + which is then captured by SearchSpaceFromYamlFileError for streamlined error + handling. + + Example: + To use this function with a YAML file 'config.yaml', you can do: + pipeline_space = pipeline_space_from_yaml('config.yaml') + """ + try: + # try to load the YAML file + try: + with open(yaml_file_path) as file: + config = yaml.safe_load(file) + except yaml.YAMLError as e: + raise ValueError( + f"The file at {str(yaml_file_path)} is not a valid YAML file." + ) from e + + # check for init key pipeline_space + if "pipeline_space" not in config: + raise KeyError( + "The YAML file is incorrectly constructed: the 'pipeline_space:' " + "reference is missing at the top of the file." + ) + + # Initialize the pipeline space + pipeline_space = {} + + # Iterate over the items in the YAML configuration + for name, details in config["pipeline_space"].items(): + # get parameter type + param_type = deduce_and_validate_param_type(name, details) + + # init parameter by checking type + if param_type in ("int", "integer"): + # Integer Parameter + pipeline_space[name] = IntegerParameter( + lower=details["lower"], + upper=details["upper"], + log=details.get("log", False), + is_fidelity=details.get("is_fidelity", False), + default=details.get("default", None), + default_confidence=details.get("default_confidence", "low"), + ) + elif param_type == "float": + # Float Parameter + pipeline_space[name] = FloatParameter( + lower=details["lower"], + upper=details["upper"], + log=details.get("log", False), + is_fidelity=details.get("is_fidelity", False), + default=details.get("default", None), + default_confidence=details.get("default_confidence", "low"), + ) + elif param_type in ("cat", "categorical"): + # Categorical parameter + pipeline_space[name] = CategoricalParameter( + choices=details["choices"], + is_fidelity=details.get("is_fidelity", False), + default=details.get("default", None), + default_confidence=details.get("default_confidence", "low"), + ) + elif param_type in ("const", "constant"): + # Constant parameter + pipeline_space[name] = ConstantParameter( + value=details["value"], is_fidelity=details.get("is_fidelity", False) + ) + else: + # Handle unknown parameter type + raise TypeError( + f"Unsupported parameter type{details['type']} for '{name}'.\n" + f"Supported Types for argument type are:\n" + "For integer parameter: int, integer\n" + "For float parameter: float\n" + "For categorical parameter: cat, categorical\n" + "For constant parameter: const, constant\n" + ) + except (KeyError, TypeError, ValueError) as e: + raise SearchSpaceFromYamlFileError(e) from e + return pipeline_space + + class SearchSpace(collections.abc.Mapping): def __init__(self, **hyperparameters): self.hyperparameters = OrderedDict() @@ -83,12 +204,17 @@ def __init__(self, **hyperparameters): ) self.fidelity = hyperparameter - # Check if defaults exists to construct prior from - if hasattr(hyperparameter, "default") and hyperparameter.default is not None: + # Check if defaults exists to construct prior from, except of + # ConstantParameter because default gets init always by the given value + if ( + hasattr(hyperparameter, "default") + and hyperparameter.default is not None + and not isinstance(hyperparameter, ConstantParameter) + ): self.has_prior = True elif hasattr(hyperparameter, "has_prior") and hyperparameter.has_prior: self.has_prior = True - + # Variables for tabular bookkeeping self.custom_grid_table = None self.raw_tabular_space = None @@ -97,29 +223,40 @@ def __init__(self, **hyperparameters): def set_custom_grid_space( self, grid_table: pd.Series | pd.DataFrame, - raw_space: SearchSpace | CS.ConfigurationSpace + raw_space: SearchSpace | CS.ConfigurationSpace, ): """Set a custom grid space for the search space. - This function is used to set a custom grid space for the pipeline space. - NOTE: Only to be used if a custom set of hyperparameters from the search space - is to be sampled or used for acquisition functions. - WARNING: The type check and the table format requirement is loose and + This function is used to set a custom grid space for the pipeline space. + NOTE: Only to be used if a custom set of hyperparameters from the search space + is to be sampled or used for acquisition functions. + WARNING: The type check and the table format requirement is loose and can break certain components. """ self.custom_grid_table: pd.DataFrame | pd.Series = grid_table self.raw_tabular_space = ( SearchSpace(**raw_space) - if not isinstance(raw_space, SearchSpace) else raw_space + if not isinstance(raw_space, SearchSpace) + else raw_space ) if self.custom_grid_table is None or self.raw_tabular_space is None: raise ValueError( "Both grid_table and raw_space must be set!\n" - "A table or list of fixed configs must be supported with a " + "A table or list of fixed configs must be supported with a " "continuous space representing the type and bounds of each " "hyperparameter for accurate modeling." ) self.has_tabular = True + # Updating `custom_grid_table` as a map for quick lookup with placeholder fidelity + placeholder_config = self.raw_tabular_space.sample(ignore_fidelity=True) # sets fidelity as None + # `placeholder_config` allows to store map values as NePS SearchSpace type + # and also create a placeholder for fideity value + _map = { + idx: deepcopy(placeholder_config) + for idx in self.custom_grid_table.index.values + } + _ = [v.load_from(self.custom_grid_table.loc[k].to_dict()) for k, v in _map.items()] + self.custom_grid_table = _map @property def has_fidelity(self): @@ -201,7 +338,7 @@ def _smbo_mutation(self, patience=50, **kwargs): new_config[hp_name] = hp.mutate(**kwargs) break except Exception as e: - self.logger.warning(f"{hp_name} FAILED!") + self.logger.warning(f"{hp_name} FAILED! Error: {e}") continue return new_config @@ -356,7 +493,14 @@ def load_from(self, config: dict): self.hyperparameters[name].load_from(config[name]) def copy(self): - return deepcopy(self) + _copy = deepcopy(self) + + if _copy.has_tabular: + # each configuration does not need to carry the tabular data + _copy.has_tabular = False + _copy.custom_grid_table = None + _copy.raw_tabular_space = None + return _copy def sample_default_configuration( self, patience: int = 1, ignore_fidelity=True, ignore_missing_defaults=False @@ -440,8 +584,8 @@ def __str__(self): return pprint.pformat(self.hyperparameters) def is_equal_value(self, other, include_fidelity=True, on_decimal=8): - # This does NOT check that the entire SearchSpace is equal (and thus it is not a dunder method), - # but only checks the configuration + # This does NOT check that the entire SearchSpace is equal (and thus it is + # not a dunder method), but only checks the configuration if self.hyperparameters.keys() != other.hyperparameters.keys(): return False diff --git a/neps/search_spaces/yaml_search_space_utils.py b/neps/search_spaces/yaml_search_space_utils.py new file mode 100644 index 00000000..e0efe616 --- /dev/null +++ b/neps/search_spaces/yaml_search_space_utils.py @@ -0,0 +1,462 @@ +from __future__ import annotations + +import re + + +def convert_scientific_notation(value: str | int | float, show_usage_flag=False) \ + -> float | (float, bool): + """ + Convert a given value to a float if it's a string that matches scientific e notation. + This is especially useful for numbers like "3.3e-5" which YAML parsers may not + directly interpret as floats. + + If the 'show_usage_flag' is set to True, the function returns a tuple of the float + conversion and a boolean flag indicating whether scientific notation was detected. + + Args: + value (str | int | float): The value to convert. Can be an integer, float, + or a string representing a number, possibly in + scientific notation. + show_usage_flag (bool): Optional; defaults to False. If True, the function + also returns a flag indicating whether scientific + notation was detected in the string. + + Returns: + float: The value converted to float if 'show_usage_flag' is False. + (float, bool): A tuple containing the value converted to float and a flag + indicating scientific notation detection if 'show_usage_flag' + is True. + + Raises: + ValueError: If the value is a string and does not represent a valid number. + """ + + e_notation_pattern = r"^-?\d+(\.\d+)?[eE]-?\d+$" + + flag = False # Flag if e notation was detected + + if isinstance(value, str): + # Remove all whitespace from the string + value_no_space = value.replace(" ", "") + + # check for e notation + if re.match(e_notation_pattern, value_no_space): + flag = True + + if show_usage_flag is True: + return float(value), flag + else: + return float(value) + + +class SearchSpaceFromYamlFileError(Exception): + """ + Exception raised for errors occurring during the initialization of the search space + from a YAML file. + + Attributes: + exception_type (str): The type of the original exception. + message (str): A detailed message that includes the type of the original exception + and the error description. + + Args: + exception (Exception): The original exception that was raised during the + initialization of the search space from the YAML file. + + Example Usage: + try: + # Code to initialize search space from YAML file + except (KeyError, TypeError, ValueError) as e: + raise SearchSpaceFromYamlFileError(e) + """ + + def __init__(self, exception): + self.exception_type = type(exception).__name__ + self.message = ( + f"Error occurred during initialization of search space from " + f"YAML file.\n {self.exception_type}: {exception}" + ) + super().__init__(self.message) + + +def deduce_and_validate_param_type( + name: str, details: dict[str, str | int | float] +) -> str: + """ + Deduces the parameter type from details and validates them. + + Args: + name (str): The name of the parameter. + details (dict): A dictionary containing parameter specifications. + + Returns: + str: The deduced parameter type ('int', 'float', 'categorical', or 'constant'). + + Raises: + TypeError: If the type cannot be deduced or the details don't align with expected + constraints. + """ + # Deduce type + if "type" in details: + param_type = details["type"].lower() + else: + # Logic to infer type if not explicitly provided + param_type = deduce_param_type(name, details) + + # Validate details of a parameter based on (deduced) type + validate_param_details(name, param_type, details) + + return param_type + + +def deduce_param_type(name: str, details: dict[str, int | str | float]) -> str: + """Deduces the parameter type based on the provided details. + + The function interprets the 'details' dictionary to determine the parameter type. + The dictionary should include key-value pairs that describe the parameter's + characteristics, such as lower, upper, default value, or possible choices. + + + Args: + name (str): The name of the parameter. + details ((dict[str, int | str | float])): A dictionary containing parameter + specifications. + + Returns: + str: The deduced parameter type ('int', 'float', 'categorical', or 'constant'). + + Raises: + TypeError: If the parameter type cannot be deduced from the details, or if the + provided details have inconsistent types for expected keys. + + Example: + param_type = deduce_param_type('example_param', {'lower': 0, 'upper': 10})""" + # Logic to deduce type from details + + # check for int and float conditions + if "lower" in details and "upper" in details: + # Determine if it's an integer or float range parameter + if isinstance(details["lower"], int) and isinstance(details["upper"], int): + param_type = "int" + elif isinstance(details["lower"], float) and isinstance(details["upper"], float): + param_type = "float" + else: + try: + details["lower"], flag_lower = convert_scientific_notation( + details["lower"], show_usage_flag=True + ) + details["upper"], flag_upper = convert_scientific_notation( + details["upper"], show_usage_flag=True + ) + except ValueError as e: + raise TypeError( + f"Inconsistent types for 'lower' and 'upper' in '{name}'. " + f"Both must be either integers or floats." + ) from e + + # check if one value is e notation and if so convert it to float + if flag_lower or flag_upper: + param_type = "float" + else: + raise TypeError( + f"Inconsistent types for 'lower' and 'upper' in '{name}'. " + f"Both must be either integers or floats." + ) + # check for categorical condition + elif "choices" in details: + param_type = "categorical" + + # check for constant condition + elif "value" in details: + param_type = "constant" + else: + raise KeyError( + f"Unable to deduce parameter type from {name} " + f"with details {details}\n" + "Supported parameters:\n" + "Float and Integer: Expected keys: 'lower', 'upper'\n" + "Categorical: Expected keys: 'choices'\n" + "Constant: Expected keys: 'value'" + ) + return param_type + + +def validate_param_details( + name: str, param_type: str, details: dict[str, int | str | float] +): + """ + Validates the details of a parameter based on its type. + + This function checks the format and type-specific details of a parameter + specified in a YAML file. It ensures that the 'name' of the parameter is a string + and its 'details' are provided as a dictionary. Depending on the parameter type, + it delegates the validation to the appropriate type-specific validation function. + + Parameters: + name (str): The name of the parameter. It should be a string. + param_type (str): The type of the parameter. Supported types are 'int' (or 'integer'), + 'float', 'cat' (or 'categorical'), and 'const' (or 'constant'). + details (dict): The detailed configuration of the parameter, which includes its + attributes like 'lower', 'upper', 'default', etc. + + Raises: + KeyError: If the 'name' is not a string or 'details' is not a dictionary, or if + the necessary keys in the 'details' are missing based on the parameter type. + TypeError: If the 'param_type' is not one of the supported types. + + Example Usage: + validate_param_details("learning_rate", "float", {"lower": 0.01, "upper": 0.1, + "default": 0.05}) + """ + if not (isinstance(name, str) and isinstance(details, dict)): + raise KeyError( + f"Invalid format for {name} in YAML file. " + f"Expected 'name' as string and corresponding 'details' as a " + f"dictionary. Found 'name' type: {type(name).__name__}, 'details' " + f"type: {type(details).__name__}." + ) + param_type = param_type.lower() + # init parameter by checking type + if param_type in ("int", "integer"): + validate_integer_parameter(name, details) + + elif param_type == "float": + validate_float_parameter(name, details) + + elif param_type in ("cat", "categorical"): + validate_categorical_parameter(name, details) + + elif param_type in ("const", "constant"): + validate_constant_parameter(name, details) + else: + # Handle unknown parameter types + raise TypeError( + f"Unsupported parameter type'{details['type']}' for '{name}'.\n" + f"Supported Types for argument type are:\n" + "For integer parameter: int, integer\n" + "For float parameter: float\n" + "For categorical parameter: cat, categorical\n" + "For constant parameter: const, constant\n" + ) + + +def validate_integer_parameter(name: str, details: dict[str, str | int | float]): + """ + Validates and processes an integer parameter's details, converting scientific + notation to integers where necessary. + + This function checks the type of 'lower' and 'upper', and the 'default' + value (if present) for an integer parameter. It also handles conversion of values + in scientific notation (e.g., 1e2) to integers. + + Args: + name (str): The name of the integer parameter. + details (dict[str, str | int | float]): A dictionary containing the parameter's + specifications. Expected keys include + 'lower', 'upper', and optionally 'default', + among others. + + Raises: + TypeError: If 'lower', 'upper', or 'default' are not valid integers or cannot + be converted from scientific notation to integers. + """ + # check if all keys are allowed to use and if the mandatory ones are provided + check_keys( + name, + details, + {"lower", "upper", "type", "log", "is_fidelity", "default", "default_confidence"}, + {"lower", "upper"}, + ) + + if not isinstance(details["lower"], int) or not isinstance(details["upper"], int): + try: + # for numbers like 1e2 and 10^ + lower, flag_lower = convert_scientific_notation( + details["lower"], show_usage_flag=True + ) + upper, flag_upper = convert_scientific_notation( + details["upper"], show_usage_flag=True + ) + # check if one value format is e notation and if its an integer + if flag_lower or flag_upper: + if lower == int(lower) and upper == int(upper): + details["lower"] = int(lower) + details["upper"] = int(upper) + else: + raise TypeError() + else: + raise TypeError() + except (ValueError, TypeError) as e: + raise TypeError( + f"'lower' and 'upper' must be integer for " f"integer parameter '{name}'." + ) from e + if "default" in details: + if not isinstance(details["default"], int): + try: + # convert value can raise ValueError + default = convert_scientific_notation(details["default"]) + if default == int(default): + details["default"] = int(default) + else: + raise TypeError() # type of value is not int + except (ValueError, TypeError) as e: + raise TypeError( + f"default value {details['default']} " + f"must be integer for integer parameter {name}" + ) from e + + +def validate_float_parameter(name: str, details: dict[str, str | int | float]): + """ + Validates and processes a float parameter's details, converting scientific + notation values to float where necessary. + + This function checks the type of 'lower' and 'upper', and the 'default' + value (if present) for a float parameter. It handles conversion of values in + scientific notation (e.g., 1e-5) to float. + + Args: + name: The name of the float parameter. + details: A dictionary containing the parameter's specifications. Expected keys + include 'lower', 'upper', and optionally 'default', among others. + + Raises: + TypeError: If 'lower', 'upper', or 'default' are not valid floats or cannot + be converted from scientific notation to floats. + """ + # check if all keys are allowed to use and if the mandatory ones are provided + check_keys( + name, + details, + {"lower", "upper", "type", "log", "is_fidelity", "default", "default_confidence"}, + {"lower", "upper"}, + ) + + if not isinstance(details["lower"], float) or not isinstance(details["upper"], float): + try: + # for numbers like 1e-5 and 10^ + details["lower"] = convert_scientific_notation(details["lower"]) + details["upper"] = convert_scientific_notation(details["upper"]) + except ValueError as e: + raise TypeError( + f"'lower' and 'upper' must be integer for " f"integer parameter '{name}'." + ) from e + if "default" in details: + if not isinstance(details["default"], float): + try: + details["default"] = convert_scientific_notation(details["default"]) + except ValueError as e: + raise TypeError( + f" default'{details['default']}' must be float for float " + f"parameter {name} " + ) from e + + +def validate_categorical_parameter(name: str, details: dict[str, str | int | float]): + """ + Validates a categorical parameter, including conversion of scientific notation + values to floats within the choices. + + This function ensures that the 'choices' key in the details is a list and attempts + to convert any elements in scientific notation to floats. It also handles the + 'default' value, converting it from scientific notation if necessary. + + Args: + name: The name of the categorical parameter. + details: A dictionary containing the parameter's specifications. Required key + is 'choices', with 'default' being optional. + + Raises: + TypeError: If 'choices' is not a list + """ + # check if all keys are allowed to use and if the mandatory ones are provided + check_keys( + name, + details, + {"choices", "type", "is_fidelity", "default", "default_confidence"}, + {"choices"}, + ) + + if not isinstance(details["choices"], list): + raise TypeError(f"The 'choices' for '{name}' must be a list.") + for i, element in enumerate(details["choices"]): + try: + converted_value, e_flag = convert_scientific_notation( + element, show_usage_flag=True + ) + if e_flag: + details["choices"][ + i + ] = converted_value # Replace the element at the same position + except ValueError: + pass # If a ValueError occurs, simply continue to the next element + if "default" in details: + e_flag = False + try: + # check if e notation, if then convert to number + default, e_flag = convert_scientific_notation( + details["default"], show_usage_flag=True + ) + except ValueError: + pass # if default value is not in a numeric format, Value Error occurs + if e_flag is True: + details["default"] = default + + +def validate_constant_parameter(name: str, details: dict[str, str | int | float]): + """ + Validates a constant parameter, including conversion of values in scientific + notation to floats. + + This function checks the 'value' key in the details dictionary and converts any + value expressed in scientific notation to a float. It ensures that the mandatory + 'value' key is provided and appropriately formatted. + + Args: + name: The name of the constant parameter. + details: A dictionary containing the parameter's specifications. The required + key is 'value'. + """ + # check if all keys are allowed to use and if the mandatory ones are provided + check_keys(name, details, {"value", "type", "is_fidelity"}, {"value"}) + + # check for e notation and convert it to float + e_flag = False + try: + converted_value, e_flag = convert_scientific_notation( + details["value"], show_usage_flag=True + ) + except ValueError: + # if the value is not able to convert to float a ValueError get raised by + # convert_scientific_notation function + pass + if e_flag: + details["value"] = converted_value + + +def check_keys( + name: str, + details: dict[str, str | int | float], + allowed_keys: set, + mandatory_keys: set, +): + """ + Checks if all keys in 'my_dict' are contained in the set 'allowed_keys' and + if all keys in 'mandatory_keys' are present in 'my_dict'. + Raises an exception if an unallowed key is found or if a mandatory key is missing. + """ + # Check for unallowed keys + unallowed_keys = [key for key in details if key not in allowed_keys] + if unallowed_keys: + unallowed_keys_str = ", ".join(unallowed_keys) + raise KeyError( + f"Unallowed key(s) '{unallowed_keys_str}' found for parameter '" f"{name}'." + ) + + # Check for missing mandatory keys + missing_mandatory_keys = [key for key in mandatory_keys if key not in details] + if missing_mandatory_keys: + missing_keys_str = ", ".join(missing_mandatory_keys) + raise KeyError( + f"Missing mandatory key(s) '{missing_keys_str}' for parameter '" f"{name}'." + ) diff --git a/src/neps/status/__main__.py b/neps/status/__main__.py similarity index 100% rename from src/neps/status/__main__.py rename to neps/status/__main__.py diff --git a/src/neps/status/status.py b/neps/status/status.py similarity index 93% rename from src/neps/status/status.py rename to neps/status/status.py index 90832427..3d45d2fe 100644 --- a/src/neps/status/status.py +++ b/neps/status/status.py @@ -3,13 +3,13 @@ import logging from pathlib import Path from typing import Any +import shutil +import zipfile import pandas as pd -from metahyper import read -from metahyper._locker import Locker -from metahyper.api import ConfigResult - +from ..metahyper import ConfigResult, read +from ..metahyper._locker import Locker from ..search_spaces.search_space import SearchSpace from ..utils.result_utils import get_loss @@ -206,8 +206,8 @@ def _get_dataframes_from_summary( config_data_pending.append(config_pending) # Creating the dataframe for previous config results. - df_previous = pd.DataFrame({"Config_id": indices_prev}) - df_previous["Status"] = "Complete" + df_previous = pd.DataFrame({"config_id": indices_prev}) + df_previous["status"] = "complete" df_previous = pd.concat( [df_previous, pd.json_normalize(config_data_prev).add_prefix("config.")], axis=1 ) @@ -220,8 +220,8 @@ def _get_dataframes_from_summary( ) # Creating dataframe for pending configs. - df_pending = pd.DataFrame({"Config_id": indices_pending}) - df_pending["Status"] = "Pending" + df_pending = pd.DataFrame({"config_id": indices_pending}) + df_pending["status"] = "pending" df_pending = pd.concat( [df_pending, pd.json_normalize(config_data_pending).add_prefix("config.")], axis=1, @@ -295,7 +295,7 @@ def _save_data_to_csv( run_data_df.index == "num_evaluated_configs", "value" ] # checks if the current worker has more evaluated configs than the previous - if int(num_evaluated_configs_csv) < int(num_evaluated_configs_run): + if int(num_evaluated_configs_csv) < int(num_evaluated_configs_run.iloc[0]): config_data_df = config_data_df.sort_values( by="result.loss", ascending=True ) @@ -318,6 +318,17 @@ def _save_data_to_csv( def post_run_csv(root_directory: str | Path, logger=None) -> None: + + root_directory = Path(root_directory) + zip_filename = Path(root_directory / "results.zip") + base_result_directory =root_directory / "results" + + # Extract previous results to load if it exists + if zip_filename.exists(): + # and not any(Path(base_result_directory).iterdir()): + shutil.unpack_archive(zip_filename, base_result_directory, "zip") + zip_filename.unlink() + if logger is None: logger = logging.getLogger("neps_status") @@ -339,3 +350,6 @@ def post_run_csv(root_directory: str | Path, logger=None) -> None: df_config_data, df_run_data, ) + +def get_run_summary_csv(root_directory: str | Path): + post_run_csv(root_directory=root_directory) diff --git a/src/neps/utils/common.py b/neps/utils/common.py similarity index 82% rename from src/neps/utils/common.py rename to neps/utils/common.py index 62b95e2a..2780a7ca 100644 --- a/src/neps/utils/common.py +++ b/neps/utils/common.py @@ -1,16 +1,17 @@ from __future__ import annotations import glob +import json import os import random from pathlib import Path +from typing import Any import numpy as np import torch import yaml -from metahyper.api import ConfigInRun - +from ..metahyper.api import ConfigInRun from ..optimizers.info import SearcherConfigs @@ -231,6 +232,17 @@ def get_searcher_data(searcher: str, searcher_path: Path | str | None = None) -> return data +def get_value(obj: Any): + if isinstance(obj, (str, int, float, bool, type(None))): + return obj + elif isinstance(obj, dict): + return {key: get_value(value) for key, value in obj.items()} + elif isinstance(obj, list): + return [get_value(item) for item in obj] + else: + return obj.__name__ + + def has_instance(collection, *types): return any([isinstance(el, typ) for el in collection for typ in types]) @@ -274,3 +286,60 @@ class AttrDict(dict): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.__dict__ = self + + +class DataWriter: + """ + A class to specify how to save/write a data to the folder by + implementing your own write_data function. + Use the set_attributes function to set all your necessary attributes and the data + and then write_data will be called with only the directory path as argument + during the write process + """ + def __init__(self, name: str): + self.name = name + + def set_attributes(self, attribute_dict: dict[str, Any]): + for attribute_name, attribute in attribute_dict.items(): + setattr(self, attribute_name, attribute) + + def write_data(self, to_directory: Path): + raise NotImplementedError + + +class EvaluationData: + """ + A class to store some data for a single evaluation (configuration) + and write that data to its corresponding config folder + """ + def __init__(self): + self.data_dict: dict[str, DataWriter] = {} + + def write_all(self, directory: Path): + for _, data_writer in self.data_dict.items(): + data_writer.write_data(directory) + + +class SimpleCSVWriter(DataWriter): + def write_data(self, to_directory: Path): + # self.df: pd.DataFrame = pd.DataFrame() + path = to_directory / str(self.name + ".csv") + self.df.to_csv(path, float_format="%g") + + +class SimpleJSONWriter(DataWriter): + def __init__(self): + self.data: dict[str, Any] = {} + + def write_data(self, to_directory: Path): + # self.df: pd.DataFrame = pd.DataFrame() + path = to_directory / str(self.name + ".json") + with open(path, "w") as file: + json.dump(self.data, file) + + + + + + + diff --git a/src/neps/utils/data_loading.py b/neps/utils/data_loading.py similarity index 97% rename from src/neps/utils/data_loading.py rename to neps/utils/data_loading.py index ed2712bc..996d1583 100644 --- a/src/neps/utils/data_loading.py +++ b/neps/utils/data_loading.py @@ -9,8 +9,7 @@ import numpy as np import yaml -import metahyper.api - +from ..metahyper import read from .result_utils import get_loss @@ -40,7 +39,7 @@ def read_tasks_and_dev_stages_from_disk( continue dev_id = get_id_from_path(dev_dir_path) # TODO: Perhaps use 2nd and 3rd argument as well - result, _, _ = metahyper.api.read(dev_dir_path) + result, _, _ = read(dev_dir_path) results[task_id][dev_id] = result return results @@ -65,7 +64,7 @@ def read_user_prior_results_from_disk(path: str): continue # get name of the directory name = os.path.basename(prior_dir_path) - results[name], _, _ = metahyper.api.read(prior_dir_path) + results[name], _, _ = read(prior_dir_path) return results @@ -163,7 +162,7 @@ def summarize_results( # TOOD: only use IDs if provided final_results = results[final_task_id][final_dev_id] else: - final_results, _, _ = metahyper.api.read(seed_dir_path) + final_results, _, _ = read(seed_dir_path) # This part is copied from neps.status() best_loss = float("inf") diff --git a/src/neps/utils/result_utils.py b/neps/utils/result_utils.py similarity index 100% rename from src/neps/utils/result_utils.py rename to neps/utils/result_utils.py diff --git a/neps_examples/README.md b/neps_examples/README.md index f2173a54..4161d7ec 100644 --- a/neps_examples/README.md +++ b/neps_examples/README.md @@ -1,11 +1,11 @@ # Neural Pipeline Search Examples -1. Examples for the [basic usage](basic_usage) showing how to perform HPO / NAS / JAHS and how to analyse runs. +1. Navigate to [basic_usage](basic_usage) for demonstrations on fundamental usage. Learn how to perform Hyperparameter Optimization (HPO), Neural Architecture Search (NAS), and Joint Architecture and Hyperparameter Search (JAHS). Understand how to analyze runs on a basic level, emphasizing that no neural network training is involved at this stage; the search is performed on functions to introduce NePS. -2. Examples for how to [boost efficiency](efficiency) with expert_priors and/or multi fidelity and/or parallelization. +2. Navigate to [efficiency](efficiency) examples showcasing how to enhance efficiency in NePS. Learn about expert priors, multi-fidelity, and parallelization to streamline your pipeline and optimize search processes. -3. Examples showcasing some [utilities for your convenience](convenience). +3. Navigate to [convenience](convenience) for examples highlighting utilities that add extra features to NePS. Discover tensorboard compatibility and its integration, explore the compatibility with PyTorch Lightning, and understand file management within the run pipeline function used in NePS. -4. [Experimental examples](experimental) which are mostly useful for NePS contributors. +4. Navigate to into [experimental](experimental) examples tailored for NePS contributors. These examples provide insights and practices for experimental scenarios. -5. [template](template) which is a template for creating a neps program. +5. Navigate to [template](template) to find a basic fill-in template to kickstart your hyperparameter search with NePS. Use this template as a foundation for your projects, saving time and ensuring a structured starting point. diff --git a/neps_examples/basic_usage/defining_search_space/hpo_usage_example.py b/neps_examples/basic_usage/defining_search_space/hpo_usage_example.py new file mode 100644 index 00000000..a121d4df --- /dev/null +++ b/neps_examples/basic_usage/defining_search_space/hpo_usage_example.py @@ -0,0 +1,37 @@ +import logging +import time + +import numpy as np + +import neps + + +def run_pipeline( + float_name1, + float_name2, + categorical_name1, + categorical_name2, + integer_name1, + integer_name2, +): + # neps optimize to find values that maximizes sum, for demonstration only + loss = -float( + np.sum( + [float_name1, float_name2, categorical_name1, integer_name1, integer_name2] + ) + ) + if categorical_name2 == "a": + loss += 1 + + time.sleep(2) # For demonstration purposes only + return loss + + +logging.basicConfig(level=logging.INFO) +neps.run( + run_pipeline=run_pipeline, + pipeline_space="search_space_example.yaml", + root_directory="results/hyperparameters_example", + post_run_summary=True, + max_evaluations_total=15, +) diff --git a/neps_examples/basic_usage/defining_search_space/search_space_example.yaml b/neps_examples/basic_usage/defining_search_space/search_space_example.yaml new file mode 100644 index 00000000..27bd37c1 --- /dev/null +++ b/neps_examples/basic_usage/defining_search_space/search_space_example.yaml @@ -0,0 +1,26 @@ +search_space: + float_name1: + lower: 3e-5 + upper: 0.1 + + float_name2: + type: "float" # Optional, as neps infers type from 'lower' and 'upper' + lower: 1.7 + upper: 42.0 + log: true # Optional, default: False + + categorical_name1: + choices: [0, 1] + + categorical_name2: + type: cat + choices: ["a", "b", "c"] + + integer_name1: + lower: 32 + upper: 128 + is_fidelity: True # Optional, default: False + + integer_name2: + lower: -5 + upper: 5 diff --git a/neps_examples/convenience/neps_tblogger_tutorial.py b/neps_examples/convenience/neps_tblogger_tutorial.py index ea02a8dd..a70cc494 100644 --- a/neps_examples/convenience/neps_tblogger_tutorial.py +++ b/neps_examples/convenience/neps_tblogger_tutorial.py @@ -353,7 +353,7 @@ def run_pipeline(lr, optim, weight_decay): run_args = dict( run_pipeline=run_pipeline, pipeline_space=pipeline_space(), - root_directory="output", + root_directory="results/neps_tblogger_example", searcher="random_search", ) diff --git a/neps_examples/efficiency/multi_fidelity.py b/neps_examples/efficiency/multi_fidelity.py index 4239aee7..0731b1b5 100644 --- a/neps_examples/efficiency/multi_fidelity.py +++ b/neps_examples/efficiency/multi_fidelity.py @@ -37,6 +37,11 @@ def get_model_and_optimizer(learning_rate): return model, optimizer +# Important: Include the "pipeline_directory" and "previous_pipeline_directory" arguments +# in your run_pipeline function. This grants access to NePS's folder system and is +# critical for leveraging efficient multi-fidelity optimization strategies. + + def run_pipeline(pipeline_directory, previous_pipeline_directory, learning_rate, epoch): model, optimizer = get_model_and_optimizer(learning_rate) checkpoint_name = "checkpoint.pth" diff --git a/neps_examples/experimental/hierarchical_architecture_hierarchical_GP.py b/neps_examples/experimental/hierarchical_architecture_hierarchical_GP.py index 6fea9195..3db93bde 100644 --- a/neps_examples/experimental/hierarchical_architecture_hierarchical_GP.py +++ b/neps_examples/experimental/hierarchical_architecture_hierarchical_GP.py @@ -135,6 +135,7 @@ def run_pipeline(architecture): pipeline_space=pipeline_space, root_directory="results/hierarchical_architecture_example_new", max_evaluations_total=15, + searcher="bayesian_optimization", surrogate_model=surrogate_model, surrogate_model_args=surrogate_model_args, ) diff --git a/pyproject.toml b/pyproject.toml index 19c4336f..2867b998 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "neural-pipeline-search" -version = "v0.10.0" +version = "v0.11.1" description = "Neural Pipeline Search helps deep learning experts find the best neural pipeline." authors = [ "Danny Stoll ", @@ -27,6 +27,7 @@ classifiers = [ "Intended Audience :: Developers", "Intended Audience :: Science/Research", "Natural Language :: English", + "License :: OSI Approved :: Apache Software License", "Operating System :: POSIX :: Linux", "Operating System :: Microsoft :: Windows", "Operating System :: MacOS", @@ -38,48 +39,53 @@ classifiers = [ "Topic :: System :: Distributed Computing", ] packages = [ - { include = "neps", from = "src" }, - { include = "metahyper", from = "src" }, + { include = "neps" }, + { include = "metahyper", from = "neps"}, { include = "neps_examples" }, ] - [tool.poetry.dependencies] python = ">=3.8,<3.12" -ConfigSpace = "^0.4.19" -grakel = "^0.1.9" -numpy = "^1.23.0" -pandas = "^1.3.1" +ConfigSpace = "^0.7" +grakel = "^0.1" +numpy = "^1" +pandas = "^2" networkx = "^2.6.3" nltk = "^3.6.4" -path = "^16.2.0" -termcolor = "^1.1.0" -scipy = "^1.8" +#path = "^16.2.0" +#termcolor = "^1.1.0" +scipy = "^1" torch = ">=1.7.0,<=2.1, !=2.0.1, !=2.1.0" # fix from: https://stackoverflow.com/a/76647180 # torch = [ # {version = ">=1.7.0,<=2.1", markers = "sys_platform == 'darwin'"}, # Segfaults for macOS on github actions # {version = ">=1.7.0,<=2.1", markers = "sys_platform != 'darwin'"}, # ] -matplotlib = "^3.4" -statsmodels = "^0.13.2" -more-itertools = "^9.0.0" -portalocker = "^2.6.0" -seaborn = "^0.12.1" -pyyaml = "^6.0" -tensorboard = "^2.13" -cython = "^3.0.4" -torchvision = "<0.16.0" +matplotlib = "^3" +# statsmodels = "^0.13.2" +more-itertools = "^10" +portalocker = "^2" +seaborn = "^0.13" +pyyaml = "^6" +tensorboard = "^2" +# cython = "^3.0.4" [tool.poetry.group.dev.dependencies] -pre-commit = "^2.10" -mypy = "^0.930" -pytest = "^6.2.5" -types-PyYAML = "^6.0.12" -typing-extensions = "^4.0.1" -types-termcolor = "^1.1.2" +pre-commit = "^3" +mypy = "^1" +pytest = "^7" +types-PyYAML = "^6" +typing-extensions = "^4" +#types-termcolor = "^1.1.2" # jahs-bench = {git = "https://github.com/automl/jahs_bench_201.git", rev = "v1.0.2"} mkdocs-material = "^8.1.3" mike = "^1.1.2" +torchvision = "<0.16.0" # Used in examples + + +[tool.poetry.group.experimental] +optional = true + +[tool.poetry.group.experimental.dependencies] gpytorch = "1.8.0" [build-system] @@ -95,8 +101,8 @@ profile = 'black' line_length = 90 [tool.pytest.ini_options] -addopts = "--basetemp ./tests_tmpdir -m 'core_examples or yaml_api'" -markers = ["all_examples", "core_examples", "regression_all", "metahyper", "yaml_api", "summary_csv"] +addopts = "--basetemp ./tests_tmpdir -m 'neps_api or core_examples'" +markers = ["all_examples", "core_examples", "regression_all", "metahyper", "neps_api", "summary_csv"] filterwarnings = "ignore::DeprecationWarning:torch.utils.tensorboard.*:" [tool.mypy] diff --git a/src/metahyper/__init__.py b/src/metahyper/__init__.py deleted file mode 100644 index 4bcb998e..00000000 --- a/src/metahyper/__init__.py +++ /dev/null @@ -1,2 +0,0 @@ -from .api import ConfigResult, Sampler, read, run -from .utils import instance_from_map diff --git a/src/neps/optimizers/bayesian_optimization/acquisition_functions/__init__.py b/src/neps/optimizers/bayesian_optimization/acquisition_functions/__init__.py deleted file mode 100644 index aedb483f..00000000 --- a/src/neps/optimizers/bayesian_optimization/acquisition_functions/__init__.py +++ /dev/null @@ -1,43 +0,0 @@ -from __future__ import annotations - -from functools import partial -from typing import Callable - -from .ei import ComprehensiveExpectedImprovement -from .mf_ei import MFEI -from .ucb import UpperConfidenceBound, MF_UCB - - -AcquisitionMapping: dict[str, Callable] = { - "EI": partial( - ComprehensiveExpectedImprovement, - in_fill="best", - augmented_ei=False, - ), - "LogEI": partial( - ComprehensiveExpectedImprovement, - in_fill="best", - augmented_ei=False, - log_ei=True, - ), - # # Uses the augmented EI heuristic and changed the in-fill criterion to the best test location with - # # the highest *posterior mean*, which are preferred when the optimisation is noisy. - "AEI": partial( - ComprehensiveExpectedImprovement, - in_fill="posterior", - augmented_ei=True, - ), - "MFEI": partial( - MFEI, - in_fill="best", - augmented_ei=False, - ), - "UCB": partial( - UpperConfidenceBound, - maximize=False, - ), - "MF-UCB": partial( - MF_UCB, - maximize=False, - ), -} diff --git a/src/neps/optimizers/bayesian_optimization/acquisition_functions/mf_ei.py b/src/neps/optimizers/bayesian_optimization/acquisition_functions/mf_ei.py deleted file mode 100644 index f677f894..00000000 --- a/src/neps/optimizers/bayesian_optimization/acquisition_functions/mf_ei.py +++ /dev/null @@ -1,205 +0,0 @@ -# type: ignore -from typing import Any, Iterable, Tuple, Union - -import numpy as np -import pandas as pd -import torch -from torch.distributions import Normal - -from ....optimizers.utils import map_real_hyperparameters_from_tabular_ids -from ....search_spaces.search_space import SearchSpace -from ...multi_fidelity.utils import MFObservedData -from .ei import ComprehensiveExpectedImprovement - - -class MFEI(ComprehensiveExpectedImprovement): - def __init__( - self, - pipeline_space: SearchSpace, - surrogate_model_name: str = None, - augmented_ei: bool = False, - xi: float = 0.0, - in_fill: str = "best", - log_ei: bool = False, - ): - super().__init__(augmented_ei, xi, in_fill, log_ei) - self.pipeline_space = pipeline_space - self.surrogate_model_name = surrogate_model_name - self.surrogate_model = None - self.observations = None - self.b_step = None - - def get_budget_level(self, config) -> int: - return int((config.fidelity.value - config.fidelity.lower) / self.b_step) - - def preprocess(self, x: pd.Series) -> Tuple[Iterable, Iterable]: - """Prepares the configurations for appropriate EI calculation. - - Takes a set of points and computes the budget and incumbent for each point, as - required by the multi-fidelity Expected Improvement acquisition function. - """ - budget_list = [] - - if self.pipeline_space.has_tabular: - # preprocess tabular space differently - # expected input: IDs pertaining to the tabular data - # expected output: IDs pertaining to current observations and set of HPs - x = map_real_hyperparameters_from_tabular_ids(x, self.pipeline_space) - indices_to_drop = [] - for i, config in x.items(): - target_fidelity = config.fidelity.lower - if i <= max(self.observations.seen_config_ids): - # IMPORTANT to set the fidelity at which EI will be calculated only for - # the partial configs that have been observed already - target_fidelity = config.fidelity.value + self.b_step - - if np.less_equal(target_fidelity, config.fidelity.upper): - # only consider the configs with fidelity lower than the max fidelity - config.fidelity.value = target_fidelity - budget_list.append(self.get_budget_level(config)) - else: - # if the target_fidelity higher than the max drop the configuration - indices_to_drop.append(i) - else: - config.fidelity.value = target_fidelity - budget_list.append(self.get_budget_level(config)) - - # Drop unused configs - x.drop(labels=indices_to_drop, inplace=True) - - performances = self.observations.get_best_performance_for_each_budget() - inc_list = [] - for budget_level in budget_list: - if budget_level in performances.index: - inc = performances[budget_level] - else: - inc = self.observations.get_best_seen_performance() - inc_list.append(inc) - - return x, torch.Tensor(inc_list) - - def preprocess_gp(self, x: Iterable) -> Tuple[Iterable, Iterable]: - x, inc_list = self.preprocess(x) - return x.values.tolist(), inc_list - - def preprocess_deep_gp(self, x: Iterable) -> Tuple[Iterable, Iterable]: - x, inc_list = self.preprocess(x) - x_lcs = [] - for idx in x.index: - if idx in self.observations.df.index.levels[0]: - budget_level = self.get_budget_level(x[idx]) - lc = self.observations.extract_learning_curve(idx, budget_level) - else: - # initialize a learning curve with a place holder - # This is later padded accordingly for the Conv1D layer - lc = [0.0] - x_lcs.append(lc) - self.surrogate_model.set_prediction_learning_curves(x_lcs) - return x.values.tolist(), inc_list - - def preprocess_pfn(self, x: Iterable) -> Tuple[Iterable, Iterable, Iterable]: - """Prepares the configurations for appropriate EI calculation. - - Takes a set of points and computes the budget and incumbent for each point, as - required by the multi-fidelity Expected Improvement acquisition function. - """ - _x, inc_list = self.preprocess(x.copy()) - _x_tok = self.observations.tokenize(_x, as_tensor=True) - len_partial = len(self.observations.seen_config_ids) - z_min = x[0].fidelity.lower - # converting fidelity to the discrete budget level - # STRICT ASSUMPTION: fidelity is the first dimension - _x_tok[:len_partial, 0] = ( - _x_tok[:len_partial, 0] + self.b_step - z_min - ) / self.b_step - return _x_tok, _x, inc_list - - def eval(self, x: pd.Series, asscalar: bool = False) -> Tuple[np.ndarray, pd.Series]: - # _x = x.copy() # preprocessing needs to change the reference x Series so we don't copy here - if self.surrogate_model_name == "pfn": - _x_tok, _x, inc_list = self.preprocess_pfn( - x.copy() - ) # IMPORTANT change from vanilla-EI - ei = self.eval_pfn_ei(_x_tok, inc_list) - elif self.surrogate_model_name == "deep_gp": - _x, inc_list = self.preprocess_deep_gp( - x.copy() - ) # IMPORTANT change from vanilla-EI - ei = self.eval_gp_ei(_x, inc_list) - _x = pd.Series(_x, index=np.arange(len(_x))) - else: - _x, inc_list = self.preprocess_gp( - x.copy() - ) # IMPORTANT change from vanilla-EI - ei = self.eval_gp_ei(_x, inc_list) - _x = pd.Series(_x, index=np.arange(len(_x))) - - if ei.is_cuda: - ei = ei.cpu() - if len(x) > 1 and asscalar: - return ei.detach().numpy(), _x - else: - return ei.detach().numpy().item(), _x - - def eval_pfn_ei( - self, x: Iterable, inc_list: Iterable - ) -> Union[np.ndarray, torch.Tensor, float]: - """PFN-EI modified to preprocess samples and accept list of incumbents.""" - # x, inc_list = self.preprocess(x) # IMPORTANT change from vanilla-EI - # _x = x.copy() - ei = self.surrogate_model.get_ei(x.to(self.surrogate_model.device), inc_list) - if len(ei.shape) == 2: - ei = ei.flatten() - return ei - - def eval_gp_ei( - self, x: Iterable, inc_list: Iterable - ) -> Union[np.ndarray, torch.Tensor, float]: - """Vanilla-EI modified to preprocess samples and accept list of incumbents.""" - # x, inc_list = self.preprocess(x) # IMPORTANT change from vanilla-EI - _x = x.copy() - try: - mu, cov = self.surrogate_model.predict(_x) - except ValueError as e: - raise e - # return -1.0 # in case of error. return ei of -1 - std = torch.sqrt(torch.diag(cov)) - - mu_star = inc_list.to(mu.device) # IMPORTANT change from vanilla-EI - - gauss = Normal(torch.zeros(1, device=mu.device), torch.ones(1, device=mu.device)) - # u = (mu - mu_star - self.xi) / std - # ei = std * updf + (mu - mu_star - self.xi) * ucdf - if self.log_ei: - # we expect that f_min is in log-space - f_min = mu_star - self.xi - v = (f_min - mu) / std - ei = torch.exp(f_min) * gauss.cdf(v) - torch.exp( - 0.5 * torch.diag(cov) + mu - ) * gauss.cdf(v - std) - else: - u = (mu_star - mu - self.xi) / std - ucdf = gauss.cdf(u) - updf = torch.exp(gauss.log_prob(u)) - ei = std * updf + (mu_star - mu - self.xi) * ucdf - if self.augmented_ei: - sigma_n = self.surrogate_model.likelihood - ei *= 1.0 - torch.sqrt(torch.tensor(sigma_n, device=mu.device)) / torch.sqrt( - sigma_n + torch.diag(cov) - ) - return ei - - def set_state( - self, - pipeline_space: SearchSpace, - surrogate_model: Any, - observations: MFObservedData, - b_step: Union[int, float], - **kwargs, - ): - # overload to select incumbent differently through observations - self.pipeline_space = pipeline_space - self.surrogate_model = surrogate_model - self.observations = observations - self.b_step = b_step - return diff --git a/src/neps/optimizers/bayesian_optimization/models/__init__.py b/src/neps/optimizers/bayesian_optimization/models/__init__.py deleted file mode 100755 index 799545cd..00000000 --- a/src/neps/optimizers/bayesian_optimization/models/__init__.py +++ /dev/null @@ -1,16 +0,0 @@ -from .deepGP import DeepGP -from .gp import ComprehensiveGP -from .gp_hierarchy import ComprehensiveGPHierarchy - - -SurrogateModelMapping = { - "deep_gp": DeepGP, - "gp": ComprehensiveGP, - "gp_hierarchy": ComprehensiveGPHierarchy, -} - -try: - from .pfn import PFN_SURROGATE # only if available locally - SurrogateModelMapping.update({"pfn": PFN_SURROGATE}) -except: - pass diff --git a/src/neps/optimizers/utils.py b/src/neps/optimizers/utils.py deleted file mode 100644 index c203f4db..00000000 --- a/src/neps/optimizers/utils.py +++ /dev/null @@ -1,47 +0,0 @@ -import pandas as pd - -from ..search_spaces.search_space import SearchSpace - - -# def map_real_hyperparameters_from_tabular_ids( -# ids: pd.Series, pipeline_space: SearchSpace -# ) -> pd.Series: -# return x - - -def map_real_hyperparameters_from_tabular_ids( - x: pd.Series, pipeline_space: SearchSpace -) -> pd.Series: - """ Maps the tabular IDs to the actual HPs from the pipeline space. - - Args: - x (pd.Series): A pandas series with the tabular IDs. - TODO: Mention expected format of the series. - pipeline_space (SearchSpace): The pipeline space. - - Returns: - pd.Series: A pandas series with the actual HPs. - TODO: Mention expected format of the series. - """ - if len(x) == 0: - return x - # extract fid name - _x = x.iloc[0].hp_values() - _x.pop("id") - fid_name = list(_x.keys())[0] - for i in x.index.values: - # extracting actual HPs from the tabular space - _config = pipeline_space.custom_grid_table.loc[x.loc[i]["id"].value].to_dict() - # updating fidelities as per the candidate set passed - _config.update({fid_name: x.loc[i][fid_name].value}) - # placeholder config from the raw tabular space - config = pipeline_space.raw_tabular_space.sample( - patience=100, - user_priors=True, - ignore_fidelity=True # True allows fidelity to appear in the sample - ) - # copying values from table to placeholder config of type SearchSpace - config.load_from(_config) - # replacing the ID in the candidate set with the actual HPs of the config - x.loc[i] = config - return x diff --git a/tests/test_metahyper/test_locking.py b/tests/test_metahyper/test_locking.py index 2cd09499..dfdfcb05 100644 --- a/tests/test_metahyper/test_locking.py +++ b/tests/test_metahyper/test_locking.py @@ -8,7 +8,7 @@ from more_itertools import first_true -def launch_example_processes(n_workers: int=3) -> list: +def launch_example_processes(n_workers: int = 3) -> list: processes = [] for _ in range(n_workers): processes.append( @@ -90,7 +90,7 @@ def test_summary_csv(): config_data_df = pd.read_csv(summary_dir / "config_data.csv") assert config_data_df.shape[0] == 15 - assert (config_data_df["Status"] == "Complete").all() + assert (config_data_df["status"] == "complete").all() except Exception as e: raise e finally: diff --git a/tests/test_neps_api/solution_yamls/bo_custom_created.yaml b/tests/test_neps_api/solution_yamls/bo_custom_created.yaml new file mode 100644 index 00000000..c808c699 --- /dev/null +++ b/tests/test_neps_api/solution_yamls/bo_custom_created.yaml @@ -0,0 +1,5 @@ +searcher_name: baseoptimizer +searcher_alg: BayesianOptimization +searcher_selection: user-instantiation +neps_decision_tree: false +searcher_args: {} diff --git a/tests/test_neps_api/solution_yamls/bo_neps_decided.yaml b/tests/test_neps_api/solution_yamls/bo_neps_decided.yaml new file mode 100644 index 00000000..76935d6c --- /dev/null +++ b/tests/test_neps_api/solution_yamls/bo_neps_decided.yaml @@ -0,0 +1,13 @@ +searcher_name: bayesian_optimization +searcher_alg: bayesian_optimization +searcher_selection: neps-default +neps_decision_tree: true +searcher_args: + initial_design_size: 10 + surrogate_model: gp + acquisition: EI + log_prior_weighted: false + acquisition_sampler: mutation + random_interleave_prob: 0.0 + disable_priors: true + sample_default_first: false diff --git a/tests/test_neps_api/solution_yamls/bo_user_decided.yaml b/tests/test_neps_api/solution_yamls/bo_user_decided.yaml new file mode 100644 index 00000000..c87b923a --- /dev/null +++ b/tests/test_neps_api/solution_yamls/bo_user_decided.yaml @@ -0,0 +1,29 @@ +searcher_name: bayesian_optimization +searcher_alg: bayesian_optimization +searcher_selection: neps-default +neps_decision_tree: false +searcher_args: + initial_design_size: 10 + surrogate_model: ComprehensiveGPHierarchy + acquisition: EI + log_prior_weighted: false + acquisition_sampler: mutation + random_interleave_prob: 0.0 + disable_priors: true + sample_default_first: false + surrogate_model_args: + graph_kernels: + - WeisfeilerLehman + - WeisfeilerLehman + - WeisfeilerLehman + - WeisfeilerLehman + - WeisfeilerLehman + hp_kernels: [] + verbose: false + hierarchy_consider: + - 0 + - 1 + - 2 + - 3 + d_graph_features: 0 + vectorial_features: null diff --git a/tests/test_neps_api/solution_yamls/hyperband_custom_created.yaml b/tests/test_neps_api/solution_yamls/hyperband_custom_created.yaml new file mode 100644 index 00000000..602b965c --- /dev/null +++ b/tests/test_neps_api/solution_yamls/hyperband_custom_created.yaml @@ -0,0 +1,5 @@ +searcher_name: baseoptimizer +searcher_alg: Hyperband +searcher_selection: user-instantiation +neps_decision_tree: false +searcher_args: {} diff --git a/tests/test_neps_api/solution_yamls/hyperband_neps_decided.yaml b/tests/test_neps_api/solution_yamls/hyperband_neps_decided.yaml new file mode 100644 index 00000000..29bf8dec --- /dev/null +++ b/tests/test_neps_api/solution_yamls/hyperband_neps_decided.yaml @@ -0,0 +1,11 @@ +searcher_name: hyperband +searcher_alg: hyperband +searcher_selection: neps-default +neps_decision_tree: true +searcher_args: + eta: 3 + initial_design_type: max_budget + use_priors: false + random_interleave_prob: 0.0 + sample_default_first: false + sample_default_at_target: false diff --git a/tests/test_neps_api/solution_yamls/pibo_neps_decided.yaml b/tests/test_neps_api/solution_yamls/pibo_neps_decided.yaml new file mode 100644 index 00000000..dce4d40e --- /dev/null +++ b/tests/test_neps_api/solution_yamls/pibo_neps_decided.yaml @@ -0,0 +1,14 @@ +searcher_name: pibo +searcher_alg: bayesian_optimization +searcher_selection: neps-default +neps_decision_tree: true +searcher_args: + initial_design_size: 10 + surrogate_model: gp + acquisition: EI + log_prior_weighted: false + acquisition_sampler: mutation + random_interleave_prob: 0.0 + disable_priors: false + prior_confidence: medium + sample_default_first: false diff --git a/tests/test_neps_api/solution_yamls/priorband_bo_user_decided.yaml b/tests/test_neps_api/solution_yamls/priorband_bo_user_decided.yaml new file mode 100644 index 00000000..cd7c82ec --- /dev/null +++ b/tests/test_neps_api/solution_yamls/priorband_bo_user_decided.yaml @@ -0,0 +1,23 @@ +searcher_name: priorband_bo +searcher_alg: priorband +searcher_selection: neps-default +neps_decision_tree: false +searcher_args: + eta: 3 + initial_design_type: max_budget + prior_confidence: medium + random_interleave_prob: 0.0 + sample_default_first: true + sample_default_at_target: false + prior_weight_type: geometric + inc_sample_type: mutation + inc_mutation_rate: 0.5 + inc_mutation_std: 0.25 + inc_style: dynamic + model_based: true + modelling_type: joint + initial_design_size: 5 + surrogate_model: gp + acquisition: EI + log_prior_weighted: false + acquisition_sampler: mutation diff --git a/tests/test_neps_api/solution_yamls/priorband_neps_decided.yaml b/tests/test_neps_api/solution_yamls/priorband_neps_decided.yaml new file mode 100644 index 00000000..eb3b0179 --- /dev/null +++ b/tests/test_neps_api/solution_yamls/priorband_neps_decided.yaml @@ -0,0 +1,17 @@ +searcher_name: priorband +searcher_alg: priorband +searcher_selection: neps-default +neps_decision_tree: true +searcher_args: + eta: 3 + initial_design_type: max_budget + prior_confidence: medium + random_interleave_prob: 0.0 + sample_default_first: true + sample_default_at_target: false + prior_weight_type: geometric + inc_sample_type: mutation + inc_mutation_rate: 0.5 + inc_mutation_std: 0.25 + inc_style: dynamic + model_based: false diff --git a/tests/test_neps_api/solution_yamls/user_yaml_bo.yaml b/tests/test_neps_api/solution_yamls/user_yaml_bo.yaml new file mode 100644 index 00000000..156d67e4 --- /dev/null +++ b/tests/test_neps_api/solution_yamls/user_yaml_bo.yaml @@ -0,0 +1,14 @@ +searcher_name: optimizer_test +searcher_alg: bayesian_optimization +searcher_selection: user-yaml +neps_decision_tree: false +searcher_args: + initial_design_size: 5 + surrogate_model: gp + acquisition: EI + log_prior_weighted: false + acquisition_sampler: random + random_interleave_prob: 0.1 + disable_priors: false + prior_confidence: high + sample_default_first: false diff --git a/tests/test_neps_api/test_api.py b/tests/test_neps_api/test_api.py new file mode 100644 index 00000000..a50b91d1 --- /dev/null +++ b/tests/test_neps_api/test_api.py @@ -0,0 +1,130 @@ +import logging +import os +import runpy +from pathlib import Path + +import pytest +import yaml + + +# To change the working directly into the tmp_path when testing function +@pytest.fixture(autouse=True) +def use_tmpdir(tmp_path, request): + os.chdir(tmp_path) + yield + os.chdir(request.config.invocation_dir) + + +# https://stackoverflow.com/a/59745629 +# Fail tests if there is a logging.error +@pytest.fixture(autouse=True) +def no_logs_gte_error(caplog): + yield + errors = [ + record for record in caplog.get_records("call") if record.levelno >= logging.ERROR + ] + assert not errors + + +testing_scripts = [ + "default_neps", + "baseoptimizer_neps", + "user_yaml_neps", +] + +examples_folder = Path(__file__, "..", "testing_scripts").resolve() +solution_folder = Path(__file__, "..", "solution_yamls").resolve() +neps_api_example_script = [ + examples_folder / f"{example}.py" for example in testing_scripts +] + + +@pytest.mark.neps_api +def test_default_examples(tmp_path): + # Running the example files holding multiple neps.run commands. + + runpy.run_path( + neps_api_example_script[0], + run_name="__main__", + ) + + # Testing each folder with its corresponding expected dictionary + for folder_name in os.listdir(tmp_path): + folder_path = os.path.join(tmp_path, folder_name) + + assert os.path.exists(folder_path), f"Directory does not exist: {folder_path}" + + info_yaml_path = os.path.join(folder_path, ".optimizer_info.yaml") + + assert os.path.exists( + str(info_yaml_path) + ), f"File does not exist: {info_yaml_path}" + + # Load the YAML file + with open(str(info_yaml_path)) as yaml_config: + loaded_data = yaml.safe_load(yaml_config) + + with open(str(solution_folder / (folder_name + ".yaml"))) as solution_yaml: + expected_data = yaml.safe_load(solution_yaml) + + assert loaded_data == expected_data + + +@pytest.mark.neps_api +def test_baseoptimizer_examples(tmp_path): + # Running the example files holding multiple neps.run commands. + + runpy.run_path( + neps_api_example_script[1], + run_name="__main__", + ) + + # Testing each folder with its corresponding expected dictionary + for folder_name in os.listdir(tmp_path): + folder_path = os.path.join(tmp_path, folder_name) + + assert os.path.exists(folder_path), f"Directory does not exist: {folder_path}" + + info_yaml_path = os.path.join(folder_path, ".optimizer_info.yaml") + + assert os.path.exists( + str(info_yaml_path) + ), f"File does not exist: {info_yaml_path}" + + # Load the YAML file + with open(str(info_yaml_path)) as yaml_config: + loaded_data = yaml.safe_load(yaml_config) + + with open(str(solution_folder / (folder_name + ".yaml"))) as solution_yaml: + expected_data = yaml.safe_load(solution_yaml) + + assert loaded_data == expected_data + + +@pytest.mark.neps_api +def test_user_created_yaml_examples(tmp_path): + runpy.run_path( + neps_api_example_script[2], + run_name="__main__", + ) + + # Testing each folder with its corresponding expected dictionary + for folder_name in os.listdir(tmp_path): + folder_path = os.path.join(tmp_path, folder_name) + + assert os.path.exists(folder_path), f"Directory does not exist: {folder_path}" + + info_yaml_path = os.path.join(folder_path, ".optimizer_info.yaml") + + assert os.path.exists( + str(info_yaml_path) + ), f"File does not exist: {info_yaml_path}" + + # Load the YAML file + with open(str(info_yaml_path)) as yaml_config: + loaded_data = yaml.safe_load(yaml_config) + + with open(str(solution_folder / (folder_name + ".yaml"))) as solution_yaml: + expected_data = yaml.safe_load(solution_yaml) + + assert loaded_data == expected_data diff --git a/tests/test_neps_api/test_yaml_api.py b/tests/test_neps_api/test_yaml_api.py deleted file mode 100644 index 364dc49b..00000000 --- a/tests/test_neps_api/test_yaml_api.py +++ /dev/null @@ -1,98 +0,0 @@ -import logging -import os -import runpy -from pathlib import Path - -import pytest -import yaml - - -# To change the working directly into the tmp_path when testing function -@pytest.fixture(autouse=True) -def use_tmpdir(tmp_path, request): - os.chdir(tmp_path) - yield - os.chdir(request.config.invocation_dir) - - -# https://stackoverflow.com/a/59745629 -# Fail tests if there is a logging.error -@pytest.fixture(autouse=True) -def no_logs_gte_error(caplog): - yield - errors = [ - record for record in caplog.get_records("call") if record.levelno >= logging.ERROR - ] - assert not errors - - -# Expected outcomes of the optimizer YAML according to different cases of neps.run -# all based on the examples in tests/test_neps_api/examples_test_api.py -expected_dicts = { - "priorband_bo_user_decided": { - "searcher_name": "priorband_bo", - "searcher_alg": "priorband", - "user_defined_searcher": True, - "searcher_args_user_modified": True, - }, - "priorband_neps_decided": { - "searcher_name": "priorband", - "searcher_alg": "priorband", - "user_defined_searcher": False, - "searcher_args_user_modified": False, - }, - "bo_neps_decided": { - "searcher_name": "bayesian_optimization", - "searcher_alg": "bayesian_optimization", - "user_defined_searcher": False, - "searcher_args_user_modified": False, - }, - "pibo_neps_decided": { - "searcher_name": "pibo", - "searcher_alg": "bayesian_optimization", - "user_defined_searcher": False, - "searcher_args_user_modified": False, - }, - "hyperband_neps_decided": { - "searcher_name": "hyperband", - "searcher_alg": "hyperband", - "user_defined_searcher": False, - "searcher_args_user_modified": False, - }, - "bo_custom_created": { - "searcher_name": "custom", - "searcher_alg": "BayesianOptimization", - "user_defined_searcher": True, - "searcher_args_user_modified": False, - }, -} - - -yaml_api_example = "examples_test_api" # Run locally and on github actions - -examples_folder = Path(__file__, "..").resolve() -yaml_api_example_script = examples_folder / f"{yaml_api_example}.py" - - -@pytest.mark.yaml_api -def test_core_examples(tmp_path): - # Running the example files holding multiple neps.run commands. - runpy.run_path(yaml_api_example_script, run_name="__main__") - - # Testing each folder with its corresponding expected dictionary - for folder_name in os.listdir(tmp_path): - folder_path = os.path.join(tmp_path, folder_name) - - assert os.path.exists(folder_path), f"Directory does not exist: {folder_path}" - - info_yaml_path = os.path.join(folder_path, ".optimizer_info.yaml") - - assert os.path.exists( - str(info_yaml_path) - ), f"File does not exist: {info_yaml_path}" - - # Load the YAML file - with open(str(info_yaml_path)) as yaml_config: - loaded_data = yaml.safe_load(yaml_config) - - assert loaded_data == expected_dicts[folder_name] diff --git a/tests/test_neps_api/testing_scripts/baseoptimizer_neps.py b/tests/test_neps_api/testing_scripts/baseoptimizer_neps.py new file mode 100644 index 00000000..1fe9a219 --- /dev/null +++ b/tests/test_neps_api/testing_scripts/baseoptimizer_neps.py @@ -0,0 +1,51 @@ +import logging + +import neps +from neps.optimizers.bayesian_optimization.optimizer import BayesianOptimization +from neps.optimizers.multi_fidelity.hyperband import Hyperband +from neps.search_spaces.search_space import SearchSpace + +pipeline_space_fidelity = dict( + val1=neps.FloatParameter(lower=-10, upper=10), + val2=neps.IntegerParameter(lower=1, upper=5, is_fidelity=True), +) + +pipeline_space = dict( + val1=neps.FloatParameter(lower=-10, upper=10), + val2=neps.IntegerParameter(lower=1, upper=5), +) + + +def run_pipeline(val1, val2): + loss = val1 * val2 + return loss + + +def run_pipeline_fidelity(val1, val2): + loss = val1 * val2 + return {"loss": loss, "cost": 1} + + +logging.basicConfig(level=logging.INFO) + +# Case 1: Testing BaseOptimizer as searcher with Bayesian Optimization +search_space = SearchSpace(**pipeline_space) +my_custom_searcher_1 = BayesianOptimization( + pipeline_space=search_space, initial_design_size=5 +) +neps.run( + run_pipeline=run_pipeline, + root_directory="bo_custom_created", + max_evaluations_total=1, + searcher=my_custom_searcher_1, +) + +# Case 2: Testing BaseOptimizer as searcher with Hyperband +search_space_fidelity = SearchSpace(**pipeline_space_fidelity) +my_custom_searcher_2 = Hyperband(pipeline_space=search_space_fidelity, budget=1) +neps.run( + run_pipeline=run_pipeline_fidelity, + root_directory="hyperband_custom_created", + max_cost_total=1, + searcher=my_custom_searcher_2, +) diff --git a/tests/test_neps_api/examples_test_api.py b/tests/test_neps_api/testing_scripts/default_neps.py similarity index 67% rename from tests/test_neps_api/examples_test_api.py rename to tests/test_neps_api/testing_scripts/default_neps.py index 8738fac2..5384042a 100644 --- a/tests/test_neps_api/examples_test_api.py +++ b/tests/test_neps_api/testing_scripts/default_neps.py @@ -1,8 +1,10 @@ import logging import neps -from neps.optimizers.bayesian_optimization.optimizer import BayesianOptimization -from neps.search_spaces.search_space import SearchSpace +from neps.optimizers.bayesian_optimization.kernels import GraphKernelMapping +from neps.optimizers.bayesian_optimization.models.gp_hierarchy import ( + ComprehensiveGPHierarchy, +) pipeline_space_fidelity_priors = dict( val1=neps.FloatParameter(lower=-10, upper=10, default=1), @@ -34,6 +36,9 @@ def run_pipeline(val1, val2): # Testing user input "priorband_bo" with argument changes that should be # accepted in the run. + +# Case 1: Choosing priorband + neps.run( run_pipeline=run_pipeline, pipeline_space=pipeline_space_fidelity_priors, @@ -44,6 +49,39 @@ def run_pipeline(val1, val2): eta=3, ) +# Case 2: Choosing Bayesian optimization + +early_hierarchies_considered = "0_1_2_3" +hierarchy_considered = [int(hl) for hl in early_hierarchies_considered.split("_")] +graph_kernels = ["wl"] * (len(hierarchy_considered) + 1) +wl_h = [2, 1] + [2] * (len(hierarchy_considered) - 1) +graph_kernels = [ + GraphKernelMapping[kernel]( + h=wl_h[j], + oa=False, + se_kernel=None, + ) + for j, kernel in enumerate(graph_kernels) +] +surrogate_model = ComprehensiveGPHierarchy +surrogate_model_args = { + "graph_kernels": graph_kernels, + "hp_kernels": [], + "verbose": False, + "hierarchy_consider": hierarchy_considered, + "d_graph_features": 0, + "vectorial_features": None, +} +neps.run( + run_pipeline=run_pipeline, + pipeline_space=pipeline_space_not_fidelity, + root_directory="bo_user_decided", + max_evaluations_total=1, + searcher="bayesian_optimization", + surrogate_model=surrogate_model, + surrogate_model_args=surrogate_model_args, +) + # Testing neps decision tree on deciding the searcher and rejecting the # additional arguments. @@ -82,16 +120,3 @@ def run_pipeline(val1, val2): max_evaluations_total=1, eta=2, ) - -# Testing neps when the user creates their own custom searcher -search_space = SearchSpace(**pipeline_space_fidelity) -my_custom_searcher = BayesianOptimization( - pipeline_space=search_space, initial_design_size=5 -) -neps.run( - run_pipeline=run_pipeline, - pipeline_space=pipeline_space_not_fidelity, - root_directory="bo_custom_created", - max_evaluations_total=1, - searcher=my_custom_searcher, -) diff --git a/tests/test_neps_api/testing_scripts/user_yaml_neps.py b/tests/test_neps_api/testing_scripts/user_yaml_neps.py new file mode 100644 index 00000000..6a93c4bd --- /dev/null +++ b/tests/test_neps_api/testing_scripts/user_yaml_neps.py @@ -0,0 +1,31 @@ +import logging +import os + +import neps + +pipeline_space = dict( + val1=neps.FloatParameter(lower=-10, upper=10), + val2=neps.IntegerParameter(lower=1, upper=5), +) + + +def run_pipeline(val1, val2): + loss = val1 * val2 + return loss + + +logging.basicConfig(level=logging.INFO) + +# Testing using created yaml with api +script_directory = os.path.dirname(os.path.abspath(__file__)) +parent_directory = os.path.join(script_directory, os.pardir) +searcher_path = os.path.join(parent_directory, "testing_yaml") +neps.run( + run_pipeline=run_pipeline, + pipeline_space=pipeline_space, + root_directory="user_yaml_bo", + max_evaluations_total=1, + searcher="optimizer_test", + searcher_path=searcher_path, + initial_design_size=5, +) diff --git a/tests/test_neps_api/testing_yaml/optimizer_test.yaml b/tests/test_neps_api/testing_yaml/optimizer_test.yaml new file mode 100644 index 00000000..cad2221d --- /dev/null +++ b/tests/test_neps_api/testing_yaml/optimizer_test.yaml @@ -0,0 +1,12 @@ +searcher_init: + algorithm: bayesian_optimization +searcher_kwargs: # Specific arguments depending on the searcher + initial_design_size: 7 + surrogate_model: gp + acquisition: EI + log_prior_weighted: false + acquisition_sampler: random + random_interleave_prob: 0.1 + disable_priors: false + prior_confidence: high + sample_default_first: false \ No newline at end of file diff --git a/tests/test_yaml_search_space/config_including_unknown_types.yaml b/tests/test_yaml_search_space/config_including_unknown_types.yaml new file mode 100644 index 00000000..790f473d --- /dev/null +++ b/tests/test_yaml_search_space/config_including_unknown_types.yaml @@ -0,0 +1,20 @@ +pipeline_space: + learning_rate: + type: numerical + lower: 0.00001 + upper: 0.1 + log: true + + num_epochs: + type: numerical + lower: 3 + upper: 30 + is_fidelity: True + + optimizer: + type: numerical + choices: ["adam", "sgd", "rmsprop"] + + dropout_rate: + type: numerical + value: 0.5 diff --git a/tests/test_yaml_search_space/config_including_wrong_types.yaml b/tests/test_yaml_search_space/config_including_wrong_types.yaml new file mode 100644 index 00000000..df3a4602 --- /dev/null +++ b/tests/test_yaml_search_space/config_including_wrong_types.yaml @@ -0,0 +1,20 @@ +pipeline_space: + learning_rate: + type: int + lower: 0.00001 + upper: 0.1 + log: true + + num_epochs: + type: int + lower: 3 + upper: 30 + is_fidelity: True + + optimizer: + type: cat + choices: ["adam", "sgd", "rmsprop"] + + dropout_rate: + type: const + value: 0.5 diff --git a/tests/test_yaml_search_space/correct_config.yaml b/tests/test_yaml_search_space/correct_config.yaml new file mode 100644 index 00000000..895efa38 --- /dev/null +++ b/tests/test_yaml_search_space/correct_config.yaml @@ -0,0 +1,32 @@ +pipeline_space: + param_float1: + lower: 0.00001 + upper: 0.1 + log: TRUE + is_fidelity: off + + param_int1: + lower: -3 + upper: 30 + log: false + is_fidelity: on + param_int2: + type: int + lower: 1E2 + upper: 3e4 + log: ON + is_fidelity: FALSE + + param_float2: + lower: 3.3e-5 + upper: 1.5E-1 + + param_cat: + choices: [2, "sgd", 10e-3] + + param_const1: + value: 0.5 + + param_const2: + value: 1e3 + is_fidelity: TRUE diff --git a/tests/test_yaml_search_space/correct_config_including_priors.yml b/tests/test_yaml_search_space/correct_config_including_priors.yml new file mode 100644 index 00000000..a73f2157 --- /dev/null +++ b/tests/test_yaml_search_space/correct_config_including_priors.yml @@ -0,0 +1,22 @@ +pipeline_space: + learning_rate: + lower: 0.00001 + upper: 0.1 + log: true + default: 3.3E-2 + default_confidence: high + + num_epochs: + lower: 3 + upper: 30 + is_fidelity: True + default: 1e1 + + optimizer: + choices: [adam, 90E-3, rmsprop] + default: 90E-3 + default_confidence: "medium" + + dropout_rate: + value: 1E3 + is_fidelity: true diff --git a/tests/test_yaml_search_space/correct_config_including_types.yaml b/tests/test_yaml_search_space/correct_config_including_types.yaml new file mode 100644 index 00000000..60fc4995 --- /dev/null +++ b/tests/test_yaml_search_space/correct_config_including_types.yaml @@ -0,0 +1,37 @@ +pipeline_space: + param_float1: + type: float + lower: 0.00001 + upper: 1e-1 + log: true + + param_int1: + type: integer + lower: -3 + upper: 30 + is_fidelity: True + + param_int2: + type: "int" + lower: 1e2 + upper: 3E4 + log: true + is_fidelity: false + + param_float2: + type: "float" + lower: 3.3e-5 + upper: 1.5E-1 + + param_cat: + type: cat + choices: [2, "sgd", 10E-3] + + param_const1: + type: const + value: 0.5 + + param_const2: + type: const + value: 1e3 + is_fidelity: true diff --git a/tests/test_yaml_search_space/inconsistent_types_config.yml b/tests/test_yaml_search_space/inconsistent_types_config.yml new file mode 100644 index 00000000..797658c4 --- /dev/null +++ b/tests/test_yaml_search_space/inconsistent_types_config.yml @@ -0,0 +1,17 @@ +pipeline_space: + learning_rate: + lower: "string" # Lower is now a string + upper: 1e3 + log: true + + num_epochs: + lower: 3 + upper: 30 + is_fidelity: True + + optimizer: + choices: ["adam", "sgd", "rmsprop"] + + dropout_rate: + value: 0.5 + is_fidelity: True diff --git a/tests/test_yaml_search_space/inconsistent_types_config2.yml b/tests/test_yaml_search_space/inconsistent_types_config2.yml new file mode 100644 index 00000000..d126b52e --- /dev/null +++ b/tests/test_yaml_search_space/inconsistent_types_config2.yml @@ -0,0 +1,18 @@ +pipeline_space: + learning_rate: + type: int + lower: 2.3 # float + upper: 1e3 + log: true + + num_epochs: + lower: 3 + upper: 30 + is_fidelity: True + + optimizer: + choices: ["adam", "sgd", "rmsprop"] + + dropout_rate: + value: 0.5 + is_fidelity: True diff --git a/tests/test_yaml_search_space/incorrect_config.txt b/tests/test_yaml_search_space/incorrect_config.txt new file mode 100644 index 00000000..cff7baa4 --- /dev/null +++ b/tests/test_yaml_search_space/incorrect_config.txt @@ -0,0 +1,5 @@ +pipeline_space # : is missing + learning_rate: + lower: 0.00001 + upper: 0.1 + log: true diff --git a/tests/test_yaml_search_space/missing_key_config.yml b/tests/test_yaml_search_space/missing_key_config.yml new file mode 100644 index 00000000..db0f6361 --- /dev/null +++ b/tests/test_yaml_search_space/missing_key_config.yml @@ -0,0 +1,15 @@ +pipeline_space: + learning_rate: + lower: 0.00001 + log: true + + num_epochs: + lower: 3 + upper: 30 + is_fidelity: True + + optimizer: + choices: ["adam", "sgd", "rmsprop"] + + dropout_rate: + value: 0.5 diff --git a/tests/test_yaml_search_space/not_allowed_key_config.yml b/tests/test_yaml_search_space/not_allowed_key_config.yml new file mode 100644 index 00000000..59887401 --- /dev/null +++ b/tests/test_yaml_search_space/not_allowed_key_config.yml @@ -0,0 +1,26 @@ +pipeline_space: + float_name1: + lower: 3e-5 + upper: 0.1 + + float_name2: + type: "float" # Optional, as neps infers type from 'lower' and 'upper' + lower: 1.7 + upper: 42.0 + log: true + + categorical_name1: + choices: [0, 1] + + categorical_name2: + type: cat + choices: ["a", "b", "c"] + + integer_name1: + lower: 32 + upper: 128 + fidelity: True # error, fidelity instead of is_fidelity + + integer_name2: + lower: -5 + upper: 5 diff --git a/tests/test_yaml_search_space/test_search_space.py b/tests/test_yaml_search_space/test_search_space.py new file mode 100644 index 00000000..c5cfed06 --- /dev/null +++ b/tests/test_yaml_search_space/test_search_space.py @@ -0,0 +1,159 @@ +from pathlib import Path + +import pytest +from neps.search_spaces.search_space import ( + SearchSpaceFromYamlFileError, + pipeline_space_from_yaml, +) + +from neps import CategoricalParameter, ConstantParameter, FloatParameter, IntegerParameter + + +@pytest.mark.neps_api +def test_correct_yaml_files(): + def test_correct_yaml_file(path): + """Test the function with a correctly formatted YAML file.""" + pipeline_space = pipeline_space_from_yaml(path) + assert isinstance(pipeline_space, dict) + assert isinstance(pipeline_space["param_float1"], FloatParameter) + assert pipeline_space["param_float1"].lower == 0.00001 + assert pipeline_space["param_float1"].upper == 0.1 + assert pipeline_space["param_float1"].log is True + assert pipeline_space["param_float1"].is_fidelity is False + assert pipeline_space["param_float1"].default is None + assert pipeline_space["param_float1"].default_confidence_score == 0.5 + assert isinstance(pipeline_space["param_int1"], IntegerParameter) + assert pipeline_space["param_int1"].lower == -3 + assert pipeline_space["param_int1"].upper == 30 + assert pipeline_space["param_int1"].log is False + assert pipeline_space["param_int1"].is_fidelity is True + assert pipeline_space["param_int1"].default is None + assert pipeline_space["param_int1"].default_confidence_score == 0.5 + assert isinstance(pipeline_space["param_int2"], IntegerParameter) + assert pipeline_space["param_int2"].lower == 100 + assert pipeline_space["param_int2"].upper == 30000 + assert pipeline_space["param_int2"].log is True + assert pipeline_space["param_int2"].is_fidelity is False + assert pipeline_space["param_int2"].default is None + assert pipeline_space["param_int2"].default_confidence_score == 0.5 + assert isinstance(pipeline_space["param_float2"], FloatParameter) + assert pipeline_space["param_float2"].lower == 3.3e-5 + assert pipeline_space["param_float2"].upper == 0.15 + assert pipeline_space["param_float2"].log is False + assert pipeline_space["param_float2"].is_fidelity is False + assert pipeline_space["param_float2"].default is None + assert pipeline_space["param_float2"].default_confidence_score == 0.5 + assert isinstance(pipeline_space["param_cat"], CategoricalParameter) + assert pipeline_space["param_cat"].choices == [2, "sgd", 10e-3] + assert pipeline_space["param_cat"].is_fidelity is False + assert pipeline_space["param_cat"].default is None + assert pipeline_space["param_cat"].default_confidence_score == 2 + assert isinstance(pipeline_space["param_const1"], ConstantParameter) + assert pipeline_space["param_const1"].value == 0.5 + assert pipeline_space["param_const1"].is_fidelity is False + assert isinstance(pipeline_space["param_const2"], ConstantParameter) + assert pipeline_space["param_const2"].value == 1e3 + assert pipeline_space["param_const2"].is_fidelity is True + + test_correct_yaml_file("tests/test_yaml_search_space/correct_config.yaml") + test_correct_yaml_file( + "tests/test_yaml_search_space/correct_config_including_types" ".yaml" + ) + + +@pytest.mark.neps_api +def test_correct_including_priors_yaml_file(): + """Test the function with a correctly formatted YAML file.""" + pipeline_space = pipeline_space_from_yaml( + "tests/test_yaml_search_space/correct_config_including_priors.yml" + ) + assert isinstance(pipeline_space, dict) + assert isinstance(pipeline_space["learning_rate"], FloatParameter) + assert pipeline_space["learning_rate"].lower == 0.00001 + assert pipeline_space["learning_rate"].upper == 0.1 + assert pipeline_space["learning_rate"].log is True + assert pipeline_space["learning_rate"].is_fidelity is False + assert pipeline_space["learning_rate"].default == 3.3e-2 + assert pipeline_space["learning_rate"].default_confidence_score == 0.125 + assert isinstance(pipeline_space["num_epochs"], IntegerParameter) + assert pipeline_space["num_epochs"].lower == 3 + assert pipeline_space["num_epochs"].upper == 30 + assert pipeline_space["num_epochs"].log is False + assert pipeline_space["num_epochs"].is_fidelity is True + assert pipeline_space["num_epochs"].default == 10 + assert pipeline_space["num_epochs"].default_confidence_score == 0.5 + assert isinstance(pipeline_space["optimizer"], CategoricalParameter) + assert pipeline_space["optimizer"].choices == ["adam", 90e-3, "rmsprop"] + assert pipeline_space["optimizer"].is_fidelity is False + assert pipeline_space["optimizer"].default == 90e-3 + assert pipeline_space["optimizer"].default_confidence_score == 4 + assert isinstance(pipeline_space["dropout_rate"], ConstantParameter) + assert pipeline_space["dropout_rate"].value == 1e3 + assert pipeline_space["dropout_rate"].default == 1e3 + + +@pytest.mark.neps_api +def test_incorrect_yaml_file(): + """Test the function with an incorrectly formatted YAML file.""" + with pytest.raises(SearchSpaceFromYamlFileError) as excinfo: + pipeline_space_from_yaml( + Path("tests/test_yaml_search_space/incorrect_config.txt") + ) + assert excinfo.value.exception_type == "ValueError" + + +@pytest.mark.neps_api +def test_yaml_file_with_missing_key(): + """Test the function with a YAML file missing a required key.""" + with pytest.raises(SearchSpaceFromYamlFileError) as excinfo: + pipeline_space_from_yaml("tests/test_yaml_search_space/missing_key_config.yml") + assert excinfo.value.exception_type == "KeyError" + + +@pytest.mark.neps_api +def test_yaml_file_with_inconsistent_types(): + """Test the function with a YAML file having inconsistent types for + 'lower' and 'upper'.""" + with pytest.raises(SearchSpaceFromYamlFileError) as excinfo: + pipeline_space_from_yaml( + "tests/test_yaml_search_space/inconsistent_types_config.yml" + ) + assert str(excinfo.value.exception_type == "TypeError") + with pytest.raises(SearchSpaceFromYamlFileError) as excinfo: + pipeline_space_from_yaml( + Path("tests/test_yaml_search_space/inconsistent_types_config2.yml") + ) + assert excinfo.value.exception_type == "TypeError" + + +@pytest.mark.neps_api +def test_yaml_file_including_wrong_types(): + """Test the function with a YAML file that defines the wrong but existing type + int to float as an optional argument""" + with pytest.raises(SearchSpaceFromYamlFileError) as excinfo: + pipeline_space_from_yaml( + "tests/test_yaml_search_space/config_including_wrong_types.yaml" + ) + assert excinfo.value.exception_type == "TypeError" + + +@pytest.mark.neps_api +def test_yaml_file_including_unkown_types(): + """Test the function with a YAML file that defines an unknown type as an optional + argument""" + with pytest.raises(SearchSpaceFromYamlFileError) as excinfo: + pipeline_space_from_yaml( + "tests/test_yaml_search_space/config_including_unknown_types.yaml" + ) + assert excinfo.value.exception_type == "TypeError" + + +@pytest.mark.neps_api +def test_yaml_file_including_not_allowed_parameter_keys(): + """Test the function with a YAML file that defines an unknown type as an optional + argument""" + with pytest.raises(SearchSpaceFromYamlFileError) as excinfo: + pipeline_space_from_yaml( + "tests/test_yaml_search_space/not_allowed_key_config.yml" + ) + assert excinfo.value.exception_type == "KeyError" From 98ee2108d388bb7461a549ee90d0415d81e8fe4c Mon Sep 17 00:00:00 2001 From: karibbov Date: Mon, 8 Apr 2024 14:27:59 +0200 Subject: [PATCH 2/6] pre-commit hook auto-changes --- .github/workflows/tests.yaml | 1 - README.md | 46 +-- docs/README.md | 29 +- docs/analyse.md | 61 ++-- docs/getting_started.md | 43 ++- docs/installation.md | 3 +- docs/neps_run.md | 99 ++++--- docs/optimizers.md | 1 + docs/parallelization.md | 2 +- docs/pipeline_space.md | 149 +++++----- docs/run_pipeline.md | 21 +- neps/metahyper/__init__.py | 2 +- neps/metahyper/api.py | 8 +- .../acquisition_functions/__init__.py | 7 +- .../acquisition_functions/mf_ei.py | 37 ++- .../acquisition_functions/mf_pi.py | 67 +++-- .../acquisition_functions/mf_two_step.py | 99 +++---- .../acquisition_functions/mf_ucb.py | 36 +-- .../acquisition_functions/ucb.py | 4 +- .../freeze_thaw_sampler.py | 7 +- .../bayesian_optimization/mf_tpe.py | 2 +- .../bayesian_optimization/models/DPL.py | 267 ++++++++++-------- .../bayesian_optimization/models/__init__.py | 2 +- .../bayesian_optimization/models/deepGP.py | 29 +- .../bayesian_optimization/optimizer.py | 2 +- .../default_searchers/priorband.yaml | 2 +- .../default_searchers/priorband_bo.yaml | 2 +- neps/optimizers/multi_fidelity/mf_bo.py | 24 +- .../multi_fidelity_prior/async_priorband.py | 2 +- .../multi_fidelity_prior/priorband.py | 2 +- neps/optimizers/utils.py | 13 +- neps/plot/tensorboard_eval.py | 2 +- neps/search_spaces/architecture/graph.py | 2 +- neps/search_spaces/hyperparameters/integer.py | 6 +- neps/search_spaces/search_space.py | 8 +- neps/search_spaces/yaml_search_space_utils.py | 5 +- neps/status/status.py | 11 +- neps/utils/common.py | 9 +- neps_examples/README.md | 8 +- .../architecture_and_hyperparameters.py | 1 + .../convenience/neps_tblogger_tutorial.py | 2 +- ...erarchical_architecture_hierarchical_GP.py | 6 +- neps_examples/template/lightning_template.py | 2 +- neps_examples/template/priorband_template.py | 2 +- .../testing_scripts/baseoptimizer_neps.py | 3 +- .../testing_scripts/default_neps.py | 5 +- .../testing_yaml/optimizer_test.yaml | 2 +- 47 files changed, 604 insertions(+), 539 deletions(-) diff --git a/.github/workflows/tests.yaml b/.github/workflows/tests.yaml index 54b648f5..4c52f9d5 100644 --- a/.github/workflows/tests.yaml +++ b/.github/workflows/tests.yaml @@ -42,4 +42,3 @@ jobs: - name: Run pytest timeout-minutes: 15 run: poetry run pytest -m "all_examples or metahyper or neps_api or summary_csv" - diff --git a/README.md b/README.md index a83ac11d..fd2f6c64 100644 --- a/README.md +++ b/README.md @@ -11,27 +11,30 @@ NePS houses recently published and some more well-established algorithms that ar Take a look at our [documentation](https://automl.github.io/neps/latest/) and continue following through current README for instructions on how to use NePS! - ## Key Features In addition to the common features offered by traditional HPO and NAS libraries, NePS stands out with the following key features: 1. [**Hyperparameter Optimization (HPO) With Prior Knowledge:**](neps_examples/template/priorband_template.py) - - NePS excels in efficiently tuning hyperparameters using algorithms that enable users to make use of their prior knowledge within the search space. This is leveraged by the insights presented in: - - [PriorBand: Practical Hyperparameter Optimization in the Age of Deep Learning](https://arxiv.org/abs/2306.12370) - - [πBO: Augmenting Acquisition Functions with User Beliefs for Bayesian Optimization](https://arxiv.org/abs/2204.11051) -2. [**Neural Architecture Search (NAS) With Context-free Grammar Search Spaces:**](neps_examples/basic_usage/architecture.py) - - NePS is equipped to handle context-free grammar search spaces, providing advanced capabilities for designing and optimizing architectures. this is leveraged by the insights presented in: - - [Construction of Hierarchical Neural Architecture Search Spaces based on Context-free Grammars](https://arxiv.org/abs/2211.01842) + - NePS excels in efficiently tuning hyperparameters using algorithms that enable users to make use of their prior knowledge within the search space. This is leveraged by the insights presented in: + - [PriorBand: Practical Hyperparameter Optimization in the Age of Deep Learning](https://arxiv.org/abs/2306.12370) + - [πBO: Augmenting Acquisition Functions with User Beliefs for Bayesian Optimization](https://arxiv.org/abs/2204.11051) + +1. [**Neural Architecture Search (NAS) With Context-free Grammar Search Spaces:**](neps_examples/basic_usage/architecture.py) + + - NePS is equipped to handle context-free grammar search spaces, providing advanced capabilities for designing and optimizing architectures. this is leveraged by the insights presented in: + - [Construction of Hierarchical Neural Architecture Search Spaces based on Context-free Grammars](https://arxiv.org/abs/2211.01842) -3. [**Easy Parallelization and Resumption of Runs:**](docs/parallelization.md) - - NePS simplifies the process of parallelizing optimization tasks both on individual computers and in distributed - computing environments. It also allows users to conveniently resume these optimization tasks after completion to - ensure a seamless and efficient workflow for long-running experiments. +1. [**Easy Parallelization and Resumption of Runs:**](docs/parallelization.md) -4. [**Seamless User Code Integration:**](neps_examples/template/) - - NePS's modular design ensures flexibility and extensibility. Integrate NePS effortlessly into existing machine learning workflows. + - NePS simplifies the process of parallelizing optimization tasks both on individual computers and in distributed + computing environments. It also allows users to conveniently resume these optimization tasks after completion to + ensure a seamless and efficient workflow for long-running experiments. + +1. [**Seamless User Code Integration:**](neps_examples/template/) + + - NePS's modular design ensures flexibility and extensibility. Integrate NePS effortlessly into existing machine learning workflows. ## Getting Started @@ -51,8 +54,8 @@ Using `neps` always follows the same pattern: 1. Define a `run_pipeline` function capable of evaluating different architectural and/or hyperparameter configurations for your problem. -2. Define a search space named `pipeline_space` of those Parameters e.g. via a dictionary -3. Call `neps.run` to optimize `run_pipeline` over `pipeline_space` +1. Define a search space named `pipeline_space` of those Parameters e.g. via a dictionary +1. Call `neps.run` to optimize `run_pipeline` over `pipeline_space` In code, the usage pattern can look like this: @@ -111,18 +114,19 @@ if __name__ == "__main__": ## Examples Discover how NePS works through these practical examples: -* **[Pipeline Space via YAML](neps_examples/basic_usage/defining_search_space)**: Explore how to define the `pipeline_space` using a + +- **[Pipeline Space via YAML](neps_examples/basic_usage/defining_search_space)**: Explore how to define the `pipeline_space` using a YAML file instead of a dictionary. -* **[Hyperparameter Optimization (HPO)](neps_examples/basic_usage/hyperparameters.py)**: Learn the essentials of hyperparameter optimization with NePS. +- **[Hyperparameter Optimization (HPO)](neps_examples/basic_usage/hyperparameters.py)**: Learn the essentials of hyperparameter optimization with NePS. -* **[Architecture Search with Primitives](neps_examples/basic_usage/architecture.py)**: Dive into architecture search using primitives in NePS. +- **[Architecture Search with Primitives](neps_examples/basic_usage/architecture.py)**: Dive into architecture search using primitives in NePS. -* **[Multi-Fidelity Optimization](neps_examples/efficiency/multi_fidelity.py)**: Understand how to leverage multi-fidelity optimization for efficient model tuning. +- **[Multi-Fidelity Optimization](neps_examples/efficiency/multi_fidelity.py)**: Understand how to leverage multi-fidelity optimization for efficient model tuning. -* **[Utilizing Expert Priors for Hyperparameters](neps_examples/efficiency/expert_priors_for_hyperparameters.py)**: Learn how to incorporate expert priors for more efficient hyperparameter selection. +- **[Utilizing Expert Priors for Hyperparameters](neps_examples/efficiency/expert_priors_for_hyperparameters.py)**: Learn how to incorporate expert priors for more efficient hyperparameter selection. -* **[Additional NePS Examples](neps_examples/)**: Explore more examples, including various use cases and advanced configurations in NePS. +- **[Additional NePS Examples](neps_examples/)**: Explore more examples, including various use cases and advanced configurations in NePS. ## Documentation diff --git a/docs/README.md b/docs/README.md index 28f2f0dd..ccab4aa3 100644 --- a/docs/README.md +++ b/docs/README.md @@ -9,24 +9,27 @@ Welcome to NePS, a powerful and flexible Python library for hyperparameter optim NePS houses recently published and some more well-established algorithms that are all capable of being run massively parallel on any distributed setup, with tools to analyze runs, restart runs, etc. - ## Key Features In addition to the common features offered by traditional HPO and NAS libraries, NePS stands out with the following key features: 1. [**Hyperparameter Optimization (HPO) With Prior Knowledge:**](https://github.com/automl/neps/tree/master/neps_examples/template/priorband_template.py) - - NePS excels in efficiently tuning hyperparameters using algorithms that enable users to make use of their prior knowledge within the search space. This is leveraged by the insights presented in: - - [PriorBand: Practical Hyperparameter Optimization in the Age of Deep Learning](https://arxiv.org/abs/2306.12370) - - [πBO: Augmenting Acquisition Functions with User Beliefs for Bayesian Optimization](https://arxiv.org/abs/2204.11051) -2. [**Neural Architecture Search (NAS) With Context-free Grammar Search Spaces:**](https://github.com/automl/neps/tree/master/neps_examples/basic_usage/architecture.py) - - NePS is equipped to handle context-free grammar search spaces, providing advanced capabilities for designing and optimizing architectures. this is leveraged by the insights presented in: - - [Construction of Hierarchical Neural Architecture Search Spaces based on Context-free Grammars](https://arxiv.org/abs/2211.01842) + - NePS excels in efficiently tuning hyperparameters using algorithms that enable users to make use of their prior knowledge within the search space. This is leveraged by the insights presented in: + - [PriorBand: Practical Hyperparameter Optimization in the Age of Deep Learning](https://arxiv.org/abs/2306.12370) + - [πBO: Augmenting Acquisition Functions with User Beliefs for Bayesian Optimization](https://arxiv.org/abs/2204.11051) + +1. [**Neural Architecture Search (NAS) With Context-free Grammar Search Spaces:**](https://github.com/automl/neps/tree/master/neps_examples/basic_usage/architecture.py) + + - NePS is equipped to handle context-free grammar search spaces, providing advanced capabilities for designing and optimizing architectures. this is leveraged by the insights presented in: + - [Construction of Hierarchical Neural Architecture Search Spaces based on Context-free Grammars](https://arxiv.org/abs/2211.01842) + +1. [**Easy Parallelization and Resumption of Runs:**](https://automl.github.io/neps/latest/parallelization) + + - NePS simplifies the process of parallelizing optimization tasks both on individual computers and in distributed + computing environments. It also allows users to conveniently resume these optimization tasks after completion to + ensure a seamless and efficient workflow for long-running experiments. -3. [**Easy Parallelization and Resumption of Runs:**](https://automl.github.io/neps/latest/parallelization) - - NePS simplifies the process of parallelizing optimization tasks both on individual computers and in distributed - computing environments. It also allows users to conveniently resume these optimization tasks after completion to - ensure a seamless and efficient workflow for long-running experiments. +1. [**Seamless User Code Integration:**](https://github.com/automl/neps/tree/master/neps_examples/template/) -4. [**Seamless User Code Integration:**](https://github.com/automl/neps/tree/master/neps_examples/template/) - - NePS's modular design ensures flexibility and extensibility. Integrate NePS effortlessly into existing machine learning workflows. + - NePS's modular design ensures flexibility and extensibility. Integrate NePS effortlessly into existing machine learning workflows. diff --git a/docs/analyse.md b/docs/analyse.md index cd78a14d..f76ddf18 100644 --- a/docs/analyse.md +++ b/docs/analyse.md @@ -17,6 +17,7 @@ ROOT_DIRECTORY ├── best_loss_trajectory.txt └── best_loss_with_config_trajectory.txt ``` + ## Summary CSV The argument `post_run_summary` in `neps.run` allows for the automatic generation of CSV files after a run is complete. The new root directory after utilizing this argument will look like the following: @@ -50,11 +51,14 @@ ROOT_DIRECTORY The `tblogger.log` function is invoked within the model's training loop to facilitate logging of key metrics. -!!! tip +!!! tip - The logger function is primarily designed for implementation within the `run_pipeline` function during the training of the neural network. +``` +The logger function is primarily designed for implementation within the `run_pipeline` function during the training of the neural network. +``` - **Signature:** + ```python tblogger.log( loss: float, @@ -67,37 +71,42 @@ tblogger.log( ``` - **Parameters:** - - `loss` (float): The loss value to be logged. - - `current_epoch` (int): The current epoch or iteration number. - - `write_config_scalar` (bool, optional): Set to `True` for a live loss trajectory for each configuration. - - `write_config_hparam` (bool, optional): Set to `True` for live parallel coordinate, scatter plot matrix, and table view. - - `write_summary_incumbent` (bool, optional): Set to `True` for a live incumbent trajectory. - - `extra_data` (dict, optional): Additional data to be logged, provided as a dictionary. + - `loss` (float): The loss value to be logged. + - `current_epoch` (int): The current epoch or iteration number. + - `write_config_scalar` (bool, optional): Set to `True` for a live loss trajectory for each configuration. + - `write_config_hparam` (bool, optional): Set to `True` for live parallel coordinate, scatter plot matrix, and table view. + - `write_summary_incumbent` (bool, optional): Set to `True` for a live incumbent trajectory. + - `extra_data` (dict, optional): Additional data to be logged, provided as a dictionary. ### Extra Custom Logging -NePS provides dedicated functions for customized logging using the `extra_data` argument. +NePS provides dedicated functions for customized logging using the `extra_data` argument. !!! note "Custom Logging Instructions" - Name the dictionary keys as the names of the values you want to log and pass one of the following functions as the values for a successful logging process. +``` +Name the dictionary keys as the names of the values you want to log and pass one of the following functions as the values for a successful logging process. +``` #### 1- Extra Scalar Logging Logs new scalar data during training. Uses `current_epoch` from the log function as its `global_step`. - **Signature:** + ```python tblogger.scalar_logging(value: float) ``` + - **Parameters:** - - `value` (float): Any scalar value to be logged at the current epoch of `tblogger.log` function. + - `value` (float): Any scalar value to be logged at the current epoch of `tblogger.log` function. #### 2- Extra Image Logging Logs images during training. Images can be resized, randomly selected, and a specified number can be logged at specified intervals. Uses `current_epoch` from the log function as its `global_step`. - **Signature:** + ```python tblogger.image_logging( image: torch.Tensor, @@ -110,12 +119,12 @@ tblogger.image_logging( ``` - **Parameters:** - - `image` (torch.Tensor): Image tensor to be logged. - - `counter` (int): Log images every counter epochs (i.e., when current_epoch % counter equals 0). - - `resize_images` (list of int, optional): List of integers for image sizes after resizing (default: [32, 32]). - - `random_images` (bool, optional): Images are randomly selected if True (default: True). - - `num_images` (int, optional): Number of images to log (default: 20). - - `seed` (int or np.random.RandomState or None, optional): Seed value or RandomState instance to control randomness and reproducibility (default: None). + - `image` (torch.Tensor): Image tensor to be logged. + - `counter` (int): Log images every counter epochs (i.e., when current_epoch % counter equals 0). + - `resize_images` (list of int, optional): List of integers for image sizes after resizing (default: \[32, 32\]). + - `random_images` (bool, optional): Images are randomly selected if True (default: True). + - `num_images` (int, optional): Number of images to log (default: 20). + - `seed` (int or np.random.RandomState or None, optional): Seed value or RandomState instance to control randomness and reproducibility (default: None). ### Logging Example @@ -124,17 +133,19 @@ For illustration purposes, we have employed a straightforward example involving You can find this example [here](https://github.com/automl/neps/blob/master/neps_examples/convenience/neps_tblogger_tutorial.py) !!! info "Important" - We have optimized the example for computational efficiency. If you wish to replicate the exact results showcased in the following section, we recommend the following modifications: +We have optimized the example for computational efficiency. If you wish to replicate the exact results showcased in the following section, we recommend the following modifications: - 1- Increase maximum epochs from 2 to 10 +``` +1- Increase maximum epochs from 2 to 10 + +2- Set the `write_summary_incumbent` argument to `True` - 2- Set the `write_summary_incumbent` argument to `True` +3- Change the searcher from `random_search` to `bayesian_optimization` - 3- Change the searcher from `random_search` to `bayesian_optimization` - - 4- Increase the maximum evaluations before disabling `tblogger` from 2 to 14 +4- Increase the maximum evaluations before disabling `tblogger` from 2 to 14 - 5- Increase the maximum evaluations after disabling `tblogger` from 3 to 15 +5- Increase the maximum evaluations after disabling `tblogger` from 3 to 15 +``` ### Visualization Results @@ -144,7 +155,7 @@ The following command will open a local host for TensorBoard visualizations, all tensorboard --logdir path/to/root_directory ``` -This image shows visualizations related to scalar values logged during training. Scalars typically include metrics such as loss, incumbent trajectory, a summary of losses for all configurations, and any additional data provided via the `extra_data` argument in the `tblogger.log` function. +This image shows visualizations related to scalar values logged during training. Scalars typically include metrics such as loss, incumbent trajectory, a summary of losses for all configurations, and any additional data provided via the `extra_data` argument in the `tblogger.log` function. ![scalar_loggings](doc_images/tensorboard/tblogger_scalar.jpg) diff --git a/docs/getting_started.md b/docs/getting_started.md index 7f87e21b..52c5cbdb 100644 --- a/docs/getting_started.md +++ b/docs/getting_started.md @@ -5,22 +5,24 @@ This approach ensures flexibility and efficiency in evaluating different archite for your problem. ## The 3 Main Components + 1. **Define a [`run_pipeline`](https://automl.github.io/neps/latest/run_pipeline) Function**: This function is essential -for evaluating different configurations. You'll implement the specific logic for your problem within this function. -For detailed instructions on initializing and effectively using `run_pipeline`, refer to the guide. + for evaluating different configurations. You'll implement the specific logic for your problem within this function. + For detailed instructions on initializing and effectively using `run_pipeline`, refer to the guide. -2. **Establish a [`pipeline_space`](https://automl.github.io/neps/latest/pipeline_space)**: Your search space for -defining parameters. You can structure this in various formats, including dictionaries, YAML, or ConfigSpace. -The guide offers insights into defining and configuring your search space. +1. **Establish a [`pipeline_space`](https://automl.github.io/neps/latest/pipeline_space)**: Your search space for + defining parameters. You can structure this in various formats, including dictionaries, YAML, or ConfigSpace. + The guide offers insights into defining and configuring your search space. -3. **Execute with [`neps.run`](https://automl.github.io/neps/latest/neps_run)**: Optimize your `run_pipeline` over -the `pipeline_space` using this function. For a thorough overview of the arguments and their explanations, -check out the detailed documentation. +1. **Execute with [`neps.run`](https://automl.github.io/neps/latest/neps_run)**: Optimize your `run_pipeline` over + the `pipeline_space` using this function. For a thorough overview of the arguments and their explanations, + check out the detailed documentation. By following these steps and utilizing the extensive resources provided in the guides, you can tailor NePS to meet your specific requirements, ensuring a streamlined and effective optimization process. ## Basic Usage + In code, the usage pattern can look like this: ```python @@ -80,22 +82,17 @@ if __name__ == "__main__": Discover the features of NePS through these practical examples: -* **[Hyperparameter Optimization (HPO)]( -https://github.com/automl/neps/blob/master/neps_examples/template/basic_template.py)**: Learn the essentials of -hyperparameter optimization with NePS. +- **[Hyperparameter Optimization (HPO)](https://github.com/automl/neps/blob/master/neps_examples/template/basic_template.py)**: Learn the essentials of + hyperparameter optimization with NePS. -* **[Architecture Search with Primitives]( -https://github.com/automl/neps/tree/master/neps_examples/basic_usage/architecture.py)**: Dive into architecture search -using primitives in NePS. +- **[Architecture Search with Primitives](https://github.com/automl/neps/tree/master/neps_examples/basic_usage/architecture.py)**: Dive into architecture search + using primitives in NePS. -* **[Multi-Fidelity Optimization]( -https://github.com/automl/neps/tree/master/neps_examples/efficiency/multi_fidelity.py)**: Understand how to leverage -multi-fidelity optimization for efficient model tuning. +- **[Multi-Fidelity Optimization](https://github.com/automl/neps/tree/master/neps_examples/efficiency/multi_fidelity.py)**: Understand how to leverage + multi-fidelity optimization for efficient model tuning. -* **[Utilizing Expert Priors for Hyperparameters]( -https://github.com/automl/neps/blob/master/neps_examples/template/priorband_template.py)**: -Learn how to incorporate expert priors for more efficient hyperparameter selection. +- **[Utilizing Expert Priors for Hyperparameters](https://github.com/automl/neps/blob/master/neps_examples/template/priorband_template.py)**: + Learn how to incorporate expert priors for more efficient hyperparameter selection. -* **[Additional NePS Examples]( -https://github.com/automl/neps/tree/master/neps_examples/)**: Explore more examples, including various use cases and -advanced configurations in NePS. +- **[Additional NePS Examples](https://github.com/automl/neps/tree/master/neps_examples/)**: Explore more examples, including various use cases and + advanced configurations in NePS. diff --git a/docs/installation.md b/docs/installation.md index 90066f37..cae5cb9d 100644 --- a/docs/installation.md +++ b/docs/installation.md @@ -10,12 +10,13 @@ any additional dependencies via pip. ```bash pip install neural-pipeline-search ``` + > Note: As indicated with the `v0.x.x` version number, NePS is early stage code and APIs might change in the future. ## Install from source !!! note - We use [poetry](https://python-poetry.org/docs/) to manage dependecies. +We use [poetry](https://python-poetry.org/docs/) to manage dependecies. ```bash git clone https://github.com/automl/neps.git diff --git a/docs/neps_run.md b/docs/neps_run.md index 886ff91c..b719a26e 100644 --- a/docs/neps_run.md +++ b/docs/neps_run.md @@ -5,6 +5,7 @@ and architectures takes place. This document outlines the arguments and options providing a detailed guide to customize the optimization process to your specific needs. ## Search Strategy + At default NePS intelligently selects the most appropriate search strategy based on your defined configurations in `pipeline_space`. The characteristics of your search space, as represented in the `pipeline_space`, play a crucial role in determining @@ -16,10 +17,12 @@ matches your specific needs. For more information, refer [here](https://automl.g ## Arguments ### Mandatory Arguments + - **`run_pipeline`** (function): The objective function, targeted by NePS for minimization, by evaluation various configurations. It requires these configurations as input and should return either a dictionary or a sole loss value as the -output. For correct setup instructions, refer to [here](https://automl.github.io/neps/latest/run_pipeline) + output. For correct setup instructions, refer to [here](https://automl.github.io/neps/latest/run_pipeline) + - **`pipeline_space`** (dict | yaml | configspace): This defines the search space for the configurations from which the optimizer samples. It accepts either a dictionary with the configuration names as keys, a path to a YAML configuration file, or a configSpace.ConfigurationSpace object. For comprehensive information and examples, @@ -29,61 +32,71 @@ output. For correct setup instructions, refer to [here](https://automl.github.io stored. This is also used to synchronize multiple calls to run(.) for parallelization. - **Budget**: -To define a budget, provide either or both of the following parameters: + To define a budget, provide either or both of the following parameters: - - **`max_evaluations_total`** (int, default: None): Specifies the total number of evaluations to conduct before - halting the optimization process. - - **`max_cost_total`** (int, default: None): Prevents the initiation of new evaluations once this cost - threshold is surpassed. This requires adding a cost value to the output of the `run_pipeline` function, - for example, return {'loss': loss, 'cost': cost}. For more details, please refer - [here](https://automl.github/io/neps/latest/run_pipeline) + - **`max_evaluations_total`** (int, default: None): Specifies the total number of evaluations to conduct before + halting the optimization process. + - **`max_cost_total`** (int, default: None): Prevents the initiation of new evaluations once this cost + threshold is surpassed. This requires adding a cost value to the output of the `run_pipeline` function, + for example, return {'loss': loss, 'cost': cost}. For more details, please refer + [here](https://automl.github/io/neps/latest/run_pipeline) ### Optional Arguments + ##### Further Monitoring Options - - **`overwrite_working_directory`** (bool, default: False): When set to True, the working directory - specified by - `root_directory` will be - cleared at the beginning of the run. This is e.g. useful when debugging a `run_pipeline` function. - - **`post_run_summary`** (bool, default: False): When enabled, this option generates a summary CSV file - upon the - completion of the - optimization process. The summary includes details of the optimization procedure, such as the best configuration, - the number of errors occurred, and the final performance metrics. - - **`development_stage_id`** (int | float | str, default: None): An optional identifier used when working with - multiple development stages. Instead of creating new root directories, use this identifier to save the results - of an optimization run in a separate dev_id folder within the root_directory. - - **`task_id`** (int | float | str, default: None): An optional identifier used when the optimization process - involves multiple tasks. This functions similarly to `development_stage_id`, but it creates a folder named - after the task_id instead of dev_id, providing an organized way to separate results for different tasks within - the `root_directory`. + +- **`overwrite_working_directory`** (bool, default: False): When set to True, the working directory + specified by + `root_directory` will be + cleared at the beginning of the run. This is e.g. useful when debugging a `run_pipeline` function. +- **`post_run_summary`** (bool, default: False): When enabled, this option generates a summary CSV file + upon the + completion of the + optimization process. The summary includes details of the optimization procedure, such as the best configuration, + the number of errors occurred, and the final performance metrics. +- **`development_stage_id`** (int | float | str, default: None): An optional identifier used when working with + multiple development stages. Instead of creating new root directories, use this identifier to save the results + of an optimization run in a separate dev_id folder within the root_directory. +- **`task_id`** (int | float | str, default: None): An optional identifier used when the optimization process + involves multiple tasks. This functions similarly to `development_stage_id`, but it creates a folder named + after the task_id instead of dev_id, providing an organized way to separate results for different tasks within + the `root_directory`. + ##### Parallelization Setup - - **`max_evaluations_per_run`** (int, default: None): Limits the number of evaluations for this specific call of - `neps.run`. - - **`continue_until_max_evaluation_completed`** (bool, default: False): In parallel setups, pending evaluations - normally count towards max_evaluations_total, halting new ones when this limit is reached. Setting this to - True enables continuous sampling of new evaluations until the total of completed ones meets max_evaluations_total, - optimizing resource use in time-sensitive scenarios. + +- **`max_evaluations_per_run`** (int, default: None): Limits the number of evaluations for this specific call of + `neps.run`. +- **`continue_until_max_evaluation_completed`** (bool, default: False): In parallel setups, pending evaluations + normally count towards max_evaluations_total, halting new ones when this limit is reached. Setting this to + True enables continuous sampling of new evaluations until the total of completed ones meets max_evaluations_total, + optimizing resource use in time-sensitive scenarios. For an overview and further resources on how NePS supports parallelization in distributed systems, refer to the [Parallelization Overview](#parallelization). + ##### Handling Errors - - **`loss_value_on_error`** (float, default: None): When set, any error encountered in an evaluated configuration - will not halt the process; instead, the specified loss value will be used for that configuration. - - **`cost_value_on_error`** (float, default: None): Similar to `loss_value_on_error`, but for the cost value. - - **`ignore_errors`** (bool, default: False): If True, errors encountered during the evaluation of configurations - will be ignored, and the optimization will continue. Note: This error configs still count towards - max_evaluations_total. + +- **`loss_value_on_error`** (float, default: None): When set, any error encountered in an evaluated configuration + will not halt the process; instead, the specified loss value will be used for that configuration. +- **`cost_value_on_error`** (float, default: None): Similar to `loss_value_on_error`, but for the cost value. +- **`ignore_errors`** (bool, default: False): If True, errors encountered during the evaluation of configurations + will be ignored, and the optimization will continue. Note: This error configs still count towards + max_evaluations_total. + ##### Search Strategy Customization - - **`searcher`** (Literal["bayesian_optimization", "hyperband",..] | BaseOptimizer, default: "default"): Specifies - manually which of the optimization strategy to use. Provide a string identifying one of the built-in - search strategies or an instance of a custom `BaseOptimizer`. - - **`searcher_path`** (Path | str, default: None): A path to a custom searcher implementation. - - **`**searcher_kwargs`**: Additional keyword arguments to be passed to the searcher. - For more information about the available searchers and how to customize your own, refer +- **`searcher`** (Literal\["bayesian_optimization", "hyperband",..\] | BaseOptimizer, default: "default"): Specifies + manually which of the optimization strategy to use. Provide a string identifying one of the built-in + search strategies or an instance of a custom `BaseOptimizer`. +- **`searcher_path`** (Path | str, default: None): A path to a custom searcher implementation. +- **`**searcher_kwargs`**: Additional keyword arguments to be passed to the searcher. + +For more information about the available searchers and how to customize your own, refer [here](https://automl.github.io/neps/latest/optimizers). + ##### Others - - **`pre_load_hooks`** (Iterable, default: None): A list of hook functions to be called before loading results. + +- **`pre_load_hooks`** (Iterable, default: None): A list of hook functions to be called before loading results. ## Parallelization diff --git a/docs/optimizers.md b/docs/optimizers.md index c6155ed6..d2aa5bca 100644 --- a/docs/optimizers.md +++ b/docs/optimizers.md @@ -19,6 +19,7 @@ The optimizer selection is based on the following characteristics of your `pipel For example, running the following format, without specifying a searcher will choose an optimizer depending on the `pipeline_space` passed. + ```python neps.run( run_pipeline=run_function, diff --git a/docs/parallelization.md b/docs/parallelization.md index 9a265a40..42c1e60c 100644 --- a/docs/parallelization.md +++ b/docs/parallelization.md @@ -8,7 +8,7 @@ This concept also applies to resuming runs even after termination. Example: !!! note - The following example assumes all necessary imports are included, in addition to already having defined the [pipeline_space](https://automl.github.io/neps/latest/pipeline_space/) and the [run_pipeline](https://automl.github.io/neps/latest/run_pipeline/) functions. One can apply the same idea on [this](https://github.com/automl/neps/blob/master/neps_examples/basic_usage/hyperparameters.py) example. +The following example assumes all necessary imports are included, in addition to already having defined the [pipeline_space](https://automl.github.io/neps/latest/pipeline_space/) and the [run_pipeline](https://automl.github.io/neps/latest/run_pipeline/) functions. One can apply the same idea on [this](https://github.com/automl/neps/blob/master/neps_examples/basic_usage/hyperparameters.py) example. ```python logging.basicConfig(level=logging.INFO) diff --git a/docs/pipeline_space.md b/docs/pipeline_space.md index ab49a221..3019cf75 100644 --- a/docs/pipeline_space.md +++ b/docs/pipeline_space.md @@ -8,8 +8,8 @@ within which these parameters are defined and organized. This section not only g setting up your `pipeline_space` using these methods but also provides detailed instructions and examples on how to effectively incorporate various parameter types, ensuring that NePS can utilize them in the optimization process. - ## Methods for Defining the NePS Pipeline Space + ### Option 1: Using a Python Dictionary To define the `pipeline_space` using a Python dictionary, follow these steps: @@ -54,10 +54,9 @@ Ensure your YAML file starts with `pipeline_space:`. This is the root key under which all parameter configurations are defined. !!! note "Note" - The various types of parameters displayed in the Dictionary of Option 1 are here automatically determined by the - data. If desired, you have the option to define them manually by providing the argument `type`. For more details, - refer to the section on [Supported Hyperparameter Types](#supported-hyperparameter-types). - +The various types of parameters displayed in the Dictionary of Option 1 are here automatically determined by the +data. If desired, you have the option to define them manually by providing the argument `type`. For more details, +refer to the section on [Supported Hyperparameter Types](#supported-hyperparameter-types). ### Option 3: Using ConfigSpace @@ -75,59 +74,69 @@ configspace.add_hyperparameter( For additional information on ConfigSpace and its features, please visit the following [link](https://github.com/automl/ConfigSpace). + ## Supported Hyperparameter Types ### Float/Integer Parameter - **Expected Arguments:** - - `lower`: The minimum value of the parameter. - - `upper`: The maximum value of the parameter. - - Accepted values: int or float depending on the specific parameter type one wishes to use. + - `lower`: The minimum value of the parameter. + - `upper`: The maximum value of the parameter. + - Accepted values: int or float depending on the specific parameter type one wishes to use. - **Optional Arguments:** - - `log`: Boolean that indicates if the parameter uses a logarithmic scale (default: False) - - [Details on how YAML interpret Boolean Values](#important-note-on-yaml-data-type-interpretation) - - `is_fidelity`: Boolean that marks the parameter as a fidelity parameter (default: False). - - `default`: Sets a prior central value for the parameter (default: None). - > Note: Currently, if you define a prior for one parameter, you must do so for all your variables. - - `default_confidence`: Specifies the confidence level of the default value, - indicating how strongly the prior - should be considered (default: 'low'). - - Accepted values: 'low', 'medium', or 'high'. - - `type`: Specifies the data type of the parameter. - - Accepted values: 'int', 'integer', or 'float'. - > Note: If type is not specified e notation gets converted to float + - `log`: Boolean that indicates if the parameter uses a logarithmic scale (default: False) + + - [Details on how YAML interpret Boolean Values](#important-note-on-yaml-data-type-interpretation) + + - `is_fidelity`: Boolean that marks the parameter as a fidelity parameter (default: False). + + - `default`: Sets a prior central value for the parameter (default: None). + + > Note: Currently, if you define a prior for one parameter, you must do so for all your variables. + + - `default_confidence`: Specifies the confidence level of the default value, + indicating how strongly the prior + should be considered (default: 'low'). + + - Accepted values: 'low', 'medium', or 'high'. - !!! note "YAML Method Specific:" - The type argument, used to specify the data type of parameters as 'int', 'integer', or 'float', - is unique to defining the pipeline_space with a YAML file. This explicit specification of the parameter - type is not required when using a Python dictionary or ConfigSpace, as these methods inherently determine - the data types based on the syntax and structure of the code. + - `type`: Specifies the data type of the parameter. + + - Accepted values: 'int', 'integer', or 'float'. + + > Note: If type is not specified e notation gets converted to float + + !!! note "YAML Method Specific:" + The type argument, used to specify the data type of parameters as 'int', 'integer', or 'float', + is unique to defining the pipeline_space with a YAML file. This explicit specification of the parameter + type is not required when using a Python dictionary or ConfigSpace, as these methods inherently determine + the data types based on the syntax and structure of the code. ### Categorical Parameter - **Expected Arguments:** - - `choices`: A list of discrete options (int | float | str) that the parameter can take. + - `choices`: A list of discrete options (int | float | str) that the parameter can take. - **Optional Arguments:** - - `is_fidelity`: Marks the parameter as a fidelity parameter (default: False). - - [Details on how YAML interpret Boolean Values](#important-note-on-yaml-data-type-interpretation) - - `default`: Sets a prior central value for the parameter (default: None). - > Note: Currently, if you define a prior for one parameter, you must do so for all your variables. - - `default_confidence`: Specifies the confidence level of the default value, - indicating how strongly the prior - should be considered (default: "low"). - - `type`: Specifies the data type of the parameter. - - Accepted values: 'cat' or 'categorical'. - > Note: Yaml Method Specific + - `is_fidelity`: Marks the parameter as a fidelity parameter (default: False). + - [Details on how YAML interpret Boolean Values](#important-note-on-yaml-data-type-interpretation) + - `default`: Sets a prior central value for the parameter (default: None). + > Note: Currently, if you define a prior for one parameter, you must do so for all your variables. + - `default_confidence`: Specifies the confidence level of the default value, + indicating how strongly the prior + should be considered (default: "low"). + - `type`: Specifies the data type of the parameter. + - Accepted values: 'cat' or 'categorical'. + > Note: Yaml Method Specific ### Constant Parameter - **Expected Arguments:** - - `value`: The fixed value (int | float | str) for the parameter. + - `value`: The fixed value (int | float | str) for the parameter. - **Optional Arguments:** - - `type`: Specifies the data type of the parameter. - - Accepted values: 'const' or 'constant'. - > Note: Yaml Method Specific - - `is_fidelity`: Marks the parameter as a fidelity parameter (default: False). + - `type`: Specifies the data type of the parameter. + - Accepted values: 'const' or 'constant'. + > Note: Yaml Method Specific + - `is_fidelity`: Marks the parameter as a fidelity parameter (default: False). ### Important Note on YAML Data Type Interpretation @@ -135,46 +144,48 @@ When working with YAML files, it's essential to understand how the format interp 1. **Strings in Quotes:** - - Any value enclosed in single (`'`) or double (`"`) quotes is treated as a string. - - Example: `"true"`, `'123'` are read as strings. + - Any value enclosed in single (`'`) or double (`"`) quotes is treated as a string. + - Example: `"true"`, `'123'` are read as strings. -2. **Boolean Interpretation:** +1. **Boolean Interpretation:** - - Specific unquoted values are interpreted as booleans. This includes: - - `true`, `True`, `TRUE` - - `false`, `False`, `FALSE` - - `on`, `On`, `ON` - - `off`, `Off`, `OFF` - - `yes`, `Yes`, `YES` - - `no`, `No`, `NO` + - Specific unquoted values are interpreted as booleans. This includes: + - `true`, `True`, `TRUE` + - `false`, `False`, `FALSE` + - `on`, `On`, `ON` + - `off`, `Off`, `OFF` + - `yes`, `Yes`, `YES` + - `no`, `No`, `NO` -3. **Numbers:** +1. **Numbers:** - - Unquoted numeric values are interpreted as integers or floating-point numbers, depending on their format. - - By default, when the 'type' is not specified, any number in scientific notation (e.g., 1e3) is interpreted as a - floating-point number. This interpretation is unique to our system. + - Unquoted numeric values are interpreted as integers or floating-point numbers, depending on their format. + - By default, when the 'type' is not specified, any number in scientific notation (e.g., 1e3) is interpreted as a + floating-point number. This interpretation is unique to our system. -4. **Empty Strings:** +1. **Empty Strings:** - - An empty string `""` or a key with no value is always treated as `null` in YAML. + - An empty string `""` or a key with no value is always treated as `null` in YAML. -5. **Unquoted Non-Boolean, Non-Numeric Strings:** +1. **Unquoted Non-Boolean, Non-Numeric Strings:** - - Unquoted values that don't match boolean patterns or numeric formats are treated as strings. - - Example: `example` is a string. + - Unquoted values that don't match boolean patterns or numeric formats are treated as strings. + - Example: `example` is a string. Remember to use appropriate quotes and formats to ensure values are interpreted as intended. ## Supported Architecture parameter Types !!! note "Note" - The configuration of `pipeline_space` from a YAML file does not currently support architecture parameter types. +The configuration of `pipeline_space` from a YAML file does not currently support architecture parameter types. !!! note "Note" - A comprehensive documentation for the Architecture parameter will be available soon. - If you are interested in exploring architecture parameters, you can find detailed - examples and usage in the following resources: - - - [Basic Usage Examples](https://github.com/automl/neps/tree/master/neps_examples/basic_usage) - Basic usage - examples that can help you understand the fundamentals of Architecture parameters. - - [Experimental Examples](https://github.com/automl/neps/tree/master/neps_examples/experimental) - For more advanced - and experimental use cases, including Hierarchical parameters, check out this collection of examples. +A comprehensive documentation for the Architecture parameter will be available soon. +If you are interested in exploring architecture parameters, you can find detailed +examples and usage in the following resources: + +``` +- [Basic Usage Examples](https://github.com/automl/neps/tree/master/neps_examples/basic_usage) - Basic usage + examples that can help you understand the fundamentals of Architecture parameters. +- [Experimental Examples](https://github.com/automl/neps/tree/master/neps_examples/experimental) - For more advanced + and experimental use cases, including Hierarchical parameters, check out this collection of examples. +``` diff --git a/docs/run_pipeline.md b/docs/run_pipeline.md index fb0e9bed..c677046a 100644 --- a/docs/run_pipeline.md +++ b/docs/run_pipeline.md @@ -16,7 +16,7 @@ Assuming the `pipeline_space` was already created (have a look at [pipeline spac ```python def run_pipeline( - **config, # The hyperparameters to be used in the pipeline + **config, # The hyperparameters to be used in the pipeline ): element_1 = config["element_1"] element_2 = config["element_2"] @@ -37,7 +37,9 @@ One crucial return variable is the `loss`. This metric serves as a fundamental i !!! note - Loss can be any value that is to be minimized by the objective function. +``` +Loss can be any value that is to be minimized by the objective function. +``` ```python def run_pipeline( @@ -64,10 +66,11 @@ def run_pipeline( Along with the return of the `loss`, the `run_pipeline` function would optionally need to return a `cost` in certain cases. Specifically when the `max_cost_total` parameter is being utilized in the `neps.run` function. - !!! note - `max_cost_total` sums the cost from all returned configuration results and checks whether the maximum allowed cost has been reached (if so, the search will come to an end). +``` +`max_cost_total` sums the cost from all returned configuration results and checks whether the maximum allowed cost has been reached (if so, the search will come to an end). +``` ```python import neps @@ -75,9 +78,8 @@ import logging def run_pipeline( - **config, # The hyperparameters to be used in the pipeline + **config, # The hyperparameters to be used in the pipeline ): - element_1 = config["element_1"] element_2 = config["element_2"] element_3 = config["element_3"] @@ -90,11 +92,12 @@ def run_pipeline( "cost": cost, } + if __name__ == "__main__": logging.basicConfig(level=logging.INFO) neps.run( run_pipeline=run_pipeline, - pipeline_space=pipeline_space, # Assuming the pipeline space is defined + pipeline_space=pipeline_space, # Assuming the pipeline space is defined root_directory="results/bo", max_cost_total=10, searcher="bayesian_optimization", @@ -111,9 +114,9 @@ Regard an example to be run with a multi-fidelity searcher, some checkpointing w ```python def run_pipeline( - pipeline_directory, # The directory where the config is saved + pipeline_directory, # The directory where the config is saved previous_pipeline_directory, # The directory of the immediate lower fidelity config - **config, # The hyperparameters to be used in the pipeline + **config, # The hyperparameters to be used in the pipeline ): # Assume element3 is our fidelity element element_1 = config["element_1"] diff --git a/neps/metahyper/__init__.py b/neps/metahyper/__init__.py index 6e2aa0f7..6a76b9d1 100644 --- a/neps/metahyper/__init__.py +++ b/neps/metahyper/__init__.py @@ -1,2 +1,2 @@ -from .api import ConfigResult, Sampler, read, metahyper_run +from .api import ConfigResult, Sampler, metahyper_run, read from .utils import instance_from_map diff --git a/neps/metahyper/api.py b/neps/metahyper/api.py index a868e6c2..b49d5922 100644 --- a/neps/metahyper/api.py +++ b/neps/metahyper/api.py @@ -1,8 +1,8 @@ from __future__ import annotations -import os import inspect import logging +import os import shutil import time import warnings @@ -269,10 +269,10 @@ def _check_max_evaluations( max_evaluations, serializer, logger, - continue_until_max_evaluation_completed + continue_until_max_evaluation_completed, ): logger.debug("Checking if max evaluations is reached") - #TODO: maybe not read everything again? + # TODO: maybe not read everything again? previous_results, pending_configs, pending_configs_free = read( optimization_dir, serializer, logger ) @@ -318,7 +318,7 @@ def _sample_config(optimization_dir, sampler, serializer, logger, pre_load_hooks "communication, but most likely some configs crashed during their execution " "or a jobtime-limit was reached." ) - # write some extra data per configuration if the optimizer has any + # write some extra data per configuration if the optimizer has any # if hasattr(sampler, "evaluation_data"): # sampler.evaluation_data.write_all(pipeline_directory) diff --git a/neps/optimizers/bayesian_optimization/acquisition_functions/__init__.py b/neps/optimizers/bayesian_optimization/acquisition_functions/__init__.py index 45380755..6aadfbca 100644 --- a/neps/optimizers/bayesian_optimization/acquisition_functions/__init__.py +++ b/neps/optimizers/bayesian_optimization/acquisition_functions/__init__.py @@ -6,10 +6,9 @@ from .ei import ComprehensiveExpectedImprovement from .mf_ei import MFEI, MFEI_AtMax, MFEI_Dyna, MFEI_Random from .mf_pi import MFPI, MFPI_AtMax, MFPI_Dyna, MFPI_Random, MFPI_Random_HiT -from .ucb import UpperConfidenceBound -from .mf_ucb import MF_UCB, MF_UCB_AtMax, MF_UCB_Dyna from .mf_two_step import MF_TwoStep - +from .mf_ucb import MF_UCB, MF_UCB_AtMax, MF_UCB_Dyna +from .ucb import UpperConfidenceBound AcquisitionMapping: dict[str, Callable] = { "EI": partial( @@ -113,5 +112,5 @@ MFPI_Random_HiT, in_fill="best", augmented_ei=False, - ) + ), } diff --git a/neps/optimizers/bayesian_optimization/acquisition_functions/mf_ei.py b/neps/optimizers/bayesian_optimization/acquisition_functions/mf_ei.py index 5b059db0..cc3d702f 100644 --- a/neps/optimizers/bayesian_optimization/acquisition_functions/mf_ei.py +++ b/neps/optimizers/bayesian_optimization/acquisition_functions/mf_ei.py @@ -18,6 +18,7 @@ class MFStepBase(BaseAcquisition): WARNING: Unsafe use of self attributes, can break if not used correctly. """ + def set_state( self, pipeline_space: SearchSpace, @@ -36,7 +37,6 @@ def set_state( def get_budget_level(self, config) -> int: return int((config.fidelity.value - config.fidelity.lower) / self.b_step) - def preprocess_gp(self, x: pd.Series) -> Tuple[pd.Series, torch.Tensor]: x, inc_list = self.preprocess(x) return x, inc_list @@ -58,7 +58,9 @@ def preprocess_deep_gp(self, x: pd.Series) -> Tuple[pd.Series, torch.Tensor]: self.surrogate_model.set_prediction_learning_curves(x_lcs) return x, inc_list - def preprocess_pfn(self, x: pd.Series) -> Tuple[torch.Tensor, pd.Series, torch.Tensor]: + def preprocess_pfn( + self, x: pd.Series + ) -> Tuple[torch.Tensor, pd.Series, torch.Tensor]: """Prepares the configurations for appropriate EI calculation. Takes a set of points and computes the budget and incumbent for each point, as @@ -158,14 +160,10 @@ def eval(self, x: pd.Series, asscalar: bool = False) -> Tuple[np.ndarray, pd.Ser ) # IMPORTANT change from vanilla-EI ei = self.eval_pfn_ei(_x_tok, inc_list) elif self.surrogate_model_name in ["deep_gp", "dpl"]: - _x, inc_list = self.preprocess_deep_gp( - _x - ) # IMPORTANT change from vanilla-EI + _x, inc_list = self.preprocess_deep_gp(_x) # IMPORTANT change from vanilla-EI ei = self.eval_gp_ei(_x.values.tolist(), inc_list) elif self.surrogate_model_name == "gp": - _x, inc_list = self.preprocess_gp( - _x - ) # IMPORTANT change from vanilla-EI + _x, inc_list = self.preprocess_gp(_x) # IMPORTANT change from vanilla-EI ei = self.eval_gp_ei(_x.values.tolist(), inc_list) else: raise ValueError( @@ -236,7 +234,6 @@ def eval_gp_ei( class MFEI_AtMax(MFEI): - def preprocess_inc_list(self, **kwargs) -> list: assert "len_x" in kwargs, "Requires the length of the candidate set." len_x = kwargs["len_x"] @@ -306,7 +303,9 @@ def preprocess(self, x: pd.Series) -> Tuple[pd.Series, torch.Tensor]: ## marker 1: the fidelity value at which the best seen performance was recorded z_inc = self.b_step * z_inc_level + self.pipeline_space.fidelity.lower ## marker 2: the maximum fidelity value recorded in observation history - pseudo_z_max = self.b_step * pseudo_z_level_max + self.pipeline_space.fidelity.lower + pseudo_z_max = ( + self.b_step * pseudo_z_level_max + self.pipeline_space.fidelity.lower + ) # TODO: compare with this first draft logic # def update_fidelity(config): @@ -328,7 +327,7 @@ def update_fidelity(config): return config # collect IDs for partial configurations - _partial_config_ids = (x.index <= max(self.observations.seen_config_ids)) + _partial_config_ids = x.index <= max(self.observations.seen_config_ids) # filter for configurations that reached max budget indices_to_drop = [ _idx @@ -348,7 +347,6 @@ def update_fidelity(config): class MFEI_Random(MFEI): - BUDGET = 1000 def set_state( @@ -362,18 +360,18 @@ def set_state( # set RNG self.rng = np.random.RandomState(seed=42) for i in range(len(observations.completed_runs)): - self.rng.uniform(-4,-1) - self.rng.randint(1,51) + self.rng.uniform(-4, -1) + self.rng.randint(1, 51) return super().set_state(pipeline_space, surrogate_model, observations, b_step) def sample_horizon(self, steps_passed): shortest = self.pipeline_space.fidelity.lower longest = min(self.pipeline_space.fidelity.upper, self.BUDGET - steps_passed) - return self.rng.randint(shortest, longest+1) + return self.rng.randint(shortest, longest + 1) def sample_threshold(self, f_inc): - lu = 10**self.rng.uniform(-4,-1) # % of gap closed + lu = 10 ** self.rng.uniform(-4, -1) # % of gap closed return f_inc * (1 - lu) def preprocess(self, x: pd.Series) -> Tuple[pd.Series, torch.Tensor]: @@ -387,7 +385,6 @@ def preprocess(self, x: pd.Series) -> Tuple[pd.Series, torch.Tensor]: # expected input: IDs pertaining to the tabular data x = map_real_hyperparameters_from_tabular_ids(x, self.pipeline_space) - indices_to_drop = [] inc_list = [] @@ -413,14 +410,16 @@ def preprocess(self, x: pd.Series) -> Tuple[pd.Series, torch.Tensor]: else: # a candidate partial training run to continue target_fidelity = config.fidelity.value + horizon - config.fidelity.value = min(config.fidelity.value + horizon, config.fidelity.upper) # if horizon exceeds max, query at max + config.fidelity.value = min( + config.fidelity.value + horizon, config.fidelity.upper + ) # if horizon exceeds max, query at max inc_list.append(inc_value) else: # a candidate new training run that we would need to start current_fidelity = 0 config.fidelity.value = horizon inc_list.append(inc_value) - #print(f"- {x.index.values[i]}: {current_fidelity} --> {config.fidelity.value}") + # print(f"- {x.index.values[i]}: {current_fidelity} --> {config.fidelity.value}") # Drop unused configs x.drop(labels=indices_to_drop, inplace=True) diff --git a/neps/optimizers/bayesian_optimization/acquisition_functions/mf_pi.py b/neps/optimizers/bayesian_optimization/acquisition_functions/mf_pi.py index 3f02bbc5..c8c4ca5c 100644 --- a/neps/optimizers/bayesian_optimization/acquisition_functions/mf_pi.py +++ b/neps/optimizers/bayesian_optimization/acquisition_functions/mf_pi.py @@ -1,4 +1,5 @@ # type: ignore +from copy import deepcopy from pathlib import Path from typing import Any, Iterable, Tuple, Union @@ -7,16 +8,15 @@ import torch from torch.distributions import Normal -from copy import deepcopy - from ....optimizers.utils import map_real_hyperparameters_from_tabular_ids from ....search_spaces.search_space import IntegerParameter, SearchSpace +from ....utils.common import SimpleCSVWriter from ...multi_fidelity.utils import MFObservedData from .base_acquisition import BaseAcquisition from .ei import ComprehensiveExpectedImprovement -from ....utils.common import SimpleCSVWriter from .mf_ei import MFStepBase + # NOTE: the order of inheritance is important class MFPI(MFStepBase, ComprehensiveExpectedImprovement): def __init__( @@ -95,14 +95,10 @@ def eval(self, x: pd.Series, asscalar: bool = False) -> Tuple[np.ndarray, pd.Ser ) # IMPORTANT change from vanilla-EI pi = self.eval_pfn_pi(_x_tok, inc_list) elif self.surrogate_model_name in ["deep_gp", "dpl"]: - _x, inc_list = self.preprocess_deep_gp( - _x - ) # IMPORTANT change from vanilla-EI + _x, inc_list = self.preprocess_deep_gp(_x) # IMPORTANT change from vanilla-EI pi = self.eval_gp_pi(_x.values.tolist(), inc_list) elif self.surrogate_model_name == "gp": - _x, inc_list = self.preprocess_gp( - _x - ) # IMPORTANT change from vanilla-EI + _x, inc_list = self.preprocess_gp(_x) # IMPORTANT change from vanilla-EI pi = self.eval_gp_pi(_x.values.tolist(), inc_list) else: raise ValueError( @@ -138,12 +134,11 @@ def eval_gp_pi( mu_star = inc_list.to(mu.device) gauss = Normal(torch.zeros(1, device=mu.device), torch.ones(1, device=mu.device)) - pi = gauss.cdf((mu - mu_star) / (std + 1E-9)) + pi = gauss.cdf((mu - mu_star) / (std + 1e-9)) return pi class MFPI_AtMax(MFPI): - def preprocess_inc_list(self, **kwargs) -> list: assert "len_x" in kwargs, "Requires the length of the candidate set." len_x = kwargs["len_x"] @@ -213,7 +208,9 @@ def preprocess(self, x: pd.Series) -> Tuple[pd.Series, torch.Tensor]: ## marker 1: the fidelity value at which the best seen performance was recorded z_inc = self.b_step * z_inc_level + self.pipeline_space.fidelity.lower ## marker 2: the maximum fidelity value recorded in observation history - pseudo_z_max = self.b_step * pseudo_z_level_max + self.pipeline_space.fidelity.lower + pseudo_z_max = ( + self.b_step * pseudo_z_level_max + self.pipeline_space.fidelity.lower + ) # TODO: compare with this first draft logic # def update_fidelity(config): @@ -235,7 +232,7 @@ def update_fidelity(config): return config # collect IDs for partial configurations - _partial_config_ids = (x.index <= max(self.observations.seen_config_ids)) + _partial_config_ids = x.index <= max(self.observations.seen_config_ids) # filter for configurations that reached max budget indices_to_drop = [ _idx @@ -255,7 +252,6 @@ def update_fidelity(config): class MFPI_Random(MFPI): - BUDGET = 1000 def __init__( @@ -269,12 +265,12 @@ def __init__( in_fill: str = "best", log_ei: bool = False, ): - super().__init__(pipeline_space, surrogate_model_name, augmented_ei, xi, in_fill, log_ei) + super().__init__( + pipeline_space, surrogate_model_name, augmented_ei, xi, in_fill, log_ei + ) self.horizon = horizon self.threshold = threshold - - def set_state( self, pipeline_space: SearchSpace, @@ -286,24 +282,24 @@ def set_state( # set RNG self.rng = np.random.RandomState(seed=42) for i in range(len(observations.completed_runs)): - self.rng.uniform(-4,-1) - self.rng.randint(1,51) + self.rng.uniform(-4, -1) + self.rng.randint(1, 51) return super().set_state(pipeline_space, surrogate_model, observations, b_step) def sample_horizon(self, steps_passed): - if self.horizon == 'random': + if self.horizon == "random": shortest = self.pipeline_space.fidelity.lower longest = min(self.pipeline_space.fidelity.upper, self.BUDGET - steps_passed) - return self.rng.randint(shortest, longest+1) - elif self.horizon == 'max': + return self.rng.randint(shortest, longest + 1) + elif self.horizon == "max": return min(self.pipeline_space.fidelity.upper, self.BUDGET - steps_passed) else: return int(self.horizon) def sample_threshold(self, f_inc): - if self.threshold == 'random': - lu = 10**self.rng.uniform(-4,-1) # % of gap closed + if self.threshold == "random": + lu = 10 ** self.rng.uniform(-4, -1) # % of gap closed else: lu = float(self.threshold) return f_inc * (1 - lu) @@ -319,7 +315,6 @@ def preprocess(self, x: pd.Series) -> Tuple[pd.Series, torch.Tensor]: # expected input: IDs pertaining to the tabular data x = map_real_hyperparameters_from_tabular_ids(x, self.pipeline_space) - indices_to_drop = [] inc_list = [] @@ -346,14 +341,16 @@ def preprocess(self, x: pd.Series) -> Tuple[pd.Series, torch.Tensor]: else: # a candidate partial training run to continue target_fidelity = config.fidelity.value + horizon - config.fidelity.value = min(config.fidelity.value + horizon, config.fidelity.upper) # if horizon exceeds max, query at max + config.fidelity.value = min( + config.fidelity.value + horizon, config.fidelity.upper + ) # if horizon exceeds max, query at max inc_list.append(inc_value) else: # a candidate new training run that we would need to start current_fidelity = 0 config.fidelity.value = horizon inc_list.append(inc_value) - #print(f"- {x.index.values[i]}: {current_fidelity} --> {config.fidelity.value}") + # print(f"- {x.index.values[i]}: {current_fidelity} --> {config.fidelity.value}") # Drop unused configs x.drop(labels=indices_to_drop, inplace=True) @@ -364,7 +361,6 @@ def preprocess(self, x: pd.Series) -> Tuple[pd.Series, torch.Tensor]: class MFPI_Random_HiT(MFPI): - BUDGET = 1000 def set_state( @@ -378,18 +374,18 @@ def set_state( # set RNG self.rng = np.random.RandomState(seed=42) for i in range(len(observations.completed_runs)): - self.rng.uniform(-4,0) - self.rng.randint(1,51) + self.rng.uniform(-4, 0) + self.rng.randint(1, 51) return super().set_state(pipeline_space, surrogate_model, observations, b_step) def sample_horizon(self, steps_passed): shortest = self.pipeline_space.fidelity.lower longest = min(self.pipeline_space.fidelity.upper, self.BUDGET - steps_passed) - return self.rng.randint(shortest, longest+1) + return self.rng.randint(shortest, longest + 1) def sample_threshold(self, f_inc): - lu = 10**self.rng.uniform(-4,0) # % of gap closed + lu = 10 ** self.rng.uniform(-4, 0) # % of gap closed return f_inc * (1 - lu) def preprocess(self, x: pd.Series) -> Tuple[pd.Series, torch.Tensor]: @@ -403,7 +399,6 @@ def preprocess(self, x: pd.Series) -> Tuple[pd.Series, torch.Tensor]: # expected input: IDs pertaining to the tabular data x = map_real_hyperparameters_from_tabular_ids(x, self.pipeline_space) - indices_to_drop = [] inc_list = [] @@ -430,14 +425,16 @@ def preprocess(self, x: pd.Series) -> Tuple[pd.Series, torch.Tensor]: else: # a candidate partial training run to continue target_fidelity = config.fidelity.value + horizon - config.fidelity.value = min(config.fidelity.value + horizon, config.fidelity.upper) # if horizon exceeds max, query at max + config.fidelity.value = min( + config.fidelity.value + horizon, config.fidelity.upper + ) # if horizon exceeds max, query at max inc_list.append(inc_value) else: # a candidate new training run that we would need to start current_fidelity = 0 config.fidelity.value = horizon inc_list.append(inc_value) - #print(f"- {x.index.values[i]}: {current_fidelity} --> {config.fidelity.value}") + # print(f"- {x.index.values[i]}: {current_fidelity} --> {config.fidelity.value}") # Drop unused configs x.drop(labels=indices_to_drop, inplace=True) diff --git a/neps/optimizers/bayesian_optimization/acquisition_functions/mf_two_step.py b/neps/optimizers/bayesian_optimization/acquisition_functions/mf_two_step.py index 3c9b3524..1d1175a2 100644 --- a/neps/optimizers/bayesian_optimization/acquisition_functions/mf_two_step.py +++ b/neps/optimizers/bayesian_optimization/acquisition_functions/mf_two_step.py @@ -1,6 +1,7 @@ +from typing import Any, Tuple, Union + import numpy as np import pandas as pd -from typing import Any, Tuple, Union from ....search_spaces.search_space import SearchSpace from ...multi_fidelity.utils import MFObservedData @@ -10,18 +11,18 @@ class MF_TwoStep(BaseAcquisition): - """ 2-step acquisition: employs 3 different acquisition calls. - """ + """2-step acquisition: employs 3 different acquisition calls.""" # HYPER-PARAMETERS: Going with the Freeze-Thaw BO (Swersky et al. 2014) values N_PARTIAL = 10 N_NEW = 3 - def __init__(self, + def __init__( + self, pipeline_space: SearchSpace, surrogate_model_name: str = None, - beta: float=1.0, - maximize: bool=False, + beta: float = 1.0, + maximize: bool = False, augmented_ei: bool = False, xi: float = 0.0, in_fill: str = "best", @@ -42,8 +43,8 @@ def __init__(self, augmented_ei=augmented_ei, xi=xi, in_fill=in_fill, - log_ei=log_ei - ) + log_ei=log_ei, + ) # Acquisition 2: For trimming down new candidate set self.acq_new_filter = MFEI( pipeline_space=pipeline_space, @@ -51,14 +52,14 @@ def __init__(self, augmented_ei=augmented_ei, xi=xi, in_fill=in_fill, - log_ei=log_ei + log_ei=log_ei, ) # Acquisition 3: For final selection of winners from Acquisitions 1 & 2 self.acq_combined = MF_UCB_Dyna( pipeline_space=pipeline_space, surrogate_model_name=surrogate_model_name, beta=beta, - maximize=maximize + maximize=maximize, ) self.pipeline_space = pipeline_space self.surrogate_model_name = surrogate_model_name @@ -80,22 +81,13 @@ def set_state( self.observations = observations self.b_step = b_step self.acq_partial_filter.set_state( - self.pipeline_space, - self.surrogate_model, - self.observations, - self.b_step + self.pipeline_space, self.surrogate_model, self.observations, self.b_step ) self.acq_new_filter.set_state( - self.pipeline_space, - self.surrogate_model, - self.observations, - self.b_step + self.pipeline_space, self.surrogate_model, self.observations, self.b_step ) self.acq_combined.set_state( - self.pipeline_space, - self.surrogate_model, - self.observations, - self.b_step + self.pipeline_space, self.surrogate_model, self.observations, self.b_step ) def eval(self, x: pd.Series, asscalar: bool = False) -> Tuple[np.ndarray, pd.Series]: @@ -113,38 +105,48 @@ def eval(self, x: pd.Series, asscalar: bool = False) -> Tuple[np.ndarray, pd.Ser acq.loc[_samples.index.values <= max_seen_id] = 0 # NOTE: setting to 0 works as EI-based AF returns > 0 # find configs not in top-N_NEW set as per acquisition value, to be dropped - not_top_new_idx = acq.sort_values().index[:-self.N_NEW] # len(acq) - N_NEW + not_top_new_idx = acq.sort_values().index[: -self.N_NEW] # len(acq) - N_NEW # drop these configurations - acq.loc[not_top_new_idx] = 0 # to ignore in the argmax of the acquisition function + acq.loc[ + not_top_new_idx + ] = 0 # to ignore in the argmax of the acquisition function # NOTE: setting to 0 works as EI-based AF returns > 0 # result of first round of filtering of new candidates - acq_new_mask = pd.Series({ - idx: val for idx, val in _samples.items() if acq.loc[idx] > 0 - }) + acq_new_mask = pd.Series( + {idx: val for idx, val in _samples.items() if acq.loc[idx] > 0} + ) # for partial candidate set acq, _samples = self.acq_partial_filter.eval(x, asscalar=True) acq = pd.Series(acq, index=_samples.index) # weigh the acq value based on max seen for each config acq = self._weigh_partial_acq_scores(acq=acq) # drop new configurations - acq.loc[_samples.index.values > max_seen_id] = 0 # to ignore in the argmax of the acquisition function + acq.loc[ + _samples.index.values > max_seen_id + ] = 0 # to ignore in the argmax of the acquisition function # find configs not in top-N_NEW set as per acquisition value _top_n_partial = min(self.N_PARTIAL, total_seen_id) - not_top_new_idx = acq.sort_values().index[:-_top_n_partial] # acq.argsort()[::-1][_top_n_partial:] # sorts in ascending-flips-leaves out top-N_PARTIAL + not_top_new_idx = acq.sort_values().index[ + :-_top_n_partial + ] # acq.argsort()[::-1][_top_n_partial:] # sorts in ascending-flips-leaves out top-N_PARTIAL # drop these configurations - acq.loc[not_top_new_idx] = 0 # to ignore in the argmax of the acquisition function + acq.loc[ + not_top_new_idx + ] = 0 # to ignore in the argmax of the acquisition function # NOTE: setting to 0 works as EI-based AF returns > 0 # result of first round of filtering of partial candidates - acq_partial_mask = pd.Series({ - idx: val for idx, val in _samples.items() if acq.loc[idx] > 0 - }) + acq_partial_mask = pd.Series( + {idx: val for idx, val in _samples.items() if acq.loc[idx] > 0} + ) eligible_set = set( - np.concatenate([ - acq_partial_mask.index.values.tolist(), - acq_new_mask.index.values.tolist() - ]) + np.concatenate( + [ + acq_partial_mask.index.values.tolist(), + acq_new_mask.index.values.tolist(), + ] + ) ) # for combined selection @@ -153,16 +155,20 @@ def eval(self, x: pd.Series, asscalar: bool = False) -> Tuple[np.ndarray, pd.Ser # applying mask from step-1 to make final selection among (N_NEW + N_PARTIAL) mask = acq.index.isin(eligible_set) # NOTE: setting to -np.inf works as MF-UCB here is max.(-LCB) instead of min.(LCB) - acq[~mask] = -np.inf # will be ignored in the argmax of the acquisition function - acq_combined = pd.Series({ - idx: acq.loc[idx] for idx, val in _samples.items() if acq.loc[idx] != -np.inf - }) + acq[~mask] = -np.inf # will be ignored in the argmax of the acquisition function + acq_combined = pd.Series( + { + idx: acq.loc[idx] + for idx, val in _samples.items() + if acq.loc[idx] != -np.inf + } + ) # NOTE: setting to -np.inf works as MF-UCB here is max.(-LCB) instead of min.(LCB) acq_combined = acq_combined.reindex(acq.index, fill_value=-np.inf) acq = acq_combined.values - + return acq, _samples - + def _weigh_partial_acq_scores(self, acq: pd.Series) -> pd.Series: # find the best performance per configuration seen inc_list_partial = self.observations.get_best_performance_per_config() @@ -187,8 +193,7 @@ def _weigh_partial_acq_scores(self, acq: pd.Series) -> pd.Series: class MFEI_PartialFilter(MFEI): - """Custom redefinition of MF-EI with Dynamic extrapolation length to adjust incumbents. - """ + """Custom redefinition of MF-EI with Dynamic extrapolation length to adjust incumbents.""" def preprocess_inc_list(self, **kwargs) -> list: # the assertion exists to forcibly check the call to the super().preprocess() @@ -212,8 +217,7 @@ def preprocess_inc_list(self, **kwargs) -> list: class MFEI_Dyna_PartialFilter(MFEI_Dyna): - """Custom redefinition of MF-EI with Dynamic extrapolation length to adjust incumbents. - """ + """Custom redefinition of MF-EI with Dynamic extrapolation length to adjust incumbents.""" def preprocess_inc_list(self, **kwargs) -> list: # the assertion exists to forcibly check the call to the super().preprocess() @@ -235,4 +239,3 @@ def preprocess_inc_list(self, **kwargs) -> list: inc_list[:n_partial] = inc_list_partial return inc_list - \ No newline at end of file diff --git a/neps/optimizers/bayesian_optimization/acquisition_functions/mf_ucb.py b/neps/optimizers/bayesian_optimization/acquisition_functions/mf_ucb.py index 6bf1dc94..0fffada7 100644 --- a/neps/optimizers/bayesian_optimization/acquisition_functions/mf_ucb.py +++ b/neps/optimizers/bayesian_optimization/acquisition_functions/mf_ucb.py @@ -13,11 +13,12 @@ # NOTE: the order of inheritance is important class MF_UCB(MFStepBase, UpperConfidenceBound): - def __init__(self, + def __init__( + self, pipeline_space: SearchSpace, surrogate_model_name: str = None, - beta: float=1.0, - maximize: bool=False + beta: float = 1.0, + maximize: bool = False, ): """Upper Confidence Bound (UCB) acquisition function. @@ -74,8 +75,8 @@ def preprocess(self, x: pd.Series) -> Tuple[pd.Series, torch.Tensor]: return x, torch.Tensor(betas) def preprocess_gp( - self, x: pd.Series, surrogate_name: str = "gp" - ) -> Tuple[pd.Series, torch.Tensor]: + self, x: pd.Series, surrogate_name: str = "gp" + ) -> Tuple[pd.Series, torch.Tensor]: if surrogate_name == "gp": x, inc_list = self.preprocess(x) return x, inc_list @@ -94,17 +95,15 @@ def preprocess_gp( self.surrogate_model.set_prediction_learning_curves(x_lcs) return x, inc_list else: - raise ValueError( - f"Unrecognized surrogate model name: {surrogate_name}" - ) + raise ValueError(f"Unrecognized surrogate model name: {surrogate_name}") def eval_pfn_ucb( - self, x: Iterable, beta: float=(1-.682)/2 + self, x: Iterable, beta: float = (1 - 0.682) / 2 ) -> Union[np.ndarray, torch.Tensor, float]: """PFN-UCB modified to preprocess samples and accept list of incumbents.""" ucb = self.surrogate_model.get_ucb( x_test=x.to(self.surrogate_model.device), - beta=beta # TODO: extend to have different betas for each candidates in x + beta=beta, # TODO: extend to have different betas for each candidates in x ) if len(ucb.shape) == 2: ucb = ucb.flatten() @@ -112,15 +111,10 @@ def eval_pfn_ucb( def eval(self, x: pd.Series, asscalar: bool = False) -> Tuple[np.ndarray, pd.Series]: if self.surrogate_model_name == "pfn": - _x, _x_tok, _ = self.preprocess_pfn( - x.copy() - ) + _x, _x_tok, _ = self.preprocess_pfn(x.copy()) ucb = self.eval_pfn_ucb(_x_tok) elif self.surrogate_model_name in ["deep_gp", "gp", "dpl"]: - _x, betas = self.preprocess_gp( - x.copy(), - self.surrogate_model_name - ) + _x, betas = self.preprocess_gp(x.copy(), self.surrogate_model_name) ucb = super().eval(_x.values.tolist(), betas, asscalar) else: raise ValueError( @@ -131,7 +125,6 @@ def eval(self, x: pd.Series, asscalar: bool = False) -> Tuple[np.ndarray, pd.Ser class MF_UCB_AtMax(MF_UCB): - def preprocess(self, x: pd.Series) -> Tuple[pd.Series, torch.Tensor]: """Prepares the configurations for appropriate EI calculation. @@ -167,7 +160,6 @@ def preprocess(self, x: pd.Series) -> Tuple[pd.Series, torch.Tensor]: class MF_UCB_Dyna(MF_UCB): - def preprocess(self, x: pd.Series) -> Tuple[pd.Series, torch.Tensor]: """Prepares the configurations for appropriate EI calculation. @@ -189,7 +181,9 @@ def preprocess(self, x: pd.Series) -> Tuple[pd.Series, torch.Tensor]: ## marker 1: the fidelity value at which the best seen performance was recorded z_inc = self.b_step * z_inc_level + self.pipeline_space.fidelity.lower ## marker 2: the maximum fidelity value recorded in observation history - pseudo_z_max = self.b_step * pseudo_z_level_max + self.pipeline_space.fidelity.lower + pseudo_z_max = ( + self.b_step * pseudo_z_level_max + self.pipeline_space.fidelity.lower + ) # TODO: compare with this first draft logic # def update_fidelity(config): @@ -211,7 +205,7 @@ def update_fidelity(config): return config # collect IDs for partial configurations - _partial_config_ids = (x.index <= max(self.observations.seen_config_ids)) + _partial_config_ids = x.index <= max(self.observations.seen_config_ids) # filter for configurations that reached max budget indices_to_drop = [ _idx diff --git a/neps/optimizers/bayesian_optimization/acquisition_functions/ucb.py b/neps/optimizers/bayesian_optimization/acquisition_functions/ucb.py index beba8fa3..f3c89a39 100644 --- a/neps/optimizers/bayesian_optimization/acquisition_functions/ucb.py +++ b/neps/optimizers/bayesian_optimization/acquisition_functions/ucb.py @@ -9,7 +9,7 @@ class UpperConfidenceBound(BaseAcquisition): - def __init__(self, beta: float=1.0, maximize: bool=False): + def __init__(self, beta: float = 1.0, maximize: bool = False): """Upper Confidence Bound (UCB) acquisition function. Args: @@ -35,7 +35,7 @@ def set_state(self, surrogate_model, **kwargs): def eval( self, x: Iterable, betas: torch.Tensor | None = None, asscalar: bool = False - ) -> Union[np.ndarray, torch.Tensor, float]: + ) -> np.ndarray | torch.Tensor | float: try: mu, cov = self.surrogate_model.predict(x) std = torch.sqrt(torch.diag(cov)) diff --git a/neps/optimizers/bayesian_optimization/acquisition_samplers/freeze_thaw_sampler.py b/neps/optimizers/bayesian_optimization/acquisition_samplers/freeze_thaw_sampler.py index 1fdb01db..8b5c6145 100644 --- a/neps/optimizers/bayesian_optimization/acquisition_samplers/freeze_thaw_sampler.py +++ b/neps/optimizers/bayesian_optimization/acquisition_samplers/freeze_thaw_sampler.py @@ -1,12 +1,12 @@ # type: ignore from __future__ import annotations +import time import warnings from copy import deepcopy import numpy as np import pandas as pd -import time from ....search_spaces.search_space import SearchSpace from ...multi_fidelity.utils import MFObservedData @@ -14,7 +14,6 @@ class FreezeThawSampler(AcquisitionSampler): - SAMPLES_TO_DRAW = 100 # number of random samples to draw at lowest fidelity def __init__(self, **kwargs): @@ -28,7 +27,7 @@ def __init__(self, **kwargs): self.sample_full_table = None self.set_sample_full_tabular(True) # sets flag that samples full table - def set_sample_full_tabular(self, flag: bool=False): + def set_sample_full_tabular(self, flag: bool = False): if self.is_tabular: self.sample_full_table = flag @@ -154,7 +153,7 @@ def sample( # they are not reset in every sampling step partial_configs = pd.Series( [deepcopy(p_config_) for idx, p_config_ in partial_configs.items()], - index=partial_configs.index + index=partial_configs.index, ) # Updating fidelity values diff --git a/neps/optimizers/bayesian_optimization/mf_tpe.py b/neps/optimizers/bayesian_optimization/mf_tpe.py index f705f9f0..cb72940a 100644 --- a/neps/optimizers/bayesian_optimization/mf_tpe.py +++ b/neps/optimizers/bayesian_optimization/mf_tpe.py @@ -7,7 +7,7 @@ import numpy as np import torch from scipy.stats import spearmanr -from typing_extensions import Literal +from typing import Literal from ...metahyper import ConfigResult, instance_from_map from ...search_spaces import ( diff --git a/neps/optimizers/bayesian_optimization/models/DPL.py b/neps/optimizers/bayesian_optimization/models/DPL.py index 82bd78c1..37279824 100644 --- a/neps/optimizers/bayesian_optimization/models/DPL.py +++ b/neps/optimizers/bayesian_optimization/models/DPL.py @@ -1,26 +1,24 @@ from __future__ import annotations -from copy import deepcopy import logging import os import time -from typing import List, Tuple, Any, Type +from copy import deepcopy +from pathlib import Path +from typing import Any, List, Tuple, Type import numpy as np - -from scipy.stats import norm -from pathlib import Path import torch import torch.nn as nn +from scipy.stats import norm -from neps.search_spaces.search_space import ( +from ....search_spaces.search_space import ( CategoricalParameter, FloatParameter, IntegerParameter, SearchSpace, ) - -from neps.optimizers.multi_fidelity.utils import MFObservedData +from ...multi_fidelity.utils import MFObservedData # TODO: Move to utils @@ -47,7 +45,6 @@ def get_best_loss(root_directory: Path | str) -> float: class ConditionedPowerLaw(nn.Module): - def __init__( self, nr_initial_features=10, @@ -75,7 +72,7 @@ def __init__( nr_cnn_layers: int The number of cnn layers to be used. """ - super(ConditionedPowerLaw, self).__init__() + super().__init__() self.use_learning_curve = use_learning_curve self.kernel_size = kernel_size @@ -171,8 +168,8 @@ def forward( self.last_act_func(torch.cat((betas, betas))), torch.pow( predict_budgets, - torch.mul(self.last_act_func(torch.cat((gammas, gammas))), -1) - ) + torch.mul(self.last_act_func(torch.cat((gammas, gammas))), -1), + ), ), ) @@ -181,7 +178,7 @@ def forward( ModelClass = ConditionedPowerLaw -MODEL_MAPPING: dict[str, Type[ModelClass]] = {"power_law": ConditionedPowerLaw} +MODEL_MAPPING: dict[str, type[ModelClass]] = {"power_law": ConditionedPowerLaw} class PowerLawSurrogate: @@ -197,12 +194,14 @@ class PowerLawSurrogate: # init params default_n_initial_full_trainings = 10 default_n_models = 5 - default_model_config = dict(nr_units=128, - nr_layers=2, - use_learning_curve=False, - kernel_size=3, - nr_filters=4, - nr_cnn_layers=2) + default_model_config = dict( + nr_units=128, + nr_layers=2, + use_learning_curve=False, + kernel_size=3, + nr_filters=4, + nr_cnn_layers=2, + ) # fit+predict params default_padding_type = "zero" @@ -210,9 +209,9 @@ class PowerLawSurrogate: default_use_min_budget = False default_y_normalize = False - # Defined in __init__(...) default_no_improvement_patience = ... + def __init__( self, pipeline_space: SearchSpace, @@ -236,7 +235,7 @@ def __init__( n_models: int = default_n_models, model_classes: list[str] | None = None, model_configs: list[dict[str, Any]] | None = None, - refine_batch_size: int | None = None + refine_batch_size: int | None = None, ): if pipeline_space.has_tabular: self.cover_pipeline_space = pipeline_space @@ -249,25 +248,29 @@ def __init__( self.observed_data = observed_data self.__preprocess_search_space(self.real_pipeline_space) self.seeds = np.random.choice(100, n_models, replace=False) - self.model_configs = [dict( - nr_initial_features=self.input_size, **default_model_config)] * n_models if not model_configs else model_configs - self.model_classes = [MODEL_MAPPING[default_model_class]] * n_models \ - if not model_classes \ + self.model_configs = ( + [dict(nr_initial_features=self.input_size, **default_model_config)] * n_models + if not model_configs + else model_configs + ) + self.model_classes = ( + [MODEL_MAPPING[default_model_class]] * n_models + if not model_classes else [MODEL_MAPPING[m_class] for m_class in model_classes] + ) self.device = "cpu" - self.models: list[ModelClass] = [self.__initialize_model(config, - self.model_classes[ - index], - self.device) - for index, config in - enumerate(self.model_configs)] + self.models: list[ModelClass] = [ + self.__initialize_model(config, self.model_classes[index], self.device) + for index, config in enumerate(self.model_configs) + ] self.checkpointing = checkpointing self.refine_epochs = refine_epochs self.refine_batch_size = refine_batch_size self.n_initial_full_trainings = n_initial_full_trainings - self.default_no_improvement_patience = int(self.max_fidelity + - 0.2 * self.max_fidelity) + self.default_no_improvement_patience = int( + self.max_fidelity + 0.2 * self.max_fidelity + ) if checkpointing: assert ( @@ -283,8 +286,9 @@ def __init__( if self.surrogate_model_fit_args.get("no_improvement_patience", None) is None: # To replicate how the original DPL implementation handles the # no_improvement_threshold - self.surrogate_model_fit_args["no_improvement_patience"] = ( - self.default_no_improvement_patience) + self.surrogate_model_fit_args[ + "no_improvement_patience" + ] = self.default_no_improvement_patience self.categories_array = np.array(self.categories) @@ -335,21 +339,16 @@ def __encode_config(self, config: SearchSpace) -> np.ndarray: encoding = np.concatenate([categorical_encoding, continuous_encoding]) return encoding - def __normalize_budgets(self, - budgets: np.ndarray, - use_min_budget: bool) -> np.ndarray: + def __normalize_budgets( + self, budgets: np.ndarray, use_min_budget: bool + ) -> np.ndarray: min_budget = self.min_fidelity if use_min_budget else 0 - normalized_budgets = (budgets - min_budget) / ( - self.max_fidelity - min_budget - ) + normalized_budgets = (budgets - min_budget) / (self.max_fidelity - min_budget) return normalized_budgets def __extract_budgets( - self, x_train: list[SearchSpace], - normalized: bool, - use_min_budget: bool + self, x_train: list[SearchSpace], normalized: bool, use_min_budget: bool ) -> np.ndarray: - budgets = np.array([config.fidelity.value for config in x_train], dtype=np.single) if normalized: @@ -398,7 +397,7 @@ def __reset_xy( normalize_y: bool = default_y_normalize, normalize_budget: bool = default_budget_normalize, use_min_budget: bool = default_use_min_budget, - padding_type: str = default_padding_type + padding_type: str = default_padding_type, ): self.normalize_budget = ( # pylint: disable=attribute-defined-outside-init normalize_budget @@ -406,13 +405,15 @@ def __reset_xy( self.use_min_budget = ( # pylint: disable=attribute-defined-outside-init use_min_budget ) - self.padding_type = ( # pylint: disable=attribute-defined-outside-init - padding_type - ) + self.padding_type = padding_type # pylint: disable=attribute-defined-outside-init self.normalize_y = normalize_y # pylint: disable=attribute-defined-outside-init x_train, train_budgets, learning_curves = self._preprocess_input( - x_train, learning_curves, self.normalize_budget, self.use_min_budget, self.padding_type + x_train, + learning_curves, + self.normalize_budget, + self.use_min_budget, + self.padding_type, ) y_train = self._preprocess_y(y_train, normalize_y) @@ -432,7 +433,7 @@ def _preprocess_input( learning_curves: list[list[float]], normalize_budget: bool, use_min_budget: bool, - padding_type: str + padding_type: str, ) -> [torch.tensor, torch.tensor, torch.tensor]: budgets = self.__extract_budgets(x, normalize_budget, use_min_budget) learning_curves = self.__preprocess_learning_curves(learning_curves, padding_type) @@ -445,8 +446,7 @@ def _preprocess_input( return x, budgets, learning_curves - def _preprocess_y(self, y_train: list[float], - normalize_y: bool) -> torch.tensor: + def _preprocess_y(self, y_train: list[float], normalize_y: bool) -> torch.tensor: y_train_array = np.array(y_train, dtype=np.single) self.min_y = y_train_array.min() # pylint: disable=attribute-defined-outside-init self.max_y = y_train_array.max() # pylint: disable=attribute-defined-outside-init @@ -472,8 +472,9 @@ def __is_refine(self, no_improvement_patience: int) -> bool: self.logger.debug(f"No improvement for: {non_improvement_steps} evaulations") - return ((non_improvement_steps < no_improvement_patience) - and (self.n_initial_full_trainings <= total_optimizer_steps)) + return (non_improvement_steps < no_improvement_patience) and ( + self.n_initial_full_trainings <= total_optimizer_steps + ) def fit( self, @@ -483,22 +484,22 @@ def fit( ): self._fit(x_train, y_train, learning_curves, **self.surrogate_model_fit_args) - def _fit(self, - x_train: list[SearchSpace], - y_train: list[float], - learning_curves: list[list[float]], - nr_epochs: int = default_nr_epochs, - batch_size: int = default_batch_size, - early_stopping: bool = default_early_stopping, - early_stopping_patience: int = default_early_stopping_patience, - no_improvement_patience: int = default_no_improvement_patience, - optimizer_args: dict[str, Any] | None = None, - - normalize_y: bool = default_y_normalize, - normalize_budget: bool = default_budget_normalize, - use_min_budget: bool = default_use_min_budget, - padding_type: str = default_padding_type): - + def _fit( + self, + x_train: list[SearchSpace], + y_train: list[float], + learning_curves: list[list[float]], + nr_epochs: int = default_nr_epochs, + batch_size: int = default_batch_size, + early_stopping: bool = default_early_stopping, + early_stopping_patience: int = default_early_stopping_patience, + no_improvement_patience: int = default_no_improvement_patience, + optimizer_args: dict[str, Any] | None = None, + normalize_y: bool = default_y_normalize, + normalize_budget: bool = default_budget_normalize, + use_min_budget: bool = default_use_min_budget, + padding_type: str = default_padding_type, + ): self.__reset_xy( x_train, y_train, @@ -509,7 +510,11 @@ def _fit(self, padding_type=padding_type, ) # check when to refine - if self.checkpointing and self.__is_refine(no_improvement_patience) and self.checkpoint_path.exists(): + if ( + self.checkpointing + and self.__is_refine(no_improvement_patience) + and self.checkpoint_path.exists() + ): # self.__initialize_model() self.load_state() weight_new_point = True @@ -522,35 +527,38 @@ def _fit(self, optimizer_args = {"lr": self.default_lr} for model_index, model in enumerate(self.models): - self._train_a_model(model_index, - self.x_train, - self.train_budgets, - self.y_train, - self.learning_curves, - nr_epochs=nr_epochs, - batch_size=batch_size, - early_stopping_patience=early_stopping_patience, - early_stopping=early_stopping, - weight_new_point=weight_new_point, - optimizer_args=optimizer_args) + self._train_a_model( + model_index, + self.x_train, + self.train_budgets, + self.y_train, + self.learning_curves, + nr_epochs=nr_epochs, + batch_size=batch_size, + early_stopping_patience=early_stopping_patience, + early_stopping=early_stopping, + weight_new_point=weight_new_point, + optimizer_args=optimizer_args, + ) # save model after training if checkpointing if self.checkpointing: self.save_state() - def _train_a_model(self, - model_index: int, - x_train: torch.tensor, - train_budgets: torch.tensor, - y_train: torch.tensor, - learning_curves: torch.tensor, - nr_epochs: int, - batch_size: int, - early_stopping_patience: int, - early_stopping: bool, - weight_new_point: bool, - optimizer_args: dict[str, Any]): - + def _train_a_model( + self, + model_index: int, + x_train: torch.tensor, + train_budgets: torch.tensor, + y_train: torch.tensor, + learning_curves: torch.tensor, + nr_epochs: int, + batch_size: int, + early_stopping_patience: int, + early_stopping: bool, + weight_new_point: bool, + optimizer_args: dict[str, Any], + ): # Setting seeds will interfere with SearchSpace random sampling if self.cover_pipeline_space.has_tabular: seed = self.seeds[model_index] @@ -559,8 +567,8 @@ def _train_a_model(self, model = self.models[model_index] - optimizer = ( - torch.optim.Adam(**dict({"params": model.parameters()}, **optimizer_args)) + optimizer = torch.optim.Adam( + **dict({"params": model.parameters()}, **optimizer_args) ) count_down = early_stopping_patience @@ -575,7 +583,6 @@ def _train_a_model(self, new_x, new_b, new_lc, new_y = [torch.tensor([])] * 4 for epoch in range(0, nr_epochs): - if early_stopping and count_down == 0: self.logger.info( f"Epoch: {epoch - 1} surrogate training stops due to early " @@ -626,13 +633,12 @@ def _train_a_model(self, # Zero backprop gradients optimizer.zero_grad(set_to_none=True) - outputs = model(batch_x, batch_budget, batch_budget, - batch_lc) + outputs = model(batch_x, batch_budget, batch_budget, batch_lc) loss = self.criterion(outputs, batch_y) loss.backward() optimizer.step() - total_scaled_loss += (loss.detach().item() * minibatch_size) + total_scaled_loss += loss.detach().item() * minibatch_size running_loss = total_scaled_loss / n_examples_batch @@ -660,7 +666,7 @@ def predict( self, x: list[SearchSpace], learning_curves: list[list[float]] | None = None, - real_budgets: list[int | float] | None = None + real_budgets: list[int | float] | None = None, ) -> [torch.tensor, torch.tensor]: # Preprocess input # [print(_x.hp_values()) for _x in x] @@ -672,12 +678,15 @@ def predict( real_budgets = [len(lc) + 1 for lc in learning_curves] x_test, prediction_budgets, learning_curves = self._preprocess_input( - x, learning_curves, self.normalize_budget, self.use_min_budget, self.padding_type + x, + learning_curves, + self.normalize_budget, + self.use_min_budget, + self.padding_type, ) # preprocess the list of budgets the configs are evaluated for real_budgets = np.array(real_budgets, dtype=np.single) - real_budgets = self.__normalize_budgets(real_budgets, - self.use_min_budget) + real_budgets = self.__normalize_budgets(real_budgets, self.use_min_budget) real_budgets = torch.tensor(real_budgets).to(self.device) all_predictions = [] @@ -704,14 +713,18 @@ def load_state(self, state: dict[str, int | str | dict[str, Any]] | None = None) for model_index in range(checkpoint["n_models"]): self.models[model_index].load_state_dict( - checkpoint[f"model_{model_index}_state_dict"]) + checkpoint[f"model_{model_index}_state_dict"] + ) self.models[model_index].to(self.device) def get_state(self) -> dict[str, int | str | dict[str, Any]]: n_models = len(self.models) - model_states = {f"model_{model_index}_state_dict": - deepcopy(self.models[model_index].state_dict()) - for model_index in range(n_models)} + model_states = { + f"model_{model_index}_state_dict": deepcopy( + self.models[model_index].state_dict() + ) + for model_index in range(n_models) + } # get last point last_point = self.get_last_point() @@ -724,7 +737,7 @@ def __config_ids(self) -> list[str]: all_losses_file = self.root_dir / "all_losses_and_configs.txt" if all_losses_file.exists(): - # Read all losses from the file in the order they are explored + # Read all losses from the file in the order they are explored config_ids = [ str(line[11:]) for line in all_losses_file.read_text(encoding="utf-8").splitlines() @@ -743,9 +756,9 @@ def save_state(self, state: dict[str, int | str | dict[str, Any]] | None = None) self.checkpoint_path, ) else: - assert ("last_point" in state and - "n_models" in state), \ - "The state dictionary is not complete" + assert ( + "last_point" in state and "n_models" in state + ), "The state dictionary is not complete" torch.save( state, self.checkpoint_path, @@ -768,8 +781,9 @@ def get_new_points(self) -> [list[SearchSpace], list[list[float]], list[float]]: else: index = len(config_ids) - 1 - new_config_indices = [tuple(map(int, config_id.split("_"))) for config_id in - config_ids[index:]] + new_config_indices = [ + tuple(map(int, config_id.split("_"))) for config_id in config_ids[index:] + ] # Only include the points that exist in the observed data already # (not a use case for single worker runs) @@ -778,13 +792,15 @@ def get_new_points(self) -> [list[SearchSpace], list[list[float]], list[float]]: new_config_df = self.observed_data.df.loc[existing_index_map, :].copy(deep=True) new_configs, new_lcs, new_y = self.observed_data.get_training_data_4DyHPO( - new_config_df, self.cover_pipeline_space) + new_config_df, self.cover_pipeline_space + ) return new_configs, new_lcs, new_y @staticmethod - def __initialize_model(model_params: dict[str, Any], model_class: Type[ModelClass], - device: str) -> ModelClass: + def __initialize_model( + model_params: dict[str, Any], model_class: type[ModelClass], device: str + ) -> ModelClass: model = model_class(**model_params) model.to(device) return model @@ -792,18 +808,19 @@ def __initialize_model(model_params: dict[str, Any], model_class: Type[ModelClas def prep_new_point(self) -> [torch.tensor, torch.tensor, torch.tensor, torch.tensor]: new_point, new_lc, new_y = self.get_new_points() - new_x, new_b, new_lc = self._preprocess_input(new_point, - new_lc, - self.normalize_budget, - self.use_min_budget, - self.padding_type + new_x, new_b, new_lc = self._preprocess_input( + new_point, + new_lc, + self.normalize_budget, + self.use_min_budget, + self.padding_type, ) new_y = self._preprocess_y(new_y, self.normalize_y) return new_x, new_b, new_lc, new_y def __get_mean_initial_value(self): - mean = self.observed_data.get_learning_curves().loc[:, 0].mean() + mean = self.observed_data.get_trajectories().loc[:, 0].mean() return mean diff --git a/neps/optimizers/bayesian_optimization/models/__init__.py b/neps/optimizers/bayesian_optimization/models/__init__.py index 3f9bec50..4e8bf42f 100755 --- a/neps/optimizers/bayesian_optimization/models/__init__.py +++ b/neps/optimizers/bayesian_optimization/models/__init__.py @@ -1,7 +1,7 @@ from ....metahyper.utils import MissingDependencyError +from .DPL import PowerLawSurrogate from .gp import ComprehensiveGP from .gp_hierarchy import ComprehensiveGPHierarchy -from .DPL import PowerLawSurrogate try: from .deepGP import DeepGP diff --git a/neps/optimizers/bayesian_optimization/models/deepGP.py b/neps/optimizers/bayesian_optimization/models/deepGP.py index 862f8a6e..9b7fd841 100644 --- a/neps/optimizers/bayesian_optimization/models/deepGP.py +++ b/neps/optimizers/bayesian_optimization/models/deepGP.py @@ -17,12 +17,10 @@ SearchSpace, ) -def get_optimizer_losses(root_directory: Path | str) -> list[float]: - +def get_optimizer_losses(root_directory: Path | str) -> list[float]: all_losses_file = root_directory / "all_losses_and_configs.txt" - # Read all losses from the file in the order they are explored losses = [ float(line[6:]) @@ -31,6 +29,7 @@ def get_optimizer_losses(root_directory: Path | str) -> list[float]: ] return losses + def get_best_loss(root_directory: Path | str) -> float: root_directory = Path(root_directory) best_loss_fiel = root_directory / "best_loss_trajectory.txt" @@ -210,8 +209,9 @@ def __init__( if self.surrogate_model_fit_args.get("perf_patience", -1) is None: # To replicate how the original DyHPO implementation handles the # no_improvement_threshold - self.surrogate_model_fit_args["perf_patience"] = int(self.max_fidelity + - 0.2 * self.max_fidelity) + self.surrogate_model_fit_args["perf_patience"] = int( + self.max_fidelity + 0.2 * self.max_fidelity + ) # build the neural network self.nn = NeuralFeatureExtractor(self.input_size, **neural_network_args) @@ -265,8 +265,9 @@ def __is_refine(self, perf_patience: int): self.logger.debug(f"No improvement for: {non_improvement_steps} evaulations") - return ((non_improvement_steps < perf_patience) - and (self.n_initial_full_trainings <= total_optimizer_steps)) + return (non_improvement_steps < perf_patience) and ( + self.n_initial_full_trainings <= total_optimizer_steps + ) def __preprocess_search_space(self, pipeline_space: SearchSpace): self.categories = [] @@ -308,17 +309,15 @@ def __encode_config(self, config: SearchSpace): return encoding def __extract_budgets( - self, x_train: list[SearchSpace], + self, + x_train: list[SearchSpace], normalized: bool = True, - use_min_budget: bool = False + use_min_budget: bool = False, ) -> np.ndarray: - min_budget = self.min_fidelity if use_min_budget else 0 budgets = np.array([config.fidelity.value for config in x_train], dtype=np.single) if normalized: - normalized_budgets = (budgets - min_budget) / ( - self.max_fidelity - min_budget - ) + normalized_budgets = (budgets - min_budget) / (self.max_fidelity - min_budget) budgets = normalized_budgets return budgets @@ -382,7 +381,7 @@ def _preprocess_input( x: list[SearchSpace], learning_curves: list[list[float]], normalize_budget: bool = True, - use_min_budget: bool = False + use_min_budget: bool = False, ): budgets = self.__extract_budgets(x, normalize_budget, use_min_budget) learning_curves = self.__preprocess_learning_curves(learning_curves) @@ -434,7 +433,7 @@ def _fit( learning_curves, normalize_y=normalize_y, normalize_budget=normalize_budget, - use_min_budget=use_min_budget + use_min_budget=use_min_budget, ) self.model, self.likelihood, self.mll = self.__initialize_gp_model(len(y_train)) self.nn = NeuralFeatureExtractor(self.input_size, **self.nn_args) diff --git a/neps/optimizers/bayesian_optimization/optimizer.py b/neps/optimizers/bayesian_optimization/optimizer.py index 6c47ac8b..90aac0ac 100644 --- a/neps/optimizers/bayesian_optimization/optimizer.py +++ b/neps/optimizers/bayesian_optimization/optimizer.py @@ -3,7 +3,7 @@ import random from typing import Any -from typing_extensions import Literal +from typing import Literal from ...metahyper import ConfigResult, instance_from_map from ...search_spaces.hyperparameters.categorical import ( diff --git a/neps/optimizers/default_searchers/priorband.yaml b/neps/optimizers/default_searchers/priorband.yaml index 9b11ae9a..0b2cf1ae 100644 --- a/neps/optimizers/default_searchers/priorband.yaml +++ b/neps/optimizers/default_searchers/priorband.yaml @@ -9,7 +9,7 @@ searcher_kwargs: sample_default_first: true sample_default_at_target: false prior_weight_type: geometric - inc_sample_type: mutation + inc_sample_type: mutation inc_mutation_rate: 0.5 inc_mutation_std: 0.25 inc_style: dynamic diff --git a/neps/optimizers/default_searchers/priorband_bo.yaml b/neps/optimizers/default_searchers/priorband_bo.yaml index 04e530c1..4c00280e 100644 --- a/neps/optimizers/default_searchers/priorband_bo.yaml +++ b/neps/optimizers/default_searchers/priorband_bo.yaml @@ -16,7 +16,7 @@ searcher_kwargs: # arguments for model model_based: true # crucial argument to set to allow model-search - modelling_type: joint + modelling_type: joint initial_design_size: 10 surrogate_model: gp # or {"gp_hierarchy"} acquisition: EI # or {"LogEI", "AEI"} diff --git a/neps/optimizers/multi_fidelity/mf_bo.py b/neps/optimizers/multi_fidelity/mf_bo.py index c825120b..67bca1f4 100755 --- a/neps/optimizers/multi_fidelity/mf_bo.py +++ b/neps/optimizers/multi_fidelity/mf_bo.py @@ -200,8 +200,10 @@ def __init__( self.surrogate_model_args.update({"pipeline_space": pipeline_space}) elif self.surrogate_model_name == "dpl": self.surrogate_model_args.update( - {"pipeline_space": self.pipeline_space, - "observed_data": self.observed_configs} + { + "pipeline_space": self.pipeline_space, + "observed_data": self.observed_configs, + } ) # instantiate the surrogate model @@ -269,8 +271,10 @@ def set_state( ) if self.surrogate_model_name == "dpl": self.surrogate_model_args.update( - {"pipeline_space": self.pipeline_space, - "observed_data": self.observed_configs} + { + "pipeline_space": self.pipeline_space, + "observed_data": self.observed_configs, + } ) self.surrogate_model = instance_from_map( SurrogateModelMapping, @@ -287,8 +291,10 @@ def set_state( ) elif self.surrogate_model_name == "dpl": self.surrogate_model_args.update( - {"pipeline_space": self.pipeline_space, - "observed_data": self.observed_configs} + { + "pipeline_space": self.pipeline_space, + "observed_data": self.observed_configs, + } ) # instantiate the surrogate model, again, with the new pipeline space self.surrogate_model = instance_from_map( @@ -299,8 +305,10 @@ def set_state( ) elif self.surrogate_model_name == "dpl": self.surrogate_model_args.update( - {"pipeline_space": self.pipeline_space, - "observed_data": self.observed_configs} + { + "pipeline_space": self.pipeline_space, + "observed_data": self.observed_configs, + } ) self.surrogate_model = instance_from_map( SurrogateModelMapping, diff --git a/neps/optimizers/multi_fidelity_prior/async_priorband.py b/neps/optimizers/multi_fidelity_prior/async_priorband.py index c932d45d..a054ad10 100644 --- a/neps/optimizers/multi_fidelity_prior/async_priorband.py +++ b/neps/optimizers/multi_fidelity_prior/async_priorband.py @@ -3,7 +3,7 @@ import typing import numpy as np -from typing_extensions import Literal +from typing import Literal from ...metahyper import ConfigResult from ...search_spaces.search_space import SearchSpace diff --git a/neps/optimizers/multi_fidelity_prior/priorband.py b/neps/optimizers/multi_fidelity_prior/priorband.py index eca50ebe..95c23eb7 100644 --- a/neps/optimizers/multi_fidelity_prior/priorband.py +++ b/neps/optimizers/multi_fidelity_prior/priorband.py @@ -5,7 +5,7 @@ import typing import numpy as np -from typing_extensions import Literal +from typing import Literal from ...search_spaces.search_space import SearchSpace from ..bayesian_optimization.acquisition_functions.base_acquisition import BaseAcquisition diff --git a/neps/optimizers/utils.py b/neps/optimizers/utils.py index 757dd0b3..32fa87fa 100644 --- a/neps/optimizers/utils.py +++ b/neps/optimizers/utils.py @@ -6,14 +6,14 @@ def map_real_hyperparameters_from_tabular_ids( x: pd.Series, pipeline_space: SearchSpace ) -> pd.Series: - """ Maps the tabular IDs to the actual HPs from the pipeline space. - + """Maps the tabular IDs to the actual HPs from the pipeline space. + Args: x (pd.Series): A pandas series with the tabular IDs. TODO: Mention expected format of the series. pipeline_space (SearchSpace): The pipeline space. - Returns: + Returns: pd.Series: A pandas series with the actual HPs. TODO: Mention expected format of the series. """ @@ -21,8 +21,11 @@ def map_real_hyperparameters_from_tabular_ids( return x # copying hyperparameter configs based on IDs _x = pd.Series( - [pipeline_space.custom_grid_table[x.loc[idx]["id"].value] for idx in x.index.values], - index=x.index + [ + pipeline_space.custom_grid_table[x.loc[idx]["id"].value] + for idx in x.index.values + ], + index=x.index, ) # setting the passed fidelities for the corresponding IDs for idx in _x.index.values: diff --git a/neps/plot/tensorboard_eval.py b/neps/plot/tensorboard_eval.py index 6463563e..9e4b7393 100644 --- a/neps/plot/tensorboard_eval.py +++ b/neps/plot/tensorboard_eval.py @@ -484,7 +484,7 @@ def log( curve on tensorboard (default: True) writer_config_hparam (bool, optional): Write hyperparameters logging of the configs (default: True). - write_summary_incumbent (bool, optional): Set to `True` for a live + write_summary_incumbent (bool, optional): Set to `True` for a live incumbent trajectory. extra_data (dict, optional): Additional experiment data for logging. """ diff --git a/neps/search_spaces/architecture/graph.py b/neps/search_spaces/architecture/graph.py index 42b2c388..d6a58124 100644 --- a/neps/search_spaces/architecture/graph.py +++ b/neps/search_spaces/architecture/graph.py @@ -6,13 +6,13 @@ import sys import types from collections import Counter +from pathlib import Path from typing import Callable from typing import Counter as CounterType import networkx as nx import torch from networkx.algorithms.dag import lexicographical_topological_sort -from pathlib import Path from torch import nn from ...utils.common import AttrDict diff --git a/neps/search_spaces/hyperparameters/integer.py b/neps/search_spaces/hyperparameters/integer.py index 32789251..122a3514 100644 --- a/neps/search_spaces/hyperparameters/integer.py +++ b/neps/search_spaces/hyperparameters/integer.py @@ -2,7 +2,7 @@ from copy import deepcopy -from typing_extensions import Literal +from typing import Literal from .float import FloatParameter @@ -33,10 +33,10 @@ def __init__( def __repr__(self): return f"" - + def load_from(self, value): super().load_from(int(value)) - + def _set_float_hp_val(self): # IMPORTANT function to call wherever `self.float_hp` is used in this class self.float_hp.value = None if self.value is None else float(self.value) diff --git a/neps/search_spaces/search_space.py b/neps/search_spaces/search_space.py index d74fac11..c0a6b36b 100644 --- a/neps/search_spaces/search_space.py +++ b/neps/search_spaces/search_space.py @@ -248,14 +248,18 @@ def set_custom_grid_space( ) self.has_tabular = True # Updating `custom_grid_table` as a map for quick lookup with placeholder fidelity - placeholder_config = self.raw_tabular_space.sample(ignore_fidelity=True) # sets fidelity as None + placeholder_config = self.raw_tabular_space.sample( + ignore_fidelity=True + ) # sets fidelity as None # `placeholder_config` allows to store map values as NePS SearchSpace type # and also create a placeholder for fideity value _map = { idx: deepcopy(placeholder_config) for idx in self.custom_grid_table.index.values } - _ = [v.load_from(self.custom_grid_table.loc[k].to_dict()) for k, v in _map.items()] + _ = [ + v.load_from(self.custom_grid_table.loc[k].to_dict()) for k, v in _map.items() + ] self.custom_grid_table = _map @property diff --git a/neps/search_spaces/yaml_search_space_utils.py b/neps/search_spaces/yaml_search_space_utils.py index e0efe616..d3ed7041 100644 --- a/neps/search_spaces/yaml_search_space_utils.py +++ b/neps/search_spaces/yaml_search_space_utils.py @@ -3,8 +3,9 @@ import re -def convert_scientific_notation(value: str | int | float, show_usage_flag=False) \ - -> float | (float, bool): +def convert_scientific_notation( + value: str | int | float, show_usage_flag=False +) -> float | (float, bool): """ Convert a given value to a float if it's a string that matches scientific e notation. This is especially useful for numbers like "3.3e-5" which YAML parsers may not diff --git a/neps/status/status.py b/neps/status/status.py index 3d45d2fe..df459a35 100644 --- a/neps/status/status.py +++ b/neps/status/status.py @@ -1,10 +1,9 @@ from __future__ import annotations import logging +import shutil from pathlib import Path from typing import Any -import shutil -import zipfile import pandas as pd @@ -295,7 +294,9 @@ def _save_data_to_csv( run_data_df.index == "num_evaluated_configs", "value" ] # checks if the current worker has more evaluated configs than the previous - if int(num_evaluated_configs_csv) < int(num_evaluated_configs_run.iloc[0]): + if int(num_evaluated_configs_csv) < int( + num_evaluated_configs_run.iloc[0] + ): config_data_df = config_data_df.sort_values( by="result.loss", ascending=True ) @@ -318,10 +319,9 @@ def _save_data_to_csv( def post_run_csv(root_directory: str | Path, logger=None) -> None: - root_directory = Path(root_directory) zip_filename = Path(root_directory / "results.zip") - base_result_directory =root_directory / "results" + base_result_directory = root_directory / "results" # Extract previous results to load if it exists if zip_filename.exists(): @@ -351,5 +351,6 @@ def post_run_csv(root_directory: str | Path, logger=None) -> None: df_run_data, ) + def get_run_summary_csv(root_directory: str | Path): post_run_csv(root_directory=root_directory) diff --git a/neps/utils/common.py b/neps/utils/common.py index 2780a7ca..dad37e37 100644 --- a/neps/utils/common.py +++ b/neps/utils/common.py @@ -296,6 +296,7 @@ class DataWriter: and then write_data will be called with only the directory path as argument during the write process """ + def __init__(self, name: str): self.name = name @@ -312,6 +313,7 @@ class EvaluationData: A class to store some data for a single evaluation (configuration) and write that data to its corresponding config folder """ + def __init__(self): self.data_dict: dict[str, DataWriter] = {} @@ -336,10 +338,3 @@ def write_data(self, to_directory: Path): path = to_directory / str(self.name + ".json") with open(path, "w") as file: json.dump(self.data, file) - - - - - - - diff --git a/neps_examples/README.md b/neps_examples/README.md index 4161d7ec..3ce8dd6e 100644 --- a/neps_examples/README.md +++ b/neps_examples/README.md @@ -2,10 +2,10 @@ 1. Navigate to [basic_usage](basic_usage) for demonstrations on fundamental usage. Learn how to perform Hyperparameter Optimization (HPO), Neural Architecture Search (NAS), and Joint Architecture and Hyperparameter Search (JAHS). Understand how to analyze runs on a basic level, emphasizing that no neural network training is involved at this stage; the search is performed on functions to introduce NePS. -2. Navigate to [efficiency](efficiency) examples showcasing how to enhance efficiency in NePS. Learn about expert priors, multi-fidelity, and parallelization to streamline your pipeline and optimize search processes. +1. Navigate to [efficiency](efficiency) examples showcasing how to enhance efficiency in NePS. Learn about expert priors, multi-fidelity, and parallelization to streamline your pipeline and optimize search processes. -3. Navigate to [convenience](convenience) for examples highlighting utilities that add extra features to NePS. Discover tensorboard compatibility and its integration, explore the compatibility with PyTorch Lightning, and understand file management within the run pipeline function used in NePS. +1. Navigate to [convenience](convenience) for examples highlighting utilities that add extra features to NePS. Discover tensorboard compatibility and its integration, explore the compatibility with PyTorch Lightning, and understand file management within the run pipeline function used in NePS. -4. Navigate to into [experimental](experimental) examples tailored for NePS contributors. These examples provide insights and practices for experimental scenarios. +1. Navigate to into [experimental](experimental) examples tailored for NePS contributors. These examples provide insights and practices for experimental scenarios. -5. Navigate to [template](template) to find a basic fill-in template to kickstart your hyperparameter search with NePS. Use this template as a foundation for your projects, saving time and ensuring a structured starting point. +1. Navigate to [template](template) to find a basic fill-in template to kickstart your hyperparameter search with NePS. Use this template as a foundation for your projects, saving time and ensuring a structured starting point. diff --git a/neps_examples/basic_usage/architecture_and_hyperparameters.py b/neps_examples/basic_usage/architecture_and_hyperparameters.py index e0b63fe4..53a65e23 100644 --- a/neps_examples/basic_usage/architecture_and_hyperparameters.py +++ b/neps_examples/basic_usage/architecture_and_hyperparameters.py @@ -117,6 +117,7 @@ def run_pipeline(**config): neps.run( run_pipeline=run_pipeline, pipeline_space=pipeline_space, + searcher="random_search", root_directory="results/hyperparameters_architecture_example", max_evaluations_total=15, ) diff --git a/neps_examples/convenience/neps_tblogger_tutorial.py b/neps_examples/convenience/neps_tblogger_tutorial.py index a70cc494..c435cce8 100644 --- a/neps_examples/convenience/neps_tblogger_tutorial.py +++ b/neps_examples/convenience/neps_tblogger_tutorial.py @@ -57,13 +57,13 @@ import torch.nn as nn import torch.nn.functional as F import torchvision +from neps.plot.tensorboard_eval import tblogger from torch.optim import lr_scheduler from torch.utils.data.dataloader import DataLoader from torch.utils.data.sampler import SubsetRandomSampler from torchvision.transforms import transforms import neps -from neps.plot.tensorboard_eval import tblogger """ Steps for a successful training pipeline: diff --git a/neps_examples/experimental/hierarchical_architecture_hierarchical_GP.py b/neps_examples/experimental/hierarchical_architecture_hierarchical_GP.py index 3db93bde..15ca9c9e 100644 --- a/neps_examples/experimental/hierarchical_architecture_hierarchical_GP.py +++ b/neps_examples/experimental/hierarchical_architecture_hierarchical_GP.py @@ -3,13 +3,13 @@ import logging import time +from neps.optimizers.bayesian_optimization.models.gp_hierarchy import ( + ComprehensiveGPHierarchy, +) from torch import nn import neps from neps.optimizers.bayesian_optimization.kernels import GraphKernelMapping -from neps.optimizers.bayesian_optimization.models.gp_hierarchy import ( - ComprehensiveGPHierarchy, -) from neps.search_spaces.architecture import primitives as ops from neps.search_spaces.architecture import topologies as topos diff --git a/neps_examples/template/lightning_template.py b/neps_examples/template/lightning_template.py index 9c674fc4..b91f856a 100644 --- a/neps_examples/template/lightning_template.py +++ b/neps_examples/template/lightning_template.py @@ -37,9 +37,9 @@ import torch from lightning.pytorch.callbacks import ModelCheckpoint from lightning.pytorch.loggers import TensorBoardLogger +from neps.utils.common import get_initial_directory, load_lightning_checkpoint import neps -from neps.utils.common import get_initial_directory, load_lightning_checkpoint logger = logging.getLogger("neps_template.run") diff --git a/neps_examples/template/priorband_template.py b/neps_examples/template/priorband_template.py index a8bd8f3c..da47feaf 100644 --- a/neps_examples/template/priorband_template.py +++ b/neps_examples/template/priorband_template.py @@ -31,9 +31,9 @@ import torch import torch.nn as nn import torch.nn.functional as F +from neps.utils.common import load_checkpoint, save_checkpoint import neps -from neps.utils.common import load_checkpoint, save_checkpoint logger = logging.getLogger("neps_template.run") diff --git a/tests/test_neps_api/testing_scripts/baseoptimizer_neps.py b/tests/test_neps_api/testing_scripts/baseoptimizer_neps.py index 1fe9a219..d1634267 100644 --- a/tests/test_neps_api/testing_scripts/baseoptimizer_neps.py +++ b/tests/test_neps_api/testing_scripts/baseoptimizer_neps.py @@ -1,10 +1,11 @@ import logging -import neps from neps.optimizers.bayesian_optimization.optimizer import BayesianOptimization from neps.optimizers.multi_fidelity.hyperband import Hyperband from neps.search_spaces.search_space import SearchSpace +import neps + pipeline_space_fidelity = dict( val1=neps.FloatParameter(lower=-10, upper=10), val2=neps.IntegerParameter(lower=1, upper=5, is_fidelity=True), diff --git a/tests/test_neps_api/testing_scripts/default_neps.py b/tests/test_neps_api/testing_scripts/default_neps.py index 5384042a..1b5c57b0 100644 --- a/tests/test_neps_api/testing_scripts/default_neps.py +++ b/tests/test_neps_api/testing_scripts/default_neps.py @@ -1,11 +1,12 @@ import logging -import neps -from neps.optimizers.bayesian_optimization.kernels import GraphKernelMapping from neps.optimizers.bayesian_optimization.models.gp_hierarchy import ( ComprehensiveGPHierarchy, ) +import neps +from neps.optimizers.bayesian_optimization.kernels import GraphKernelMapping + pipeline_space_fidelity_priors = dict( val1=neps.FloatParameter(lower=-10, upper=10, default=1), val2=neps.IntegerParameter(lower=1, upper=5, is_fidelity=True), diff --git a/tests/test_neps_api/testing_yaml/optimizer_test.yaml b/tests/test_neps_api/testing_yaml/optimizer_test.yaml index cad2221d..96c585a7 100644 --- a/tests/test_neps_api/testing_yaml/optimizer_test.yaml +++ b/tests/test_neps_api/testing_yaml/optimizer_test.yaml @@ -9,4 +9,4 @@ searcher_kwargs: # Specific arguments depending on the searcher random_interleave_prob: 0.1 disable_priors: false prior_confidence: high - sample_default_first: false \ No newline at end of file + sample_default_first: false From eb46e3524aae80e42686590385a9e7688612c6e7 Mon Sep 17 00:00:00 2001 From: karibbov Date: Mon, 8 Apr 2024 15:05:32 +0200 Subject: [PATCH 3/6] SH, HB using both MFObservedData and observed_configs --- neps/optimizers/multi_fidelity/dyhpo.py | 45 ++- neps/optimizers/multi_fidelity/hyperband.py | 7 +- .../multi_fidelity/successive_halving.py | 151 ++++++--- neps/optimizers/multi_fidelity/utils.py | 291 ++++++++++++------ 4 files changed, 324 insertions(+), 170 deletions(-) diff --git a/neps/optimizers/multi_fidelity/dyhpo.py b/neps/optimizers/multi_fidelity/dyhpo.py index 5e540bc3..b23f82ba 100755 --- a/neps/optimizers/multi_fidelity/dyhpo.py +++ b/neps/optimizers/multi_fidelity/dyhpo.py @@ -6,12 +6,10 @@ import numpy as np import pandas as pd -import time - -from ...utils.common import EvaluationData, SimpleCSVWriter from ...metahyper import ConfigResult, instance_from_map from ...search_spaces.search_space import FloatParameter, IntegerParameter, SearchSpace +from ...utils.common import EvaluationData, SimpleCSVWriter from ..base_optimizer import BaseOptimizer from ..bayesian_optimization.acquisition_functions import AcquisitionMapping from ..bayesian_optimization.acquisition_functions.base_acquisition import BaseAcquisition @@ -28,11 +26,15 @@ class AcqWriter(SimpleCSVWriter): def set_data(self, sample_configs: pd.Series, acq_vals: pd.Series): - config_vals = pd.DataFrame([config.hp_values() for config in sample_configs], index=sample_configs.index) + config_vals = pd.DataFrame( + [config.hp_values() for config in sample_configs], index=sample_configs.index + ) if isinstance(acq_vals, pd.Series): acq_vals.name = "Acq Value" + # pylint: disable=attribute-defined-outside-init self.df = config_vals.join(acq_vals) self.df = self.df.sort_values(by="Acq Value") + # pylint: enable=attribute-defined-outside-init class MFEIBO(BaseOptimizer): @@ -118,8 +120,11 @@ def __init__( self.total_fevals: int = 0 self.observed_configs = MFObservedData( - columns=["config", "perf", "learning_curves"], - index_names=["config_id", "budget_id"], + config_id="config_id", + budget_id="budget_id", + config_col="config", + perf_col="perf", + learning_curve_col="learning_curves", ) # Preparing model @@ -304,10 +309,12 @@ def load_results( previous_results (dict[str, ConfigResult]): [description] pending_evaluations (dict[str, ConfigResult]): [description] """ - start = time.time() self.observed_configs = MFObservedData( - columns=["config", "perf", "learning_curves"], - index_names=["config_id", "budget_id"], + config_id="config_id", + budget_id="budget_id", + config_col="config", + perf_col="perf", + learning_curve_col="learning_curves", ) # previous optimization run exists and needs to be loaded self._load_previous_observations(previous_results) @@ -328,9 +335,6 @@ def load_results( init_phase = self.is_init_phase() if not init_phase: self._fit_models() - # print("-" * 50) - # print(f"| Total time for `load_results()`: {time.time()-start:.2f}s") - # print("-" * 50) @classmethod def _get_config_id_split(cls, config_id: str) -> tuple[str, str]: @@ -444,29 +448,21 @@ def get_config_and_ids( # pylint: disable=no-self-use else: if self.count == 0: self.logger.info("\nPartial learning curves as initial design:\n") - self.logger.info(f"{self.observed_configs.get_learning_curves()}\n") + self.logger.info(f"{self.observed_configs.get_trajectories()}\n") self.count += 1 # main acquisition call here after initial design is turned off self.logger.info("acquiring...") # generates candidate samples for acquisition calculation - start = time.time() samples = self.acquisition_sampler.sample( set_new_sample_fidelity=self.pipeline_space.fidelity.lower ) # fidelity values here should be the observations or min. fidelity - # print("-" * 50) - # print(f"| Total time for acq. sampling: {time.time()-start:.2f}s") - # print("-" * 50) - start = time.time() # calculating acquisition function values for the candidate samples acq, _samples = self.acquisition.eval( # type: ignore[attr-defined] x=samples, asscalar=True ) acq = pd.Series(acq, index=_samples.index) - # print("-" * 50) - # print(f"| Total time for acq. eval: {time.time()-start:.2f}s") - # print("-" * 50) # maximizing acquisition function best_idx = acq.sort_values().index[-1] # extracting the config ID for the selected maximizer @@ -519,8 +515,11 @@ def get_config_and_ids( # pylint: disable=no-self-use if best_idx > max(self.observed_configs.seen_config_ids) else ( self.get_budget_value( - self.observed_configs.get_max_observed_fidelity_level_per_config().loc[best_idx] - ) + self.step_size # ONE-STEP FIDELITY QUERY + self.observed_configs.get_max_observed_fidelity_level_per_config().loc[ + best_idx + ] + ) + + self.step_size # ONE-STEP FIDELITY QUERY ) ) # generating correct IDs diff --git a/neps/optimizers/multi_fidelity/hyperband.py b/neps/optimizers/multi_fidelity/hyperband.py index 86ff2f5f..1278cbee 100644 --- a/neps/optimizers/multi_fidelity/hyperband.py +++ b/neps/optimizers/multi_fidelity/hyperband.py @@ -4,10 +4,9 @@ import typing from copy import deepcopy -from typing import Any +from typing import Any, Literal import numpy as np -from typing_extensions import Literal from ...metahyper import ConfigResult from ...search_spaces.search_space import SearchSpace @@ -100,6 +99,8 @@ def _update_sh_bracket_state(self) -> None: # TODO: can we avoid copying full observation history bracket = self.sh_brackets[self.current_sh_bracket] # type: ignore bracket.observed_configs = self.observed_configs.copy() + # TODO: Do we NEED to copy here instead? + bracket.MFobserved_configs = self.MFobserved_configs # pylint: disable=no-self-use def clear_old_brackets(self): @@ -302,7 +303,7 @@ def __init__( prior_confidence=prior_confidence, random_interleave_prob=random_interleave_prob, sample_default_first=sample_default_first, - sample_default_at_target=sample_default_at_target + sample_default_at_target=sample_default_at_target, ) self.sampling_args = { "inc": None, diff --git a/neps/optimizers/multi_fidelity/successive_halving.py b/neps/optimizers/multi_fidelity/successive_halving.py index a3145dc2..94bdaeb5 100644 --- a/neps/optimizers/multi_fidelity/successive_halving.py +++ b/neps/optimizers/multi_fidelity/successive_halving.py @@ -5,10 +5,10 @@ import random import typing from copy import deepcopy +from typing import Literal import numpy as np import pandas as pd -from typing_extensions import Literal from ...metahyper import ConfigResult from ...search_spaces.hyperparameters.categorical import ( @@ -22,6 +22,7 @@ from ..base_optimizer import BaseOptimizer from .promotion_policy import AsyncPromotionPolicy, SyncPromotionPolicy from .sampling_policy import FixedPriorPolicy, RandomUniformPolicy +from .utils import MFObservedData CUSTOM_FLOAT_CONFIDENCE_SCORES = FLOAT_CONFIDENCE_SCORES.copy() CUSTOM_FLOAT_CONFIDENCE_SCORES.update({"ultra": 0.05}) @@ -102,8 +103,7 @@ def __init__( # the parameter is exposed to allow HB to call SH with different stopping rates self.early_stopping_rate = early_stopping_rate self.sampling_policy = sampling_policy( - pipeline_space=self.pipeline_space, - logger=self.logger + pipeline_space=self.pipeline_space, logger=self.logger ) self.promotion_policy = promotion_policy(self.eta) @@ -132,6 +132,15 @@ def __init__( self.sampling_args: dict = {} self.fidelities = list(self.rung_map.values()) + + self.MFobserved_configs = MFObservedData( + config_id="config_id", + budget_id="budget_id", + config_col="config", + perf_col="perf", + auxiliary_cols=["rung"], + ) + # TODO: replace with MFobserved_configs # stores the observations made and the corresponding fidelity explored # crucial data structure used for determining promotion candidates self.observed_configs = pd.DataFrame([], columns=("config", "rung", "perf")) @@ -164,6 +173,10 @@ def _get_rung_trace(cls, rung_map: dict, config_map: dict) -> list[int]: return rung_trace def get_incumbent_score(self): + # budget_perf = self.MFobserved_configs.get_best_performance_for_each_budget() + # y_star = budget_perf[budget_perf.index.max] + + # TODO: replace this with existing method y_star = np.inf # minimizing optimizer if len(self.observed_configs): y_star = self.observed_configs.perf.values.min() @@ -219,52 +232,88 @@ def _get_config_id_split(cls, config_id: str) -> tuple[str, str]: def _load_previous_observations( self, previous_results: dict[str, ConfigResult] ) -> None: - for config_id, config_val in previous_results.items(): + def index_data_split(config_id: str, config_val): _config, _rung = self._get_config_id_split(config_id) perf = self.get_loss(config_val.result) - if int(_config) in self.observed_configs.index: - # config already recorded in dataframe - rung_recorded = self.observed_configs.at[int(_config), "rung"] - if rung_recorded < int(_rung): - # config recorded for a lower rung but higher rung eval available - self.observed_configs.at[int(_config), "config"] = config_val.config - self.observed_configs.at[int(_config), "rung"] = int(_rung) - self.observed_configs.at[int(_config), "perf"] = perf - else: - _df = pd.DataFrame( - [[config_val.config, int(_rung), perf]], - columns=self.observed_configs.columns, - index=pd.Series(int(_config)), # key for config_id - ) - self.observed_configs = pd.concat( - (self.observed_configs, _df) - ).sort_index() - # for efficiency, redefining the function to have the - # `rung_histories` assignment inside the for loop - # rung histories are collected only for `previous` and not `pending` configs - self.rung_histories[int(_rung)]["config"].append(int(_config)) - self.rung_histories[int(_rung)]["perf"].append(perf) + index = int(_config), int(_rung) + _data = [config_val.config, perf, int(_rung)] + return index, _data + + if len(previous_results) > 0: + index_row = [ + tuple(index_data_split(config_id, config_val)) + for config_id, config_val in previous_results.items() + ] + indices, rows = zip(*index_row) + self.MFobserved_configs.add_data(data=list(rows), index=list(indices)) + # TODO: replace this with new optimized method + # for config_id, config_val in previous_results.items(): + # _config, _rung = self._get_config_id_split(config_id) + # perf = self.get_loss(config_val.result) + # if int(_config) in self.observed_configs.index: + # # config already recorded in dataframe + # rung_recorded = self.observed_configs.at[int(_config), "rung"] + # if rung_recorded < int(_rung): + # # config recorded for a lower rung but higher rung eval available + # self.observed_configs.at[int(_config), "config"] = config_val.config + # self.observed_configs.at[int(_config), "rung"] = int(_rung) + # self.observed_configs.at[int(_config), "perf"] = perf + # else: + # _df = pd.DataFrame( + # [[config_val.config, int(_rung), perf]], + # columns=self.observed_configs.columns, + # index=pd.Series(int(_config)), # key for config_id + # ) + # self.observed_configs = pd.concat( + # (self.observed_configs, _df) + # ).sort_index() + # # for efficiency, redefining the function to have the + # # `rung_histories` assignment inside the for loop + # # rung histories are collected only for `previous` and not `pending` configs + # self.rung_histories[int(_rung)]["config"].append(int(_config)) + # self.rung_histories[int(_rung)]["perf"].append(perf) return def _handle_pending_evaluations( self, pending_evaluations: dict[str, ConfigResult] ) -> None: + def index_data_split(config_id: str, config_val): + _config, _rung = self._get_config_id_split(config_id) + # perf = self.get_loss(config_val.result) + index = int(_config), int(_rung) + _data = [ + # use `config_val` instead of `config_val.config` + # unlike `previous_results` case + config_val, + np.nan, + int(_rung), + ] + return index, _data + + if len(pending_evaluations) > 0: + index_row = [ + tuple(index_data_split(config_id, config_val)) + for config_id, config_val in pending_evaluations.items() + ] + indices, rows = zip(*index_row) + self.MFobserved_configs.add_data(data=list(rows), index=list(indices)) + # TODO: replace this # iterates over all pending evaluations and updates the list of observed # configs with the rung and performance as None - for config_id, config in pending_evaluations.items(): - _config, _rung = self._get_config_id_split(config_id) - if int(_config) not in self.observed_configs.index: - _df = pd.DataFrame( - [[config, int(_rung), np.nan]], - columns=self.observed_configs.columns, - index=pd.Series(int(_config)), # key for config_id - ) - self.observed_configs = pd.concat( - (self.observed_configs, _df) - ).sort_index() - else: - self.observed_configs.at[int(_config), "rung"] = int(_rung) - self.observed_configs.at[int(_config), "perf"] = np.nan + # for config_id, config in pending_evaluations.items(): + # _config, _rung = self._get_config_id_split(config_id) + # if int(_config) not in self.observed_configs.index: + # _df = pd.DataFrame( + # [[config, int(_rung), np.nan]], + # columns=self.observed_configs.columns, + # index=pd.Series(int(_config)), # key for config_id + # ) + # self.observed_configs = pd.concat( + # (self.observed_configs, _df) + # ).sort_index() + # else: + # self.observed_configs.at[int(_config), "rung"] = int(_rung) + # self.observed_configs.at[int(_config), "perf"] = np.nan return def clean_rung_information(self): @@ -290,6 +339,7 @@ def _get_rungs_state(self, observed_configs=None): # iterates over the list of explored configs and buckets them to respective # rungs depending on the highest fidelity it was evaluated at self.clean_rung_information() + # TODO: create a new method for this for _rung in observed_configs.rung.unique(): idxs = observed_configs.rung == _rung self.rung_members[_rung] = observed_configs.index[idxs].values @@ -331,7 +381,15 @@ def load_results( for rung in range(self.min_rung, self.max_rung + 1) } - self.observed_configs = pd.DataFrame([], columns=("config", "rung", "perf")) + self.MFobserved_configs = MFObservedData( + config_id="config_id", + budget_id="budget_id", + config_col="config", + perf_col="perf", + auxiliary_cols=["rung"], + ) + + # self.observed_configs = pd.DataFrame([], columns=("config", "rung", "perf")) # previous optimization run exists and needs to be loaded self._load_previous_observations(previous_results) @@ -340,6 +398,12 @@ def load_results( # account for pending evaluations self._handle_pending_evaluations(pending_evaluations) + # TODO: change this after testing + # Copy data into old format + self.observed_configs = self.MFobserved_configs.copy_df( + df=self.MFobserved_configs.reduce_to_max_seen_budgets() + ) + # process optimization state and bucket observations per rung self._get_rungs_state() @@ -374,7 +438,9 @@ def sample_new_config( return config def _generate_new_config_id(self): - return self.observed_configs.index.max() + 1 if len(self.observed_configs) else 0 + return self.MFobserved_configs.next_config_id() + # TODO: replace this with existing + # return self.observed_configs.index.max() + 1 if len(self.observed_configs) else 0 def get_default_configuration(self): pass @@ -403,6 +469,7 @@ def get_config_and_ids( # pylint: disable=no-self-use rung_to_promote = self.is_promotable() if rung_to_promote is not None: # promotes the first recorded promotable config in the argsort-ed rung + # TODO: What to do with this? row = self.observed_configs.iloc[self.rung_promotions[rung_to_promote][0]] config = deepcopy(row["config"]) rung = rung_to_promote + 1 diff --git a/neps/optimizers/multi_fidelity/utils.py b/neps/optimizers/multi_fidelity/utils.py index 80a6a230..cbc456db 100644 --- a/neps/optimizers/multi_fidelity/utils.py +++ b/neps/optimizers/multi_fidelity/utils.py @@ -1,18 +1,19 @@ # type: ignore from __future__ import annotations +from copy import deepcopy from typing import Any, Sequence import numpy as np import pandas as pd -import time import torch -from copy import deepcopy - from ...optimizers.utils import map_real_hyperparameters_from_tabular_ids from ...search_spaces.search_space import SearchSpace +# from neps.optimizers.utils import map_real_hyperparameters_from_tabular_ids +# from neps.search_spaces.search_space import SearchSpace + def continuous_to_tabular( config: SearchSpace, categorical_space: SearchSpace @@ -62,32 +63,32 @@ class MFObservedData: def __init__( self, - columns: list[str] | None = None, - index_names: list[str] | None = None, + config_id: str | None = None, + budget_id: str | None = None, + config_col: str | None = None, + perf_col: str | None = None, + learning_curve_col: str | None = None, + auxiliary_cols: list[str] | None = None, ): - if columns is None: - columns = [self.default_config_col, self.default_perf_col] - if index_names is None: - index_names = [self.default_config_idx, self.default_budget_idx] + self.config_col = self.default_config_col if config_col is None else config_col + self.perf_col = self.default_perf_col if perf_col is None else perf_col - self.config_col = columns[0] - self.perf_col = columns[1] + self.config_idx = self.default_config_idx if config_id is None else config_id + self.budget_idx = self.default_budget_idx if budget_id is None else budget_id - if len(columns) > 2: - self.lc_col_name = columns[2] - else: - self.lc_col_name = self.default_lc_col + self.lc_col_name = learning_curve_col - if len(index_names) == 1: - index_names += ["budget_id"] + auxiliary_cols = [] if auxiliary_cols is None else auxiliary_cols - self.config_idx = index_names[0] - self.budget_idx = index_names[1] - self.index_names = index_names + self.index_names = [self.config_idx, self.budget_idx] + col_names = [self.config_col, self.perf_col, self.lc_col_name] + auxiliary_cols + self.columns = [col_name for col_name in col_names if col_name is not None] - index = pd.MultiIndex.from_tuples([], names=index_names) + index = pd.MultiIndex.from_tuples([], names=self.index_names) - self.df = pd.DataFrame([], columns=columns, index=index) + self.df = pd.DataFrame([], columns=self.columns, index=index) + + self.mutable_columns = [self.config_col, self.lc_col_name] @property def pending_condition(self): @@ -116,6 +117,13 @@ def next_config_id(self) -> int: else: return 0 + @staticmethod + def __validate_index(index_list): + """Extends single indices to multi-index case""" + if all([isinstance(idx, int) for idx in index_list]): + index_list = list(zip(index_list, [0] * len(index_list))) + return index_list + def add_data( self, data: list[Any] | list[list[Any]], @@ -125,7 +133,6 @@ def add_data( """ Add data only if none of the indices are already existing in the DataFrame """ - # TODO: If index is only config_id extend it if not isinstance(index, list): index_list = [index] data_list = [data] @@ -133,6 +140,8 @@ def add_data( index_list = index data_list = data + index_list = self.__validate_index(index_list) + if not self.df.index.isin(index_list).any(): index = pd.MultiIndex.from_tuples(index_list, names=self.index_names) _df = pd.DataFrame(data_list, columns=self.df.columns, index=index) @@ -157,6 +166,9 @@ def update_data( index_list = [index] else: index_list = index + + index_list = self.__validate_index(index_list) + if self.df.index.isin(index_list).sum() == len(index_list): column_names, data = zip(*data_dict.items()) data = list(zip(*data)) @@ -169,7 +181,7 @@ def update_data( f"Given indices: {index_list}" ) - def get_learning_curves(self): + def get_trajectories(self): return self.df.pivot_table( index=self.df.index.names[0], columns=self.df.index.names[1], @@ -186,11 +198,11 @@ def get_incumbents_for_budgets(self, maximize: bool = False): Note: this will always map the best lowest ID if two configurations have the same performance at the same fidelity """ - learning_curves = self.get_learning_curves() + trajectories = self.get_trajectories() if maximize: - config_ids = learning_curves.idxmax(axis=0) + config_ids = trajectories.idxmax(axis=0) else: - config_ids = learning_curves.idxmin(axis=0) + config_ids = trajectories.idxmin(axis=0) indices = list(zip(config_ids.values.tolist(), config_ids.index.to_list())) partial_configs = self.df.loc[indices, self.config_col].to_list() @@ -203,17 +215,16 @@ def get_best_performance_for_each_budget(self, maximize: bool = False): Note: this will always map the best lowest ID if two configurations has the same performance at the same fidelity """ - learning_curves = self.get_learning_curves() + trajectories = self.get_trajectories() if maximize: - performance = learning_curves.max(axis=0) + performance = trajectories.max(axis=0) else: - performance = learning_curves.min(axis=0) + performance = trajectories.min(axis=0) return performance def get_budget_level_for_best_performance(self, maximize: bool = False) -> int: - """Returns the lowest budget level at which the highest performance was recorded. - """ + """Returns the lowest budget level at which the highest performance was recorded.""" perf_per_z = self.get_best_performance_for_each_budget(maximize=maximize) y_star = self.get_best_seen_performance(maximize=maximize) # uses the minimum of the budget that see the maximum obseved score @@ -228,29 +239,62 @@ def get_best_learning_curve_id(self, maximize: bool = False): Note: this will always return the single best lowest ID if two configurations has the same performance """ - learning_curves = self.get_learning_curves() + trajectories = self.get_trajectories() if maximize: - return learning_curves.max(axis=1).idxmax() + return trajectories.max(axis=1).idxmax() else: - return learning_curves.min(axis=1).idxmin() + return trajectories.min(axis=1).idxmin() def get_best_seen_performance(self, maximize: bool = False): - learning_curves = self.get_learning_curves() + trajectories = self.get_trajectories() if maximize: - return learning_curves.max(axis=1).max() + return trajectories.max(axis=1).max() else: - return learning_curves.min(axis=1).min() + return trajectories.min(axis=1).min() def add_budget_column(self): - combined_df = self.df.reset_index(level=1) - combined_df.set_index( - keys=[self.budget_idx], drop=False, append=True, inplace=True - ) - return combined_df + pass + # budget_column = self.df.index.get_level_values(1) + # self.df[self.budget_idx] = budget_column + # combined_df = self.df.reset_index(level=1) + # combined_df.set_index( + # keys=[self.budget_idx], drop=False, append=True, inplace=True + # ) + # return combined_df + + def copy_df(self, df: pd.DataFrame | None = None): + """ + Use this function to copy df if you are going to + perform some operations on its elements. + + DataFrames are not meant for mutable data-types, + nevertheless we do put mutable SearchSpace objects into the config_col of the DF + In order not to change the values stored objects in the DF we deepcopy all + mutable columns here. + + self.mutable_columns must keep track of + the mutable columns at all times. + """ + if df is None: + df = self.df + new_df = pd.DataFrame() + new_df.index = df.index.copy(deep=True) + + for column in df.columns: + if column in self.mutable_columns: + new_column = [deepcopy(value) for value in df[column].values] + new_df[column] = new_column + else: + new_df[column] = df[column].copy(deep=True) + + return new_df def reduce_to_max_seen_budgets(self): self.df.sort_index(inplace=True) - combined_df = self.add_budget_column() + budget_column = self.df.index.get_level_values(1) + combined_df = self.df.copy(deep=True) + combined_df[self.budget_idx] = budget_column + # combined_df = self.copy_df(df=combined_df) return combined_df.groupby(level=0).last() def get_partial_configs_at_max_seen(self): @@ -262,7 +306,9 @@ def extract_learning_curve( if budget_id is None: # budget_id only None when predicting # extract full observed learning curve for prediction pipeline - budget_id = max(self.df.loc[config_id].index.get_level_values("budget_id").values) + 1 + budget_id = ( + max(self.df.loc[config_id].index.get_level_values("budget_id").values) + 1 + ) # For the first epoch we have no learning curve available if budget_id == 0: @@ -273,14 +319,13 @@ def extract_learning_curve( if self.lc_col_name in self.df.columns: lc = self.df.loc[(config_id, budget_id), self.lc_col_name] else: - lcs = self.get_learning_curves() - lc = lcs.loc[config_id, :budget_id].values.flatten().tolist() + trajectories = self.get_trajectories() + lc = trajectories.loc[config_id, :budget_id].values.flatten().tolist() return deepcopy(lc) def get_training_data_4DyHPO( self, df: pd.DataFrame, pipeline_space: SearchSpace | None = None ): - start = time.time() configs = [] learning_curves = [] performance = [] @@ -295,30 +340,27 @@ def get_training_data_4DyHPO( configs.append(row[self.config_col]) performance.append(row[self.perf_col]) learning_curves.append(self.extract_learning_curve(config_id, budget_id)) - # print("-" * 50) - # print(f"| Time for `get_training_data_4DyHPO()`: {time.time()-start:.2f}s") - # print("-" * 50) return configs, learning_curves, performance def get_best_performance_per_config(self, maximize: bool = False) -> pd.Series: - """Returns the best score recorded per config across fidelities seen. - """ + """Returns the best score recorded per config across fidelities seen.""" op = np.max if maximize else np.min perf = ( - self.df - .sort_values("budget_id", ascending=False) # sorts with largest budget first + self.df.sort_values( + "budget_id", ascending=False + ) # sorts with largest budget first .groupby("config_id") # retains only config_id .first() # retrieves the largest budget seen for each config_id - .learning_curves # extracts all values seen till largest budget for a config - .apply(op) # finds the minimum over per-config learning curve + .learning_curves.apply( # extracts all values seen till largest budget for a config + op + ) # finds the minimum over per-config learning curve ) return perf def get_max_observed_fidelity_level_per_config(self) -> pd.Series: - """Returns the highest fidelity level recorded per config seen. - """ + """Returns the highest fidelity level recorded per config seen.""" max_z_observed = { - _id: self.df.loc[_id,:].index.sort_values()[-1] + _id: self.df.loc[_id, :].index.sort_values()[-1] for _id in self.df.index.get_level_values("config_id").sort_values() } return pd.Series(max_z_observed) @@ -353,48 +395,93 @@ def token_ids(self) -> np.ndarray: if __name__ == "__main__": # TODO: Either delete these or convert them to tests (karibbov) + + def multi_index_parallel(): + data = MFObservedData( + config_id="config_id", + budget_id="budget_id", + config_col="config", + perf_col="perf", + ) + + # When adding multiple indices data should be list of rows(lists) and the index should be list of tuples + data.add_data( + [["conf1", 0.5], ["conf2", 0.7], ["conf1", 0.6], ["conf2", 0.4]], + index=[(0, 0), (1, 1), (0, 3), (1, 0)], + ) + # print(data.df) + + data.add_data( + [["conf1", 0.5], ["conf2", 0.10], ["conf1", 0.11]], + index=[(0, 2), (1, 2), (0, 1)], + ) + + print(data.df) + # print(data.get_trajectories()) + # print( + # "Mapping of budget IDs into best performing configurations at each fidelity:\n", + # data.get_incumbents_for_budgets(), + # ) + # print( + # "Best Performance at each budget level:\n", + # data.get_best_performance_for_each_budget(), + # ) + # print( + # "Configuration ID of the best observed performance so far: ", + # data.get_best_learning_curve_id(), + # ) + # print(data.extract_learning_curve(0, 2)) + # # data.df.sort_index(inplace=True) + # print(data.get_partial_configs_at_max_seen()) + # + # # When updating multiple indices at a time both the values in the data dictionary and the indices should be lists + data.update_data({"perf": [1.8, 1.5]}, index=[(1, 1), (0, 0)]) + print(data.df) + + def multi_index_single(): + data = MFObservedData( + config_id="config_id", + budget_id="budget_id", + config_col="config", + perf_col="perf", + ) + + # when adding a single row second level list is not necessary + data.add_data(["conf1", 0.5], index=(0, 0)) + data.add_data(["conf1", 0.8], index=(1, 0)) + print(data.df) + + data.update_data({"perf": [1.8], "budget_col": [5]}, index=(0, 0)) + print(data.df) + + def single_index_parallel(): + data = MFObservedData( + config_id="config_id", + budget_id="budget_id", + config_col="config", + perf_col="perf", + ) + + # When adding multiple indices data should be list of rows(lists) and the index should be list of tuples + data.add_data( + [["conf1", 0.5], ["conf2", 0.7]], + index=[(0), (1)], + ) + print(data.df) + + data.add_data( + [["conf1", 0.5], ["conf2", 0.10]], + index=[(2), (3)], + ) + + print(data.df) + + data.update_data({"perf": [1.8, 1.5]}, index=[(1), (0)]) + print(data.df) + """ Here are a few examples of how to manage data with this class: """ - data = MFObservedData(["config", "perf"], index_names=["config_id", "budget_id"]) - - # When adding multiple indices data should be list of rows(lists) and the index should be list of tuples - data.add_data( - [["conf1", 0.5], ["conf2", 0.7], ["conf1", 0.6], ["conf2", 0.4]], - index=[(0, 0), (1, 1), (0, 3), (1, 0)], - ) - data.add_data( - [["conf1", 0.5], ["conf2", 0.10], ["conf1", 0.11]], - index=[(0, 2), (1, 2), (0, 1)], - ) - - print(data.df) - print(data.get_learning_curves()) - print( - "Mapping of budget IDs into best performing configurations at each fidelity:\n", - data.get_incumbents_for_budgets(), - ) - print( - "Best Performance at each budget level:\n", - data.get_best_performance_for_each_budget(), - ) - print( - "Configuration ID of the best observed performance so far: ", - data.get_best_learning_curve_id(), - ) - print(data.extract_learning_curve(0, 2)) - # data.df.sort_index(inplace=True) - print(data.get_partial_configs_at_max_seen()) - - # When updating multiple indices at a time both the values in the data dictionary and the indices should be lists - data.update_data({"perf": [1.8, 1.5]}, index=[(1, 1), (0, 0)]) - print(data.df) - - data = MFObservedData(["config", "perf"], index_names=["config_id", "budget_id"]) - - # when adding a single row second level list is not necessary - data.add_data(["conf1", 0.5], index=(0, 0)) - print(data.df) - - data.update_data({"perf": [1.8], "budget_col": [5]}, index=(0, 0)) - print(data.df) + single_index_parallel() + multi_index_single() + single_index_parallel() From e824c3f158475fa69a0641ec28d7846e15645336 Mon Sep 17 00:00:00 2001 From: karibbov Date: Wed, 10 Apr 2024 15:52:55 +0200 Subject: [PATCH 4/6] refactor: observed_configs -> max_budget_configs --- neps/optimizers/multi_fidelity/hyperband.py | 12 ++--- .../multi_fidelity/successive_halving.py | 45 +++++++++++++------ .../multi_fidelity_prior/async_priorband.py | 4 +- .../multi_fidelity_prior/priorband.py | 22 ++++----- 4 files changed, 51 insertions(+), 32 deletions(-) diff --git a/neps/optimizers/multi_fidelity/hyperband.py b/neps/optimizers/multi_fidelity/hyperband.py index 1278cbee..1db92056 100644 --- a/neps/optimizers/multi_fidelity/hyperband.py +++ b/neps/optimizers/multi_fidelity/hyperband.py @@ -98,7 +98,7 @@ def _update_sh_bracket_state(self) -> None: # for the current SH bracket in HB # TODO: can we avoid copying full observation history bracket = self.sh_brackets[self.current_sh_bracket] # type: ignore - bracket.observed_configs = self.observed_configs.copy() + # bracket.max_budget_configs = self.max_budget_configs.copy() # TODO: Do we NEED to copy here instead? bracket.MFobserved_configs = self.MFobserved_configs @@ -170,7 +170,7 @@ def clear_old_brackets(self): base_rung_sizes = [] # sorted(self.config_map.values(), reverse=True) for bracket in self.sh_brackets.values(): base_rung_sizes.append(sorted(bracket.config_map.values(), reverse=True)[0]) - while end <= len(self.observed_configs): + while end <= len(self.max_budget_configs): # subsetting only this SH bracket from the history sh_bracket = self.sh_brackets[self.current_sh_bracket] sh_bracket.clean_rung_information() @@ -178,14 +178,14 @@ def clear_old_brackets(self): # correct SH bracket object to make the right budget calculations # pylint: disable=protected-access bracket_budget_used = sh_bracket._calc_budget_used_in_bracket( - deepcopy(self.observed_configs.rung.values[start:end]) + deepcopy(self.max_budget_configs.rung.values[start:end]) ) # if budget used is less than the total SH budget then still an active bracket current_bracket_full_budget = sum(sh_bracket.full_rung_trace) if bracket_budget_used < current_bracket_full_budget: # updating rung information of the current bracket # pylint: disable=protected-access - sh_bracket._get_rungs_state(self.observed_configs.iloc[start:end]) + sh_bracket._get_rungs_state(self.max_budget_configs.iloc[start:end]) # extra call to use the updated rung member info to find promotions # SyncPromotion signals a wait if a rung is full but with # incomplete/pending evaluations, signals to starts a new SH bracket @@ -210,7 +210,7 @@ def clear_old_brackets(self): # updates rung info with the latest active, incomplete bracket sh_bracket = self.sh_brackets[self.current_sh_bracket] # pylint: disable=protected-access - sh_bracket._get_rungs_state(self.observed_configs.iloc[start:end]) + sh_bracket._get_rungs_state(self.max_budget_configs.iloc[start:end]) sh_bracket._handle_promotions() # self._handle_promotion() need not be called as it is called by load_results() @@ -380,7 +380,7 @@ def _update_sh_bracket_state(self) -> None: config_map=bracket.config_map, ) bracket.rung_promotions = bracket.promotion_policy.retrieve_promotions() - bracket.observed_configs = self.observed_configs.copy() + bracket.max_budget_configs = self.max_budget_configs.copy() def _get_bracket_to_run(self): """Samples the ASHA bracket to run. diff --git a/neps/optimizers/multi_fidelity/successive_halving.py b/neps/optimizers/multi_fidelity/successive_halving.py index 94bdaeb5..eb540e69 100644 --- a/neps/optimizers/multi_fidelity/successive_halving.py +++ b/neps/optimizers/multi_fidelity/successive_halving.py @@ -8,7 +8,6 @@ from typing import Literal import numpy as np -import pandas as pd from ...metahyper import ConfigResult from ...search_spaces.hyperparameters.categorical import ( @@ -143,7 +142,9 @@ def __init__( # TODO: replace with MFobserved_configs # stores the observations made and the corresponding fidelity explored # crucial data structure used for determining promotion candidates - self.observed_configs = pd.DataFrame([], columns=("config", "rung", "perf")) + self.__max_observed_configs = None + self.history_length = 0 + # self.max_budget_configs = pd.DataFrame([], columns=("config", "rung", "perf")) # stores which configs occupy each rung at any time self.rung_members: dict = dict() # stores config IDs per rung self.rung_members_performance: dict = dict() # performances recorded per rung @@ -164,6 +165,22 @@ def __init__( self._enhance_priors() self.rung_histories = None + @property + def max_budget_configs(self): + """ + Make this property dynamically dependent on self.MFobserved_configs. So the state + of the algo only depends on self.MFobserved_configs. + """ + if self.__max_observed_configs is None or self.history_length != len( + self.MFobserved_configs.df + ): + self.__max_observed_configs = self.MFobserved_configs.copy_df( + df=self.MFobserved_configs.reduce_to_max_seen_budgets() + ) + self.history_length = len(self.MFobserved_configs.df) + + return self.__max_observed_configs + @classmethod def _get_rung_trace(cls, rung_map: dict, config_map: dict) -> list[int]: """Lists the rung IDs in sequence of the flattened SH tree.""" @@ -178,8 +195,8 @@ def get_incumbent_score(self): # TODO: replace this with existing method y_star = np.inf # minimizing optimizer - if len(self.observed_configs): - y_star = self.observed_configs.perf.values.min() + if len(self.max_budget_configs): + y_star = self.max_budget_configs.perf.values.min() return y_star def _get_rung_map(self, s: int = 0) -> dict: @@ -325,7 +342,7 @@ def _get_rungs_state(self, observed_configs=None): """Collects info on configs at a rung and their performance there.""" # to account for incomplete evaluations from being promoted --> working on a copy observed_configs = ( - self.observed_configs.copy().dropna(inplace=False) + self.max_budget_configs.copy().dropna(inplace=False) if observed_configs is None else observed_configs ) @@ -400,9 +417,9 @@ def load_results( # TODO: change this after testing # Copy data into old format - self.observed_configs = self.MFobserved_configs.copy_df( - df=self.MFobserved_configs.reduce_to_max_seen_budgets() - ) + # self.max_budget_configs = self.MFobserved_configs.copy_df( + # df=self.MFobserved_configs.reduce_to_max_seen_budgets() + # ) # process optimization state and bucket observations per rung self._get_rungs_state() @@ -470,7 +487,7 @@ def get_config_and_ids( # pylint: disable=no-self-use if rung_to_promote is not None: # promotes the first recorded promotable config in the argsort-ed rung # TODO: What to do with this? - row = self.observed_configs.iloc[self.rung_promotions[rung_to_promote][0]] + row = self.max_budget_configs.iloc[self.rung_promotions[rung_to_promote][0]] config = deepcopy(row["config"]) rung = rung_to_promote + 1 # assigning the fidelity to evaluate the config at @@ -484,7 +501,7 @@ def get_config_and_ids( # pylint: disable=no-self-use if ( self.use_priors and self.sample_default_first - and len(self.observed_configs) == 0 + and len(self.max_budget_configs) == 0 ): if self.sample_default_at_target: # sets the default config to be evaluated at the target fidelity @@ -568,15 +585,15 @@ def clear_old_brackets(self): start += 1 end += 1 # iterates over the different SH brackets which span start-end by index - while end <= len(self.observed_configs): + while end <= len(self.max_budget_configs): # for the SH bracket in start-end, calculate total SH budget used bracket_budget_used = self._calc_budget_used_in_bracket( - deepcopy(self.observed_configs.rung.values[start:end]) + deepcopy(self.max_budget_configs.rung.values[start:end]) ) # if budget used is less than a SH bracket budget then still an active bracket if bracket_budget_used < sum(self.full_rung_trace): # subsetting only this SH bracket from the history - self._get_rungs_state(self.observed_configs.iloc[start:end]) + self._get_rungs_state(self.max_budget_configs.iloc[start:end]) # extra call to use the updated rung member info to find promotions # SyncPromotion signals a wait if a rung is full but with # incomplete/pending evaluations, and signals to starts a new SH bracket @@ -594,7 +611,7 @@ def clear_old_brackets(self): end = start + self.config_map[self.min_rung] # updates rung info with the latest active, incomplete bracket - self._get_rungs_state(self.observed_configs.iloc[start:end]) + self._get_rungs_state(self.max_budget_configs.iloc[start:end]) # _handle_promotion() need not be called as it is called by load_results() return diff --git a/neps/optimizers/multi_fidelity_prior/async_priorband.py b/neps/optimizers/multi_fidelity_prior/async_priorband.py index a054ad10..df58b5a3 100644 --- a/neps/optimizers/multi_fidelity_prior/async_priorband.py +++ b/neps/optimizers/multi_fidelity_prior/async_priorband.py @@ -1,9 +1,9 @@ from __future__ import annotations import typing +from typing import Literal import numpy as np -from typing import Literal from ...metahyper import ConfigResult from ...search_spaces.search_space import SearchSpace @@ -238,7 +238,7 @@ def _update_sh_bracket_state(self) -> None: config_map=bracket.config_map, ) bracket.rung_promotions = bracket.promotion_policy.retrieve_promotions() - bracket.observed_configs = self.observed_configs.copy() + bracket.max_budget_configs = self.max_budget_configs.copy() bracket.rung_histories = self.rung_histories def load_results( diff --git a/neps/optimizers/multi_fidelity_prior/priorband.py b/neps/optimizers/multi_fidelity_prior/priorband.py index 95c23eb7..ba66d98f 100644 --- a/neps/optimizers/multi_fidelity_prior/priorband.py +++ b/neps/optimizers/multi_fidelity_prior/priorband.py @@ -3,9 +3,9 @@ from __future__ import annotations import typing +from typing import Literal import numpy as np -from typing import Literal from ...search_spaces.search_space import SearchSpace from ..bayesian_optimization.acquisition_functions.base_acquisition import BaseAcquisition @@ -34,7 +34,7 @@ def find_all_distances_from_incumbent(self, incumbent): """Finds the distance to the nearest neighbour.""" dist = lambda x: compute_config_dist(incumbent, x) # computing distance of incumbent from all seen points in history - distances = [dist(config) for config in self.observed_configs.config] + distances = [dist(config) for config in self.max_budget_configs.config] # ensuring the distances exclude 0 or the distance from itself distances = [d for d in distances if d > 0] return distances @@ -47,14 +47,14 @@ def find_1nn_distance_from_incumbent(self, incumbent): def find_incumbent(self, rung: int = None) -> SearchSpace: """Find the best performing configuration seen so far.""" - rungs = self.observed_configs.rung.values - idxs = self.observed_configs.index.values + rungs = self.max_budget_configs.rung.values + idxs = self.max_budget_configs.index.values while rung is not None: # enters this scope is `rung` argument passed and not left empty or None if rung not in rungs: self.logger.warn(f"{rung} not in {np.unique(idxs)}") # filtering by rung based on argument passed - idxs = self.observed_configs.rung.values == rung + idxs = self.max_budget_configs.rung.values == rung # checking width of current rung if len(idxs) < self.eta: self.logger.warn( @@ -63,9 +63,9 @@ def find_incumbent(self, rung: int = None) -> SearchSpace: # extracting the incumbent configuration if len(idxs): # finding the config with the lowest recorded performance - _perfs = self.observed_configs.loc[idxs].perf.values + _perfs = self.max_budget_configs.loc[idxs].perf.values inc_idx = np.nanargmin([np.nan if t is None else t for t in _perfs]) - inc = self.observed_configs.loc[idxs].iloc[inc_idx].config + inc = self.max_budget_configs.loc[idxs].iloc[inc_idx].config else: # THIS block should not ever execute, but for runtime anomalies, if no # incumbent can be extracted, the prior is treated as the incumbent @@ -126,7 +126,9 @@ def is_activate_inc(self) -> bool: resources += bracket.config_map[rung] * continuation_resources # find resources spent so far for all finished evaluations - resources_used = calc_total_resources_spent(self.observed_configs, self.rung_map) + resources_used = calc_total_resources_spent( + self.max_budget_configs, self.rung_map + ) if resources_used >= resources and len( self.rung_histories[self.max_rung]["config"] @@ -190,7 +192,7 @@ def prior_to_incumbent_ratio(self) -> float | float: if self.inc_style == "constant": return self._prior_to_incumbent_ratio_constant() elif self.inc_style == "decay": - resources = calc_total_resources_spent(self.observed_configs, self.rung_map) + resources = calc_total_resources_spent(self.max_budget_configs, self.rung_map) return self._prior_to_incumbent_ratio_decay( resources, self.eta, self.min_budget, self.max_budget ) @@ -244,7 +246,7 @@ def _prior_to_incumbent_ratio_dynamic(self, rung: int) -> float | float: [ # `compute_scores` returns a tuple of scores resp. by prior and inc compute_scores( - self.observed_configs.loc[config_id].config, prior, inc + self.max_budget_configs.loc[config_id].config, prior, inc ) for config_id in top_configs ] From 47cfe38f38c875004dec10a4899b1867adebb5bb Mon Sep 17 00:00:00 2001 From: karibbov Date: Wed, 10 Apr 2024 16:01:38 +0200 Subject: [PATCH 5/6] Priorband BO refactor: observed_configs -> max_budget_configs --- neps/optimizers/multi_fidelity/mf_bo.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/neps/optimizers/multi_fidelity/mf_bo.py b/neps/optimizers/multi_fidelity/mf_bo.py index 67bca1f4..18703903 100755 --- a/neps/optimizers/multi_fidelity/mf_bo.py +++ b/neps/optimizers/multi_fidelity/mf_bo.py @@ -33,7 +33,7 @@ def _fit_models(self): if self.pipeline_space.has_prior: # PriorBand + BO total_resources = calc_total_resources_spent( - self.observed_configs, self.rung_map + self.max_budget_configs, self.rung_map ) decay_t = total_resources / self.max_budget else: @@ -42,7 +42,7 @@ def _fit_models(self): # extract pending configurations # doing this separately as `rung_histories` do not record pending configs - pending_df = self.observed_configs[self.observed_configs.perf.isna()] + pending_df = self.max_budget_configs[self.max_budget_configs.perf.isna()] if self.modelling_type == "rung": # collect only the finished configurations at the highest active `rung` # for training the surrogate and considering only those pending @@ -58,7 +58,7 @@ def _fit_models(self): ) self.logger.info(f"Building model at rung {rung}") # collecting finished evaluations at `rung` - train_df = self.observed_configs.loc[ + train_df = self.max_budget_configs.loc[ self.rung_histories[rung]["config"] ].copy() @@ -89,7 +89,7 @@ def _fit_models(self): pending_x = [] for rung in range(self.min_rung, self.max_rung + 1): _ids = self.rung_histories[rung]["config"] - _x = deepcopy(self.observed_configs.loc[_ids].config.values.tolist()) + _x = deepcopy(self.max_budget_configs.loc[_ids].config.values.tolist()) # update fidelity fidelity = [self.rung_map[rung]] * len(_x) _x = list(map(update_fidelity, _x, fidelity)) @@ -131,7 +131,7 @@ def is_init_phase(self) -> bool: # builds a model across all fidelities with the fidelity as a dimension # in this case, calculate the total number of function evaluations spent # and in vanilla BO fashion use that to compare with the initital design size - resources = calc_total_resources_spent(self.observed_configs, self.rung_map) + resources = calc_total_resources_spent(self.max_budget_configs, self.rung_map) resources /= self.max_budget if resources < self.init_size: return True From d6e123faf41dde2461241a20b2014e4345d9a2a3 Mon Sep 17 00:00:00 2001 From: karibbov Date: Wed, 10 Apr 2024 18:21:18 +0200 Subject: [PATCH 6/6] remove zipfile --- neps/status/status.py | 9 --------- 1 file changed, 9 deletions(-) diff --git a/neps/status/status.py b/neps/status/status.py index 8696ad16..247dfbe7 100644 --- a/neps/status/status.py +++ b/neps/status/status.py @@ -1,7 +1,6 @@ from __future__ import annotations import logging -import shutil import time from pathlib import Path from typing import Any @@ -323,14 +322,6 @@ def _save_data_to_csv( def post_run_csv(root_directory: str | Path, logger=None) -> None: root_directory = Path(root_directory) - zip_filename = Path(root_directory / "results.zip") - base_result_directory = root_directory / "results" - - # Extract previous results to load if it exists - if zip_filename.exists(): - # and not any(Path(base_result_directory).iterdir()): - shutil.unpack_archive(zip_filename, base_result_directory, "zip") - zip_filename.unlink() if logger is None: logger = logging.getLogger("neps_status")