Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

Feature/refactor for reduced complexity #11

Closed
wants to merge 255 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
255 commits
Select commit Hold shift + click to select a range
be9c2f6
code refactoring, goytorch integration, 1D example
Mar 24, 2020
fb62778
Merge pull request #1 from irinaespejo/refactor
Mar 24, 2020
d42a48b
2D working example gpytorch
Mar 30, 2020
2fd84f8
2D working example gpytorch
Mar 30, 2020
d3bdb52
Merge pull request #2 from irinaespejo/refactor
Mar 30, 2020
10a7d04
2D working example gpytorch
Mar 30, 2020
6991a5d
Merge pull request #3 from irinaespejo/refactor
Mar 30, 2020
7a97030
adding MES
Apr 6, 2020
7ad2ec5
Merge branch 'master' of https://github.com/irinaespejo/excursion
Apr 6, 2020
5ef5c07
Merge pull request #4 from irinaespejo/refactor
Apr 6, 2020
9845c3b
add pic
Apr 6, 2020
ab2f201
Merge branch 'master' of https://github.com/irinaespejo/excursion
Apr 6, 2020
214aada
add pic
Apr 6, 2020
b6b0123
add pic
Apr 6, 2020
f8bd688
add pic
Apr 6, 2020
9ab8468
add pic
Apr 7, 2020
64db51e
add gifs
Apr 8, 2020
53a84bc
new features
Apr 18, 2020
7a657cd
starting to make changes
Apr 21, 2020
b1937e0
reorganization in a ExcursionSetEstimation class
Apr 25, 2020
9a5ddf9
working refactory all dimensions toy examples
Apr 27, 2020
80b2918
Merge pull request #5 from irinaespejo/refactor
Apr 28, 2020
9bde66a
up to date
Apr 28, 2020
372da4a
Merge pull request #6 from irinaespejo/refactor
Apr 28, 2020
a9c21a3
introduced GridKernelRegression
May 3, 2020
b4516cf
introduced GridKernelRegression
May 3, 2020
e14b5a7
Merge pull request #7 from irinaespejo/refactor
May 3, 2020
62c0be2
CUDA device agnostic implementation
May 7, 2020
9071e89
Merge pull request #8 from irinaespejo/refactor
May 7, 2020
e568c04
fix minor argparse bug
May 10, 2020
02369c4
Merge pull request #9 from irinaespejo/refactor
May 10, 2020
749a40a
Saving CUDA progress before major CUDA refactor to make code device a…
May 22, 2020
a4dd93a
device agnostic implementation; tested on HPC GPUs
May 24, 2020
6c8161f
black code format
May 25, 2020
af0bd94
modify .gitignore include python+jupyternotebook
May 25, 2020
4b48579
.gitignore is now working
May 25, 2020
cd2409a
Merge pull request #10 from irinaespejo/gpu
May 25, 2020
51beedf
working lineal prior; need to fix hardcoded bits
Jun 2, 2020
0fa8fb9
working linear prior; GPU test still left
Jun 3, 2020
7f6c7f1
modify gitignore include testing folders
Jun 3, 2020
8aed160
changes
Jun 3, 2020
3ccb45f
eliminate click
Jun 4, 2020
4eee5ed
ignore results from developing
Jun 4, 2020
abd362d
ignore results from developing
Jun 4, 2020
02b8c0a
ignore results from developing
Jun 4, 2020
1ddedb4
solve merge conflicts, give preference to GPU features except in the …
Jun 5, 2020
d016711
solved conflict
Jun 5, 2020
8991b9a
Circular prior introduced
Jul 12, 2020
0af5dad
Black formatting
Jul 12, 2020
eee83d0
Merge pull request #12 from irinaespejo/developer
Jul 12, 2020
5c6a155
cleaning up results from testing
Jul 15, 2020
3ce0701
Merge pull request #13 from irinaespejo/cleanup
Jul 15, 2020
4bd72e6
working 3D testcase; still left GPU test
Jul 20, 2020
3afffc0
3D testcase complete
Jul 23, 2020
38f3466
small fix to accomodate plotting in HPC
Jul 26, 2020
38811a1
more .to(gpu) where forgotten
Aug 20, 2020
028c445
implementing CI + one test via pytest
Aug 25, 2020
8de0e18
travis
Aug 25, 2020
c308ab4
travis
Aug 25, 2020
86fafb4
Update README.md
Aug 25, 2020
f2fdef4
add .txt
Aug 26, 2020
067b96c
Merge branch 'testcase-3D' of https://github.com/irinaespejo/excursio…
Aug 26, 2020
cda0d42
typos
Aug 26, 2020
d221be9
typos
Aug 26, 2020
e597f27
requiriments
Aug 26, 2020
c2886e4
typos
Aug 26, 2020
0bfe348
fic pip installation
Aug 26, 2020
9bebe24
typos
Aug 26, 2020
b22b2e0
changed requirements
Sep 4, 2020
4229719
more
Sep 4, 2020
890d23b
fix travis
Sep 4, 2020
1efa0fc
travis
Sep 4, 2020
aa89747
travis
Sep 4, 2020
acc6545
travis
Sep 4, 2020
e10f7ae
small bug fix dimension independent
Sep 4, 2020
91c48dd
small bug fix
Sep 4, 2020
d7c9f79
travis
Sep 4, 2020
1c47b25
travis
Sep 4, 2020
1a04562
travis
Sep 4, 2020
41d8355
travis
Sep 4, 2020
41b8e8f
travis
Sep 4, 2020
6dbec32
travis
Sep 4, 2020
26b38ac
travis
Sep 5, 2020
c98d7ac
travis
Sep 5, 2020
adb1451
travis
Sep 5, 2020
fff5266
pytest passes
Sep 5, 2020
91ec582
Merge pull request #14 from irinaespejo/testcase-3D
Sep 5, 2020
02777dd
coverage
Sep 5, 2020
4642621
Update README.md
Sep 5, 2020
5d3f029
black
Sep 5, 2020
49e1f58
Update README.md
Sep 5, 2020
1882e42
Update README.md
Sep 5, 2020
d26c6b5
Merge branch 'master' of https://github.com/irinaespejo/excursion
Sep 5, 2020
492d3a0
added more tests including a full one
Sep 5, 2020
d4eba13
Merge pull request #15 from irinaespejo/testing
Sep 5, 2020
2d98276
Merge branch 'master' of https://github.com/irinaespejo/excursion
Sep 5, 2020
a5348b2
naive batch implemented
Sep 7, 2020
719024e
KB batches working for 2D but not 1D
Sep 7, 2020
acdd189
KB, Naive and No batch working for all examples
Sep 7, 2020
4325a54
remove testing
Sep 8, 2020
43260e0
Update README.md
Sep 22, 2020
792ee73
Update README.md
Sep 22, 2020
bab06bd
algorithm for batches trapped in infinite loop, solved, argmax wrong …
Sep 23, 2020
596471a
left to do better plot
Sep 26, 2020
4c7a7a1
solved weird bug 1D .diag() in batches
Sep 29, 2020
f14c00b
solved smooth acq
Oct 1, 2020
6108953
solved some bugs
Oct 1, 2020
9ee45a7
solved issues
Oct 8, 2020
f67b0a2
ready to merge in master: all good with non-batch
Oct 13, 2020
8177014
solving bugs in testing travis
Oct 13, 2020
46f0f3e
more travis testing added for 2 and 3 dimensions
Oct 13, 2020
a3ae00e
Merge pull request #16 from irinaespejo/batches
Oct 13, 2020
7addb84
introduced more batch testing, all good, ready to merge
Oct 15, 2020
360aa53
forgot to upload algorithm specs for testing cases
Oct 15, 2020
d61380c
forgot to change testing function's names
Oct 15, 2020
4cc0282
Merge pull request #18 from irinaespejo/batches
Oct 15, 2020
4528083
Merge branch 'master' of https://github.com/irinaespejo/excursion
Oct 15, 2020
6735bd4
added testcase files for parabola experiment up to 19 dimensions
Oct 24, 2020
1bfea42
making tutorial 1D work again after refactor
Nov 5, 2020
ae15dd5
Merge pull request #19 from irinaespejo/notebooks
Nov 5, 2020
2e0071c
changed name requirements.txy
Nov 5, 2020
3a79ed1
Merge branch 'master' of https://github.com/irinaespejo/excursion
Nov 5, 2020
a17b17f
changed name requirements.txy
Nov 5, 2020
bee116c
changed name requirements.txy
Nov 5, 2020
842bb31
changed name requirements.txy
Nov 5, 2020
e3d420a
Update README.md
Nov 5, 2020
c0a4cf4
requeriments
Nov 6, 2020
6027df9
Merge branch 'master' of https://github.com/irinaespejo/excursion
Nov 6, 2020
d00a84e
tutorial 2D works after refactoring
Nov 6, 2020
b109558
Merge pull request #20 from irinaespejo/notebooks
Nov 6, 2020
ea896c3
Delete requirements.txt
Nov 6, 2020
2766ded
Delete output.txt
Nov 6, 2020
14e18af
high-level modification of testcases and configuration
Nov 24, 2020
e301dce
Merge remote-tracking branch 'origin/master'
Nov 24, 2020
ec86223
pycharm save configurations
Nov 24, 2020
beb6560
added some fixes to make it run
tutrie May 26, 2021
ed340ab
update function file path
tutrie May 26, 2021
a00627b
ran tutorial_1d
tutrie May 26, 2021
c7c93bc
some comments
tutrie Jun 23, 2021
fdf333d
moved acquisition functions into their own subpackage
tutrie Jun 23, 2021
142fc47
more changes to package structure
tutrie Jun 24, 2021
ca842be
move excursionEstimator class
tutrie Jun 24, 2021
027b5e3
delete testcases init.py
tutrie Jun 24, 2021
b73c30f
fixed import error
tutrie Jun 24, 2021
2310eaa
removed unused imports
tutrie Jun 24, 2021
8479cf4
untested code for abstracting kernel options
tutrie Jun 27, 2021
54690ae
refactored kernels and gp initialization
tutrie Jun 28, 2021
52b187f
fixed commandline import error
tutrie Jun 28, 2021
233fd2b
messing with structure some
tutrie Jun 28, 2021
4b5bf62
removed unused code
tutrie Jun 28, 2021
cd3695a
reducing complexity
tutrie Jun 28, 2021
a182781
reduced imports line count by moving to package init
tutrie Jun 28, 2021
3e2a607
removed line in update posterior
tutrie Jun 28, 2021
4f2b56f
extra emphasis, is this line needed?
tutrie Jun 29, 2021
9bf23e7
reduced imports, maybe removed more redundant code from estimator.py
tutrie Jun 29, 2021
7985b0f
code style formatting
tutrie Jun 29, 2021
6047d85
fixed func signature in notebooks
tutrie Jun 29, 2021
72b5532
broken code for worstcase init option
tutrie Jun 29, 2021
cc7e67c
testing out PES
tutrie Jun 29, 2021
73417c0
find old diagnosis module w/ methods
tutrie Jun 29, 2021
3e9cdc1
made thresholds a tensor
tutrie Jun 29, 2021
cdc94b3
tried readding older code
tutrie Jun 29, 2021
99e8f62
moved tests outside of main package
tutrie Jun 29, 2021
d2eb3d9
added paramter to threshold list to tensor call
tutrie Jun 29, 2021
22cfd06
got PES running, plotting broke
tutrie Jun 29, 2021
a9fb702
removed some print statements
tutrie Jun 29, 2021
0edf98b
PES working with 1D notebook
tutrie Jun 29, 2021
90bd8ba
added some parens for clarity
tutrie Jun 29, 2021
4aaad7d
code to eyeball runtime
tutrie Jun 30, 2021
98d2324
comparing results
tutrie Jul 1, 2021
15bc7c8
Update __init__.py
tutrie Jul 9, 2021
9ec481e
Revert "Update __init__.py"
tutrie Jul 9, 2021
105af23
manually merged some file
tutrie Jul 9, 2021
32b9827
made 1d plotter device agnostic
tutrie Jul 9, 2021
6147dc4
fixing acquistition function
tutrie Jul 10, 2021
badf5f9
removed if else by changing call signature
tutrie Jul 10, 2021
83ee4e5
update PES for cuda
tutrie Jul 10, 2021
f0829af
tryna get the test suit working
tutrie Jul 10, 2021
671aaa7
changed value name to update
tutrie Jul 10, 2021
40ce80a
running some tests, all good
tutrie Jul 10, 2021
6a02a2f
benchmarking
tutrie Jul 10, 2021
22d11ad
benchedmark
tutrie Jul 10, 2021
9aaac5d
basic boilerplate for major refactor
tutrie Jul 22, 2021
178c8b4
simple model builder implemented
tutrie Jul 22, 2021
52261a4
fixed bug with training jumpstart
tutrie Jul 22, 2021
b29f35c
cleaning up import structure for plotting refactor
tutrie Jul 22, 2021
8f1aa29
checking something
tutrie Jul 22, 2021
19bd91c
got result object working for plotting
tutrie Jul 23, 2021
6ea66e6
got plotting for 1d and 2d torch GPU
tutrie Jul 25, 2021
890d38e
got jump-start working
tutrie Jul 25, 2021
03462f0
working intro tutorial
tutrie Jul 26, 2021
f95e8f4
added PES
tutrie Jul 27, 2021
64e9bb3
messed up MRO, fixed
tutrie Jul 27, 2021
530811e
PES crashes in 2d
tutrie Jul 27, 2021
970a96b
changed notebook name
tutrie Jul 29, 2021
132a460
refactoring model base.py
tutrie Jul 29, 2021
c4c4f98
moved some code for model fitting
tutrie Jul 29, 2021
1ce2510
slow changes
tutrie Jul 29, 2021
b1bdaf6
spun off fit and update
tutrie Jul 29, 2021
c7b7d6e
removing multi function support
tutrie Jul 29, 2021
6894c46
added cook function for init_points
tutrie Jul 29, 2021
66317cf
change data update order in tell
tutrie Jul 29, 2021
b45c470
backup estimator.py for reference
tutrie Jul 29, 2021
288cffa
fixed jumpstart
tutrie Jul 29, 2021
443d99a
model initialized w/ zero points
tutrie Jul 30, 2021
a2c1a8b
works
tutrie Jul 30, 2021
8e94062
changes from meeting notes
tutrie Jul 31, 2021
9388990
new logic for _tell and build_result
tutrie Jul 31, 2021
9973d94
implemented new algo spec
tutrie Jul 31, 2021
478e036
added prelim support for likelihood
tutrie Aug 1, 2021
a6d9270
added support for likelihood algo options
tutrie Aug 1, 2021
66f1d88
remove print statements
tutrie Aug 1, 2021
c7812ee
added gridkernel support
tutrie Aug 2, 2021
711db03
abt to add support for diagnostics and logging
tutrie Aug 2, 2021
697606e
reduced reading complexity for likelihood builder
tutrie Aug 2, 2021
fa1405a
reduced complexity for noise in estimator
tutrie Aug 2, 2021
692232e
added support for result diagnostics
tutrie Aug 3, 2021
1c0fad7
refactored for scikit learn
tutrie Aug 3, 2021
260e75e
pep8 fixes, deleted unused docs/code
tutrie Aug 3, 2021
f0ff59a
minor update for last commit
tutrie Aug 3, 2021
b939443
added parabola nD example
tutrie Aug 3, 2021
46edbaf
cleaning up file structure
tutrie Aug 4, 2021
6e61919
added 3d plotting
tutrie Aug 4, 2021
1a29674
moved everything into excursion
tutrie Aug 4, 2021
b746b9f
getting pes 2d to work
tutrie Aug 4, 2021
744082a
added 2d benchmark notebook
tutrie Aug 4, 2021
f6b1f1f
removing learner initiliaze method
tutrie Aug 5, 2021
8ae1bc7
removed learner initialize
tutrie Aug 5, 2021
fa58b66
removed calls to learner.intialize
tutrie Aug 5, 2021
17b5ebe
added private class variable to estimator
tutrie Aug 5, 2021
d8d0dd7
preparing ExcursionResult and estimator refactor
tutrie Aug 5, 2021
9bdffce
preparing fgr new result object
tutrie Aug 6, 2021
6ff8116
made log with result, refactored some variable names
tutrie Aug 6, 2021
71379e6
removed redundant acq_vals object from acq funcs
tutrie Aug 6, 2021
4c03a44
fixed memory issue with PES
tutrie Aug 7, 2021
d8fd9e9
benchmarked 2d pes gpu
tutrie Aug 8, 2021
905a249
renaming variables/classes/methods
tutrie Aug 9, 2021
0799947
deleting some things, fixed notebooks
tutrie Aug 9, 2021
76697e3
deleted legacy files, fixed MES builder, new .gitignore
tutrie Aug 11, 2021
33db5cd
Delete .idea directory
tutrie Aug 11, 2021
68773bd
removed old results
tutrie Aug 11, 2021
ed72ada
Merge branch 'FEATURE/refactor_for_reduced_complexity' of https://git…
tutrie Aug 11, 2021
a51ff74
Revert "Delete .idea directory"
tutrie Aug 11, 2021
25d4c61
tried adding .idea to local exclude
tutrie Aug 11, 2021
e2eae77
found bug and update dtype implementation
tutrie Aug 13, 2021
c296c8b
fixed bug with excursion result instance variables
tutrie Aug 13, 2021
2b0cc96
removed _tell and data object
tutrie Aug 13, 2021
3d18c4e
getting ready for last legacy deletion
tutrie Aug 13, 2021
24e87f4
updated import structure, deleted legacy, removed unsued code, create…
tutrie Aug 14, 2021
5cf5a91
final deletes
tutrie Aug 14, 2021
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
100644 → 100755
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
*.pyc
__pycache__
.idea/
Empty file modified LICENSE
100644 → 100755
Empty file.
1 change: 0 additions & 1 deletion MANIFEST.in

This file was deleted.

12 changes: 10 additions & 2 deletions README.md
100644 → 100755
Original file line number Diff line number Diff line change
@@ -1,6 +1,14 @@
# `excursion` — Efficient Excursion Set Estimation

[![Build Status](https://travis-ci.org/irinaespejo/excursion.svg?branch=master)](https://travis-ci.org/irinaespejo/excursion)
[![DOI](https://zenodo.org/badge/DOI/10.5281/zenodo.1634427.svg)](https://zenodo.org/badge/latestdoi/146087019)
[![Binder](https://mybinder.org/badge_logo.svg)](https://mybinder.org/v2/gh/irinaespejo/excursion/master?urlpath=https%3A%2F%2Fgithub.com%2Firinaespejo%2Fexcursion%2Fblob%2Fmaster%2Fexamples%2Ftutorial_1D.ipynb)
[![Documentation Status](https://readthedocs.org/projects/excursion/badge/?version=latest)](https://excursion.readthedocs.io/en/latest/?badge=latest)
[![Code style: black](https://img.shields.io/badge/code%20style-black-000000.svg)](https://github.com/psf/black)
[![License](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](https://opensource.org/licenses/Apache-2.0)



# `excursion` — Efficient Excursion Set Estimation
[ReadTheDocs](https://excursion.readthedocs.io/en/latest/)

This package implements a Bayesian Optimization procedure based on Gaussian Processes to efficiently determine excursion sets (or equivalently iso-surfaces) of one or many expensive black-box functions.

Expand Down
Binary file added assets/2D_PES_movie.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/2D_movie_MES.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/PES.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/equation_PES.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Empty file modified assets/example.gif
100644 → 100755
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
330 changes: 330 additions & 0 deletions assets/example.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Empty file modified assets/example1D.gif
100644 → 100755
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Empty file modified assets/truth.png
100644 → 100755
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
52 changes: 52 additions & 0 deletions conf.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
# 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

# sys.path.insert(0, os.path.abspath('.'))


# -- Project information -----------------------------------------------------

project = "excursion"
copyright = "2020, Lukas Heinrich, Irina Espejo, Giles Louppe, Kyle Cranmer"
author = "Lukas Heinrich, Irina Espejo, Giles Louppe, Kyle Cranmer"


# -- 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 = []

# 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 = ["_build", "Thumbs.db", ".DS_Store"]


# -- Options for HTML output -------------------------------------------------

# The theme to use for HTML and HTML Help pages. See the documentation for
# a list of builtin themes.
#
html_theme = "alabaster"

# 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"]
367 changes: 0 additions & 367 deletions examples/1DExample.ipynb

This file was deleted.

1,296 changes: 0 additions & 1,296 deletions examples/2DMultipleFunctions.ipynb

This file was deleted.

2,136 changes: 2,136 additions & 0 deletions examples/basic_tutorial.ipynb

Large diffs are not rendered by default.

623 changes: 623 additions & 0 deletions examples/builder_example.ipynb

Large diffs are not rendered by default.

34 changes: 5 additions & 29 deletions excursion/__init__.py
100644 → 100755
Original file line number Diff line number Diff line change
@@ -1,29 +1,5 @@
import numpy as np
from scipy.linalg import cho_solve
from scipy.stats import norm
from sklearn.gaussian_process import GaussianProcessRegressor
from sklearn.gaussian_process.kernels import RBF
from sklearn.gaussian_process.kernels import ConstantKernel
from sklearn.gaussian_process.kernels import WhiteKernel
from sklearn.gaussian_process.kernels import Matern


def get_gp(X, y, alpha=10**-7, kernel_name='const_rbf'):
if kernel_name == 'const_rbf':
length_scale = [1.]*X.shape[-1]
kernel = ConstantKernel() * RBF(length_scale_bounds=[0.1, 100.0], length_scale = length_scale)
elif kernel_name == 'tworbf_white':
kernel = ConstantKernel() * RBF(length_scale_bounds=[1e-2,100]) + \
ConstantKernel() * RBF(length_scale_bounds=[100., 1000.0]) + \
WhiteKernel(noise_level_bounds=[1e-7,1e-4])
elif kernel_name == 'onerbf_white':
kernel = ConstantKernel() * RBF(length_scale_bounds=[1e-2,100]) + WhiteKernel(noise_level_bounds=[1e-7,1e-1])
else:
raise RuntimeError('unknown kernel')
gp = GaussianProcessRegressor(kernel=kernel,
n_restarts_optimizer=10,
alpha=alpha,
random_state=1234)
gp.fit(X, y.ravel())
return gp

from .plotting import plot
from .excursion import ExcursionProblem
from .optimizer import Optimizer
from .learner import Learner
__all__ = ["plot", "ExcursionProblem", "Optimizer", "Learner"]
62 changes: 62 additions & 0 deletions excursion/acquisition/MES.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
import torch
from .utils import cdf
from .base import AcquisitionFunction


class MES(AcquisitionFunction):
def __init__(self, device=None, dtype=None, batch=False, ):
self._prev_acq_point_index = []
self.device = device
self.dtype = dtype
self.batch = batch
self.acq_vals = None

def acquire(self, gp, thresholds, X_pointsgrid):
# compute predictive posterior of Y(x) | trin data
likelihood = gp.likelihood
gp.eval()
likelihood.eval()

# ok
prediction = likelihood(gp(X_pointsgrid))
pred_mean = prediction.mean

pred_stdev = torch.sqrt(prediction.variance)

num_points = X_pointsgrid.size()[0]
entropy_grid = torch.zeros(num_points,).to(device=self.device, dtype=self.dtype)

for j in range(len(thresholds) - 1):
p_j = cdf(pred_mean, pred_stdev, thresholds[j + 1]) - cdf(pred_mean, pred_stdev, thresholds[j])

entropy_grid[p_j > 0] -= torch.log(torch.exp(p_j[p_j > 0])) * torch.log(torch.exp(torch.log(p_j[p_j > 0])))

acq_cand_vals = entropy_grid
self.acq_vals = torch.clone(entropy_grid)

Choose a reason for hiding this comment

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

Why is torch.clone necessary? Can we do self.acq_vals = acq_cand_vals or am I missing something?


if self.batch:
print("Will implement this later for batched results\n")
pass

return X_pointsgrid[self.get_first_max_index(gp, X_pointsgrid, acq_cand_vals)]

def get_first_max_index(self, gp, X_pointsgrid, acq_cand_vals):
X_train = gp.train_inputs[0].to(device=self.device, dtype=self.dtype)
X_train = X_train.tolist()
new_index = torch.argmax(acq_cand_vals)

# if the index is not already picked nor in the training set
# accept it ans remove from future picks
return self._check_prev_acq(new_index, X_train, X_pointsgrid, acq_cand_vals)

# recursion helper function
def _check_prev_acq(self, new_index, X_train, X_pointsgrid, acq_cand_vals):
new_X = X_pointsgrid[new_index]
if (new_index not in self._prev_acq_point_index) and (
new_X.tolist() not in X_train):
self._prev_acq_point_index.append(new_index.item())
return new_index.item()
else:
acq_cand_vals[new_index] = torch.Tensor([(-1.0) * float("Inf")])
new_index = torch.argmax(acq_cand_vals)
return self._check_prev_acq(new_index, X_train, X_pointsgrid, acq_cand_vals)
103 changes: 103 additions & 0 deletions excursion/acquisition/PES.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
import torch
from .utils import truncated_std_conditional
from .utils import h_normal
from .base import AcquisitionFunction


class PES(AcquisitionFunction):
def __init__(self, device=None, dtype=None, batch=False, ):
self._prev_acq_point_index = []
self.device = device
self.dtype = dtype
self.batch = batch
self.acq_vals = None

def _acquire(self, gp, thresholds, X_pointsgrid, x_candidate):

Choose a reason for hiding this comment

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

Why does class MES() have a method called acquire but PES has _acquire ? I think without underscore is fine


# compute predictive posterior of Y(x) | train data
kernel = gp.covar_module
likelihood = gp.likelihood
gp.eval()
likelihood.eval()
X_all = torch.cat((x_candidate, X_pointsgrid))
Y_pred_all = likelihood(gp(X_all))
Y_pred_grid = torch.distributions.Normal(
loc=Y_pred_all.mean[1:], scale=(Y_pred_all.variance[1:]) ** 0.5)

# vector of expected value H1 under S(x) for each x in X_grid
# E_S_H1 = torch.zeros(len(X_grid)).to(device=self.device, dtype=self.dtype)
E_S_H1 = torch.zeros(len(X_pointsgrid)).to(device=self.device, dtype=self.dtype)

for j in range(len(thresholds) - 1):
# vector of sigma(Y(x_candidate)|S(x)=j) truncated
trunc_std_j = truncated_std_conditional(
Y_pred_all, thresholds[j], thresholds[j + 1]
)
H1_j = h_normal(trunc_std_j)

# vector of p(S(x)=j)
p_j = Y_pred_grid.cdf(thresholds[j + 1]) - Y_pred_grid.cdf(thresholds[j])
mask = torch.where(p_j == 0.0)
H1_j[mask] = 0.0
# print(p_j)
# print(H1_j)
E_S_H1 += p_j * H1_j # expected value of H1 under S(x)

# entropy of Y(x_candidate)
H0 = h_normal(Y_pred_all.variance[0] ** 0.5)

# info gain on the grid, vector
info_gain = H0 - E_S_H1

info_gain[~torch.isfinite(info_gain)] = 0.0 # just to avoid NaN

# cumulative info gain over grid
cumulative_info_gain = info_gain.sum()
return cumulative_info_gain.item()

def acquire(self, gp, thresholds, X_pointsgrid):
"""
Calculates information gain of choosing x_candidate as next point to evaluate.
Performs this calculation with the Predictive Entropy Search approximation. Roughly,
PES(x_candidate) = int dx { H[Y(x_candidate)] - E_{S(x=j)} H[Y(x_candidate)|S(x=j)] }
Notation: PES(x_candidate) = int dx H0 - E_Sj H1

"""

# compute predictive posterior of Y(x) | train data
# likelihood = gp.likelihood
# gp.eval()
# likelihood.eval()
acquisition_values = []

# for x_candidate in X_grid:
for x_candidate in X_pointsgrid:
x_candidate = x_candidate.view(1, -1).to(device=self.device, dtype=self.dtype)
acquisition_values.append(self._acquire(gp, thresholds, X_pointsgrid, x_candidate))

acq_cand_vals = torch.Tensor(acquisition_values).to(device=self.device, dtype=self.dtype)
self.acq_vals = torch.clone(acq_cand_vals)

return X_pointsgrid[self.get_first_max_index(gp, X_pointsgrid, acq_cand_vals)]
Comment on lines +58 to +81

Choose a reason for hiding this comment

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

ok I see the utility of _acquire here. Same comment with torch.clone. The code for PES looks good to me.



def get_first_max_index(self, gp, X_pointsgrid, acq_cand_vals):
X_train = gp.train_inputs[0].to(device=self.device, dtype=self.dtype)
X_train = X_train.tolist()
new_index = torch.argmax(acq_cand_vals)

# if the index is not already picked nor in the training set
# accept it ans remove from future picks
return self._check_prev_acq(new_index, X_train, X_pointsgrid, acq_cand_vals)

# recursion helper function
def _check_prev_acq(self, new_index, X_train, X_pointsgrid, acq_cand_vals):
new_X = X_pointsgrid[new_index]
if (new_index not in self._prev_acq_point_index) and (
new_X.tolist() not in X_train):
self._prev_acq_point_index.append(new_index.item())
return new_index.item()
else:
acq_cand_vals[new_index] = torch.Tensor([(-1.0) * float("Inf")])
new_index = torch.argmax(acq_cand_vals)
return self._check_prev_acq(new_index, X_train, X_pointsgrid, acq_cand_vals)
9 changes: 9 additions & 0 deletions excursion/acquisition/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
from .MES import MES
from .PES import PES
from .base import AcquisitionFunction

__all__ = [
"PES",
"MES",
"AcquisitionFunction",
]
75 changes: 75 additions & 0 deletions excursion/acquisition/approximations.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
# from scipy.stats import norm
# import torch
# import numpy as np
#
#
# def h_normal_gpytorch(s):
# """ Entropy of a normal distribution """
# return torch.log(s * (2 * np.e * np.pi) ** 0.5)
#
#
# def approx_mi_vec_gpytorch(mu, cov, thresholds):
# # Expectation Propagation
# mu1 = mu[:, 0]
# std1 = cov[:, 0, 0] ** 0.5
# mu2 = mu[:, 1]
# std2 = cov[:, 1, 1] ** 0.5
# rho = cov[:, 0, 1] / (std1 * std2)
#
# std_sx = []
#
# for j in range(len(thresholds) - 1):
# alpha_j = (thresholds[j] - mu2) / std2
# beta_j = (thresholds[j + 1] - mu2) / std2
# alpha_j = alpha_j.detach().numpy()
# beta_j = beta_j.detach().numpy()
#
# c_j = norm.cdf(beta_j) - norm.cdf(alpha_j)
#
# # \sigma(Y(X)|S(x')=j)
# b_phi_b = beta_j * norm.pdf(beta_j)
# b_phi_b[~np.isfinite(beta_j)] = 0.0
# a_phi_a = alpha_j * norm.pdf(alpha_j)
# a_phi_a[~np.isfinite(alpha_j)] = 0.0
#
# alpha_j = torch.tensor(alpha_j)
# beta_j = torch.tensor(beta_j)
#
# mu_cond = mu1 - std1 * rho / torch.tensor(c_j) * (
# torch.tensor(norm.pdf(beta_j)) - torch.tensor(norm.pdf(alpha_j))
# )
# var_cond = (
# mu1 ** 2
# - 2
# * mu1
# * std1
# * (
# rho
# / torch.tensor(c_j)
# * (torch.tensor(norm.pdf(beta_j)) - torch.tensor(norm.pdf(alpha_j)))
# )
# + std1 ** 2
# * (
# 1.0
# - (rho ** 2 / torch.tensor(c_j))
# * (torch.tensor(b_phi_b) - torch.tensor(a_phi_a))
# )
# - mu_cond ** 2
# )
#
# std_sx_j = var_cond ** 0.5
#
# std_sx.append(std_sx_j)
#
# # Entropy
# h = h_normal_gpytorch(std1)
#
# for j in range(len(thresholds) - 1):
# p_j = norm(mu2.detach().numpy(), std2.detach().numpy()).cdf(
# thresholds[j + 1]
# ) - norm(mu2.detach().numpy(), std2.detach().numpy()).cdf(thresholds[j])
# print("pj ", p_j)
# dec = torch.tensor(p_j) * h_normal_gpytorch(std_sx[j])
# h[p_j > 0.0] -= dec[p_j > 0.0]
#
# return h
28 changes: 28 additions & 0 deletions excursion/acquisition/base.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
from collections import defaultdict


class AcquisitionFunction(object):

Choose a reason for hiding this comment

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

Also, why is there no init method?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

No init since it is an abstract interface and not an abstract object. this ensures all the future acq classes which implement it will be able to use the ask-and-tell API

Copy link

@irinaespejo irinaespejo Aug 10, 2021

Choose a reason for hiding this comment

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

end ✔️

"""All acquisition functions used by the library should implement this interface
to be used by the optimizer object."""
def acquire(self, gp, thresholds, meshgrid):
raise NotImplemented

def set_params(self, **params):
"""
Set the parameters of this acquisition function.
Parameters
----------
**params : dict
Function parameters.
Returns
-------
self : object
Function instance.
"""
if not params:
# Simple optimization to gain speed (inspect is slow)
return self
for key, value in params.items():
setattr(self, key, value)

return self
Comment on lines +10 to +28

Choose a reason for hiding this comment

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

We don't use acquisition function with parameters, that would be a bit meta. Let's erase the method if you can't give a use case.

Loading