From 00a5bd572149e00541fbff9716c5edbaeebb87a9 Mon Sep 17 00:00:00 2001 From: brendan Date: Thu, 2 Jan 2025 11:15:31 +1100 Subject: [PATCH] initial set up of paper branch --- .github/ISSUE_TEMPLATE/bug_report.md | 48 - .github/ISSUE_TEMPLATE/feature_request.md | 23 - .github/generate_paper.yml | 25 + .github/workflows/build_docs.yml | 124 -- .github/workflows/format_and_lint.yml | 26 - .github/workflows/python-publish.yml | 23 - .github/workflows/run_tests.yml | 39 - .gitignore | 39 - .pre-commit-config.yaml | 9 - LICENSE | 9 - README.md | 201 +--- bayes_opt/__init__.py | 26 - bayes_opt/acquisition.py | 1037 ----------------- bayes_opt/bayesian_optimization.py | 358 ------ bayes_opt/constraint.py | 263 ----- bayes_opt/domain_reduction.py | 295 ----- bayes_opt/event.py | 17 - bayes_opt/exception.py | 31 - bayes_opt/logger.py | 304 ----- bayes_opt/observer.py | 62 - bayes_opt/parameter.py | 506 -------- bayes_opt/py.typed | 0 bayes_opt/target_space.py | 712 ----------- bayes_opt/util.py | 84 -- docsrc/Makefile | 26 - docsrc/conf.py | 203 ---- docsrc/func.ico | Bin 136207 -> 0 bytes docsrc/index.rst | 222 ---- docsrc/make.bat | 44 - docsrc/reference/acquisition.rst | 14 - docsrc/reference/acquisition/ConstantLiar.rst | 5 - .../acquisition/ExpectedImprovement.rst | 5 - docsrc/reference/acquisition/GPHedge.rst | 5 - .../acquisition/ProbabilityOfImprovement.rst | 5 - .../acquisition/UpperConfidenceBound.rst | 5 - docsrc/reference/bayes_opt.rst | 5 - docsrc/reference/constraint.rst | 7 - docsrc/reference/domain_reduction.rst | 7 - docsrc/reference/exception.rst | 5 - docsrc/reference/other.rst | 11 - docsrc/reference/parameter.rst | 5 - docsrc/reference/target_space.rst | 5 - docsrc/requirements.txt | 3 - docsrc/static/bayesian_optimization.gif | Bin 16351229 -> 0 bytes docsrc/static/bo_example.png | Bin 97697 -> 0 bytes docsrc/static/func.png | Bin 15400 -> 0 bytes docsrc/static/sdr.png | Bin 29028 -> 0 bytes examples/acquisition_functions.ipynb | 395 ------- examples/advanced-tour.ipynb | 468 -------- examples/async_optimization.py | 137 --- examples/async_optimization_dummies.py | 92 -- examples/basic-tour.ipynb | 515 -------- examples/constraints.ipynb | 632 ---------- examples/domain_reduction.ipynb | 306 ----- examples/duplicate_point.py | 20 - examples/exploitation_vs_exploration.ipynb | 384 ------ examples/parameter_types.ipynb | 756 ------------ examples/sklearn_example.py | 121 -- examples/typed_hyperparameter_tuning.py | 94 -- examples/visualization.ipynb | 572 --------- paper.bib | 212 ++++ paper.md | 47 + pyproject.toml | 58 - ruff.toml | 131 --- scripts/check.sh | 5 - scripts/check_precommit.sh | 5 - scripts/format.sh | 6 - tests/test_acquisition.py | 353 ------ tests/test_bayesian_optimization.py | 335 ------ tests/test_constraint.py | 170 --- tests/test_logs.log | 5 - tests/test_logs_bounds.log | 5 - tests/test_logs_constrained.log | 7 - tests/test_logs_duplicates.log | 6 - tests/test_logs_multiple_constraints.log | 12 - tests/test_notebooks_run.py | 29 - tests/test_observer.py | 116 -- tests/test_parameter.py | 246 ---- tests/test_seq_domain_red.py | 187 --- tests/test_target_space.py | 311 ----- tests/test_util.py | 100 -- 81 files changed, 287 insertions(+), 11394 deletions(-) delete mode 100644 .github/ISSUE_TEMPLATE/bug_report.md delete mode 100644 .github/ISSUE_TEMPLATE/feature_request.md create mode 100644 .github/generate_paper.yml delete mode 100644 .github/workflows/build_docs.yml delete mode 100644 .github/workflows/format_and_lint.yml delete mode 100644 .github/workflows/python-publish.yml delete mode 100644 .github/workflows/run_tests.yml delete mode 100644 .gitignore delete mode 100644 .pre-commit-config.yaml delete mode 100644 LICENSE delete mode 100644 bayes_opt/__init__.py delete mode 100644 bayes_opt/acquisition.py delete mode 100644 bayes_opt/bayesian_optimization.py delete mode 100644 bayes_opt/constraint.py delete mode 100644 bayes_opt/domain_reduction.py delete mode 100644 bayes_opt/event.py delete mode 100644 bayes_opt/exception.py delete mode 100644 bayes_opt/logger.py delete mode 100644 bayes_opt/observer.py delete mode 100644 bayes_opt/parameter.py delete mode 100644 bayes_opt/py.typed delete mode 100644 bayes_opt/target_space.py delete mode 100644 bayes_opt/util.py delete mode 100644 docsrc/Makefile delete mode 100644 docsrc/conf.py delete mode 100644 docsrc/func.ico delete mode 100644 docsrc/index.rst delete mode 100644 docsrc/make.bat delete mode 100644 docsrc/reference/acquisition.rst delete mode 100644 docsrc/reference/acquisition/ConstantLiar.rst delete mode 100644 docsrc/reference/acquisition/ExpectedImprovement.rst delete mode 100644 docsrc/reference/acquisition/GPHedge.rst delete mode 100644 docsrc/reference/acquisition/ProbabilityOfImprovement.rst delete mode 100644 docsrc/reference/acquisition/UpperConfidenceBound.rst delete mode 100644 docsrc/reference/bayes_opt.rst delete mode 100644 docsrc/reference/constraint.rst delete mode 100644 docsrc/reference/domain_reduction.rst delete mode 100644 docsrc/reference/exception.rst delete mode 100644 docsrc/reference/other.rst delete mode 100644 docsrc/reference/parameter.rst delete mode 100644 docsrc/reference/target_space.rst delete mode 100644 docsrc/requirements.txt delete mode 100644 docsrc/static/bayesian_optimization.gif delete mode 100644 docsrc/static/bo_example.png delete mode 100644 docsrc/static/func.png delete mode 100644 docsrc/static/sdr.png delete mode 100644 examples/acquisition_functions.ipynb delete mode 100644 examples/advanced-tour.ipynb delete mode 100644 examples/async_optimization.py delete mode 100644 examples/async_optimization_dummies.py delete mode 100644 examples/basic-tour.ipynb delete mode 100644 examples/constraints.ipynb delete mode 100644 examples/domain_reduction.ipynb delete mode 100644 examples/duplicate_point.py delete mode 100644 examples/exploitation_vs_exploration.ipynb delete mode 100644 examples/parameter_types.ipynb delete mode 100644 examples/sklearn_example.py delete mode 100644 examples/typed_hyperparameter_tuning.py delete mode 100644 examples/visualization.ipynb create mode 100644 paper.bib create mode 100644 paper.md delete mode 100644 pyproject.toml delete mode 100644 ruff.toml delete mode 100755 scripts/check.sh delete mode 100755 scripts/check_precommit.sh delete mode 100755 scripts/format.sh delete mode 100644 tests/test_acquisition.py delete mode 100644 tests/test_bayesian_optimization.py delete mode 100644 tests/test_constraint.py delete mode 100644 tests/test_logs.log delete mode 100644 tests/test_logs_bounds.log delete mode 100644 tests/test_logs_constrained.log delete mode 100644 tests/test_logs_duplicates.log delete mode 100644 tests/test_logs_multiple_constraints.log delete mode 100644 tests/test_notebooks_run.py delete mode 100644 tests/test_observer.py delete mode 100644 tests/test_parameter.py delete mode 100644 tests/test_seq_domain_red.py delete mode 100644 tests/test_target_space.py delete mode 100644 tests/test_util.py diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md deleted file mode 100644 index 8132ec16f..000000000 --- a/.github/ISSUE_TEMPLATE/bug_report.md +++ /dev/null @@ -1,48 +0,0 @@ ---- -name: Bug report -about: Create a report to help us improve -title: '' -labels: bug, enhancement -assignees: '' - ---- - -**Describe the bug** -A clear and concise description of what the bug is. -Ex: Using `scipy==1.8` with `bayesian-optimization==1.2.0` results in `TypeError: 'float' object is not subscriptable`. - - - -**To Reproduce** -A concise, self-contained code snippet that reproduces the bug you would like to report. - -Ex: -```python -from bayes_opt import BayesianOptimization - -black_box_function = lambda x, y: -x ** 2 - (y - 1) ** 2 + 1 - -pbounds = {'x': (2, 4), 'y': (-3, 3)} - -optimizer = BayesianOptimization( - f=black_box_function, - pbounds=pbounds -) -optimizer.maximize() -``` - -**Expected behavior** -A clear and concise description of what you expected to happen. - -**Screenshots** -If applicable, add screenshots to help explain your problem. - -**Environment (please complete the following information):** - - OS: [e.g. Arch Linux, macOS, Windows] - - `python` Version [e.g. 3.8.9] - - `numpy` Version [e.g. 1.21.6] - - `scipy` Version [e.g. 1.8.0] - - `bayesian-optimization` Version [e.g. 1.2.0] - -**Additional context** -Add any other context about the problem here. diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md deleted file mode 100644 index d2c798b84..000000000 --- a/.github/ISSUE_TEMPLATE/feature_request.md +++ /dev/null @@ -1,23 +0,0 @@ ---- -name: Feature request -about: Suggest an idea for this project -title: '' -labels: enhancement -assignees: '' - ---- - -**Is your feature request related to a problem? Please describe.** -A clear and concise description of what the problem is. - -**Describe the solution you'd like** -A clear and concise description of what you want to happen. - -**References or alternative approaches** -If this feature was described in literature, please add references here. Additionally, feel free to add descriptions of any alternative solutions or features you've considered. - -**Additional context** -Add any other context or screenshots about the feature request here. - -**Are you able and willing to implement this feature yourself and open a pull request?** -- [ ] Yes, I can provide this feature. diff --git a/.github/generate_paper.yml b/.github/generate_paper.yml new file mode 100644 index 000000000..4dacc968a --- /dev/null +++ b/.github/generate_paper.yml @@ -0,0 +1,25 @@ +on: + push: + branches: [ joss_paper ] + +jobs: + paper: + runs-on: ubuntu-latest + name: Paper Draft + steps: + - name: Checkout + uses: actions/checkout@v2 + - name: Build draft PDF + uses: openjournals/openjournals-draft-action@master + with: + journal: joss + # This should be the path to the paper within your repo. + paper-path: paper.md + - name: Upload + uses: actions/upload-artifact@v1 + with: + name: paper + # This is the output path where Pandoc will write the compiled + # PDF. Note, this should be the same directory as the input + # paper.md + path: paper.pdf \ No newline at end of file diff --git a/.github/workflows/build_docs.yml b/.github/workflows/build_docs.yml deleted file mode 100644 index 43e7d988e..000000000 --- a/.github/workflows/build_docs.yml +++ /dev/null @@ -1,124 +0,0 @@ -name: docs - -on: - release: - types: [published] - push: - branches: - - master - pull_request: - -concurrency: - group: ${{ github.workflow }} - -jobs: - build-docs-and-publish: - runs-on: ubuntu-20.04 - permissions: - contents: write - steps: - - uses: actions/checkout@v3 - - name: Setup Python - uses: actions/setup-python@v3 - with: - python-version: '3.10' - - name: Get tag - uses: olegtarasov/get-tag@v2.1 - - name: Install pandoc - run: sudo apt-get install -y pandoc - - name: Install Poetry - uses: snok/install-poetry@v1 - - name: Install package and test dependencies - run: | - poetry install --with dev,nbtools - - name: build sphinx docs - run: | - cd docsrc - poetry run make github - - name: Determine directory to publish docs to - id: docs-publish-dir - uses: jannekem/run-python-script-action@v1 - with: - script: | - import os, re - github_ref = os.environ.get('GITHUB_REF') - m = re.match(r'^refs/tags/v([0-9]+\.[0-9]+\.[0-9]+(-dev\.[0-9]+)?)$', - github_ref) - if m: - target = m.group(1) - elif github_ref == 'refs/heads/master': - target = 'master' - else: - target = '' - set_output('target', target) - - name: Deploy - uses: peaceiris/actions-gh-pages@v3 - if: steps.docs-publish-dir.outputs.target != '' - with: - github_token: ${{ secrets.GITHUB_TOKEN }} - publish_dir: ./docs/html - destination_dir: ${{ steps.docs-publish-dir.outputs.target }} - keep_files: false - outputs: - docs-target: ${{ steps.docs-publish-dir.outputs.target }} - update-versions: - name: Update docs versions JSON - needs: build-docs-and-publish - if: needs.build-docs-and-publish.outputs.docs-target != '' - runs-on: Ubuntu-latest - permissions: - contents: write - steps: - - uses: actions/checkout@v3 - with: - ref: gh-pages - - name: Write versions to JSON file - uses: jannekem/run-python-script-action@v1 - with: - script: | - import json - import re - - # dependency of sphinx, so should be installed - from packaging import version as version_ - from pathlib import Path - - cwd = Path.cwd() - - versions = sorted((item.name for item in cwd.iterdir() - if item.is_dir() and not item.name.startswith('.')), - reverse=True) - - # Filter out master and dev versions - parseable_versions = [] - for version in versions: - try: - version_.parse(version) - except version_.InvalidVersion: - continue - parseable_versions.append(version) - - if parseable_versions: - max_version = max(parseable_versions, key=version_.parse) - else: - max_version = None - target_dir = Path('gh-pages') - target_dir.mkdir(parents=True) - - versions = [ - dict( - version=version, - title=version + ' (stable)' if version == max_version else version, - aliases=['stable'] if version == max_version else [], - ) for version in versions - ] - target_file = target_dir / 'versions.json' - with target_file.open('w') as f: - json.dump(versions, f) - - - name: Publish versions JSON to GitHub pages - uses: peaceiris/actions-gh-pages@v3 - with: - github_token: ${{ secrets.GITHUB_TOKEN }} - publish_dir: gh-pages - keep_files: true diff --git a/.github/workflows/format_and_lint.yml b/.github/workflows/format_and_lint.yml deleted file mode 100644 index 7a870481a..000000000 --- a/.github/workflows/format_and_lint.yml +++ /dev/null @@ -1,26 +0,0 @@ -name: Code format and lint - -on: - push: - branches: [ "master" ] - pull_request: - -permissions: - contents: read - -jobs: - check: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v3 - - name: Set up Python 3.9 - uses: actions/setup-python@v3 - with: - python-version: "3.9" - - name: Install Poetry - uses: snok/install-poetry@v1 - - name: Install dependencies - run: | - poetry install --with dev - - name: Run pre-commit - run : poetry run pre-commit run --all-files --show-diff-on-failure --color=always diff --git a/.github/workflows/python-publish.yml b/.github/workflows/python-publish.yml deleted file mode 100644 index 5395e7540..000000000 --- a/.github/workflows/python-publish.yml +++ /dev/null @@ -1,23 +0,0 @@ -# This workflow will upload a Python Package using poetry when a release is created -# Note that you must manually update the version number in pyproject.toml before attempting this. - -name: Upload Python Package - -on: - release: - types: [published] - -permissions: - contents: read - -jobs: - deploy: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v3 - - name: Build and publish to pypi - uses: JRubics/poetry-publish@v2.0 - with: - pypi_token: ${{ secrets.PYPI_API_TOKEN }} - # python_version: "3.10" - # poetry_version: "==1.8" # can lock versions if we want diff --git a/.github/workflows/run_tests.yml b/.github/workflows/run_tests.yml deleted file mode 100644 index 8501d8cd6..000000000 --- a/.github/workflows/run_tests.yml +++ /dev/null @@ -1,39 +0,0 @@ -# This workflow will install Python dependencies, run tests and lint with a single version of Python -# For more information see: https://help.github.com/actions/language-and-framework-guides/using-python-with-github-actions - -name: tests - -on: - push: - branches: [ "master" ] - pull_request: - -permissions: - contents: read - -jobs: - build: - name: Python ${{ matrix.python-version }} - numpy ${{ matrix.numpy-version }} - runs-on: ubuntu-latest - strategy: - matrix: - python-version: ["3.9", "3.10", "3.11", "3.12", "3.13"] - numpy-version: [">=1.25,<2", ">=2"] - - steps: - - uses: actions/checkout@v3 - - name: Set up Python - uses: actions/setup-python@v3 - with: - python-version: ${{ matrix.python-version }} - - name: Install Poetry - uses: snok/install-poetry@v1 - - name: Install test dependencies - run: | - poetry add "numpy${{ matrix.numpy-version }}" - poetry install --with dev,nbtools - - name: Test with pytest - run: | - poetry run pytest --cov-report xml --cov=bayes_opt/ - - name: Upload coverage to Codecov - uses: codecov/codecov-action@v3 diff --git a/.gitignore b/.gitignore deleted file mode 100644 index 786d95c87..000000000 --- a/.gitignore +++ /dev/null @@ -1,39 +0,0 @@ -.ipynb_checkpoints -*.pyc -*.egg-info/ -build/ -dist/ -scratch/ -.idea/ -.DS_Store -bo_eg*.png -gif/ - -# Unit test / coverage reports -htmlcov/ -.tox/ -.coverage -.coverage.* -.cache -nosetests.xml -coverage.xml -*,cover -.hypothesis/ - -# Environments -.env -.venv -env/ -venv/ -ENV/ -env.bak/ -venv.bak/ -*temp* - -docs/* -docsrc/.ipynb_checkpoints/* -docsrc/*.ipynb -docsrc/static/* -docsrc/README.md - -poetry.lock \ No newline at end of file diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml deleted file mode 100644 index 999080796..000000000 --- a/.pre-commit-config.yaml +++ /dev/null @@ -1,9 +0,0 @@ -repos: - - hooks: - - id: ruff - name: ruff-lint - - id: ruff-format - name: ruff-format - args: [--check] - repo: https://github.com/astral-sh/ruff-pre-commit - rev: v0.6.6 \ No newline at end of file diff --git a/LICENSE b/LICENSE deleted file mode 100644 index 94cdec40f..000000000 --- a/LICENSE +++ /dev/null @@ -1,9 +0,0 @@ -The MIT License (MIT) - -Copyright (c) 2014 Fernando M. F. Nogueira - -Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. \ No newline at end of file diff --git a/README.md b/README.md index c485d11ca..5be6fbd0a 100644 --- a/README.md +++ b/README.md @@ -1,200 +1,5 @@ -
-

-
+# Joss Paper -# Bayesian Optimization +:warning: do not merge! -![tests](https://github.com/bayesian-optimization/BayesianOptimization/actions/workflows/run_tests.yml/badge.svg) -[![docs - stable](https://img.shields.io/badge/docs-stable-blue)](https://bayesian-optimization.github.io/BayesianOptimization/index.html) -[![Codecov](https://codecov.io/github/bayesian-optimization/BayesianOptimization/badge.svg?branch=master&service=github)](https://codecov.io/github/bayesian-optimization/BayesianOptimization?branch=master) -[![Pypi](https://img.shields.io/pypi/v/bayesian-optimization.svg)](https://pypi.python.org/pypi/bayesian-optimization) -![PyPI - Python Version](https://img.shields.io/pypi/pyversions/bayesian-optimization) - - -Pure Python implementation of bayesian global optimization with gaussian -processes. - - -This is a constrained global optimization package built upon bayesian inference -and gaussian processes, that attempts to find the maximum value of an unknown -function in as few iterations as possible. This technique is particularly -suited for optimization of high cost functions and situations where the balance -between exploration and exploitation is important. - -## Installation - -* pip (via PyPI): - -```console -$ pip install bayesian-optimization -``` - -* Conda (via conda-forge): - -```console -$ conda install -c conda-forge bayesian-optimization -``` - -## How does it work? - -See the [documentation](https://bayesian-optimization.github.io/BayesianOptimization/) for how to use this package. - -Bayesian optimization works by constructing a posterior distribution of functions (gaussian process) that best describes the function you want to optimize. As the number of observations grows, the posterior distribution improves, and the algorithm becomes more certain of which regions in parameter space are worth exploring and which are not, as seen in the picture below. - -![BayesianOptimization in action](docsrc/static/bo_example.png) - -As you iterate over and over, the algorithm balances its needs of exploration and exploitation taking into account what it knows about the target function. At each step a Gaussian Process is fitted to the known samples (points previously explored), and the posterior distribution, combined with a exploration strategy (such as UCB (Upper Confidence Bound), or EI (Expected Improvement)), are used to determine the next point that should be explored (see the gif below). - -![BayesianOptimization in action](docsrc/static/bayesian_optimization.gif) - -This process is designed to minimize the number of steps required to find a combination of parameters that are close to the optimal combination. To do so, this method uses a proxy optimization problem (finding the maximum of the acquisition function) that, albeit still a hard problem, is cheaper (in the computational sense) and common tools can be employed. Therefore Bayesian Optimization is most adequate for situations where sampling the function to be optimized is a very expensive endeavor. See the references for a proper discussion of this method. - -This project is under active development. If you run into trouble, find a bug or notice -anything that needs correction, please let us know by filing an issue. - - -## Basic tour of the Bayesian Optimization package - -### 1. Specifying the function to be optimized - -This is a function optimization package, therefore the first and most important ingredient is, of course, the function to be optimized. - -**DISCLAIMER:** We know exactly how the output of the function below depends on its parameter. Obviously this is just an example, and you shouldn't expect to know it in a real scenario. However, it should be clear that you don't need to. All you need in order to use this package (and more generally, this technique) is a function `f` that takes a known set of parameters and outputs a real number. - - -```python -def black_box_function(x, y): - """Function with unknown internals we wish to maximize. - - This is just serving as an example, for all intents and - purposes think of the internals of this function, i.e.: the process - which generates its output values, as unknown. - """ - return -x ** 2 - (y - 1) ** 2 + 1 -``` - -### 2. Getting Started - -All we need to get started is to instantiate a `BayesianOptimization` object specifying a function to be optimized `f`, and its parameters with their corresponding bounds, `pbounds`. This is a constrained optimization technique, so you must specify the minimum and maximum values that can be probed for each parameter in order for it to work - - -```python -from bayes_opt import BayesianOptimization - -# Bounded region of parameter space -pbounds = {'x': (2, 4), 'y': (-3, 3)} - -optimizer = BayesianOptimization( - f=black_box_function, - pbounds=pbounds, - random_state=1, -) -``` - -The BayesianOptimization object will work out of the box without much tuning needed. The main method you should be aware of is `maximize`, which does exactly what you think it does. - -There are many parameters you can pass to maximize, nonetheless, the most important ones are: -- `n_iter`: How many steps of bayesian optimization you want to perform. The more steps the more likely to find a good maximum you are. -- `init_points`: How many steps of **random** exploration you want to perform. Random exploration can help by diversifying the exploration space. - - -```python -optimizer.maximize( - init_points=2, - n_iter=3, -) -``` - - | iter | target | x | y | - ------------------------------------------------- - | 1 | -7.135 | 2.834 | 1.322 | - | 2 | -7.78 | 2.0 | -1.186 | - | 3 | -19.0 | 4.0 | 3.0 | - | 4 | -16.3 | 2.378 | -2.413 | - | 5 | -4.441 | 2.105 | -0.005822 | - ================================================= - - -The best combination of parameters and target value found can be accessed via the property `optimizer.max`. - - -```python -print(optimizer.max) ->>> {'target': -4.441293113411222, 'params': {'y': -0.005822117636089974, 'x': 2.104665051994087}} -``` - - -While the list of all parameters probed and their corresponding target values is available via the property `optimizer.res`. - - -```python -for i, res in enumerate(optimizer.res): - print("Iteration {}: \n\t{}".format(i, res)) - ->>> Iteration 0: ->>> {'target': -7.135455292718879, 'params': {'y': 1.3219469606529488, 'x': 2.8340440094051482}} ->>> Iteration 1: ->>> {'target': -7.779531005607566, 'params': {'y': -1.1860045642089614, 'x': 2.0002287496346898}} ->>> Iteration 2: ->>> {'target': -19.0, 'params': {'y': 3.0, 'x': 4.0}} ->>> Iteration 3: ->>> {'target': -16.29839645063864, 'params': {'y': -2.412527795983739, 'x': 2.3776144540856503}} ->>> Iteration 4: ->>> {'target': -4.441293113411222, 'params': {'y': -0.005822117636089974, 'x': 2.104665051994087}} -``` - - -## Minutiae - -### Citation - -If you used this package in your research, please cite it: - -``` -@Misc{, - author = {Fernando Nogueira}, - title = {{Bayesian Optimization}: Open source constrained global optimization tool for {Python}}, - year = {2014--}, - url = " https://github.com/bayesian-optimization/BayesianOptimization" -} -``` -If you used any of the advanced functionalities, please additionally cite the corresponding publication: - -For the `SequentialDomainTransformer`: -``` -@article{ - author = {Stander, Nielen and Craig, Kenneth}, - year = {2002}, - month = {06}, - pages = {}, - title = {On the robustness of a simple domain reduction scheme for simulation-based optimization}, - volume = {19}, - journal = {International Journal for Computer-Aided Engineering and Software (Eng. Comput.)}, - doi = {10.1108/02644400210430190} -} -``` - -For constrained optimization: -``` -@inproceedings{gardner2014bayesian, - title={Bayesian optimization with inequality constraints.}, - author={Gardner, Jacob R and Kusner, Matt J and Xu, Zhixiang Eddie and Weinberger, Kilian Q and Cunningham, John P}, - booktitle={ICML}, - volume={2014}, - pages={937--945}, - year={2014} -} -``` - -For optimization over non-float parameters: -``` -@article{garrido2020dealing, - title={Dealing with categorical and integer-valued variables in bayesian optimization with gaussian processes}, - author={Garrido-Merch{\'a}n, Eduardo C and Hern{\'a}ndez-Lobato, Daniel}, - journal={Neurocomputing}, - volume={380}, - pages={20--35}, - year={2020}, - publisher={Elsevier} -} -``` +This branch only exists for the purpose of drafting a JOSS paper. \ No newline at end of file diff --git a/bayes_opt/__init__.py b/bayes_opt/__init__.py deleted file mode 100644 index 7ed07ed46..000000000 --- a/bayes_opt/__init__.py +++ /dev/null @@ -1,26 +0,0 @@ -"""Pure Python implementation of bayesian global optimization with gaussian processes.""" - -from __future__ import annotations - -import importlib.metadata - -from bayes_opt import acquisition -from bayes_opt.bayesian_optimization import BayesianOptimization, Events -from bayes_opt.constraint import ConstraintModel -from bayes_opt.domain_reduction import SequentialDomainReductionTransformer -from bayes_opt.logger import JSONLogger, ScreenLogger -from bayes_opt.target_space import TargetSpace - -__version__ = importlib.metadata.version("bayesian-optimization") - - -__all__ = [ - "acquisition", - "BayesianOptimization", - "TargetSpace", - "ConstraintModel", - "Events", - "ScreenLogger", - "JSONLogger", - "SequentialDomainReductionTransformer", -] diff --git a/bayes_opt/acquisition.py b/bayes_opt/acquisition.py deleted file mode 100644 index 167bd5dc0..000000000 --- a/bayes_opt/acquisition.py +++ /dev/null @@ -1,1037 +0,0 @@ -"""Acquisition functions for Bayesian Optimization. - -The acquisition functions in this module can be grouped the following way: - -- One of the base acquisition functions - (:py:class:`UpperConfidenceBound`, - :py:class:`ProbabilityOfImprovement` and - :py:class:`ExpectedImprovement`) is always dictating the basic - behavior of the suggestion step. They can be used alone or combined with a meta acquisition function. -- :py:class:`GPHedge` is a meta acquisition function that combines multiple - base acquisition functions and determines the most suitable one for a particular problem. -- :py:class:`ConstantLiar` is a meta acquisition function that can be - used for parallelized optimization and discourages sampling near a previously suggested, but not yet - evaluated, point. -- :py:class:`AcquisitionFunction` is the base class for all - acquisition functions. You can implement your own acquisition function by subclassing it. See the - `Acquisition Functions notebook <../acquisition.html>`__ to understand the many ways this class can be - modified. -""" - -from __future__ import annotations - -import abc -import warnings -from copy import deepcopy -from typing import TYPE_CHECKING, Any, Literal, NoReturn - -import numpy as np -from numpy.random import RandomState -from scipy.optimize import minimize -from scipy.special import softmax -from scipy.stats import norm -from sklearn.gaussian_process import GaussianProcessRegressor - -from bayes_opt.exception import ( - ConstraintNotSupportedError, - NoValidPointRegisteredError, - TargetSpaceEmptyError, -) -from bayes_opt.target_space import TargetSpace - -if TYPE_CHECKING: - from collections.abc import Callable, Sequence - - from numpy.typing import NDArray - from scipy.optimize import OptimizeResult - - from bayes_opt.constraint import ConstraintModel - - Float = np.floating[Any] - - -class AcquisitionFunction(abc.ABC): - """Base class for acquisition functions. - - Parameters - ---------- - random_state : int, RandomState, default None - Set the random state for reproducibility. - """ - - def __init__(self, random_state: int | RandomState | None = None) -> None: - if random_state is not None: - if isinstance(random_state, RandomState): - self.random_state = random_state - else: - self.random_state = RandomState(random_state) - else: - self.random_state = RandomState() - self.i = 0 - - @abc.abstractmethod - def base_acq(self, *args: Any, **kwargs: Any) -> NDArray[Float]: - """Provide access to the base acquisition function.""" - - def _fit_gp(self, gp: GaussianProcessRegressor, target_space: TargetSpace) -> None: - # Sklearn's GP throws a large number of warnings at times, but - # we don't really need to see them here. - with warnings.catch_warnings(): - warnings.simplefilter("ignore") - gp.fit(target_space.params, target_space.target) - if target_space.constraint is not None: - target_space.constraint.fit(target_space.params, target_space._constraint_values) - - def suggest( - self, - gp: GaussianProcessRegressor, - target_space: TargetSpace, - n_random: int = 10_000, - n_l_bfgs_b: int = 10, - fit_gp: bool = True, - ) -> NDArray[Float]: - """Suggest a promising point to probe next. - - Parameters - ---------- - gp : GaussianProcessRegressor - A fitted Gaussian Process. - - target_space : TargetSpace - The target space to probe. - - n_random : int, default 10_000 - Number of random samples to use. - - n_l_bfgs_b : int, default 10 - Number of starting points for the L-BFGS-B optimizer. - - fit_gp : bool, default True - Whether to fit the Gaussian Process to the target space. - Set to False if the GP is already fitted. - - Returns - ------- - np.ndarray - Suggested point to probe next. - """ - if len(target_space) == 0: - msg = ( - "Cannot suggest a point without previous samples. Use " - " target_space.random_sample() to generate a point and " - " target_space.probe(*) to evaluate it." - ) - raise TargetSpaceEmptyError(msg) - self.i += 1 - if fit_gp: - self._fit_gp(gp=gp, target_space=target_space) - - acq = self._get_acq(gp=gp, constraint=target_space.constraint) - return self._acq_min(acq, target_space, n_random=n_random, n_l_bfgs_b=n_l_bfgs_b) - - def _get_acq( - self, gp: GaussianProcessRegressor, constraint: ConstraintModel | None = None - ) -> Callable[[NDArray[Float]], NDArray[Float]]: - """Prepare the acquisition function for minimization. - - Transforms a base_acq Callable, which takes `mean` and `std` as - input, into an acquisition function that only requires an array of - parameters. - Handles GP predictions and constraints. - - Parameters - ---------- - gp : GaussianProcessRegressor - A fitted Gaussian Process. - - constraint : ConstraintModel, default None - A fitted constraint model, if constraints are present and the - acquisition function supports them. - - Returns - ------- - Callable - Function to minimize. - """ - dim = gp.X_train_.shape[1] - if constraint is not None: - - def acq(x: NDArray[Float]) -> NDArray[Float]: - x = x.reshape(-1, dim) - with warnings.catch_warnings(): - warnings.simplefilter("ignore") - mean: NDArray[Float] - std: NDArray[Float] - p_constraints: NDArray[Float] - mean, std = gp.predict(x, return_std=True) - p_constraints = constraint.predict(x) - return -1 * self.base_acq(mean, std) * p_constraints - else: - - def acq(x: NDArray[Float]) -> NDArray[Float]: - x = x.reshape(-1, dim) - with warnings.catch_warnings(): - warnings.simplefilter("ignore") - mean: NDArray[Float] - std: NDArray[Float] - mean, std = gp.predict(x, return_std=True) - return -1 * self.base_acq(mean, std) - - return acq - - def _acq_min( - self, - acq: Callable[[NDArray[Float]], NDArray[Float]], - space: TargetSpace, - n_random: int = 10_000, - n_l_bfgs_b: int = 10, - ) -> NDArray[Float]: - """Find the maximum of the acquisition function. - - Uses a combination of random sampling (cheap) and the 'L-BFGS-B' - optimization method. First by sampling `n_warmup` (1e5) points at random, - and then running L-BFGS-B from `n_iter` (10) random starting points. - - Parameters - ---------- - acq : Callable - Acquisition function to use. Should accept an array of parameters `x`. - - space : TargetSpace - The target space over which to optimize. - - n_random : int - Number of random samples to use. - - n_l_bfgs_b : int - Number of starting points for the L-BFGS-B optimizer. - - Returns - ------- - np.ndarray - Parameters maximizing the acquisition function. - - """ - if n_random == 0 and n_l_bfgs_b == 0: - error_msg = "Either n_random or n_l_bfgs_b needs to be greater than 0." - raise ValueError(error_msg) - x_min_r, min_acq_r, x_seeds = self._random_sample_minimize( - acq, space, n_random=max(n_random, n_l_bfgs_b), n_x_seeds=n_l_bfgs_b - ) - if n_l_bfgs_b: - x_min_l, min_acq_l = self._l_bfgs_b_minimize(acq, space, x_seeds=x_seeds) - # Either n_random or n_l_bfgs_b is not 0 => at least one of x_min_r and x_min_l is not None - if min_acq_r > min_acq_l: - return x_min_l - return x_min_r - - def _random_sample_minimize( - self, - acq: Callable[[NDArray[Float]], NDArray[Float]], - space: TargetSpace, - n_random: int, - n_x_seeds: int = 0, - ) -> tuple[NDArray[Float] | None, float]: - """Random search to find the minimum of `acq` function. - - Parameters - ---------- - acq : Callable - Acquisition function to use. Should accept an array of parameters `x`. - - space : TargetSpace - The target space over which to optimize. - - n_random : int - Number of random samples to use. - - n_x_seeds : int - Number of top points to return, for use as starting points for L-BFGS-B. - Returns - ------- - x_min : np.ndarray - Random sample minimizing the acquisition function. - - min_acq : float - Acquisition function value at `x_min` - """ - if n_random == 0: - return None, np.inf - x_tries = space.random_sample(n_random, random_state=self.random_state) - ys = acq(x_tries) - x_min = x_tries[ys.argmin()] - min_acq = ys.min() - if n_x_seeds != 0: - idxs = np.argsort(ys)[-n_x_seeds:] - x_seeds = x_tries[idxs] - else: - x_seeds = [] - return x_min, min_acq, x_seeds - - def _l_bfgs_b_minimize( - self, - acq: Callable[[NDArray[Float]], NDArray[Float]], - space: TargetSpace, - x_seeds: NDArray[Float] | None = None, - ) -> tuple[NDArray[Float] | None, float]: - """Random search to find the minimum of `acq` function. - - Parameters - ---------- - acq : Callable - Acquisition function to use. Should accept an array of parameters `x`. - - space : TargetSpace - The target space over which to optimize. - - x_seeds : int - Starting points for the L-BFGS-B optimizer. - - Returns - ------- - x_min : np.ndarray - Minimal result of the L-BFGS-B optimizer. - - min_acq : float - Acquisition function value at `x_min` - """ - continuous_dimensions = space.continuous_dimensions - continuous_bounds = space.bounds[continuous_dimensions] - - if not continuous_dimensions.any(): - min_acq = np.inf - x_min = np.array([np.nan] * space.bounds.shape[0]) - return x_min, min_acq - - min_acq: float | None = None - x_try: NDArray[Float] - x_min: NDArray[Float] - for x_try in x_seeds: - - def continuous_acq(x: NDArray[Float], x_try=x_try) -> NDArray[Float]: - x_try[continuous_dimensions] = x - return acq(x_try) - - # Find the minimum of minus the acquisition function - res: OptimizeResult = minimize( - continuous_acq, x_try[continuous_dimensions], bounds=continuous_bounds, method="L-BFGS-B" - ) - # See if success - if not res.success: - continue - - # Store it if better than previous minimum(maximum). - if min_acq is None or np.squeeze(res.fun) >= min_acq: - x_try[continuous_dimensions] = res.x - x_min = x_try - min_acq = np.squeeze(res.fun) - - if min_acq is None: - min_acq = np.inf - x_min = np.array([np.nan] * space.bounds.shape[0]) - - # Clip output to make sure it lies within the bounds. Due to floating - # point technicalities this is not always the case. - return np.clip(x_min, space.bounds[:, 0], space.bounds[:, 1]), min_acq - - -class UpperConfidenceBound(AcquisitionFunction): - r"""Upper Confidence Bound acquisition function. - - The upper confidence bound is calculated as - - .. math:: - \text{UCB}(x) = \mu(x) + \kappa \sigma(x). - - Parameters - ---------- - kappa : float, default 2.576 - Governs the exploration/exploitation tradeoff. Lower prefers - exploitation, higher prefers exploration. - - exploration_decay : float, default None - Decay rate for kappa. If None, no decay is applied. - - exploration_decay_delay : int, default None - Delay for decay. If None, decay is applied from the start. - - random_state : int, RandomState, default None - Set the random state for reproducibility. - - """ - - def __init__( - self, - kappa: float = 2.576, - exploration_decay: float | None = None, - exploration_decay_delay: int | None = None, - random_state: int | RandomState | None = None, - ) -> None: - if kappa < 0: - error_msg = "kappa must be greater than or equal to 0." - raise ValueError(error_msg) - - super().__init__(random_state=random_state) - self.kappa = kappa - self.exploration_decay = exploration_decay - self.exploration_decay_delay = exploration_decay_delay - - def base_acq(self, mean: NDArray[Float], std: NDArray[Float]) -> NDArray[Float]: - """Calculate the upper confidence bound. - - Parameters - ---------- - mean : np.ndarray - Mean of the predictive distribution. - - std : np.ndarray - Standard deviation of the predictive distribution. - - Returns - ------- - np.ndarray - Acquisition function value. - """ - return mean + self.kappa * std - - def suggest( - self, - gp: GaussianProcessRegressor, - target_space: TargetSpace, - n_random: int = 10_000, - n_l_bfgs_b: int = 10, - fit_gp: bool = True, - ) -> NDArray[Float]: - """Suggest a promising point to probe next. - - Parameters - ---------- - gp : GaussianProcessRegressor - A fitted Gaussian Process. - - target_space : TargetSpace - The target space to probe. - - n_random : int, default 10_000 - Number of random samples to use. - - n_l_bfgs_b : int, default 10 - Number of starting points for the L-BFGS-B optimizer. - - fit_gp : bool, default True - Whether to fit the Gaussian Process to the target space. - Set to False if the GP is already fitted. - - Returns - ------- - np.ndarray - Suggested point to probe next. - """ - if target_space.constraint is not None: - msg = ( - f"Received constraints, but acquisition function {type(self)} " - "does not support constrained optimization." - ) - raise ConstraintNotSupportedError(msg) - x_max = super().suggest( - gp=gp, target_space=target_space, n_random=n_random, n_l_bfgs_b=n_l_bfgs_b, fit_gp=fit_gp - ) - self.decay_exploration() - return x_max - - def decay_exploration(self) -> None: - """Decay kappa by a constant rate. - - Adjust exploration/exploitation trade-off by reducing kappa. - - Note - ---- - - This method is called automatically at the end of each ``suggest()`` call. - """ - if self.exploration_decay is not None and ( - self.exploration_decay_delay is None or self.exploration_decay_delay <= self.i - ): - self.kappa = self.kappa * self.exploration_decay - - -class ProbabilityOfImprovement(AcquisitionFunction): - r"""Probability of Improvement acqusition function. - - Calculated as - - .. math:: \text{POI}(x) = \Phi\left( \frac{\mu(x)-y_{\text{max}} - \xi }{\sigma(x)} \right) - - where :math:`\Phi` is the CDF of the normal distribution. - - Parameters - ---------- - xi : float, positive - Governs the exploration/exploitation tradeoff. Lower prefers - exploitation, higher prefers exploration. - - exploration_decay : float, default None - Decay rate for xi. If None, no decay is applied. - - exploration_decay_delay : int, default None - Delay for decay. If None, decay is applied from the start. - - random_state : int, RandomState, default None - Set the random state for reproducibility. - """ - - def __init__( - self, - xi: float, - exploration_decay: float | None = None, - exploration_decay_delay: int | None = None, - random_state: int | RandomState | None = None, - ) -> None: - super().__init__(random_state=random_state) - self.xi = xi - self.exploration_decay = exploration_decay - self.exploration_decay_delay = exploration_decay_delay - self.y_max = None - - def base_acq(self, mean: NDArray[Float], std: NDArray[Float]) -> NDArray[Float]: - """Calculate the probability of improvement. - - Parameters - ---------- - mean : np.ndarray - Mean of the predictive distribution. - - std : np.ndarray - Standard deviation of the predictive distribution. - - Returns - ------- - np.ndarray - Acquisition function value. - - Raises - ------ - ValueError - If y_max is not set. - """ - if self.y_max is None: - msg = ( - "y_max is not set. If you are calling this method outside " - "of suggest(), you must set y_max manually." - ) - raise ValueError(msg) - z = (mean - self.y_max - self.xi) / std - return norm.cdf(z) - - def suggest( - self, - gp: GaussianProcessRegressor, - target_space: TargetSpace, - n_random: int = 10_000, - n_l_bfgs_b: int = 10, - fit_gp: bool = True, - ) -> NDArray[Float]: - """Suggest a promising point to probe next. - - Parameters - ---------- - gp : GaussianProcessRegressor - A fitted Gaussian Process. - - target_space : TargetSpace - The target space to probe. - - n_random : int, default 10_000 - Number of random samples to use. - - n_l_bfgs_b : int, default 10 - Number of starting points for the L-BFGS-B optimizer. - - fit_gp : bool, default True - Whether to fit the Gaussian Process to the target space. - Set to False if the GP is already fitted. - - Returns - ------- - np.ndarray - Suggested point to probe next. - """ - y_max = target_space._target_max() - if y_max is None and not target_space.empty: - # If target space is empty, let base class handle the error - msg = ( - "Cannot suggest a point without an allowed point. Use " - "target_space.random_sample() to generate a point until " - " at least one point that satisfies the constraints is found." - ) - raise NoValidPointRegisteredError(msg) - self.y_max = y_max - x_max = super().suggest( - gp=gp, target_space=target_space, n_random=n_random, n_l_bfgs_b=n_l_bfgs_b, fit_gp=fit_gp - ) - self.decay_exploration() - return x_max - - def decay_exploration(self) -> None: - r"""Decay xi by a constant rate. - - Adjust exploration/exploitation trade-off by reducing xi. - - Note - ---- - - This method is called automatically at the end of each ``suggest()`` call. - """ - if self.exploration_decay is not None and ( - self.exploration_decay_delay is None or self.exploration_decay_delay <= self.i - ): - self.xi = self.xi * self.exploration_decay - - -class ExpectedImprovement(AcquisitionFunction): - r"""Expected Improvement acqusition function. - - Similar to Probability of Improvement (`ProbabilityOfImprovement`), but also considers the - magnitude of improvement. - Calculated as - - .. math:: - \text{EI}(x) = (\mu(x)-y_{\text{max}} - \xi) \Phi\left( - \frac{\mu(x)-y_{\text{max}} - \xi }{\sigma(x)} \right) - + \sigma(x) \phi\left( - \frac{\mu(x)-y_{\text{max}} - \xi }{\sigma(x)} \right) - - where :math:`\Phi` is the CDF and :math:`\phi` the PDF of the normal - distribution. - - Parameters - ---------- - xi : float, positive - Governs the exploration/exploitation tradeoff. Lower prefers - exploitation, higher prefers exploration. - - exploration_decay : float, default None - Decay rate for xi. If None, no decay is applied. - - exploration_decay_delay : int, default None - - random_state : int, RandomState, default None - Set the random state for reproducibility. - """ - - def __init__( - self, - xi: float, - exploration_decay: float | None = None, - exploration_decay_delay: int | None = None, - random_state: int | RandomState | None = None, - ) -> None: - super().__init__(random_state=random_state) - self.xi = xi - self.exploration_decay = exploration_decay - self.exploration_decay_delay = exploration_decay_delay - self.y_max = None - - def base_acq(self, mean: NDArray[Float], std: NDArray[Float]) -> NDArray[Float]: - """Calculate the expected improvement. - - Parameters - ---------- - mean : np.ndarray - Mean of the predictive distribution. - - std : np.ndarray - Standard deviation of the predictive distribution. - - Returns - ------- - np.ndarray - Acquisition function value. - - Raises - ------ - ValueError - If y_max is not set. - """ - if self.y_max is None: - msg = ( - "y_max is not set. If you are calling this method outside " - "of suggest(), ensure y_max is set, or set it manually." - ) - raise ValueError(msg) - a = mean - self.y_max - self.xi - z = a / std - return a * norm.cdf(z) + std * norm.pdf(z) - - def suggest( - self, - gp: GaussianProcessRegressor, - target_space: TargetSpace, - n_random: int = 10_000, - n_l_bfgs_b: int = 10, - fit_gp: bool = True, - ) -> NDArray[Float]: - """Suggest a promising point to probe next. - - Parameters - ---------- - gp : GaussianProcessRegressor - A fitted Gaussian Process. - - target_space : TargetSpace - The target space to probe. - - n_random : int, default 10_000 - Number of random samples to use. - - n_l_bfgs_b : int, default 10 - Number of starting points for the L-BFGS-B optimizer. - - fit_gp : bool, default True - Whether to fit the Gaussian Process to the target space. - Set to False if the GP is already fitted. - - Returns - ------- - np.ndarray - Suggested point to probe next. - """ - y_max = target_space._target_max() - if y_max is None and not target_space.empty: - # If target space is empty, let base class handle the error - msg = ( - "Cannot suggest a point without an allowed point. Use " - "target_space.random_sample() to generate a point until " - " at least one point that satisfies the constraints is found." - ) - raise NoValidPointRegisteredError(msg) - self.y_max = y_max - - x_max = super().suggest( - gp=gp, target_space=target_space, n_random=n_random, n_l_bfgs_b=n_l_bfgs_b, fit_gp=fit_gp - ) - self.decay_exploration() - return x_max - - def decay_exploration(self) -> None: - r"""Decay xi by a constant rate. - - Adjust exploration/exploitation trade-off by reducing xi. - - Note - ---- - - This method is called automatically at the end of each ``suggest()`` call. - """ - if self.exploration_decay is not None and ( - self.exploration_decay_delay is None or self.exploration_decay_delay <= self.i - ): - self.xi = self.xi * self.exploration_decay - - -class ConstantLiar(AcquisitionFunction): - """Constant Liar acquisition function. - - Used for asynchronous optimization. It operates on a copy of the target space - that includes the previously suggested points that have not been evaluated yet. - A GP fitted to this target space is less likely to suggest the same point again, - since the variance of the predictive distribution is lower at these points. - This is discourages the optimization algorithm from suggesting the same point - to multiple workers. - - Parameters - ---------- - base_acquisition : AcquisitionFunction - The acquisition function to use. - - strategy : float or str, default 'max' - Strategy to use for the constant liar. If a float, the constant liar - will always register dummies with this value. If 'min'/'mean'/'max', - the constant liar will register dummies with the minimum/mean/maximum - target value in the target space. - - random_state : int, RandomState, default None - Set the random state for reproducibility. - - atol : float, default 1e-5 - Absolute tolerance to eliminate a dummy point. - - rtol : float, default 1e-8 - Relative tolerance to eliminate a dummy point. - """ - - def __init__( - self, - base_acquisition: AcquisitionFunction, - strategy: Literal["min", "mean", "max"] | float = "max", - random_state: int | RandomState | None = None, - atol: float = 1e-5, - rtol: float = 1e-8, - ) -> None: - super().__init__(random_state) - self.base_acquisition = base_acquisition - self.dummies = [] - if not isinstance(strategy, float) and strategy not in ["min", "mean", "max"]: - error_msg = f"Received invalid argument {strategy} for strategy." - raise ValueError(error_msg) - self.strategy: Literal["min", "mean", "max"] | float = strategy - self.atol = atol - self.rtol = rtol - - def base_acq(self, *args: Any, **kwargs: Any) -> NDArray[Float]: - """Calculate the acquisition function. - - Calls the base acquisition function's `base_acq` method. - - Returns - ------- - np.ndarray - Acquisition function value. - """ - return self.base_acquisition.base_acq(*args, **kwargs) - - def _copy_target_space(self, target_space: TargetSpace) -> TargetSpace: - """Create a copy of the target space. - - Parameters - ---------- - target_space : TargetSpace - The target space to copy. - - Returns - ------- - TargetSpace - A copy of the target space. - """ - keys = target_space.keys - pbounds = {key: bound for key, bound in zip(keys, target_space.bounds)} - target_space_copy = TargetSpace( - None, - pbounds=pbounds, - constraint=target_space.constraint, - allow_duplicate_points=target_space._allow_duplicate_points, - ) - target_space_copy._params = deepcopy(target_space._params) - target_space_copy._target = deepcopy(target_space._target) - - return target_space_copy - - def _remove_expired_dummies(self, target_space: TargetSpace) -> None: - """Remove expired dummy points from the list of dummies. - - Once a worker has evaluated a dummy point, the dummy is discarded. To - accomplish this, we compare every dummy point to the current target - space's parameters and remove it if it is close to any of them. - - Parameters - ---------- - target_space : TargetSpace - The target space to compare the dummies to. - """ - dummies = [] - for dummy in self.dummies: - close = np.isclose(dummy, target_space.params, rtol=self.rtol, atol=self.atol) - if not close.all(axis=1).any(): - dummies.append(dummy) - self.dummies = dummies - - def suggest( - self, - gp: GaussianProcessRegressor, - target_space: TargetSpace, - n_random: int = 10_000, - n_l_bfgs_b: int = 10, - fit_gp: bool = True, - ) -> NDArray[Float]: - """Suggest a promising point to probe next. - - Parameters - ---------- - gp : GaussianProcessRegressor - A fitted Gaussian Process. - - target_space : TargetSpace - The target space to probe. - - n_random : int, default 10_000 - Number of random samples to use. - - n_l_bfgs_b : int, default 10 - Number of starting points for the L-BFGS-B optimizer. - - fit_gp : bool, default True - Whether to fit the Gaussian Process to the target space. - Set to False if the GP is already fitted. - - Returns - ------- - np.ndarray - Suggested point to probe next. - """ - if len(target_space) == 0: - msg = ( - "Cannot suggest a point without previous samples. Use " - " target_space.random_sample() to generate a point and " - " target_space.probe(*) to evaluate it." - ) - raise TargetSpaceEmptyError(msg) - - if target_space.constraint is not None: - msg = ( - f"Received constraints, but acquisition function {type(self)} " - "does not support constrained optimization." - ) - raise ConstraintNotSupportedError(msg) - - # Check if any dummies have been evaluated and remove them - self._remove_expired_dummies(target_space) - - # Create a copy of the target space - dummy_target_space = self._copy_target_space(target_space) - - dummy_target: float - # Choose the dummy target value - if isinstance(self.strategy, float): - dummy_target = self.strategy - elif self.strategy == "min": - dummy_target = target_space.target.min() - elif self.strategy == "mean": - dummy_target = target_space.target.mean() - elif self.strategy != "max": - error_msg = f"Received invalid argument {self.strategy} for strategy." - raise ValueError(error_msg) - else: - dummy_target = target_space.target.max() - - # Register the dummies to the dummy target space - for dummy in self.dummies: - dummy_target_space.register(dummy, dummy_target) - - # Fit the GP to the dummy target space and suggest a point - self._fit_gp(gp=gp, target_space=dummy_target_space) - x_max = self.base_acquisition.suggest( - gp, dummy_target_space, n_random=n_random, n_l_bfgs_b=n_l_bfgs_b, fit_gp=False - ) - - # Register the suggested point as a dummy - self.dummies.append(x_max) - - return x_max - - -class GPHedge(AcquisitionFunction): - """GPHedge acquisition function. - - At each suggestion step, GPHedge samples suggestions from each base - acquisition function acq_i. Then a candidate is selected from the - suggestions based on the on the cumulative rewards of each acq_i. - After evaluating the candidate, the gains are updated (in the next - iteration) based on the updated expectation value of the candidates. - - For more information, see: - Brochu et al., "Portfolio Allocation for Bayesian Optimization", - https://arxiv.org/abs/1009.5419 - - Parameters - ---------- - base_acquisitions : Sequence[AcquisitionFunction] - Sequence of base acquisition functions. - - random_state : int, RandomState, default None - Set the random state for reproducibility. - """ - - def __init__( - self, base_acquisitions: Sequence[AcquisitionFunction], random_state: int | RandomState | None = None - ) -> None: - super().__init__(random_state) - self.base_acquisitions = list(base_acquisitions) - self.n_acq = len(self.base_acquisitions) - self.gains = np.zeros(self.n_acq) - self.previous_candidates = None - - def base_acq(self, *args: Any, **kwargs: Any) -> NoReturn: - """Raise an error, since the base acquisition function is ambiguous.""" - msg = ( - "GPHedge base acquisition function is ambiguous." - " You may use self.base_acquisitions[i].base_acq(mean, std)" - " to get the base acquisition function for the i-th acquisition." - ) - raise TypeError(msg) - - def _sample_idx_from_softmax_gains(self) -> int: - """Sample an index weighted by the softmax of the gains.""" - cumsum_softmax_g = np.cumsum(softmax(self.gains)) - r = self.random_state.rand() - return np.argmax(r <= cumsum_softmax_g) # Returns the first True value - - def _update_gains(self, gp: GaussianProcessRegressor) -> None: - """Update the gains of the base acquisition functions.""" - with warnings.catch_warnings(): - warnings.simplefilter("ignore") - rewards = gp.predict(self.previous_candidates) - self.gains += rewards - self.previous_candidates = None - - def suggest( - self, - gp: GaussianProcessRegressor, - target_space: TargetSpace, - n_random: int = 10_000, - n_l_bfgs_b: int = 10, - fit_gp: bool = True, - ) -> NDArray[Float]: - """Suggest a promising point to probe next. - - Parameters - ---------- - gp : GaussianProcessRegressor - A fitted Gaussian Process. - - target_space : TargetSpace - The target space to probe. - - n_random : int, default 10_000 - Number of random samples to use. - - n_l_bfgs_b : int, default 10 - Number of starting points for the L-BFGS-B optimizer. - - fit_gp : bool, default True - Whether to fit the Gaussian Process to the target space. - Set to False if the GP is already fitted. - - Returns - ------- - np.ndarray - Suggested point to probe next. - """ - if len(target_space) == 0: - msg = ( - "Cannot suggest a point without previous samples. Use " - " target_space.random_sample() to generate a point and " - " target_space.probe(*) to evaluate it." - ) - raise TargetSpaceEmptyError(msg) - self.i += 1 - if fit_gp: - self._fit_gp(gp=gp, target_space=target_space) - - # Update the gains of the base acquisition functions - if self.previous_candidates is not None: - self._update_gains(gp) - - # Suggest a point using each base acquisition function - x_max = [ - base_acq.suggest( - gp=gp, - target_space=target_space, - n_random=n_random // self.n_acq, - n_l_bfgs_b=n_l_bfgs_b // self.n_acq, - fit_gp=False, - ) - for base_acq in self.base_acquisitions - ] - self.previous_candidates = np.array(x_max) - idx = self._sample_idx_from_softmax_gains() - return x_max[idx] diff --git a/bayes_opt/bayesian_optimization.py b/bayes_opt/bayesian_optimization.py deleted file mode 100644 index d7f2e4035..000000000 --- a/bayes_opt/bayesian_optimization.py +++ /dev/null @@ -1,358 +0,0 @@ -"""Main module. - -Holds the `BayesianOptimization` class, which handles the maximization of a -function over a specific target space. -""" - -from __future__ import annotations - -from collections import deque -from typing import TYPE_CHECKING, Any -from warnings import warn - -import numpy as np -from sklearn.gaussian_process import GaussianProcessRegressor -from sklearn.gaussian_process.kernels import Matern - -from bayes_opt import acquisition -from bayes_opt.constraint import ConstraintModel -from bayes_opt.domain_reduction import DomainTransformer -from bayes_opt.event import DEFAULT_EVENTS, Events -from bayes_opt.logger import _get_default_logger -from bayes_opt.parameter import wrap_kernel -from bayes_opt.target_space import TargetSpace -from bayes_opt.util import ensure_rng - -if TYPE_CHECKING: - from collections.abc import Callable, Iterable, Mapping - - from numpy.random import RandomState - from numpy.typing import NDArray - from scipy.optimize import NonlinearConstraint - - from bayes_opt.acquisition import AcquisitionFunction - from bayes_opt.constraint import ConstraintModel - from bayes_opt.domain_reduction import DomainTransformer - from bayes_opt.parameter import BoundsMapping, ParamsType - - Float = np.floating[Any] - - -class Observable: - """Inspired by https://www.protechtraining.com/blog/post/879#simple-observer.""" - - def __init__(self, events: Iterable[Any]) -> None: - # maps event names to subscribers - # str -> dict - self._events = {event: dict() for event in events} - - def get_subscribers(self, event: Any) -> Any: - """Return the subscribers of an event.""" - return self._events[event] - - def subscribe(self, event: Any, subscriber: Any, callback: Callable[..., Any] | None = None) -> None: - """Add subscriber to an event.""" - if callback is None: - callback = subscriber.update - self.get_subscribers(event)[subscriber] = callback - - def unsubscribe(self, event: Any, subscriber: Any) -> None: - """Remove a subscriber for a particular event.""" - del self.get_subscribers(event)[subscriber] - - def dispatch(self, event: Any) -> None: - """Trigger callbacks for subscribers of an event.""" - for callback in self.get_subscribers(event).values(): - callback(event, self) - - -class BayesianOptimization(Observable): - """Handle optimization of a target function over a specific target space. - - This class takes the function to optimize as well as the parameters bounds - in order to find which values for the parameters yield the maximum value - using bayesian optimization. - - Parameters - ---------- - f: function or None. - Function to be maximized. - - pbounds: dict - Dictionary with parameters names as keys and a tuple with minimum - and maximum values. - - constraint: NonlinearConstraint. - Note that the names of arguments of the constraint function and of - f need to be the same. - - random_state: int or numpy.random.RandomState, optional(default=None) - If the value is an integer, it is used as the seed for creating a - numpy.random.RandomState. Otherwise the random state provided is used. - When set to None, an unseeded random state is generated. - - verbose: int, optional(default=2) - The level of verbosity. - - bounds_transformer: DomainTransformer, optional(default=None) - If provided, the transformation is applied to the bounds. - - allow_duplicate_points: bool, optional (default=False) - If True, the optimizer will allow duplicate points to be registered. - This behavior may be desired in high noise situations where repeatedly probing - the same point will give different answers. In other situations, the acquisition - may occasionally generate a duplicate point. - """ - - def __init__( - self, - f: Callable[..., float] | None, - pbounds: Mapping[str, tuple[float, float]], - acquisition_function: AcquisitionFunction | None = None, - constraint: NonlinearConstraint | None = None, - random_state: int | RandomState | None = None, - verbose: int = 2, - bounds_transformer: DomainTransformer | None = None, - allow_duplicate_points: bool = False, - ): - self._random_state = ensure_rng(random_state) - self._allow_duplicate_points = allow_duplicate_points - self._queue: deque[ParamsType] = deque() - - if acquisition_function is None: - if constraint is None: - self._acquisition_function = acquisition.UpperConfidenceBound( - kappa=2.576, random_state=self._random_state - ) - else: - self._acquisition_function = acquisition.ExpectedImprovement( - xi=0.01, random_state=self._random_state - ) - else: - self._acquisition_function = acquisition_function - - if constraint is None: - # Data structure containing the function to be optimized, the - # bounds of its domain, and a record of the evaluations we have - # done so far - self._space = TargetSpace( - f, pbounds, random_state=random_state, allow_duplicate_points=self._allow_duplicate_points - ) - self.is_constrained = False - else: - constraint_ = ConstraintModel( - constraint.fun, constraint.lb, constraint.ub, random_state=random_state - ) - self._space = TargetSpace( - f, - pbounds, - constraint=constraint_, - random_state=random_state, - allow_duplicate_points=self._allow_duplicate_points, - ) - self.is_constrained = True - - # Internal GP regressor - self._gp = GaussianProcessRegressor( - kernel=wrap_kernel(Matern(nu=2.5), transform=self._space.kernel_transform), - alpha=1e-6, - normalize_y=True, - n_restarts_optimizer=5, - random_state=self._random_state, - ) - - self._verbose = verbose - self._bounds_transformer = bounds_transformer - if self._bounds_transformer: - if not isinstance(self._bounds_transformer, DomainTransformer): - msg = "The transformer must be an instance of DomainTransformer" - raise TypeError(msg) - self._bounds_transformer.initialize(self._space) - - self._sorting_warning_already_shown = False # TODO: remove in future version - super().__init__(events=DEFAULT_EVENTS) - - @property - def space(self) -> TargetSpace: - """Return the target space associated with the optimizer.""" - return self._space - - @property - def acquisition_function(self) -> AcquisitionFunction: - """Return the acquisition function associated with the optimizer.""" - return self._acquisition_function - - @property - def constraint(self) -> ConstraintModel | None: - """Return the constraint associated with the optimizer, if any.""" - if self.is_constrained: - return self._space.constraint - return None - - @property - def max(self) -> dict[str, Any] | None: - """Get maximum target value found and corresponding parameters. - - See `TargetSpace.max` for more information. - """ - return self._space.max() - - @property - def res(self) -> list[dict[str, Any]]: - """Get all target values and constraint fulfillment for all parameters. - - See `TargetSpace.res` for more information. - """ - return self._space.res() - - def register( - self, params: ParamsType, target: float, constraint_value: float | NDArray[Float] | None = None - ) -> None: - """Register an observation with known target. - - Parameters - ---------- - params: dict or list - The parameters associated with the observation. - - target: float - Value of the target function at the observation. - - constraint_value: float or None - Value of the constraint function at the observation, if any. - """ - # TODO: remove in future version - if isinstance(params, np.ndarray) and not self._sorting_warning_already_shown: - msg = ( - "You're attempting to register an np.ndarray. In previous versions, the optimizer internally" - " sorted parameters by key and expected any registered array to respect this order." - " In the current and any future version the order as given by the pbounds dictionary will be" - " used. If you wish to retain sorted parameters, please manually sort your pbounds" - " dictionary before constructing the optimizer." - ) - warn(msg, stacklevel=1) - self._sorting_warning_already_shown = True - self._space.register(params, target, constraint_value) - self.dispatch(Events.OPTIMIZATION_STEP) - - def probe(self, params: ParamsType, lazy: bool = True) -> None: - """Evaluate the function at the given points. - - Useful to guide the optimizer. - - Parameters - ---------- - params: dict or list - The parameters where the optimizer will evaluate the function. - - lazy: bool, optional(default=True) - If True, the optimizer will evaluate the points when calling - maximize(). Otherwise it will evaluate it at the moment. - """ - # TODO: remove in future version - if isinstance(params, np.ndarray) and not self._sorting_warning_already_shown: - msg = ( - "You're attempting to register an np.ndarray. In previous versions, the optimizer internally" - " sorted parameters by key and expected any registered array to respect this order." - " In the current and any future version the order as given by the pbounds dictionary will be" - " used. If you wish to retain sorted parameters, please manually sort your pbounds" - " dictionary before constructing the optimizer." - ) - warn(msg, stacklevel=1) - self._sorting_warning_already_shown = True - params = self._space.array_to_params(params) - if lazy: - self._queue.append(params) - else: - self._space.probe(params) - self.dispatch(Events.OPTIMIZATION_STEP) - - def suggest(self) -> dict[str, float | NDArray[Float]]: - """Suggest a promising point to probe next.""" - if len(self._space) == 0: - return self._space.array_to_params(self._space.random_sample(random_state=self._random_state)) - - # Finding argmax of the acquisition function. - suggestion = self._acquisition_function.suggest(gp=self._gp, target_space=self._space, fit_gp=True) - - return self._space.array_to_params(suggestion) - - def _prime_queue(self, init_points: int) -> None: - """Ensure the queue is not empty. - - Parameters - ---------- - init_points: int - Number of parameters to prime the queue with. - """ - if not self._queue and self._space.empty: - init_points = max(init_points, 1) - - for _ in range(init_points): - sample = self._space.random_sample(random_state=self._random_state) - self._queue.append(self._space.array_to_params(sample)) - - def _prime_subscriptions(self) -> None: - if not any([len(subs) for subs in self._events.values()]): - _logger = _get_default_logger(self._verbose, self.is_constrained) - self.subscribe(Events.OPTIMIZATION_START, _logger) - self.subscribe(Events.OPTIMIZATION_STEP, _logger) - self.subscribe(Events.OPTIMIZATION_END, _logger) - - def maximize(self, init_points: int = 5, n_iter: int = 25) -> None: - r""" - Maximize the given function over the target space. - - Parameters - ---------- - init_points : int, optional(default=5) - Number of random points to probe before starting the optimization. - - n_iter: int, optional(default=25) - Number of iterations where the method attempts to find the maximum - value. - - Warning - ------- - The maximize loop only fits the GP when suggesting a new point to - probe based on the acquisition function. This means that the GP may - not be fitted on all points registered to the target space when the - method completes. If you intend to use the GP model after the - optimization routine, make sure to fit it manually, e.g. by calling - ``optimizer._gp.fit(optimizer.space.params, optimizer.space.target)``. - """ - self._prime_subscriptions() - self.dispatch(Events.OPTIMIZATION_START) - self._prime_queue(init_points) - - iteration = 0 - while self._queue or iteration < n_iter: - try: - x_probe = self._queue.popleft() - except IndexError: - x_probe = self.suggest() - iteration += 1 - self.probe(x_probe, lazy=False) - - if self._bounds_transformer and iteration > 0: - # The bounds transformer should only modify the bounds after - # the init_points points (only for the true iterations) - self.set_bounds(self._bounds_transformer.transform(self._space)) - - self.dispatch(Events.OPTIMIZATION_END) - - def set_bounds(self, new_bounds: BoundsMapping) -> None: - """Modify the bounds of the search space. - - Parameters - ---------- - new_bounds : dict - A dictionary with the parameter name and its new bounds - """ - self._space.set_bounds(new_bounds) - - def set_gp_params(self, **params: Any) -> None: - """Set parameters of the internal Gaussian Process Regressor.""" - if "kernel" in params: - params["kernel"] = wrap_kernel(kernel=params["kernel"], transform=self._space.kernel_transform) - self._gp.set_params(**params) diff --git a/bayes_opt/constraint.py b/bayes_opt/constraint.py deleted file mode 100644 index 120169bdb..000000000 --- a/bayes_opt/constraint.py +++ /dev/null @@ -1,263 +0,0 @@ -"""Constraint handling.""" - -from __future__ import annotations - -from typing import TYPE_CHECKING, Any - -import numpy as np -from scipy.stats import norm -from sklearn.gaussian_process import GaussianProcessRegressor -from sklearn.gaussian_process.kernels import Matern - -from bayes_opt.parameter import wrap_kernel - -if TYPE_CHECKING: - from collections.abc import Callable - - from numpy.random import RandomState - from numpy.typing import NDArray - - Float = np.floating[Any] - - -class ConstraintModel: - """Model constraints using GP regressors. - - This class takes the function to optimize as well as the parameters bounds - in order to find which values for the parameters yield the maximum value - using bayesian optimization. - - Parameters - ---------- - fun : None or Callable -> float or np.ndarray - The constraint function. Should be float-valued or array-valued (if - multiple constraints are present). Needs to take the same parameters - as the optimization target with the same argument names. - - lb : float or np.ndarray - The lower bound on the constraints. Should have the same - dimensionality as the return value of the constraint function. - - ub : float or np.ndarray - The upper bound on the constraints. Should have the same - dimensionality as the return value of the constraint function. - - random_state : np.random.RandomState or int or None, default=None - Random state to use. - - Note - ---- - In case of multiple constraints, this model assumes conditional - independence. This means that the overall probability of fulfillment is a - simply the product of the individual probabilities. - """ - - def __init__( - self, - fun: Callable[..., float] | Callable[..., NDArray[Float]] | None, - lb: float | NDArray[Float], - ub: float | NDArray[Float], - transform: Callable[[Any], Any] | None = None, - random_state: int | RandomState | None = None, - ) -> None: - self.fun = fun - - self._lb = np.atleast_1d(lb) - self._ub = np.atleast_1d(ub) - - if np.any(self._lb >= self._ub): - msg = "Lower bounds must be less than upper bounds." - raise ValueError(msg) - - self._model = [ - GaussianProcessRegressor( - kernel=wrap_kernel(Matern(nu=2.5), transform) if transform is not None else Matern(nu=2.5), - alpha=1e-6, - normalize_y=True, - n_restarts_optimizer=5, - random_state=random_state, - ) - for _ in range(len(self._lb)) - ] - - @property - def lb(self) -> NDArray[Float]: - """Return lower bounds.""" - return self._lb - - @property - def ub(self) -> NDArray[Float]: - """Return upper bounds.""" - return self._ub - - @property - def model(self) -> list[GaussianProcessRegressor]: - """Return GP regressors of the constraint function.""" - return self._model - - def eval(self, **kwargs: Any) -> float | NDArray[Float]: # noqa: D417 - r"""Evaluate the constraint function. - - Parameters - ---------- - \*\*kwargs : any - Function arguments to evaluate the constraint function on. - - - Returns - ------- - Value of the constraint function. - - Raises - ------ - TypeError - If the kwargs' keys don't match the function argument names. - """ - if self.fun is None: - error_msg = "No constraint function was provided." - raise ValueError(error_msg) - - try: - return self.fun(**kwargs) - except TypeError as e: - msg = ( - "Encountered TypeError when evaluating constraint " - "function. This could be because your constraint function " - "doesn't use the same keyword arguments as the target " - f"function. Original error message:\n\n{e}" - ) - e.args = (msg,) - raise - - def fit(self, X: NDArray[Float], Y: NDArray[Float]) -> None: - """Fit internal GPRs to the data. - - Parameters - ---------- - X : np.ndarray of shape (n_samples, n_features) - Parameters of the constraint function. - Y : np.ndarray of shape (n_samples, n_constraints) - Values of the constraint function. - - - Returns - ------- - None - """ - if len(self._model) == 1: - self._model[0].fit(X, Y) - else: - for i, gp in enumerate(self._model): - gp.fit(X, Y[:, i]) - - def predict(self, X: NDArray[Float]) -> NDArray[Float]: - r"""Calculate the probability that the constraint is fulfilled at `X`. - - Note that this does not try to approximate the values of the - constraint function (for this, see `ConstraintModel.approx()`.), but - probability that the constraint function is fulfilled. That is, this - function calculates - - .. math:: - p = \text{Pr}\left\{c^{\text{low}} \leq \tilde{c}(x) \leq - c^{\text{up}} \right\} = \int_{c^{\text{low}}}^{c^{\text{up}}} - \mathcal{N}(c, \mu(x), \sigma^2(x)) \, dc. - - with :math:`\mu(x)`, :math:`\sigma^2(x)` the mean and variance at - :math:`x` as given by the GP and :math:`c^{\text{low}}`, - :math:`c^{\text{up}}` the lower and upper bounds of the constraint - respectively. - - Note - ---- - - In case of multiple constraints, we assume conditional independence. - This means we calculate the probability of constraint fulfilment - individually, with the joint probability given as their product. - - Parameters - ---------- - X : np.ndarray of shape (n_samples, n_features) - Parameters for which to predict the probability of constraint - fulfilment. - - - Returns - ------- - np.ndarray of shape (n_samples,) - Probability of constraint fulfilment. - - """ - X_shape = X.shape - X = X.reshape((-1, self._model[0].n_features_in_)) - - result: NDArray[Float] - y_mean: NDArray[Float] - y_std: NDArray[Float] - p_lower: NDArray[Float] - p_upper: NDArray[Float] - if len(self._model) == 1: - y_mean, y_std = self._model[0].predict(X, return_std=True) - - p_lower = ( - norm(loc=y_mean, scale=y_std).cdf(self._lb[0]) if self._lb[0] != -np.inf else np.array([0]) - ) - p_upper = ( - norm(loc=y_mean, scale=y_std).cdf(self._ub[0]) if self._lb[0] != np.inf else np.array([1]) - ) - result = p_upper - p_lower - return result.reshape(X_shape[:-1]) - - result = np.ones(X.shape[0]) - for j, gp in enumerate(self._model): - y_mean, y_std = gp.predict(X, return_std=True) - p_lower = ( - norm(loc=y_mean, scale=y_std).cdf(self._lb[j]) if self._lb[j] != -np.inf else np.array([0]) - ) - p_upper = ( - norm(loc=y_mean, scale=y_std).cdf(self._ub[j]) if self._lb[j] != np.inf else np.array([1]) - ) - result = result * (p_upper - p_lower) - return result.reshape(X_shape[:-1]) - - def approx(self, X: NDArray[Float]) -> NDArray[Float]: - """ - Approximate the constraint function using the internal GPR model. - - Parameters - ---------- - X : np.ndarray of shape (n_samples, n_features) - Parameters for which to estimate the constraint function value. - - Returns - ------- - np.ndarray of shape (n_samples, n_constraints) - Constraint function value estimates. - """ - X_shape = X.shape - X = X.reshape((-1, self._model[0].n_features_in_)) - if len(self._model) == 1: - return self._model[0].predict(X).reshape(X_shape[:-1]) - - result = np.column_stack([gp.predict(X) for gp in self._model]) - return result.reshape(X_shape[:-1] + (len(self._lb),)) - - def allowed(self, constraint_values: NDArray[Float]) -> NDArray[np.bool_]: - """Check whether `constraint_values` fulfills the specified limits. - - Parameters - ---------- - constraint_values : np.ndarray of shape (n_samples, n_constraints) - The values of the constraint function. - - - Returns - ------- - np.ndarrray of shape (n_samples,) - Specifying wheter the constraints are fulfilled. - - """ - if self._lb.size == 1: - return np.less_equal(self._lb, constraint_values) & np.less_equal(constraint_values, self._ub) - - return np.all(constraint_values <= self._ub, axis=-1) & np.all(constraint_values >= self._lb, axis=-1) diff --git a/bayes_opt/domain_reduction.py b/bayes_opt/domain_reduction.py deleted file mode 100644 index 243a51bd5..000000000 --- a/bayes_opt/domain_reduction.py +++ /dev/null @@ -1,295 +0,0 @@ -"""Implement domain transformation. - -In particular, this provides a base transformer class and a sequential domain -reduction transformer as based on Stander and Craig's "On the robustness of a -simple domain reduction scheme for simulation-based optimization" -""" - -from __future__ import annotations - -from abc import ABC, abstractmethod -from collections.abc import Iterable, Mapping, Sequence -from typing import TYPE_CHECKING, Any -from warnings import warn - -import numpy as np - -from bayes_opt.parameter import FloatParameter -from bayes_opt.target_space import TargetSpace - -if TYPE_CHECKING: - from numpy.typing import NDArray - - Float = np.floating[Any] - - -class DomainTransformer(ABC): - """Base class.""" - - @abstractmethod - def __init__(self, **kwargs: Any) -> None: - """To override with specific implementation.""" - - @abstractmethod - def initialize(self, target_space: TargetSpace) -> None: - """To override with specific implementation.""" - - @abstractmethod - def transform(self, target_space: TargetSpace) -> dict[str, NDArray[Float]]: - """To override with specific implementation.""" - - -class SequentialDomainReductionTransformer(DomainTransformer): - """Reduce the searchable space. - - A sequential domain reduction transformer based on the work by Stander, N. and Craig, K: - "On the robustness of a simple domain reduction scheme for simulation-based optimization" - - Parameters - ---------- - gamma_osc : float, default=0.7 - Parameter used to scale (typically dampen) oscillations. - - gamma_pan : float, default=1.0 - Parameter used to scale (typically unitary) panning. - - eta : float, default=0.9 - Zooming parameter used to shrink the region of interest. - - minimum_window : float or np.ndarray or dict, default=0.0 - Minimum window size for each parameter. If a float is provided, - the same value is used for all parameters. - """ - - def __init__( - self, - parameters: Iterable[str] | None = None, - gamma_osc: float = 0.7, - gamma_pan: float = 1.0, - eta: float = 0.9, - minimum_window: NDArray[Float] | Sequence[float] | Mapping[str, float] | float = 0.0, - ) -> None: - # TODO: Ensure that this is only applied to continuous parameters - self.parameters = parameters - self.gamma_osc = gamma_osc - self.gamma_pan = gamma_pan - self.eta = eta - - self.minimum_window_value = minimum_window - - def initialize(self, target_space: TargetSpace) -> None: - """Initialize all of the parameters. - - Parameters - ---------- - target_space : TargetSpace - TargetSpace this DomainTransformer operates on. - """ - if isinstance(self.minimum_window_value, Mapping): - self.minimum_window_value = [self.minimum_window_value[key] for key in target_space.keys] - else: - self.minimum_window_value = self.minimum_window_value - - any_not_float = any([not isinstance(p, FloatParameter) for p in target_space._params_config.values()]) - if any_not_float: - msg = "Domain reduction is only supported for all-FloatParameter optimization." - raise ValueError(msg) - # Set the original bounds - self.original_bounds = np.copy(target_space.bounds) - self.bounds = [self.original_bounds] - - self.minimum_window: NDArray[Float] | Sequence[float] - # Set the minimum window to an array of length bounds - if isinstance(self.minimum_window_value, (Sequence, np.ndarray)): - if len(self.minimum_window_value) != len(target_space.bounds): - error_msg = "Length of minimum_window must be the same as the number of parameters" - raise ValueError(error_msg) - self.minimum_window = self.minimum_window_value - else: - self.minimum_window = [self.minimum_window_value] * len(target_space.bounds) - - # Set initial values - self.previous_optimal = np.mean(target_space.bounds, axis=1) - self.current_optimal = np.mean(target_space.bounds, axis=1) - self.r = target_space.bounds[:, 1] - target_space.bounds[:, 0] - - self.previous_d = 2.0 * (self.current_optimal - self.previous_optimal) / self.r - - self.current_d = 2.0 * (self.current_optimal - self.previous_optimal) / self.r - - self.c = self.current_d * self.previous_d - self.c_hat = np.sqrt(np.abs(self.c)) * np.sign(self.c) - - self.gamma = 0.5 * (self.gamma_pan * (1.0 + self.c_hat) + self.gamma_osc * (1.0 - self.c_hat)) - - self.contraction_rate = self.eta + np.abs(self.current_d) * (self.gamma - self.eta) - - self.r = self.contraction_rate * self.r - - # check if the minimum window fits in the original bounds - self._window_bounds_compatibility(self.original_bounds) - - def _update(self, target_space: TargetSpace) -> None: - """Update contraction rate, window size, and window center. - - Parameters - ---------- - target_space : TargetSpace - TargetSpace this DomainTransformer operates on. - """ - # setting the previous - self.previous_optimal = self.current_optimal - self.previous_d = self.current_d - - self.current_optimal = target_space.params_to_array(target_space.max()["params"]) - - self.current_d = 2.0 * (self.current_optimal - self.previous_optimal) / self.r - - self.c = self.current_d * self.previous_d - - self.c_hat = np.sqrt(np.abs(self.c)) * np.sign(self.c) - - self.gamma = 0.5 * (self.gamma_pan * (1.0 + self.c_hat) + self.gamma_osc * (1.0 - self.c_hat)) - - self.contraction_rate = self.eta + np.abs(self.current_d) * (self.gamma - self.eta) - - self.r = self.contraction_rate * self.r - - def _trim(self, new_bounds: NDArray[Float], global_bounds: NDArray[Float]) -> NDArray[Float]: - """ - Adjust the new_bounds and verify that they adhere to global_bounds and minimum_window. - - Parameters - ---------- - new_bounds : np.ndarray - The proposed new_bounds that (may) need adjustment. - - global_bounds : np.ndarray - The maximum allowable bounds for each parameter. - - Returns - ------- - new_bounds : np.ndarray - The adjusted bounds after enforcing constraints. - """ - # sort bounds - new_bounds = np.sort(new_bounds) - - pbounds: NDArray[Float] - # Validate each parameter's bounds against the global_bounds - for i, pbounds in enumerate(new_bounds): - # If the one of the bounds is outside the global bounds, reset the bound to the global bound - # This is expected to happen when the window is near the global bounds, no warning is issued - if pbounds[0] < global_bounds[i, 0]: - pbounds[0] = global_bounds[i, 0] - - if pbounds[1] > global_bounds[i, 1]: - pbounds[1] = global_bounds[i, 1] - - # If a lower bound is greater than the associated global upper bound, - # reset it to the global lower bound - if pbounds[0] > global_bounds[i, 1]: - pbounds[0] = global_bounds[i, 0] - warn( - "\nDomain Reduction Warning:\n" - "A parameter's lower bound is greater than the global upper bound." - "The offensive boundary has been reset." - "Be cautious of subsequent reductions.", - stacklevel=2, - ) - - # If an upper bound is less than the associated global lower bound, - # reset it to the global upper bound - if pbounds[1] < global_bounds[i, 0]: - pbounds[1] = global_bounds[i, 1] - warn( - "\nDomain Reduction Warning:\n" - "A parameter's lower bound is greater than the global upper bound." - "The offensive boundary has been reset." - "Be cautious of subsequent reductions.", - stacklevel=2, - ) - - # Adjust new_bounds to ensure they respect the minimum window width for each parameter - for i, pbounds in enumerate(new_bounds): - current_window_width = abs(pbounds[0] - pbounds[1]) - - # If the window width is less than the minimum allowable width, adjust it - # Note that when minimum_window < width of the global bounds one side - # always has more space than required - if current_window_width < self.minimum_window[i]: - width_deficit = (self.minimum_window[i] - current_window_width) / 2.0 - available_left_space = abs(global_bounds[i, 0] - pbounds[0]) - available_right_space = abs(global_bounds[i, 1] - pbounds[1]) - - # determine how much to expand on the left and right - expand_left = min(width_deficit, available_left_space) - expand_right = min(width_deficit, available_right_space) - - # calculate the deficit on each side - expand_left_deficit = width_deficit - expand_left - expand_right_deficit = width_deficit - expand_right - - # shift the deficit to the side with more space - adjust_left = expand_left + max(expand_right_deficit, 0) - adjust_right = expand_right + max(expand_left_deficit, 0) - - # adjust the bounds - pbounds[0] -= adjust_left - pbounds[1] += adjust_right - - return new_bounds - - def _window_bounds_compatibility(self, global_bounds: NDArray[Float]) -> None: - """Check if global bounds are compatible with the minimum window sizes. - - Parameters - ---------- - global_bounds : np.ndarray - The maximum allowable bounds for each parameter. - - Raises - ------ - ValueError - If global bounds are not compatible with the minimum window size. - """ - entry: NDArray[Float] - for i, entry in enumerate(global_bounds): - global_window_width = abs(entry[1] - entry[0]) - if global_window_width < self.minimum_window[i]: - error_msg = "Global bounds are not compatible with the minimum window size." - raise ValueError(error_msg) - - def _create_bounds(self, parameters: Iterable[str], bounds: NDArray[Float]) -> dict[str, NDArray[Float]]: - """Create a dictionary of bounds for each parameter. - - Parameters - ---------- - parameters : Iterable[str] - The parameters for which to create the bounds. - - bounds : np.ndarray - The bounds for each parameter. - """ - return {param: bounds[i, :] for i, param in enumerate(parameters)} - - def transform(self, target_space: TargetSpace) -> dict[str, NDArray[Float]]: - """Transform the bounds of the target space. - - Parameters - ---------- - target_space : TargetSpace - TargetSpace this DomainTransformer operates on. - - Returns - ------- - dict - The new bounds of each parameter. - """ - self._update(target_space) - - new_bounds = np.array([self.current_optimal - 0.5 * self.r, self.current_optimal + 0.5 * self.r]).T - - new_bounds = self._trim(new_bounds, self.original_bounds) - self.bounds.append(new_bounds) - return self._create_bounds(target_space.keys, new_bounds) diff --git a/bayes_opt/event.py b/bayes_opt/event.py deleted file mode 100644 index 4badb024d..000000000 --- a/bayes_opt/event.py +++ /dev/null @@ -1,17 +0,0 @@ -"""Register optimization events variables.""" - -from __future__ import annotations - - -class Events: - """Define optimization events. - - Behaves similar to enums. - """ - - OPTIMIZATION_START = "optimization:start" - OPTIMIZATION_STEP = "optimization:step" - OPTIMIZATION_END = "optimization:end" - - -DEFAULT_EVENTS = [Events.OPTIMIZATION_START, Events.OPTIMIZATION_STEP, Events.OPTIMIZATION_END] diff --git a/bayes_opt/exception.py b/bayes_opt/exception.py deleted file mode 100644 index 628e20d77..000000000 --- a/bayes_opt/exception.py +++ /dev/null @@ -1,31 +0,0 @@ -"""This module contains custom exceptions for Bayesian Optimization.""" - -from __future__ import annotations - -__all__ = [ - "BayesianOptimizationError", - "NotUniqueError", - "ConstraintNotSupportedError", - "NoValidPointRegisteredError", - "TargetSpaceEmptyError", -] - - -class BayesianOptimizationError(Exception): - """Base class for exceptions in the Bayesian Optimization.""" - - -class NotUniqueError(BayesianOptimizationError): - """A point is non-unique.""" - - -class ConstraintNotSupportedError(BayesianOptimizationError): - """Raised when constrained optimization is not supported.""" - - -class NoValidPointRegisteredError(BayesianOptimizationError): - """Raised when an acquisition function depends on previous points but none are registered.""" - - -class TargetSpaceEmptyError(BayesianOptimizationError): - """Raised when the target space is empty.""" diff --git a/bayes_opt/logger.py b/bayes_opt/logger.py deleted file mode 100644 index 0f5cd41c2..000000000 --- a/bayes_opt/logger.py +++ /dev/null @@ -1,304 +0,0 @@ -"""Contains classes and functions for logging.""" - -from __future__ import annotations - -import json -from contextlib import suppress -from pathlib import Path -from typing import TYPE_CHECKING, Any - -import numpy as np -from colorama import Fore, just_fix_windows_console - -from bayes_opt.event import Events -from bayes_opt.observer import _Tracker - -if TYPE_CHECKING: - from os import PathLike - - from bayes_opt.bayesian_optimization import BayesianOptimization - -just_fix_windows_console() - - -def _get_default_logger(verbose: int, is_constrained: bool) -> ScreenLogger: - """ - Return the default logger. - - Parameters - ---------- - verbose : int - Verbosity level of the logger. - - is_constrained : bool - Whether the underlying optimizer uses constraints (this requires - an additional column in the output). - - Returns - ------- - ScreenLogger - The default logger. - - """ - return ScreenLogger(verbose=verbose, is_constrained=is_constrained) - - -class ScreenLogger(_Tracker): - """Logger that outputs text, e.g. to log to a terminal. - - Parameters - ---------- - verbose : int - Verbosity level of the logger. - - is_constrained : bool - Whether the logger is associated with a constrained optimization - instance. - """ - - _default_cell_size = 9 - _default_precision = 4 - _colour_new_max = Fore.MAGENTA - _colour_regular_message = Fore.RESET - _colour_reset = Fore.RESET - - def __init__(self, verbose: int = 2, is_constrained: bool = False) -> None: - self._verbose = verbose - self._is_constrained = is_constrained - self._header_length = None - super().__init__() - - @property - def verbose(self) -> int: - """Return the verbosity level.""" - return self._verbose - - @verbose.setter - def verbose(self, v: int) -> None: - """Set the verbosity level. - - Parameters - ---------- - v : int - New verbosity level of the logger. - """ - self._verbose = v - - @property - def is_constrained(self) -> bool: - """Return whether the logger is constrained.""" - return self._is_constrained - - def _format_number(self, x: float) -> str: - """Format a number. - - Parameters - ---------- - x : number - Value to format. - - Returns - ------- - A stringified, formatted version of `x`. - """ - if isinstance(x, int): - s = f"{x:<{self._default_cell_size}}" - else: - s = f"{x:<{self._default_cell_size}.{self._default_precision}}" - - if len(s) > self._default_cell_size: - if "." in s: - return s[: self._default_cell_size] - return s[: self._default_cell_size - 3] + "..." - return s - - def _format_bool(self, x: bool) -> str: - """Format a boolean. - - Parameters - ---------- - x : boolean - Value to format. - - Returns - ------- - A stringified, formatted version of `x`. - """ - x_ = ("T" if x else "F") if self._default_cell_size < 5 else str(x) - return f"{x_:<{self._default_cell_size}}" - - def _format_str(self, str_: str) -> str: - """Format a str. - - Parameters - ---------- - str_ : str - Value to format. - - Returns - ------- - A stringified, formatted version of `x`. - """ - s = f"{str_:^{self._default_cell_size}}" - if len(s) > self._default_cell_size: - return s[: self._default_cell_size - 3] + "..." - return s - - def _step(self, instance: BayesianOptimization, colour: str = _colour_regular_message) -> str: - """Log a step. - - Parameters - ---------- - instance : bayesian_optimization.BayesianOptimization - The instance associated with the event. - - colour : - (Default value = _colour_regular_message, equivalent to Fore.RESET) - - Returns - ------- - A stringified, formatted version of the most recent optimization step. - """ - res: dict[str, Any] = instance.res[-1] - keys: list[str] = instance.space.keys - # iter, target, allowed [, *params] - cells: list[str | None] = [None] * (3 + len(keys)) - - cells[:2] = self._format_number(self._iterations + 1), self._format_number(res["target"]) - if self._is_constrained: - cells[2] = self._format_bool(res["allowed"]) - params = res.get("params", {}) - cells[3:] = [ - instance.space._params_config[key].to_string(val, self._default_cell_size) - for key, val in params.items() - ] - - return "| " + " | ".join(colour + x + self._colour_reset for x in cells if x is not None) + " |" - - def _header(self, instance: BayesianOptimization) -> str: - """Print the header of the log. - - Parameters - ---------- - instance : bayesian_optimization.BayesianOptimization - The instance associated with the header. - - Returns - ------- - A stringified, formatted version of the most header. - """ - keys: list[str] = instance.space.keys - # iter, target, allowed [, *params] - cells: list[str | None] = [None] * (3 + len(keys)) - - cells[:2] = self._format_str("iter"), self._format_str("target") - if self._is_constrained: - cells[2] = self._format_str("allowed") - cells[3:] = [self._format_str(key) for key in keys] - - line = "| " + " | ".join(x for x in cells if x is not None) + " |" - self._header_length = len(line) - return line + "\n" + ("-" * self._header_length) - - def _is_new_max(self, instance: BayesianOptimization) -> bool: - """Check if the step to log produced a new maximum. - - Parameters - ---------- - instance : bayesian_optimization.BayesianOptimization - The instance associated with the step. - - Returns - ------- - boolean - """ - if instance.max is None: - # During constrained optimization, there might not be a maximum - # value since the optimizer might've not encountered any points - # that fulfill the constraints. - return False - if self._previous_max is None: - self._previous_max = instance.max["target"] - return instance.max["target"] > self._previous_max - - def update(self, event: str, instance: BayesianOptimization) -> None: - """Handle incoming events. - - Parameters - ---------- - event : str - One of the values associated with `Events.OPTIMIZATION_START`, - `Events.OPTIMIZATION_STEP` or `Events.OPTIMIZATION_END`. - - instance : bayesian_optimization.BayesianOptimization - The instance associated with the step. - """ - line = "" - if event == Events.OPTIMIZATION_START: - line = self._header(instance) + "\n" - elif event == Events.OPTIMIZATION_STEP: - is_new_max = self._is_new_max(instance) - if self._verbose != 1 or is_new_max: - colour = self._colour_new_max if is_new_max else self._colour_regular_message - line = self._step(instance, colour=colour) + "\n" - elif event == Events.OPTIMIZATION_END: - line = "=" * self._header_length + "\n" - - if self._verbose: - print(line, end="") - self._update_tracker(event, instance) - - -class JSONLogger(_Tracker): - """ - Logger that outputs steps in JSON format. - - The resulting file can be used to restart the optimization from an earlier state. - - Parameters - ---------- - path : str or os.PathLike - Path to the file to write to. - - reset : bool - Whether to overwrite the file if it already exists. - - """ - - def __init__(self, path: str | PathLike[str], reset: bool = True): - self._path = Path(path) - if reset: - with suppress(OSError): - self._path.unlink(missing_ok=True) - super().__init__() - - def update(self, event: str, instance: BayesianOptimization) -> None: - """ - Handle incoming events. - - Parameters - ---------- - event : str - One of the values associated with `Events.OPTIMIZATION_START`, - `Events.OPTIMIZATION_STEP` or `Events.OPTIMIZATION_END`. - - instance : bayesian_optimization.BayesianOptimization - The instance associated with the step. - - """ - if event == Events.OPTIMIZATION_STEP: - data = dict(instance.res[-1]) - - now, time_elapsed, time_delta = self._time_metrics() - data["datetime"] = {"datetime": now, "elapsed": time_elapsed, "delta": time_delta} - - if "allowed" in data: # fix: github.com/fmfn/BayesianOptimization/issues/361 - data["allowed"] = bool(data["allowed"]) - - if "constraint" in data and isinstance(data["constraint"], np.ndarray): - data["constraint"] = data["constraint"].tolist() - - with self._path.open("a") as f: - f.write(json.dumps(data) + "\n") - - self._update_tracker(event, instance) diff --git a/bayes_opt/observer.py b/bayes_opt/observer.py deleted file mode 100644 index f40687e67..000000000 --- a/bayes_opt/observer.py +++ /dev/null @@ -1,62 +0,0 @@ -"""Holds the parent class for loggers.""" - -from __future__ import annotations - -from datetime import datetime -from typing import TYPE_CHECKING - -from bayes_opt.event import Events - -if TYPE_CHECKING: - from bayes_opt.bayesian_optimization import BayesianOptimization - - -class _Tracker: - """Parent class for ScreenLogger and JSONLogger.""" - - def __init__(self) -> None: - self._iterations = 0 - - self._previous_max = None - self._previous_max_params = None - - self._start_time = None - self._previous_time = None - - def _update_tracker(self, event: str, instance: BayesianOptimization) -> None: - """Update the tracker. - - Parameters - ---------- - event : str - One of the values associated with `Events.OPTIMIZATION_START`, - `Events.OPTIMIZATION_STEP` or `Events.OPTIMIZATION_END`. - - instance : bayesian_optimization.BayesianOptimization - The instance associated with the step. - """ - if event == Events.OPTIMIZATION_STEP: - self._iterations += 1 - - if instance.max is None: - return - - current_max = instance.max - - if self._previous_max is None or current_max["target"] > self._previous_max: - self._previous_max = current_max["target"] - self._previous_max_params = current_max["params"] - - def _time_metrics(self) -> tuple[str, float, float]: - """Return time passed since last call.""" - now = datetime.now() # noqa: DTZ005 - if self._start_time is None: - self._start_time = now - if self._previous_time is None: - self._previous_time = now - - time_elapsed = now - self._start_time - time_delta = now - self._previous_time - - self._previous_time = now - return (now.strftime("%Y-%m-%d %H:%M:%S"), time_elapsed.total_seconds(), time_delta.total_seconds()) diff --git a/bayes_opt/parameter.py b/bayes_opt/parameter.py deleted file mode 100644 index 90fea618b..000000000 --- a/bayes_opt/parameter.py +++ /dev/null @@ -1,506 +0,0 @@ -"""Parameter classes for Bayesian optimization.""" - -from __future__ import annotations - -import abc -from collections.abc import Sequence -from inspect import signature -from numbers import Number -from typing import TYPE_CHECKING, Any, Callable, Union - -import numpy as np -from sklearn.gaussian_process import kernels - -from bayes_opt.util import ensure_rng - -if TYPE_CHECKING: - from collections.abc import Mapping - - from numpy.typing import NDArray - - Float = np.floating[Any] - Int = np.integer[Any] - - FloatBoundsWithoutType = tuple[float, float] - FloatBoundsWithType = tuple[float, float, type[float]] - FloatBounds = Union[FloatBoundsWithoutType, FloatBoundsWithType] - IntBounds = tuple[Union[int, float], Union[int, float], type[int]] - CategoricalBounds = Sequence[Any] - Bounds = Union[FloatBounds, IntBounds, CategoricalBounds] - BoundsMapping = Mapping[str, Bounds] - - # FIXME: categorical parameters can be of any type. - # This will make static type checking for parameters difficult. - ParamsType = Union[Mapping[str, Any], Sequence[Any], NDArray[Float]] - - -def is_numeric(value: Any) -> bool: - """Check if a value is numeric.""" - return isinstance(value, Number) or ( - isinstance(value, np.generic) - and (np.isdtype(value.dtype, np.number) or np.issubdtype(value.dtype, np.number)) - ) - - -class BayesParameter(abc.ABC): - """Base class for Bayesian optimization parameters. - - Parameters - ---------- - name : str - The name of the parameter. - """ - - def __init__(self, name: str, bounds: NDArray[Any]) -> None: - self.name = name - self._bounds = bounds - - @property - def bounds(self) -> NDArray[Any]: - """The bounds of the parameter in float space.""" - return self._bounds - - @property - @abc.abstractmethod - def is_continuous(self) -> bool: - """Whether the parameter is continuous.""" - - def random_sample( - self, n_samples: int, random_state: np.random.RandomState | int | None - ) -> NDArray[Float]: - """Generate random samples from the parameter. - - Parameters - ---------- - n_samples : int - The number of samples to generate. - - random_state : np.random.RandomState | int | None - The random state to use for sampling. - - Returns - ------- - np.ndarray - The samples. - """ - random_state = ensure_rng(random_state) - return random_state.uniform(self.bounds[0], self.bounds[1], n_samples) - - @abc.abstractmethod - def to_float(self, value: Any) -> float | NDArray[Float]: - """Convert a parameter value to a float. - - Parameters - ---------- - value : Any - The value to convert, should be the canonical representation of the parameter. - """ - - @abc.abstractmethod - def to_param(self, value: float | NDArray[Float]) -> Any: - """Convert a float value to a parameter. - - Parameters - ---------- - value : np.ndarray - The value to convert, should be a float. - - Returns - ------- - Any - The canonical representation of the parameter. - """ - - @abc.abstractmethod - def kernel_transform(self, value: NDArray[Float]) -> NDArray[Float]: - """Transform a parameter value for use in a kernel. - - Parameters - ---------- - value : np.ndarray - The value(s) to transform, should be a float. - - Returns - ------- - np.ndarray - """ - - def to_string(self, value: Any, str_len: int) -> str: - """Represent a parameter value as a string. - - Parameters - ---------- - value : Any - The value to represent. - - str_len : int - The maximum length of the string representation. - - Returns - ------- - str - """ - s = f"{value!r:<{str_len}}" - - if len(s) > str_len: - return s[: str_len - 3] + "..." - return s - - @property - @abc.abstractmethod - def dim(self) -> int: - """The dimensionality of the parameter.""" - - -class FloatParameter(BayesParameter): - """A parameter with float values. - - Parameters - ---------- - name : str - The name of the parameter. - - bounds : tuple[float, float] - The bounds of the parameter. - """ - - def __init__(self, name: str, bounds: tuple[float, float]) -> None: - super().__init__(name, np.array(bounds)) - - @property - def is_continuous(self) -> bool: - """Whether the parameter is continuous.""" - return True - - def to_float(self, value: float) -> float: - """Convert a parameter value to a float. - - Parameters - ---------- - value : Any - The value to convert, should be the canonical representation of the parameter. - """ - return value - - def to_param(self, value: float | NDArray[Float]) -> float: - """Convert a float value to a parameter. - - Parameters - ---------- - value : np.ndarray - The value to convert, should be a float. - - Returns - ------- - Any - The canonical representation of the parameter. - """ - return value.flatten()[0] - - def to_string(self, value: float, str_len: int) -> str: - """Represent a parameter value as a string. - - Parameters - ---------- - value : Any - The value to represent. - - str_len : int - The maximum length of the string representation. - - Returns - ------- - str - """ - s = f"{value:<{str_len}.{str_len}}" - if len(s) > str_len: - if "." in s and "e" not in s: - return s[:str_len] - return s[: str_len - 3] + "..." - return s - - def kernel_transform(self, value: NDArray[Float]) -> NDArray[Float]: - """Transform a parameter value for use in a kernel. - - Parameters - ---------- - value : np.ndarray - The value(s) to transform, should be a float. - - Returns - ------- - np.ndarray - """ - return value - - @property - def dim(self) -> int: - """The dimensionality of the parameter.""" - return 1 - - -class IntParameter(BayesParameter): - """A parameter with int values. - - Parameters - ---------- - name : str - The name of the parameter. - - bounds : tuple[int, int] - The bounds of the parameter. - """ - - def __init__(self, name: str, bounds: tuple[int, int]) -> None: - super().__init__(name, np.array(bounds)) - - @property - def is_continuous(self) -> bool: - """Whether the parameter is continuous.""" - return False - - def random_sample( - self, n_samples: int, random_state: np.random.RandomState | int | None - ) -> NDArray[Float]: - """Generate random samples from the parameter. - - Parameters - ---------- - n_samples : int - The number of samples to generate. - - random_state : np.random.RandomState | int | None - The random state to use for sampling. - - Returns - ------- - np.ndarray - The samples. - """ - random_state = ensure_rng(random_state) - return random_state.randint(self.bounds[0], self.bounds[1] + 1, n_samples).astype(float) - - def to_float(self, value: int | float) -> float: - """Convert a parameter value to a float. - - Parameters - ---------- - value : Any - The value to convert, should be the canonical representation of the parameter. - """ - return float(value) - - def to_param(self, value: int | float | NDArray[Int] | NDArray[Float]) -> int: - """Convert a float value to a parameter. - - Parameters - ---------- - value : np.ndarray - The value to convert, should be a float. - - Returns - ------- - Any - The canonical representation of the parameter. - """ - return int(np.round(np.squeeze(value))) - - def kernel_transform(self, value: NDArray[Float]) -> NDArray[Float]: - """Transform a parameter value for use in a kernel. - - Parameters - ---------- - value : np.ndarray - The value(s) to transform, should be a float. - - Returns - ------- - np.ndarray - """ - return np.round(value) - - @property - def dim(self) -> int: - """The dimensionality of the parameter.""" - return 1 - - -class CategoricalParameter(BayesParameter): - """A parameter with categorical values. - - Parameters - ---------- - name : str - The name of the parameter. - - categories : Sequence[Any] - The categories of the parameter. - """ - - def __init__(self, name: str, categories: Sequence[Any]) -> None: - if len(categories) != len(set(categories)): - msg = "Categories must be unique." - raise ValueError(msg) - if len(categories) < 2: - msg = "At least two categories are required." - raise ValueError(msg) - - self.categories = categories - lower = np.zeros(self.dim) - upper = np.ones(self.dim) - bounds = np.vstack((lower, upper)).T - super().__init__(name, bounds) - - @property - def is_continuous(self) -> bool: - """Whether the parameter is continuous.""" - return False - - def random_sample( - self, n_samples: int, random_state: np.random.RandomState | int | None - ) -> NDArray[Float]: - """Generate random float-format samples from the parameter. - - Parameters - ---------- - n_samples : int - The number of samples to generate. - - random_state : np.random.RandomState | int | None - The random state to use for sampling. - - Returns - ------- - np.ndarray - The samples. - """ - random_state = ensure_rng(random_state) - res = random_state.randint(0, len(self.categories), n_samples) - one_hot = np.zeros((n_samples, len(self.categories))) - one_hot[np.arange(n_samples), res] = 1 - return one_hot.astype(float) - - def to_float(self, value: Any) -> NDArray[Float]: - """Convert a parameter value to a float. - - Parameters - ---------- - value : Any - The value to convert, should be the canonical representation of the parameter. - """ - res = np.zeros(len(self.categories)) - one_hot_index = [i for i, val in enumerate(self.categories) if val == value] - res[one_hot_index] = 1 - return res.astype(float) - - def to_param(self, value: float | NDArray[Float]) -> Any: - """Convert a float value to a parameter. - - Parameters - ---------- - value : np.ndarray - The value to convert, should be a float. - - Returns - ------- - Any - The canonical representation of the parameter. - """ - return self.categories[int(np.argmax(value))] - - def to_string(self, value: Any, str_len: int) -> str: - """Represent a parameter value as a string. - - Parameters - ---------- - value : Any - The value to represent. - - str_len : int - The maximum length of the string representation. - - Returns - ------- - str - """ - if not isinstance(value, str): - value = repr(value) - s = f"{value:<{str_len}}" - - if len(s) > str_len: - return s[: str_len - 3] + "..." - return s - - def kernel_transform(self, value: NDArray[Float]) -> NDArray[Float]: - """Transform a parameter value for use in a kernel. - - Parameters - ---------- - value : np.ndarray - The value(s) to transform, should be a float. - - Returns - ------- - np.ndarray - """ - value = np.atleast_2d(value) - res = np.zeros(value.shape) - res[:, np.argmax(value, axis=1)] = 1 - return res - - @property - def dim(self) -> int: - """The dimensionality of the parameter.""" - return len(self.categories) - - -def wrap_kernel(kernel: kernels.Kernel, transform: Callable[[Any], Any]) -> kernels.Kernel: - """Wrap a kernel to transform input data before passing it to the kernel. - - Parameters - ---------- - kernel : kernels.Kernel - The kernel to wrap. - - transform : Callable - The transformation function to apply to the input data. - - Returns - ------- - kernels.Kernel - The wrapped kernel. - - Notes - ----- - See https://arxiv.org/abs/1805.03463 for more information. - """ - kernel_type = type(kernel) - - class WrappedKernel(kernel_type): - @_copy_signature(getattr(kernel_type.__init__, "deprecated_original", kernel_type.__init__)) - def __init__(self, **kwargs: Any) -> None: - super().__init__(**kwargs) - - def __call__(self, X: Any, Y: Any = None, eval_gradient: bool = False) -> Any: - X = transform(X) - Y = transform(Y) if Y is not None else None - return super().__call__(X, Y, eval_gradient) - - def __reduce__(self) -> str | tuple[Any, ...]: - return (wrap_kernel, (kernel, transform)) - - return WrappedKernel(**kernel.get_params()) - - -def _copy_signature(source_fct: Callable[..., Any]) -> Callable[[Callable[..., Any]], Callable[..., Any]]: - """Clone a signature from a source function to a target function. - - via - https://stackoverflow.com/a/58989918/ - """ - - def copy(target_fct: Callable[..., Any]) -> Callable[..., Any]: - target_fct.__signature__ = signature(source_fct) - return target_fct - - return copy diff --git a/bayes_opt/py.typed b/bayes_opt/py.typed deleted file mode 100644 index e69de29bb..000000000 diff --git a/bayes_opt/target_space.py b/bayes_opt/target_space.py deleted file mode 100644 index 39d1f9926..000000000 --- a/bayes_opt/target_space.py +++ /dev/null @@ -1,712 +0,0 @@ -"""Manages the optimization domain and holds points.""" - -from __future__ import annotations - -from copy import deepcopy -from typing import TYPE_CHECKING, Any -from warnings import warn - -import numpy as np -from colorama import Fore - -from bayes_opt.exception import NotUniqueError -from bayes_opt.parameter import BayesParameter, CategoricalParameter, FloatParameter, IntParameter, is_numeric -from bayes_opt.util import ensure_rng - -if TYPE_CHECKING: - from collections.abc import Callable, Mapping - - from numpy.random import RandomState - from numpy.typing import NDArray - - from bayes_opt.constraint import ConstraintModel - from bayes_opt.parameter import BoundsMapping, ParamsType - - Float = np.floating[Any] - Int = np.integer[Any] - - -def _hashable(x: NDArray[Float]) -> tuple[float, ...]: - """Ensure that a point is hashable by a python dict.""" - return tuple(map(float, x)) - - -class TargetSpace: - """Holds the param-space coordinates (X) and target values (Y). - - Allows for constant-time appends. - - Parameters - ---------- - target_func : function or None. - Function to be maximized. - - pbounds : dict - Dictionary with parameters names as keys and a tuple with minimum - and maximum values. - - random_state : int, RandomState, or None - optionally specify a seed for a random number generator - - allow_duplicate_points: bool, optional (default=False) - If True, the optimizer will allow duplicate points to be registered. - This behavior may be desired in high noise situations where repeatedly probing - the same point will give different answers. In other situations, the acquisition - may occasionally generate a duplicate point. - - Examples - -------- - >>> def target_func(p1, p2): - >>> return p1 + p2 - >>> pbounds = {"p1": (0, 1), "p2": (1, 100)} - >>> space = TargetSpace(target_func, pbounds, random_state=0) - >>> x = np.array([4, 5]) - >>> y = target_func(x) - >>> space.register(x, y) - >>> assert self.max()["target"] == 9 - >>> assert self.max()["params"] == {"p1": 1.0, "p2": 2.0} - """ - - def __init__( - self, - target_func: Callable[..., float] | None, - pbounds: BoundsMapping, - constraint: ConstraintModel | None = None, - random_state: int | RandomState | None = None, - allow_duplicate_points: bool | None = False, - ) -> None: - self.random_state = ensure_rng(random_state) - self._allow_duplicate_points = allow_duplicate_points or False - self.n_duplicate_points = 0 - - # The function to be optimized - self.target_func = target_func - - # Get the name of the parameters - self._keys: list[str] = list(pbounds.keys()) - - self._params_config = self.make_params(pbounds) - self._dim = sum([self._params_config[key].dim for key in self._keys]) - - self._masks = self.make_masks() - self._bounds = self.calculate_bounds() - - # preallocated memory for X and Y points - self._params: NDArray[Float] = np.empty(shape=(0, self.dim)) - self._target: NDArray[Float] = np.empty(shape=(0,)) - - # keep track of unique points we have seen so far - self._cache: dict[tuple[float, ...], float | tuple[float, float | NDArray[Float]]] = {} - - self._constraint: ConstraintModel | None = constraint - - if constraint is not None: - # preallocated memory for constraint fulfillment - self._constraint_values: NDArray[Float] - if constraint.lb.size == 1: - self._constraint_values = np.empty(shape=(0), dtype=float) - else: - self._constraint_values = np.empty(shape=(0, self._constraint.lb.size), dtype=float) - else: - self._constraint = None - - def __contains__(self, x: NDArray[Float]) -> bool: - """Check if this parameter has already been registered. - - Returns - ------- - bool - """ - return _hashable(x) in self._cache - - def __len__(self) -> int: - """Return number of observations registered. - - Returns - ------- - int - """ - return len(self._target) - - @property - def empty(self) -> bool: - """Check if anything has been registered. - - Returns - ------- - bool - """ - return len(self) == 0 - - @property - def params(self) -> NDArray[Float]: - """Get the parameter values registered to this TargetSpace. - - Returns - ------- - np.ndarray - """ - return self._params - - @property - def target(self) -> NDArray[Float]: - """Get the target function values registered to this TargetSpace. - - Returns - ------- - np.ndarray - """ - return self._target - - @property - def dim(self) -> int: - """Get the number of parameter names. - - Returns - ------- - int - """ - return self._dim - - @property - def keys(self) -> list[str]: - """Get the keys (or parameter names). - - Returns - ------- - list of str - """ - return self._keys - - @property - def params_config(self) -> dict[str, BayesParameter]: - """Get the parameters configuration.""" - return self._params_config - - @property - def bounds(self) -> NDArray[Float]: - """Get the bounds of this TargetSpace. - - Returns - ------- - np.ndarray - """ - return self._bounds - - @property - def constraint(self) -> ConstraintModel | None: - """Get the constraint model. - - Returns - ------- - ConstraintModel - """ - return self._constraint - - @property - def masks(self) -> dict[str, NDArray[np.bool_]]: - """Get the masks for the parameters. - - Returns - ------- - dict - """ - return self._masks - - @property - def continuous_dimensions(self) -> NDArray[np.bool_]: - """Get the continuous parameters. - - Returns - ------- - dict - """ - result = np.zeros(self.dim, dtype=bool) - masks = self.masks - for key in self.keys: - result[masks[key]] = self._params_config[key].is_continuous - return result - - def make_params(self, pbounds: BoundsMapping) -> dict[str, BayesParameter]: - """Create a dictionary of parameters from a dictionary of bounds. - - Parameters - ---------- - pbounds : dict - A dictionary with the parameter names as keys and a tuple with minimum - and maximum values. - - Returns - ------- - dict - A dictionary with the parameter names as keys and the corresponding - parameter objects as values. - """ - any_is_not_float = False # TODO: remove in an upcoming release - params: dict[str, BayesParameter] = {} - for key in pbounds: - pbound = pbounds[key] - - if isinstance(pbound, BayesParameter): - res = pbound - if not isinstance(pbound, FloatParameter): - any_is_not_float = True - elif (len(pbound) == 2 and is_numeric(pbound[0]) and is_numeric(pbound[1])) or ( - len(pbound) == 3 and pbound[-1] is float - ): - res = FloatParameter(name=key, bounds=(float(pbound[0]), float(pbound[1]))) - elif len(pbound) == 3 and pbound[-1] is int: - res = IntParameter(name=key, bounds=(int(pbound[0]), int(pbound[1]))) - any_is_not_float = True - else: - # assume categorical variable with pbound as list of possible values - res = CategoricalParameter(name=key, categories=pbound) - any_is_not_float = True - params[key] = res - if any_is_not_float: - msg = ( - "Non-float parameters are experimental and may not work as expected." - " Exercise caution when using them and please report any issues you encounter." - ) - warn(msg, stacklevel=4) - return params - - def make_masks(self) -> dict[str, NDArray[np.bool_]]: - """Create a dictionary of masks for the parameters. - - The mask can be used to select the corresponding parameters from an array. - - Returns - ------- - dict - A dictionary with the parameter names as keys and the corresponding - mask as values. - """ - masks = {} - pos = 0 - for key in self._keys: - mask = np.zeros(self._dim) - mask[pos : pos + self._params_config[key].dim] = 1 - masks[key] = mask.astype(bool) - pos = pos + self._params_config[key].dim - return masks - - def calculate_bounds(self) -> NDArray[Float]: - """Calculate the float bounds of the parameter space.""" - bounds = np.empty((self._dim, 2)) - for key in self._keys: - bounds[self.masks[key]] = self._params_config[key].bounds - return bounds - - def params_to_array(self, params: Mapping[str, float | NDArray[Float]]) -> NDArray[Float]: - """Convert a dict representation of parameters into an array version. - - Parameters - ---------- - params : dict - a single point, with len(x) == self.dim. - - Returns - ------- - np.ndarray - Representation of the parameters as an array. - """ - if set(params) != set(self.keys): - error_msg = ( - f"Parameters' keys ({params}) do " f"not match the expected set of keys ({self.keys})." - ) - raise ValueError(error_msg) - return self._to_float(params) - - @property - def constraint_values(self) -> NDArray[Float]: - """Get the constraint values registered to this TargetSpace. - - Returns - ------- - np.ndarray - """ - if self._constraint is None: - error_msg = "TargetSpace belongs to an unconstrained optimization" - raise AttributeError(error_msg) - - return self._constraint_values - - def kernel_transform(self, value: NDArray[Float]) -> NDArray[Float]: - """Transform floating-point suggestions to values used in the kernel. - - Vectorized. - """ - value = np.atleast_2d(value) - res = [self._params_config[p].kernel_transform(value[:, self.masks[p]]) for p in self._keys] - return np.hstack(res) - - def array_to_params(self, x: NDArray[Float]) -> dict[str, float | NDArray[Float]]: - """Convert an array representation of parameters into a dict version. - - Parameters - ---------- - x : np.ndarray - a single point, with len(x) == self.dim. - - Returns - ------- - dict - Representation of the parameters as dictionary. - """ - if len(x) != self._dim: - error_msg = ( - f"Size of array ({len(x)}) is different than the " - f"expected number of parameters ({self._dim})." - ) - raise ValueError(error_msg) - return self._to_params(x) - - def _to_float(self, value: Mapping[str, float | NDArray[Float]]) -> NDArray[Float]: - if set(value) != set(self.keys): - msg = f"Parameters' keys ({value}) do " f"not match the expected set of keys ({self.keys})." - raise ValueError(msg) - res = np.zeros(self._dim) - for key in self._keys: - p = self._params_config[key] - res[self.masks[key]] = p.to_float(value[key]) - return res - - def _to_params(self, value: NDArray[Float]) -> dict[str, float | NDArray[Float]]: - res: dict[str, float | NDArray[Float]] = {} - for key in self._keys: - p = self._params_config[key] - mask = self.masks[key] - res[key] = p.to_param(value[mask]) - return res - - @property - def mask(self) -> NDArray[np.bool_]: - """Return a boolean array of valid points. - - Points are valid if they satisfy both the constraint and boundary conditions. - - Returns - ------- - np.ndarray - """ - mask = np.ones_like(self.target, dtype=bool) - - # mask points that don't satisfy the constraint - if self._constraint is not None: - mask &= self._constraint.allowed(self._constraint_values) - - # mask points that are outside the bounds - if self._bounds is not None: - within_bounds = np.all( - (self._bounds[:, 0] <= self._params) & (self._params <= self._bounds[:, 1]), axis=1 - ) - mask &= within_bounds - - return mask - - def _as_array(self, x: Any) -> NDArray[Float]: - try: - x = np.asarray(x, dtype=float) - except TypeError: - x = self.params_to_array(x) - - x = x.ravel() - if x.size != self.dim: - msg = f"Size of array ({len(x)}) is different than the expected number of ({self.dim})." - raise ValueError(msg) - return x - - def register( - self, params: ParamsType, target: float, constraint_value: float | NDArray[Float] | None = None - ) -> None: - """Append a point and its target value to the known data. - - Parameters - ---------- - params : np.ndarray - a single point, with len(x) == self.dim. - - target : float - target function value - - constraint_value : float or np.ndarray or None - Constraint function value - - Raises - ------ - NotUniqueError: - if the point is not unique - - Notes - ----- - runs in amortized constant time - - Examples - -------- - >>> target_func = lambda p1, p2: p1 + p2 - >>> pbounds = {"p1": (0, 1), "p2": (1, 100)} - >>> space = TargetSpace(target_func, pbounds) - >>> len(space) - 0 - >>> x = np.array([0, 0]) - >>> y = 1 - >>> space.register(x, y) - >>> len(space) - 1 - """ - x = self._as_array(params) - - if x in self: - if self._allow_duplicate_points: - self.n_duplicate_points = self.n_duplicate_points + 1 - - print( - Fore.RED + f"Data point {x} is not unique. {self.n_duplicate_points}" - " duplicates registered. Continuing ..." + Fore.RESET - ) - else: - error_msg = ( - f"Data point {x} is not unique. You can set" - ' "allow_duplicate_points=True" to avoid this error' - ) - raise NotUniqueError(error_msg) - - # if x is not within the bounds of the parameter space, warn the user - if self._bounds is not None and not np.all((self._bounds[:, 0] <= x) & (x <= self._bounds[:, 1])): - for key in self.keys: - if not np.all( - (self._params_config[key].bounds[..., 0] <= x[self.masks[key]]) - & (x[self.masks[key]] <= self._params_config[key].bounds[..., 1]) - ): - msg = ( - f"\nData point {x} is outside the bounds of the parameter {key}." - f"\n\tBounds:\n{self._params_config[key].bounds}" - ) - warn(msg, stacklevel=2) - - # Make copies of the data, so as not to modify the originals incase something fails - # during the registration process. This prevents out-of-sync data. - params_copy: NDArray[Float] = np.concatenate([self._params, x.reshape(1, -1)]) - target_copy: NDArray[Float] = np.concatenate([self._target, [target]]) - cache_copy = self._cache.copy() # shallow copy suffices - - if self._constraint is None: - # Insert data into unique dictionary - cache_copy[_hashable(x.ravel())] = target - else: - if constraint_value is None: - msg = ( - "When registering a point to a constrained TargetSpace" - " a constraint value needs to be present." - ) - raise ValueError(msg) - # Insert data into unique dictionary - cache_copy[_hashable(x.ravel())] = (target, constraint_value) - constraint_values_copy: NDArray[Float] = np.concatenate( - [self._constraint_values, [constraint_value]] - ) - self._constraint_values = constraint_values_copy - - # Operations passed, update the variables - self._params = params_copy - self._target = target_copy - self._cache = cache_copy - - def probe(self, params: ParamsType) -> float | tuple[float, float | NDArray[Float]]: - """Evaluate the target function on a point and register the result. - - Notes - ----- - If `params` has been previously seen and duplicate points are not allowed, - returns a cached value of `result`. - - Parameters - ---------- - params : np.ndarray - a single point, with len(x) == self.dim - - Returns - ------- - result : float | Tuple(float, float) - target function value, or Tuple(target function value, constraint value) - - Example - ------- - >>> target_func = lambda p1, p2: p1 + p2 - >>> pbounds = {"p1": (0, 1), "p2": (1, 100)} - >>> space = TargetSpace(target_func, pbounds) - >>> space.probe([1, 5]) - >>> assert self.max()["target"] == 6 - >>> assert self.max()["params"] == {"p1": 1.0, "p2": 5.0} - """ - x = self._as_array(params) - if x in self and not self._allow_duplicate_points: - return self._cache[_hashable(x.ravel())] - - dict_params = self.array_to_params(x) - if self.target_func is None: - error_msg = "No target function has been provided." - raise ValueError(error_msg) - target = self.target_func(**dict_params) - - if self._constraint is None: - self.register(x, target) - return target - - constraint_value = self._constraint.eval(**dict_params) - self.register(x, target, constraint_value) - return target, constraint_value - - def random_sample( - self, n_samples: int = 0, random_state: np.random.RandomState | int | None = None - ) -> NDArray[Float]: - """ - Sample a random point from within the bounds of the space. - - Parameters - ---------- - n_samples : int, optional - Number of samples to draw. If 0, a single sample is drawn, - and a 1D array is returned. If n_samples > 0, an array of - shape (n_samples, dim) is returned. - - random_state : np.random.RandomState | int | None - The random state to use for sampling. - - Returns - ------- - data: ndarray - [1 x dim] array with dimensions corresponding to `self._keys` - - Examples - -------- - >>> target_func = lambda p1, p2: p1 + p2 - >>> pbounds = {"p1": (0, 1), "p2": (1, 100)} - >>> space = TargetSpace(target_func, pbounds, random_state=0) - >>> space.random_sample() - array([[ 0.54488318, 55.33253689]]) - """ - random_state = ensure_rng(random_state) - flatten = n_samples == 0 - n_samples = max(1, n_samples) - data = np.empty((n_samples, self._dim)) - for key, mask in self.masks.items(): - smpl = self._params_config[key].random_sample(n_samples, random_state) - data[:, mask] = smpl.reshape(n_samples, self._params_config[key].dim) - if flatten: - return data.ravel() - return data - - def _target_max(self) -> float | None: - """Get the maximum target value within the current parameter bounds. - - If there is a constraint present, the maximum value that fulfills the - constraint within the parameter bounds is returned. - - Returns - ------- - max: float - The maximum target value. - """ - if len(self.target) == 0: - return None - - if len(self.target[self.mask]) == 0: - return None - - return self.target[self.mask].max() - - def max(self) -> dict[str, Any] | None: - """Get maximum target value found and corresponding parameters. - - If there is a constraint present, the maximum value that fulfills the - constraint within the parameter bounds is returned. - - Returns - ------- - res: dict - A dictionary with the keys 'target' and 'params'. The value of - 'target' is the maximum target value, and the value of 'params' is - a dictionary with the parameter names as keys and the parameter - values as values. - """ - target_max = self._target_max() - if target_max is None: - return None - - target = self.target[self.mask] - params = self.params[self.mask] - target_max_idx = np.argmax(target) - - res = {"target": target_max, "params": dict(zip(self.keys, params[target_max_idx]))} - - if self._constraint is not None: - constraint_values = self.constraint_values[self.mask] - res["constraint"] = constraint_values[target_max_idx] - - return res - - def res(self) -> list[dict[str, Any]]: - """Get all target values and constraint fulfillment for all parameters. - - Returns - ------- - res: list - A list of dictionaries with the keys 'target', 'params', and - 'constraint'. The value of 'target' is the target value, the value - of 'params' is a dictionary with the parameter names as keys and the - parameter values as values, and the value of 'constraint' is the - constraint fulfillment. - - Notes - ----- - Does not report if points are within the bounds of the parameter space. - """ - if self._constraint is None: - params = [self.array_to_params(p) for p in self.params] - - return [{"target": target, "params": param} for target, param in zip(self.target, params)] - - params = [dict(zip(self.keys, p)) for p in self.params] - - return [ - {"target": target, "constraint": constraint_value, "params": param, "allowed": allowed} - for target, constraint_value, param, allowed in zip( - self.target, - self._constraint_values, - params, - self._constraint.allowed(self._constraint_values), - ) - ] - - def set_bounds(self, new_bounds: BoundsMapping) -> None: - """Change the lower and upper search bounds. - - Parameters - ---------- - new_bounds : dict - A dictionary with the parameter name and its new bounds - """ - new_params_config = self.make_params(new_bounds) - - dims = 0 - params_config = deepcopy(self._params_config) - for key in self.keys: - if key in new_bounds: - if not isinstance(new_params_config[key], type(self._params_config[key])): - msg = ( - f"Parameter type {type(new_params_config[key])} of" - " new bounds does not match parameter type" - f" {type(self._params_config[key])} of old bounds" - ) - raise ValueError(msg) - params_config[key] = new_params_config[key] - dims = dims + params_config[key].dim - if dims != self.dim: - msg = ( - f"Dimensions of new bounds ({dims}) does not match" f" dimensions of old bounds ({self.dim})." - ) - raise ValueError(msg) - self._params_config = params_config - self._bounds = self.calculate_bounds() diff --git a/bayes_opt/util.py b/bayes_opt/util.py deleted file mode 100644 index 2795ca07a..000000000 --- a/bayes_opt/util.py +++ /dev/null @@ -1,84 +0,0 @@ -"""Contains utility functions.""" - -from __future__ import annotations - -import json -from os import PathLike -from pathlib import Path -from typing import TYPE_CHECKING - -import numpy as np - -from bayes_opt.exception import NotUniqueError - -if TYPE_CHECKING: - from collections.abc import Iterable - - from bayes_opt.bayesian_optimization import BayesianOptimization - - -def load_logs( - optimizer: BayesianOptimization, logs: str | PathLike[str] | Iterable[str | PathLike[str]] -) -> BayesianOptimization: - """Load previous ... - - Parameters - ---------- - optimizer : BayesianOptimizer - Optimizer the register the previous observations with. - - logs : str or os.PathLike - File to load the logs from. - - Returns - ------- - The optimizer with the state loaded. - - """ - if isinstance(logs, (str, PathLike)): - logs = [logs] - - for log in logs: - with Path(log).open("r") as j: - while True: - try: - iteration = next(j) - except StopIteration: - break - - iteration = json.loads(iteration) - try: - optimizer.register( - params=iteration["params"], - target=iteration["target"], - constraint_value=(iteration["constraint"] if optimizer.is_constrained else None), - ) - except NotUniqueError: - continue - - return optimizer - - -def ensure_rng(random_state: int | np.random.RandomState | None = None) -> np.random.RandomState: - """Create a random number generator based on an optional seed. - - Parameters - ---------- - random_state : np.random.RandomState or int or None, default=None - Random state to use. if `None`, will create an unseeded random state. - If `int`, creates a state using the argument as seed. If a - `np.random.RandomState` simply returns the argument. - - Returns - ------- - np.random.RandomState - - """ - if random_state is None: - random_state = np.random.RandomState() - elif isinstance(random_state, int): - random_state = np.random.RandomState(random_state) - elif not isinstance(random_state, np.random.RandomState): - error_msg = "random_state should be an instance of np.random.RandomState, an int, or None." - raise TypeError(error_msg) - return random_state diff --git a/docsrc/Makefile b/docsrc/Makefile deleted file mode 100644 index 0e926ff11..000000000 --- a/docsrc/Makefile +++ /dev/null @@ -1,26 +0,0 @@ -# Minimal makefile for Sphinx documentation -# - -# You can set these variables from the command line, and also -# from the environment for the first two. -SPHINXOPTS ?= -SPHINXBUILD ?= sphinx-build -SOURCEDIR = . -BUILDDIR = ../docs - -# Put it first so that "make" without argument is like "make help". -# help: -# @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) - -.PHONY: help Makefile - -github: -# @cp ../README.md . - @make html - @cp -a ../docs/html/. ../docs - @cp -r ../docsrc/ ../docs - -# Catch-all target: route all unknown targets to Sphinx using the new -# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS). -%: Makefile - @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) \ No newline at end of file diff --git a/docsrc/conf.py b/docsrc/conf.py deleted file mode 100644 index 99d447796..000000000 --- a/docsrc/conf.py +++ /dev/null @@ -1,203 +0,0 @@ -# Configuration file for the Sphinx documentation builder. -# -# This file only contains a selection of the most common options. For a full -# list see the documentation: -# https://www.sphinx-doc.org/en/master/usage/configuration.html - -# -- Path setup -------------------------------------------------------------- - -# If extensions (or modules to document with autodoc) are in another directory, -# add these directories to sys.path here. If the directory is relative to the -# documentation root, use os.path.abspath to make it absolute, like shown here. -# -import os -import sys -import time -import shutil -from glob import glob -from pathlib import Path -# sys.path.insert(0, os.path.abspath('.')) -sys.path.insert(0, os.path.abspath('..')) - -# copy the latest example files: -this_file_loc = Path(__file__).parent -notebooks = glob(str(this_file_loc.parent / 'examples' / '*.ipynb')) -for notebook in notebooks: - shutil.copy(notebook, this_file_loc) - - -# -- Project information ----------------------------------------------------- - -project = 'bayesian-optimization' -author = 'Fernando Nogueira' - - -# -- General configuration --------------------------------------------------- - -# Add any Sphinx extension module names here, as strings. They can be -# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom -# ones. -extensions = [ - 'sphinx.ext.autodoc', - 'sphinx.ext.coverage', - 'sphinx.ext.githubpages', - 'nbsphinx', - 'IPython.sphinxext.ipython_console_highlighting', - 'sphinx.ext.mathjax', - "sphinx.ext.napoleon", - 'sphinx_autodoc_typehints', - 'sphinx.ext.intersphinx', - 'sphinx_immaterial', -] - -source_suffix = { - '.rst': 'restructuredtext', -} -# Add any paths that contain templates here, relative to this directory. -templates_path = ['_templates'] - -# List of patterns, relative to source directory, that match files and -# directories to ignore when looking for source files. -# This pattern also affects html_static_path and html_extra_path. -exclude_patterns = [] - -# Link types to the corresponding documentations -intersphinx_mapping = { - 'python': ('https://docs.python.org/3', None), - 'numpy': ('https://numpy.org/doc/stable', None), - 'scipy': ('https://docs.scipy.org/doc/scipy/reference', None), - 'sklearn': ('https://scikit-learn.org/stable', None), -} - - -napoleon_use_rtype = False - -# -- Options for HTML output ------------------------------------------------- - -# The theme to use for HTML and HTML Help pages. See the documentation for -# a list of builtin themes. -# - -html_title = "Bayesian Optimization" -html_theme = "sphinx_immaterial" -copyright = f"{time.strftime('%Y')}, Fernando Nogueira and the bayesian-optimization developers" - -# material theme options (see theme.conf for more information) -html_theme_options = { - "icon": { - "repo": "fontawesome/brands/github", - "edit": "material/file-edit-outline", - }, - "site_url": "https://bayesian-optimization.github.io/BayesianOptimization/", - "repo_url": "https://github.com/bayesian-optimization/BayesianOptimization/", - "repo_name": "bayesian-optimization", - "edit_uri": "blob/master/docsrc", - "globaltoc_collapse": True, - "features": [ - "navigation.expand", - # "navigation.tabs", - # "toc.integrate", - "navigation.sections", - # "navigation.instant", - # "header.autohide", - "navigation.top", - # "navigation.tracking", - # "search.highlight", - "search.share", - "toc.follow", - "toc.sticky", - "content.tabs.link", - "announce.dismiss", - ], - "palette": [ - { - "media": "(prefers-color-scheme: light)", - "scheme": "default", - "primary": "light-blue", - "accent": "light-green", - "toggle": { - "icon": "material/lightbulb-outline", - "name": "Switch to dark mode", - }, - }, - { - "media": "(prefers-color-scheme: dark)", - "scheme": "slate", - "primary": "deep-orange", - "accent": "lime", - "toggle": { - "icon": "material/lightbulb", - "name": "Switch to light mode", - }, - }, - ], - # BEGIN: version_dropdown - "version_dropdown": True, - "version_json": '../versions.json', - # END: version_dropdown - "scope": "/", # share preferences across subsites - "toc_title_is_page_title": True, - # BEGIN: social icons - "social": [ - { - "icon": "fontawesome/brands/github", - "link": "https://github.com/bayesian-optimization/BayesianOptimization", - "name": "Source on github.com", - }, - { - "icon": "fontawesome/brands/python", - "link": "https://pypi.org/project/bayesian-optimization/", - }, - { - "icon": "fontawesome/brands/python", - "link": "https://anaconda.org/conda-forge/bayesian-optimization", - } - ], - # END: social icons -} - -html_favicon = 'func.ico' - -# Add any paths that contain custom static files (such as style sheets) here, -# relative to this directory. They are copied after the builtin static files, -# so a file named "default.css" will overwrite the builtin "default.css". -# html_static_path = ['_static'] - -## extensions configuration -### sphinx-autodoc-typehints -typehints_use_signature = True -""" -If True, typehints for parameters in the signature are shown. - -see more: https://github.com/tox-dev/sphinx-autodoc-typehints/blob/main/README.md#options -""" -typehints_use_signature_return = True -""" -If True, return annotations in the signature are shown. - -see more: https://github.com/tox-dev/sphinx-autodoc-typehints/blob/main/README.md#options -""" -### autodoc -autodoc_typehints = "both" -""" -This value controls how to represent typehints. The setting takes the following values: - - `signature`: Show typehints in the signature - - `description`: Show typehints as content of the function or method - The typehints of overloaded functions or methods will still be represented in the signature. - - `none`: Do not show typehints - - `both`: Show typehints in the signature and as content of the function or method - -Overloaded functions or methods will not have typehints included in the description -because it is impossible to accurately represent all possible overloads as a list of parameters. - -see more: https://www.sphinx-doc.org/en/master/usage/extensions/autodoc.html#confval-autodoc_typehints -""" -autodoc_typehints_format = "short" -""" -This value controls the format of typehints. The setting takes the following values: - - `fully-qualified`: Show the module name and its name of typehints - - `short`: Suppress the leading module names of the typehints - (e.g. io.StringIO -> StringIO) - -see more: https://www.sphinx-doc.org/en/master/usage/extensions/autodoc.html#confval-autodoc_typehints_format -""" diff --git a/docsrc/func.ico b/docsrc/func.ico deleted file mode 100644 index f294702610b6d5db3f5c55d0e2b71ea6ec497bc5..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 136207 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 aZ - -.. toctree:: - :hidden: - :maxdepth: 3 - :caption: Example Notebooks: - - Basic Tour - Advanced Tour - Constrained Bayesian Optimization - Parameter Types - Sequential Domain Reduction - Acquisition Functions - Exploration vs. Exploitation - Visualization of a 1D-Optimization - -.. toctree:: - :hidden: - :maxdepth: 2 - :caption: API reference: - - reference/bayes_opt - reference/acquisition - reference/constraint - reference/domain_reduction - reference/target_space - reference/parameter - reference/exception - reference/other - -.. raw:: html - -
-

-
- -Bayesian Optimization -===================== - -|tests| |Codecov| |Pypi| |PyPI - Python Version| - -Pure Python implementation of bayesian global optimization with gaussian -processes. - -This is a constrained global optimization package built upon bayesian -inference and gaussian processes, that attempts to find the maximum value -of an unknown function in as few iterations as possible. This technique -is particularly suited for optimization of high cost functions and -situations where the balance between exploration and exploitation is -important. - -Installation ------------- - -pip (via PyPI) -~~~~~~~~~~~~~~ - -.. code:: console - - $ pip install bayesian-optimization - -Conda (via conda-forge) -~~~~~~~~~~~~~~~~~~~~~~~ - -.. code:: console - - $ conda install -c conda-forge bayesian-optimization - -How does it work? ------------------ - -Bayesian optimization works by constructing a posterior distribution of -functions (gaussian process) that best describes the function you want -to optimize. As the number of observations grows, the posterior -distribution improves, and the algorithm becomes more certain of which -regions in parameter space are worth exploring and which are not, as -seen in the picture below. - -.. image:: ./static/bo_example.png - :alt: BayesianOptimization in action - -As you iterate over and over, the algorithm balances its needs of -exploration and exploitation taking into account what it knows about the -target function. At each step a Gaussian Process is fitted to the known -samples (points previously explored), and the posterior distribution, -combined with a exploration strategy (such as UCB (Upper Confidence -Bound), or EI (Expected Improvement)), are used to determine the next -point that should be explored (see the gif below). - -.. image:: ./static/bayesian_optimization.gif - :alt: BayesianOptimization in action - -This process is designed to minimize the number of steps required to -find a combination of parameters that are close to the optimal -combination. To do so, this method uses a proxy optimization problem -(finding the maximum of the acquisition function) that, albeit still a -hard problem, is cheaper (in the computational sense) and common tools -can be employed. Therefore Bayesian Optimization is most adequate for -situations where sampling the function to be optimized is a very -expensive endeavor. See the references for a proper discussion of this -method. - -This project is under active development, if you find a bug, or anything -that needs correction, please let us know by filing an -`issue on GitHub `__ -. - - -Quick Index ------------ - -See below for a quick tour over the basics of the Bayesian Optimization -package. More detailed information, other advanced features, and tips on -usage/implementation can be found in the -`examples `__ -section. We suggest that you: - -- Follow the `basic tour - notebook `__ - to learn how to use the package's most important features. -- Take a look at the `advanced tour - notebook `__ - to learn how to make the package more flexible or how to use observers. -- To learn more about acquisition functions, a central building block - of bayesian optimization, see the `acquisition functions - notebook `__ -- If you want to optimize over integer-valued or categorical - parameters, see the `parameter types - notebook `__. -- Check out this - `notebook `__ - with a step by step visualization of how this method works. -- To understand how to use bayesian optimization when additional - constraints are present, see the `constrained optimization - notebook `__. -- Explore the `domain reduction - notebook `__ - to learn more about how search can be sped up by dynamically changing - parameters' bounds. -- Explore this - `notebook `__ - exemplifying the balance between exploration and exploitation and how - to control it. -- Go over this - `script `__ - for examples of how to tune parameters of Machine Learning models - using cross validation and bayesian optimization. -- Finally, take a look at this - `script `__ - for ideas on how to implement bayesian optimization in a distributed - fashion using this package. - - -Citation --------- - -If you used this package in your research, please cite it: - -:: - - @Misc{, - author={Fernando Nogueira}, - title={{Bayesian Optimization}: Open source constrained global optimization tool for {Python}}, - year={2014--}, - url="https://github.com/bayesian-optimization/BayesianOptimization" - } - -If you used any of the advanced functionalities, please additionally -cite the corresponding publication: - -For the ``SequentialDomainTransformer``: - -:: - - @article{ - author={Stander, Nielen and Craig, Kenneth}, - year={2002}, - month={06}, - pages={}, - title={On the robustness of a simple domain reduction scheme for simulation-based optimization}, - volume={19}, - journal={International Journal for Computer-Aided Engineering and Software (Eng. Comput.)}, - doi={10.1108/02644400210430190} - } - -For constrained optimization: - -:: - - @inproceedings{gardner2014bayesian, - title={Bayesian optimization with inequality constraints.}, - author={Gardner, Jacob R and Kusner, Matt J and Xu, Zhixiang Eddie and Weinberger, Kilian Q and Cunningham, John P}, - booktitle={ICML}, - volume={2014}, - pages={937--945}, - year={2014} - } - -For optimization over non-float parameters: - -:: - - @article{garrido2020dealing, - title={Dealing with categorical and integer-valued variables in bayesian optimization with gaussian processes}, - author={Garrido-Merch{\'a}n, Eduardo C and Hern{\'a}ndez-Lobato, Daniel}, - journal={Neurocomputing}, - volume={380}, - pages={20--35}, - year={2020}, - publisher={Elsevier} - } - -.. |tests| image:: https://github.com/bayesian-optimization/BayesianOptimization/actions/workflows/run_tests.yml/badge.svg -.. |Codecov| image:: https://codecov.io/github/bayesian-optimization/BayesianOptimization/badge.svg?branch=master&service=github - :target: https://codecov.io/github/bayesian-optimization/BayesianOptimization?branch=master -.. |Pypi| image:: https://img.shields.io/pypi/v/bayesian-optimization.svg - :target: https://pypi.python.org/pypi/bayesian-optimization -.. |PyPI - Python Version| image:: https://img.shields.io/pypi/pyversions/bayesian-optimization - diff --git a/docsrc/make.bat b/docsrc/make.bat deleted file mode 100644 index 654955e7e..000000000 --- a/docsrc/make.bat +++ /dev/null @@ -1,44 +0,0 @@ -@ECHO OFF - -pushd %~dp0 - -REM Command file for Sphinx documentation - -if "%SPHINXBUILD%" == "" ( - set SPHINXBUILD=sphinx-build -) -set SOURCEDIR=. -set BUILDDIR=../docs - -%SPHINXBUILD% >NUL 2>NUL -if errorlevel 9009 ( - echo. - echo.The 'sphinx-build' command was not found. Make sure you have Sphinx - echo.installed, then set the SPHINXBUILD environment variable to point - echo.to the full path of the 'sphinx-build' executable. Alternatively you - echo.may add the Sphinx directory to PATH. - echo. - echo.If you don't have Sphinx installed, grab it from - echo.https://www.sphinx-doc.org/ - exit /b 1 -) - -if "%1" == "" goto help - -if "%1" == "github" ( - %SPHINXBUILD% -M html %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% - robocopy %BUILDDIR%/html ../docs /E > nul - echo.Generated files copied to ../docs - goto end -) - - -%SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O% -goto end - - -:help -%SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O% - -:end -popd \ No newline at end of file diff --git a/docsrc/reference/acquisition.rst b/docsrc/reference/acquisition.rst deleted file mode 100644 index aa3485af4..000000000 --- a/docsrc/reference/acquisition.rst +++ /dev/null @@ -1,14 +0,0 @@ -:py:mod:`bayes_opt.acquisition` -------------------------------- - -.. automodule:: bayes_opt.acquisition - :members: AcquisitionFunction - -.. toctree:: - :hidden: - - acquisition/UpperConfidenceBound - acquisition/ProbabilityOfImprovement - acquisition/ExpectedImprovement - acquisition/GPHedge - acquisition/ConstantLiar diff --git a/docsrc/reference/acquisition/ConstantLiar.rst b/docsrc/reference/acquisition/ConstantLiar.rst deleted file mode 100644 index 1e7e4d901..000000000 --- a/docsrc/reference/acquisition/ConstantLiar.rst +++ /dev/null @@ -1,5 +0,0 @@ -:py:class:`bayes_opt.acquisition.ConstantLiar` ----------------------------------------------- - -.. autoclass:: bayes_opt.acquisition.ConstantLiar - :members: diff --git a/docsrc/reference/acquisition/ExpectedImprovement.rst b/docsrc/reference/acquisition/ExpectedImprovement.rst deleted file mode 100644 index ad606c8b9..000000000 --- a/docsrc/reference/acquisition/ExpectedImprovement.rst +++ /dev/null @@ -1,5 +0,0 @@ -:py:class:`bayes_opt.acquisition.ExpectedImprovement` ------------------------------------------------------ - -.. autoclass:: bayes_opt.acquisition.ExpectedImprovement - :members: diff --git a/docsrc/reference/acquisition/GPHedge.rst b/docsrc/reference/acquisition/GPHedge.rst deleted file mode 100644 index 8b4428d52..000000000 --- a/docsrc/reference/acquisition/GPHedge.rst +++ /dev/null @@ -1,5 +0,0 @@ -:py:class:`bayes_opt.acquisition.GPHedge` ------------------------------------------ - -.. autoclass:: bayes_opt.acquisition.GPHedge - :members: diff --git a/docsrc/reference/acquisition/ProbabilityOfImprovement.rst b/docsrc/reference/acquisition/ProbabilityOfImprovement.rst deleted file mode 100644 index fe59b54ea..000000000 --- a/docsrc/reference/acquisition/ProbabilityOfImprovement.rst +++ /dev/null @@ -1,5 +0,0 @@ -:py:class:`bayes_opt.acquisition.ProbabilityOfImprovement` ----------------------------------------------------------- - -.. autoclass:: bayes_opt.acquisition.ProbabilityOfImprovement - :members: diff --git a/docsrc/reference/acquisition/UpperConfidenceBound.rst b/docsrc/reference/acquisition/UpperConfidenceBound.rst deleted file mode 100644 index 46a08ad92..000000000 --- a/docsrc/reference/acquisition/UpperConfidenceBound.rst +++ /dev/null @@ -1,5 +0,0 @@ -:py:class:`bayes_opt.acquisition.UpperConfidenceBound` ------------------------------------------------------- - -.. autoclass:: bayes_opt.acquisition.UpperConfidenceBound - :members: diff --git a/docsrc/reference/bayes_opt.rst b/docsrc/reference/bayes_opt.rst deleted file mode 100644 index 54480284f..000000000 --- a/docsrc/reference/bayes_opt.rst +++ /dev/null @@ -1,5 +0,0 @@ -:py:class:`bayes_opt.BayesianOptimization` ------------------------------------------- - -.. autoclass:: bayes_opt.BayesianOptimization - :members: diff --git a/docsrc/reference/constraint.rst b/docsrc/reference/constraint.rst deleted file mode 100644 index 64239fa78..000000000 --- a/docsrc/reference/constraint.rst +++ /dev/null @@ -1,7 +0,0 @@ -:py:class:`bayes_opt.ConstraintModel` ------------------------------------------------- - -See the `Constrained Optimization notebook <../constraints.html#2.-Advanced-Constrained-Optimization>`__ for a complete example. - -.. autoclass:: bayes_opt.constraint.ConstraintModel - :members: diff --git a/docsrc/reference/domain_reduction.rst b/docsrc/reference/domain_reduction.rst deleted file mode 100644 index cd7524d04..000000000 --- a/docsrc/reference/domain_reduction.rst +++ /dev/null @@ -1,7 +0,0 @@ -:py:class:`bayes_opt.SequentialDomainReductionTransformer` ----------------------------------------------------------- - -See the `Sequential Domain Reduction notebook <../domain_reduction.html>`__ for a complete example. - -.. autoclass:: bayes_opt.SequentialDomainReductionTransformer - :members: \ No newline at end of file diff --git a/docsrc/reference/exception.rst b/docsrc/reference/exception.rst deleted file mode 100644 index 9315628c9..000000000 --- a/docsrc/reference/exception.rst +++ /dev/null @@ -1,5 +0,0 @@ -:py:mod:`bayes_opt.exception` -------------------------------- - -.. automodule:: bayes_opt.exception - :members: diff --git a/docsrc/reference/other.rst b/docsrc/reference/other.rst deleted file mode 100644 index 22836cfd6..000000000 --- a/docsrc/reference/other.rst +++ /dev/null @@ -1,11 +0,0 @@ -Other ------ - -.. autoclass:: bayes_opt.ScreenLogger - :members: - -.. autoclass:: bayes_opt.JSONLogger - :members: - -.. autoclass:: bayes_opt.Events - :members: diff --git a/docsrc/reference/parameter.rst b/docsrc/reference/parameter.rst deleted file mode 100644 index 91b8f2e9a..000000000 --- a/docsrc/reference/parameter.rst +++ /dev/null @@ -1,5 +0,0 @@ -:py:mod:`bayes_opt.parameter` --------------------------------- - -.. automodule:: bayes_opt.parameter - :members: diff --git a/docsrc/reference/target_space.rst b/docsrc/reference/target_space.rst deleted file mode 100644 index 38f654467..000000000 --- a/docsrc/reference/target_space.rst +++ /dev/null @@ -1,5 +0,0 @@ -:py:class:`bayes_opt.TargetSpace` ---------------------------------- - -.. autoclass:: bayes_opt.TargetSpace - :members: diff --git a/docsrc/requirements.txt b/docsrc/requirements.txt deleted file mode 100644 index 23628a910..000000000 --- a/docsrc/requirements.txt +++ /dev/null @@ -1,3 +0,0 @@ -sphinx -nbsphinx -sphinx_rtd_theme \ No newline at end of file diff --git a/docsrc/static/bayesian_optimization.gif b/docsrc/static/bayesian_optimization.gif deleted file mode 100644 index e75ace7c4d76edd33be73fd099bbf19f2e1771f7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 16351229 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

ZsXfM5uQ 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