autoemulate 0.3.3__tar.gz → 0.4.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {autoemulate-0.3.3 → autoemulate-0.4.0}/PKG-INFO +2 -2
- {autoemulate-0.3.3 → autoemulate-0.4.0}/README.md +1 -1
- {autoemulate-0.3.3 → autoemulate-0.4.0}/autoemulate/compare.py +1 -12
- {autoemulate-0.3.3 → autoemulate-0.4.0}/autoemulate/emulators/__init__.py +0 -12
- {autoemulate-0.3.3 → autoemulate-0.4.0}/autoemulate/experimental/data/utils.py +3 -3
- autoemulate-0.4.0/autoemulate/experimental/emulators/gradient_boosting.py +80 -0
- {autoemulate-0.3.3 → autoemulate-0.4.0}/autoemulate/experimental/emulators/lightgbm.py +1 -1
- {autoemulate-0.3.3 → autoemulate-0.4.0}/autoemulate/experimental/emulators/neural_processes/conditional_neural_process.py +2 -2
- autoemulate-0.4.0/autoemulate/experimental/exploratory/hm_refactor.ipynb +454 -0
- autoemulate-0.4.0/autoemulate/experimental/history_matching.py +487 -0
- {autoemulate-0.3.3 → autoemulate-0.4.0}/autoemulate/experimental/learners/base.py +2 -65
- autoemulate-0.4.0/autoemulate/experimental/sensitivity_analysis.py +258 -0
- autoemulate-0.4.0/autoemulate/experimental/simulations/base.py +175 -0
- autoemulate-0.4.0/autoemulate/experimental/simulations/epidemic.py +40 -0
- autoemulate-0.4.0/autoemulate/experimental/simulations/projectile.py +76 -0
- {autoemulate-0.3.3 → autoemulate-0.4.0}/autoemulate/history_matching_dashboard.py +17 -8
- {autoemulate-0.3.3 → autoemulate-0.4.0}/autoemulate/sensitivity_analysis.py +22 -9
- {autoemulate-0.3.3 → autoemulate-0.4.0}/pyproject.toml +2 -1
- {autoemulate-0.3.3 → autoemulate-0.4.0}/LICENSE +0 -0
- {autoemulate-0.3.3 → autoemulate-0.4.0}/autoemulate/__init__.py +0 -0
- {autoemulate-0.3.3 → autoemulate-0.4.0}/autoemulate/cross_validate.py +0 -0
- {autoemulate-0.3.3 → autoemulate-0.4.0}/autoemulate/data_splitting.py +0 -0
- {autoemulate-0.3.3 → autoemulate-0.4.0}/autoemulate/datasets.py +0 -0
- {autoemulate-0.3.3 → autoemulate-0.4.0}/autoemulate/emulators/conditional_neural_process.py +0 -0
- {autoemulate-0.3.3 → autoemulate-0.4.0}/autoemulate/emulators/conditional_neural_process_attn.py +0 -0
- {autoemulate-0.3.3 → autoemulate-0.4.0}/autoemulate/emulators/gaussian_process.py +0 -0
- {autoemulate-0.3.3 → autoemulate-0.4.0}/autoemulate/emulators/gaussian_process_mogp.py +0 -0
- {autoemulate-0.3.3 → autoemulate-0.4.0}/autoemulate/emulators/gaussian_process_mt.py +0 -0
- {autoemulate-0.3.3 → autoemulate-0.4.0}/autoemulate/emulators/gaussian_process_sklearn.py +0 -0
- {autoemulate-0.3.3 → autoemulate-0.4.0}/autoemulate/emulators/gaussian_process_utils/__init__.py +0 -0
- {autoemulate-0.3.3 → autoemulate-0.4.0}/autoemulate/emulators/gaussian_process_utils/early_stopping_criterion.py +0 -0
- {autoemulate-0.3.3 → autoemulate-0.4.0}/autoemulate/emulators/gaussian_process_utils/poly_mean.py +0 -0
- {autoemulate-0.3.3 → autoemulate-0.4.0}/autoemulate/emulators/gaussian_process_utils/polynomial_features.py +0 -0
- {autoemulate-0.3.3 → autoemulate-0.4.0}/autoemulate/emulators/gradient_boosting.py +0 -0
- {autoemulate-0.3.3 → autoemulate-0.4.0}/autoemulate/emulators/light_gbm.py +0 -0
- {autoemulate-0.3.3 → autoemulate-0.4.0}/autoemulate/emulators/neural_net_sk.py +0 -0
- {autoemulate-0.3.3 → autoemulate-0.4.0}/autoemulate/emulators/neural_networks/__init__.py +0 -0
- {autoemulate-0.3.3 → autoemulate-0.4.0}/autoemulate/emulators/neural_networks/cnp_module.py +0 -0
- {autoemulate-0.3.3 → autoemulate-0.4.0}/autoemulate/emulators/neural_networks/cnp_module_attn.py +0 -0
- {autoemulate-0.3.3 → autoemulate-0.4.0}/autoemulate/emulators/neural_networks/datasets.py +0 -0
- {autoemulate-0.3.3 → autoemulate-0.4.0}/autoemulate/emulators/neural_networks/gp_module.py +0 -0
- {autoemulate-0.3.3 → autoemulate-0.4.0}/autoemulate/emulators/neural_networks/losses.py +0 -0
- {autoemulate-0.3.3 → autoemulate-0.4.0}/autoemulate/emulators/polynomials.py +0 -0
- {autoemulate-0.3.3 → autoemulate-0.4.0}/autoemulate/emulators/radial_basis_functions.py +0 -0
- {autoemulate-0.3.3 → autoemulate-0.4.0}/autoemulate/emulators/random_forest.py +0 -0
- {autoemulate-0.3.3 → autoemulate-0.4.0}/autoemulate/emulators/support_vector_machines.py +0 -0
- {autoemulate-0.3.3 → autoemulate-0.4.0}/autoemulate/experimental/__init__.py +0 -0
- {autoemulate-0.3.3 → autoemulate-0.4.0}/autoemulate/experimental/compare.py +0 -0
- {autoemulate-0.3.3 → autoemulate-0.4.0}/autoemulate/experimental/data/preprocessors.py +0 -0
- {autoemulate-0.3.3 → autoemulate-0.4.0}/autoemulate/experimental/device.py +0 -0
- {autoemulate-0.3.3 → autoemulate-0.4.0}/autoemulate/experimental/emulators/__init__.py +0 -0
- {autoemulate-0.3.3 → autoemulate-0.4.0}/autoemulate/experimental/emulators/base.py +0 -0
- {autoemulate-0.3.3 → autoemulate-0.4.0}/autoemulate/experimental/emulators/gaussian_process/__init__.py +0 -0
- {autoemulate-0.3.3 → autoemulate-0.4.0}/autoemulate/experimental/emulators/gaussian_process/exact.py +0 -0
- {autoemulate-0.3.3 → autoemulate-0.4.0}/autoemulate/experimental/emulators/random_forest.py +0 -0
- {autoemulate-0.3.3 → autoemulate-0.4.0}/autoemulate/experimental/emulators/svm.py +0 -0
- {autoemulate-0.3.3 → autoemulate-0.4.0}/autoemulate/experimental/exploratory/active_matter/README.md +0 -0
- {autoemulate-0.3.3 → autoemulate-0.4.0}/autoemulate/experimental/exploratory/active_matter/active_matter.ipynb +0 -0
- {autoemulate-0.3.3 → autoemulate-0.4.0}/autoemulate/experimental/learners/__init__.py +0 -0
- {autoemulate-0.3.3 → autoemulate-0.4.0}/autoemulate/experimental/learners/membership.py +0 -0
- {autoemulate-0.3.3 → autoemulate-0.4.0}/autoemulate/experimental/learners/pool.py +0 -0
- {autoemulate-0.3.3 → autoemulate-0.4.0}/autoemulate/experimental/learners/stream.py +0 -0
- {autoemulate-0.3.3 → autoemulate-0.4.0}/autoemulate/experimental/model_selection.py +0 -0
- {autoemulate-0.3.3 → autoemulate-0.4.0}/autoemulate/experimental/simulations/__init__.py +0 -0
- {autoemulate-0.3.3 → autoemulate-0.4.0}/autoemulate/experimental/tuner.py +0 -0
- {autoemulate-0.3.3 → autoemulate-0.4.0}/autoemulate/experimental/types.py +0 -0
- {autoemulate-0.3.3 → autoemulate-0.4.0}/autoemulate/experimental_design.py +0 -0
- {autoemulate-0.3.3 → autoemulate-0.4.0}/autoemulate/history_matching.py +0 -0
- {autoemulate-0.3.3 → autoemulate-0.4.0}/autoemulate/hyperparam_searching.py +0 -0
- {autoemulate-0.3.3 → autoemulate-0.4.0}/autoemulate/logging_config.py +0 -0
- {autoemulate-0.3.3 → autoemulate-0.4.0}/autoemulate/mcmc.py +0 -0
- {autoemulate-0.3.3 → autoemulate-0.4.0}/autoemulate/mcmc_dashboard.py +0 -0
- {autoemulate-0.3.3 → autoemulate-0.4.0}/autoemulate/metrics.py +0 -0
- {autoemulate-0.3.3 → autoemulate-0.4.0}/autoemulate/model_processing.py +0 -0
- {autoemulate-0.3.3 → autoemulate-0.4.0}/autoemulate/model_registry.py +0 -0
- {autoemulate-0.3.3 → autoemulate-0.4.0}/autoemulate/plotting.py +0 -0
- {autoemulate-0.3.3 → autoemulate-0.4.0}/autoemulate/preprocess_target.py +0 -0
- {autoemulate-0.3.3 → autoemulate-0.4.0}/autoemulate/printing.py +0 -0
- {autoemulate-0.3.3 → autoemulate-0.4.0}/autoemulate/save.py +0 -0
- {autoemulate-0.3.3 → autoemulate-0.4.0}/autoemulate/simulations/__init__.py +0 -0
- {autoemulate-0.3.3 → autoemulate-0.4.0}/autoemulate/simulations/base.py +0 -0
- {autoemulate-0.3.3 → autoemulate-0.4.0}/autoemulate/simulations/circ_utils.py +0 -0
- {autoemulate-0.3.3 → autoemulate-0.4.0}/autoemulate/simulations/epidemic.py +0 -0
- {autoemulate-0.3.3 → autoemulate-0.4.0}/autoemulate/simulations/flow_functions.py +0 -0
- {autoemulate-0.3.3 → autoemulate-0.4.0}/autoemulate/simulations/naghavi_cardiac_ModularCirc.py +0 -0
- {autoemulate-0.3.3 → autoemulate-0.4.0}/autoemulate/simulations/projectile.py +0 -0
- {autoemulate-0.3.3 → autoemulate-0.4.0}/autoemulate/simulations/reaction_diffusion.py +0 -0
- {autoemulate-0.3.3 → autoemulate-0.4.0}/autoemulate/utils.py +0 -0
- {autoemulate-0.3.3 → autoemulate-0.4.0}/misc/AE_logo_final.png +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.3
|
|
2
2
|
Name: autoemulate
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.4.0
|
|
4
4
|
Summary: A python package for semi-automated emulation
|
|
5
5
|
License: MIT
|
|
6
6
|
Author: AutoEmulate contributors (see our GitHub page)
|
|
@@ -43,7 +43,7 @@ Description-Content-Type: text/markdown
|
|
|
43
43
|
[](https://alan-turing-institute.github.io/autoemulate/)
|
|
44
44
|
|
|
45
45
|
<!-- SPHINX-START -->
|
|
46
|
-
Simulations of physical systems are often slow and need lots of compute, which makes them unpractical for real-world applications like digital twins, or when they have to run thousands of times for sensitivity analyses. The goal of `AutoEmulate` is to make it easy to replace simulations with fast, accurate emulators. To do this, `AutoEmulate` automatically fits and compares various emulators, ranging from simple models like Radial Basis Functions and Second Order Polynomials to more complex models like Support Vector Machines
|
|
46
|
+
Simulations of physical systems are often slow and need lots of compute, which makes them unpractical for real-world applications like digital twins, or when they have to run thousands of times for sensitivity analyses. The goal of `AutoEmulate` is to make it easy to replace simulations with fast, accurate emulators. To do this, `AutoEmulate` automatically fits and compares various emulators, ranging from simple models like Radial Basis Functions and Second Order Polynomials to more complex models like Support Vector Machines and Gaussian Processes to find the best emulator for a simulation.
|
|
47
47
|
|
|
48
48
|
⚠️ Warning: This is an early version of the package and is still under development. We are working on improving the documentation and adding more features. If you have any questions or suggestions, please open an issue or a pull request.
|
|
49
49
|
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
[](https://alan-turing-institute.github.io/autoemulate/)
|
|
8
8
|
|
|
9
9
|
<!-- SPHINX-START -->
|
|
10
|
-
Simulations of physical systems are often slow and need lots of compute, which makes them unpractical for real-world applications like digital twins, or when they have to run thousands of times for sensitivity analyses. The goal of `AutoEmulate` is to make it easy to replace simulations with fast, accurate emulators. To do this, `AutoEmulate` automatically fits and compares various emulators, ranging from simple models like Radial Basis Functions and Second Order Polynomials to more complex models like Support Vector Machines
|
|
10
|
+
Simulations of physical systems are often slow and need lots of compute, which makes them unpractical for real-world applications like digital twins, or when they have to run thousands of times for sensitivity analyses. The goal of `AutoEmulate` is to make it easy to replace simulations with fast, accurate emulators. To do this, `AutoEmulate` automatically fits and compares various emulators, ranging from simple models like Radial Basis Functions and Second Order Polynomials to more complex models like Support Vector Machines and Gaussian Processes to find the best emulator for a simulation.
|
|
11
11
|
|
|
12
12
|
⚠️ Warning: This is an early version of the package and is still under development. We are working on improving the documentation and adding more features. If you have any questions or suggestions, please open an issue or a pull request.
|
|
13
13
|
|
|
@@ -986,8 +986,6 @@ class AutoEmulate:
|
|
|
986
986
|
problem=None,
|
|
987
987
|
N=1024,
|
|
988
988
|
conf_level=0.95,
|
|
989
|
-
as_df=True,
|
|
990
|
-
**plot_kwargs,
|
|
991
989
|
):
|
|
992
990
|
"""Perform Sobol sensitivity analysis on a fitted emulator.
|
|
993
991
|
|
|
@@ -1024,23 +1022,15 @@ class AutoEmulate:
|
|
|
1024
1022
|
conf_level : float, optional
|
|
1025
1023
|
Confidence level (between 0 and 1) for calculating confidence intervals of the
|
|
1026
1024
|
sensitivity indices. Default is 0.95 (95% confidence).
|
|
1027
|
-
as_df : bool, optional
|
|
1028
|
-
If True, returns results as a long-format pandas DataFrame with columns for
|
|
1029
|
-
parameters, sensitivity indices, and confidence intervals. If False, returns
|
|
1030
|
-
the raw SALib results dictionary. Default is True.
|
|
1031
1025
|
|
|
1032
1026
|
Returns
|
|
1033
1027
|
-------
|
|
1034
|
-
pandas.DataFrame
|
|
1035
|
-
If as_df=True (default), returns a DataFrame with columns:
|
|
1036
|
-
|
|
1028
|
+
pandas.DataFrame
|
|
1037
1029
|
- 'parameter': Input parameter name
|
|
1038
1030
|
- 'output': Output variable name
|
|
1039
1031
|
- 'S1', 'S2', 'ST': First, second, and total order sensitivity indices
|
|
1040
1032
|
- 'S1_conf', 'S2_conf', 'ST_conf': Confidence intervals for each index
|
|
1041
1033
|
|
|
1042
|
-
If as_df=False, returns the raw SALib results dictionary.
|
|
1043
|
-
|
|
1044
1034
|
Notes
|
|
1045
1035
|
-----
|
|
1046
1036
|
The analysis requires N * (2D + 2) model evaluations, where D is the number of input
|
|
@@ -1065,7 +1055,6 @@ class AutoEmulate:
|
|
|
1065
1055
|
X=self.X,
|
|
1066
1056
|
N=N,
|
|
1067
1057
|
conf_level=conf_level,
|
|
1068
|
-
as_df=as_df,
|
|
1069
1058
|
)
|
|
1070
1059
|
|
|
1071
1060
|
return df_results
|
|
@@ -1,8 +1,5 @@
|
|
|
1
1
|
from ..model_registry import ModelRegistry
|
|
2
|
-
from .conditional_neural_process import ConditionalNeuralProcess
|
|
3
|
-
from .conditional_neural_process_attn import AttentiveConditionalNeuralProcess
|
|
4
2
|
from .gaussian_process import GaussianProcess
|
|
5
|
-
from .gaussian_process_mogp import GaussianProcessMOGP
|
|
6
3
|
from .gaussian_process_mt import GaussianProcessMT
|
|
7
4
|
from .gaussian_process_sklearn import GaussianProcessSklearn
|
|
8
5
|
from .gradient_boosting import GradientBoosting
|
|
@@ -33,17 +30,8 @@ model_registry.register_model(
|
|
|
33
30
|
model_registry.register_model(
|
|
34
31
|
GaussianProcess().model_name, GaussianProcess, is_core=True
|
|
35
32
|
)
|
|
36
|
-
model_registry.register_model(
|
|
37
|
-
ConditionalNeuralProcess().model_name, ConditionalNeuralProcess, is_core=True
|
|
38
|
-
)
|
|
39
|
-
|
|
40
33
|
|
|
41
34
|
# non-core models
|
|
42
|
-
model_registry.register_model(
|
|
43
|
-
AttentiveConditionalNeuralProcess().model_name,
|
|
44
|
-
AttentiveConditionalNeuralProcess,
|
|
45
|
-
is_core=False,
|
|
46
|
-
)
|
|
47
35
|
model_registry.register_model(
|
|
48
36
|
GaussianProcessMT().model_name, GaussianProcessMT, is_core=False
|
|
49
37
|
)
|
|
@@ -29,11 +29,11 @@ class ConversionMixin:
|
|
|
29
29
|
if isinstance(y, np.ndarray):
|
|
30
30
|
y = torch.tensor(y, dtype=torch.float32)
|
|
31
31
|
|
|
32
|
-
if isinstance(x,
|
|
33
|
-
y,
|
|
32
|
+
if isinstance(x, torch.Tensor | np.ndarray) and isinstance(
|
|
33
|
+
y, torch.Tensor | np.ndarray
|
|
34
34
|
):
|
|
35
35
|
dataset = TensorDataset(x, y)
|
|
36
|
-
elif isinstance(x,
|
|
36
|
+
elif isinstance(x, torch.Tensor | np.ndarray) and y is None:
|
|
37
37
|
dataset = TensorDataset(x)
|
|
38
38
|
elif isinstance(x, Dataset) and y is None:
|
|
39
39
|
dataset = x
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
from typing import Literal
|
|
2
|
+
|
|
3
|
+
import numpy as np
|
|
4
|
+
from scipy.stats import loguniform
|
|
5
|
+
from sklearn.ensemble import GradientBoostingRegressor
|
|
6
|
+
|
|
7
|
+
from autoemulate.experimental.device import TorchDeviceMixin
|
|
8
|
+
from autoemulate.experimental.emulators.base import SklearnBackend
|
|
9
|
+
from autoemulate.experimental.types import DeviceLike, TensorLike
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class GradientBoosting(SklearnBackend):
|
|
13
|
+
"""Gradient Boosting Emulator.
|
|
14
|
+
|
|
15
|
+
Wraps Gradient Boosting regression from scikit-learn.
|
|
16
|
+
"""
|
|
17
|
+
|
|
18
|
+
def __init__( # noqa: PLR0913 allow too many arguments since all currently required
|
|
19
|
+
self,
|
|
20
|
+
x: TensorLike,
|
|
21
|
+
y: TensorLike,
|
|
22
|
+
loss: Literal[
|
|
23
|
+
"squared_error", "absolute_error", "huber", "quantile"
|
|
24
|
+
] = "squared_error",
|
|
25
|
+
learning_rate: float = 0.1,
|
|
26
|
+
n_estimators: int = 100,
|
|
27
|
+
max_depth: int = 3,
|
|
28
|
+
min_samples_split: int = 2,
|
|
29
|
+
min_samples_leaf: int = 1,
|
|
30
|
+
subsample: float = 1.0,
|
|
31
|
+
max_features: float | None = None,
|
|
32
|
+
ccp_alpha: float = 0.0,
|
|
33
|
+
n_iter_no_change: int | None = None,
|
|
34
|
+
random_seed: int | None = None,
|
|
35
|
+
device: DeviceLike = "cpu",
|
|
36
|
+
):
|
|
37
|
+
"""Initializes a GradientBoosting object."""
|
|
38
|
+
_, _ = x, y # ignore unused arguments
|
|
39
|
+
TorchDeviceMixin.__init__(self, device=device, cpu_only=True)
|
|
40
|
+
self.loss = loss
|
|
41
|
+
self.learning_rate = learning_rate
|
|
42
|
+
self.n_estimators = n_estimators
|
|
43
|
+
self.max_depth = max_depth
|
|
44
|
+
self.min_samples_split = min_samples_split
|
|
45
|
+
self.min_samples_leaf = min_samples_leaf
|
|
46
|
+
self.subsample = subsample
|
|
47
|
+
self.max_features = max_features
|
|
48
|
+
self.ccp_alpha = ccp_alpha
|
|
49
|
+
self.n_iter_no_change = n_iter_no_change
|
|
50
|
+
self.random_seed = random_seed
|
|
51
|
+
self.model = GradientBoostingRegressor(
|
|
52
|
+
loss=self.loss,
|
|
53
|
+
learning_rate=self.learning_rate,
|
|
54
|
+
n_estimators=self.n_estimators,
|
|
55
|
+
max_depth=self.max_depth,
|
|
56
|
+
min_samples_split=self.min_samples_split,
|
|
57
|
+
min_samples_leaf=self.min_samples_leaf,
|
|
58
|
+
subsample=self.subsample,
|
|
59
|
+
max_features=self.max_features,
|
|
60
|
+
ccp_alpha=self.ccp_alpha,
|
|
61
|
+
n_iter_no_change=self.n_iter_no_change,
|
|
62
|
+
random_state=self.random_seed,
|
|
63
|
+
)
|
|
64
|
+
|
|
65
|
+
@staticmethod
|
|
66
|
+
def is_multioutput() -> bool:
|
|
67
|
+
return False
|
|
68
|
+
|
|
69
|
+
@staticmethod
|
|
70
|
+
def get_tune_config():
|
|
71
|
+
return {
|
|
72
|
+
"learning_rate": [loguniform(0.01, 0.2).rvs()],
|
|
73
|
+
"n_estimators": [np.random.randint(100, 500)],
|
|
74
|
+
"max_depth": [np.random.randint(3, 8)],
|
|
75
|
+
"min_samples_split": [np.random.randint(2, 20)],
|
|
76
|
+
"min_samples_leaf": [np.random.randint(1, 6)],
|
|
77
|
+
"subsample": [np.random.uniform(0.6, 1.0)],
|
|
78
|
+
"max_features": ["sqrt", "log2", None],
|
|
79
|
+
"ccp_alpha": [loguniform(0.001, 0.1).rvs()],
|
|
80
|
+
}
|
|
@@ -104,7 +104,7 @@ class LightGBM(Emulator):
|
|
|
104
104
|
def _predict(self, x: TensorLike) -> OutputLike:
|
|
105
105
|
"""Predicts the output of the emulator for a given input."""
|
|
106
106
|
y_pred = self.model_.predict(x)
|
|
107
|
-
assert not isinstance(y_pred,
|
|
107
|
+
assert not isinstance(y_pred, spmatrix | list)
|
|
108
108
|
_, y = self._convert_to_tensors(x, y_pred)
|
|
109
109
|
return y
|
|
110
110
|
|
|
@@ -105,7 +105,7 @@ def cnp_collate_fn(batch, device: DeviceLike | None = None):
|
|
|
105
105
|
as we don't do layernorm or attention, but we should modify cnp etc. to handle this
|
|
106
106
|
better.
|
|
107
107
|
"""
|
|
108
|
-
X, y = zip(*batch)
|
|
108
|
+
X, y = zip(*batch, strict=False)
|
|
109
109
|
device = get_torch_device(device)
|
|
110
110
|
|
|
111
111
|
# Get the maximum number of context and target points in the batch
|
|
@@ -123,7 +123,7 @@ def cnp_collate_fn(batch, device: DeviceLike | None = None):
|
|
|
123
123
|
target_mask = torch.zeros(len(batch), max_target, dtype=torch.bool)
|
|
124
124
|
|
|
125
125
|
# Fill in the batched tensors
|
|
126
|
-
for i, (x, yi) in enumerate(zip(X, y)):
|
|
126
|
+
for i, (x, yi) in enumerate(zip(X, y, strict=False)):
|
|
127
127
|
n_context = x["x_context"].shape[0]
|
|
128
128
|
n_target = x["x_target"].shape[0]
|
|
129
129
|
|
|
@@ -0,0 +1,454 @@
|
|
|
1
|
+
{
|
|
2
|
+
"cells": [
|
|
3
|
+
{
|
|
4
|
+
"cell_type": "markdown",
|
|
5
|
+
"metadata": {},
|
|
6
|
+
"source": [
|
|
7
|
+
"# Refactored HistoryMatching workflow example\n",
|
|
8
|
+
"\n",
|
|
9
|
+
"## 1. Set up"
|
|
10
|
+
]
|
|
11
|
+
},
|
|
12
|
+
{
|
|
13
|
+
"cell_type": "code",
|
|
14
|
+
"execution_count": 1,
|
|
15
|
+
"metadata": {},
|
|
16
|
+
"outputs": [],
|
|
17
|
+
"source": [
|
|
18
|
+
"import torch\n",
|
|
19
|
+
"\n",
|
|
20
|
+
"# imports from main\n",
|
|
21
|
+
"from autoemulate.history_matching_dashboard import HistoryMatchingDashboard\n",
|
|
22
|
+
"\n",
|
|
23
|
+
"# imports from experimental\n",
|
|
24
|
+
"from autoemulate.experimental.emulators.gaussian_process.exact import (\n",
|
|
25
|
+
" GaussianProcessExact,\n",
|
|
26
|
+
")\n",
|
|
27
|
+
"from autoemulate.experimental.simulations.epidemic import Epidemic\n",
|
|
28
|
+
"from autoemulate.experimental.history_matching import HistoryMatching, HistoryMatchingWorkflow"
|
|
29
|
+
]
|
|
30
|
+
},
|
|
31
|
+
{
|
|
32
|
+
"cell_type": "markdown",
|
|
33
|
+
"metadata": {},
|
|
34
|
+
"source": []
|
|
35
|
+
},
|
|
36
|
+
{
|
|
37
|
+
"cell_type": "markdown",
|
|
38
|
+
"metadata": {},
|
|
39
|
+
"source": [
|
|
40
|
+
"### Simulate data & train a GP\n",
|
|
41
|
+
"\n",
|
|
42
|
+
"Set up a `Simulator` and generate data."
|
|
43
|
+
]
|
|
44
|
+
},
|
|
45
|
+
{
|
|
46
|
+
"cell_type": "code",
|
|
47
|
+
"execution_count": 2,
|
|
48
|
+
"metadata": {},
|
|
49
|
+
"outputs": [
|
|
50
|
+
{
|
|
51
|
+
"name": "stderr",
|
|
52
|
+
"output_type": "stream",
|
|
53
|
+
"text": [
|
|
54
|
+
"Running simulations: 100%|██████████| 10/10 [00:00<00:00, 553.21it/s]"
|
|
55
|
+
]
|
|
56
|
+
},
|
|
57
|
+
{
|
|
58
|
+
"name": "stdout",
|
|
59
|
+
"output_type": "stream",
|
|
60
|
+
"text": [
|
|
61
|
+
"Successfully completed 10/10 simulations (100.0%)\n"
|
|
62
|
+
]
|
|
63
|
+
},
|
|
64
|
+
{
|
|
65
|
+
"name": "stderr",
|
|
66
|
+
"output_type": "stream",
|
|
67
|
+
"text": [
|
|
68
|
+
"\n"
|
|
69
|
+
]
|
|
70
|
+
}
|
|
71
|
+
],
|
|
72
|
+
"source": [
|
|
73
|
+
"simulator = Epidemic()\n",
|
|
74
|
+
"x = simulator.sample_inputs(10)\n",
|
|
75
|
+
"y = simulator.forward_batch(x)"
|
|
76
|
+
]
|
|
77
|
+
},
|
|
78
|
+
{
|
|
79
|
+
"cell_type": "markdown",
|
|
80
|
+
"metadata": {},
|
|
81
|
+
"source": [
|
|
82
|
+
"The next step should be done with `AutoEmulate.compare()`."
|
|
83
|
+
]
|
|
84
|
+
},
|
|
85
|
+
{
|
|
86
|
+
"cell_type": "code",
|
|
87
|
+
"execution_count": 3,
|
|
88
|
+
"metadata": {},
|
|
89
|
+
"outputs": [],
|
|
90
|
+
"source": [
|
|
91
|
+
"gp = GaussianProcessExact(x, y)\n",
|
|
92
|
+
"gp.fit(x, y)"
|
|
93
|
+
]
|
|
94
|
+
},
|
|
95
|
+
{
|
|
96
|
+
"cell_type": "markdown",
|
|
97
|
+
"metadata": {},
|
|
98
|
+
"source": [
|
|
99
|
+
"## 2. HistoryMatching\n",
|
|
100
|
+
"\n",
|
|
101
|
+
"Firstly, one can instantiate `HistoryMatching` without a simulator or an emulator. It can be used to calculate implausability for a given set of predictions."
|
|
102
|
+
]
|
|
103
|
+
},
|
|
104
|
+
{
|
|
105
|
+
"cell_type": "code",
|
|
106
|
+
"execution_count": 4,
|
|
107
|
+
"metadata": {},
|
|
108
|
+
"outputs": [
|
|
109
|
+
{
|
|
110
|
+
"name": "stderr",
|
|
111
|
+
"output_type": "stream",
|
|
112
|
+
"text": [
|
|
113
|
+
"/var/folders/bj/kdwy1bhj3h728lr5xdj19yd40000gr/T/ipykernel_13433/4021603184.py:3: UserWarning: To copy construct from a tensor, it is recommended to use sourceTensor.detach().clone() or sourceTensor.detach().clone().requires_grad_(True), rather than torch.tensor(sourceTensor).\n",
|
|
114
|
+
" output = gp.predict(torch.tensor(x_new, dtype=torch.float32))\n"
|
|
115
|
+
]
|
|
116
|
+
}
|
|
117
|
+
],
|
|
118
|
+
"source": [
|
|
119
|
+
"# generate predictions for new x inputs\n",
|
|
120
|
+
"x_new = simulator.sample_inputs(10)\n",
|
|
121
|
+
"output = gp.predict(torch.tensor(x_new, dtype=torch.float32))\n",
|
|
122
|
+
"pred_means, pred_vars = (\n",
|
|
123
|
+
" output.mean.float().detach(),\n",
|
|
124
|
+
" output.variance.float().detach(),\n",
|
|
125
|
+
")"
|
|
126
|
+
]
|
|
127
|
+
},
|
|
128
|
+
{
|
|
129
|
+
"cell_type": "code",
|
|
130
|
+
"execution_count": 5,
|
|
131
|
+
"metadata": {},
|
|
132
|
+
"outputs": [],
|
|
133
|
+
"source": [
|
|
134
|
+
"# Define observed data with means and variances\n",
|
|
135
|
+
"observations = {\"infection_rate\": (0.3, 0.05)}\n",
|
|
136
|
+
"\n",
|
|
137
|
+
"# Create history matcher\n",
|
|
138
|
+
"hm = HistoryMatching(\n",
|
|
139
|
+
" observations=observations,\n",
|
|
140
|
+
" threshold=3.0\n",
|
|
141
|
+
")"
|
|
142
|
+
]
|
|
143
|
+
},
|
|
144
|
+
{
|
|
145
|
+
"cell_type": "code",
|
|
146
|
+
"execution_count": 6,
|
|
147
|
+
"metadata": {},
|
|
148
|
+
"outputs": [],
|
|
149
|
+
"source": [
|
|
150
|
+
"implausability = hm.calculate_implausibility(pred_means, pred_vars)"
|
|
151
|
+
]
|
|
152
|
+
},
|
|
153
|
+
{
|
|
154
|
+
"cell_type": "markdown",
|
|
155
|
+
"metadata": {},
|
|
156
|
+
"source": [
|
|
157
|
+
"Once implausability has been calculated, it can be used to identify indices of NROY parameters:"
|
|
158
|
+
]
|
|
159
|
+
},
|
|
160
|
+
{
|
|
161
|
+
"cell_type": "code",
|
|
162
|
+
"execution_count": 7,
|
|
163
|
+
"metadata": {},
|
|
164
|
+
"outputs": [
|
|
165
|
+
{
|
|
166
|
+
"data": {
|
|
167
|
+
"text/plain": [
|
|
168
|
+
"tensor([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])"
|
|
169
|
+
]
|
|
170
|
+
},
|
|
171
|
+
"execution_count": 7,
|
|
172
|
+
"metadata": {},
|
|
173
|
+
"output_type": "execute_result"
|
|
174
|
+
}
|
|
175
|
+
],
|
|
176
|
+
"source": [
|
|
177
|
+
"hm.get_nroy(implausability)"
|
|
178
|
+
]
|
|
179
|
+
},
|
|
180
|
+
{
|
|
181
|
+
"cell_type": "markdown",
|
|
182
|
+
"metadata": {},
|
|
183
|
+
"source": [
|
|
184
|
+
"Or to filter parameters at those NROY indices:"
|
|
185
|
+
]
|
|
186
|
+
},
|
|
187
|
+
{
|
|
188
|
+
"cell_type": "code",
|
|
189
|
+
"execution_count": 8,
|
|
190
|
+
"metadata": {},
|
|
191
|
+
"outputs": [
|
|
192
|
+
{
|
|
193
|
+
"data": {
|
|
194
|
+
"text/plain": [
|
|
195
|
+
"tensor([[0.1709, 0.0508],\n",
|
|
196
|
+
" [0.4401, 0.0828],\n",
|
|
197
|
+
" [0.3762, 0.0232],\n",
|
|
198
|
+
" [0.1998, 0.1910],\n",
|
|
199
|
+
" [0.3041, 0.1451],\n",
|
|
200
|
+
" [0.2680, 0.0296],\n",
|
|
201
|
+
" [0.4938, 0.1741],\n",
|
|
202
|
+
" [0.2367, 0.0964],\n",
|
|
203
|
+
" [0.1025, 0.1294],\n",
|
|
204
|
+
" [0.3978, 0.1181]])"
|
|
205
|
+
]
|
|
206
|
+
},
|
|
207
|
+
"execution_count": 8,
|
|
208
|
+
"metadata": {},
|
|
209
|
+
"output_type": "execute_result"
|
|
210
|
+
}
|
|
211
|
+
],
|
|
212
|
+
"source": [
|
|
213
|
+
"\n",
|
|
214
|
+
"hm.get_nroy(implausability, x_new)"
|
|
215
|
+
]
|
|
216
|
+
},
|
|
217
|
+
{
|
|
218
|
+
"cell_type": "markdown",
|
|
219
|
+
"metadata": {},
|
|
220
|
+
"source": [
|
|
221
|
+
"Optionally, `HistoryMatching` can be instantiated with an emulator to make extracting prediction means and variances easier."
|
|
222
|
+
]
|
|
223
|
+
},
|
|
224
|
+
{
|
|
225
|
+
"cell_type": "code",
|
|
226
|
+
"execution_count": 9,
|
|
227
|
+
"metadata": {},
|
|
228
|
+
"outputs": [
|
|
229
|
+
{
|
|
230
|
+
"data": {
|
|
231
|
+
"text/plain": [
|
|
232
|
+
"tensor([[0.0526],\n",
|
|
233
|
+
" [0.0409],\n",
|
|
234
|
+
" [0.0536],\n",
|
|
235
|
+
" [0.0313],\n",
|
|
236
|
+
" [0.0283],\n",
|
|
237
|
+
" [0.0547],\n",
|
|
238
|
+
" [0.0281],\n",
|
|
239
|
+
" [0.0363],\n",
|
|
240
|
+
" [0.0300],\n",
|
|
241
|
+
" [0.0315]])"
|
|
242
|
+
]
|
|
243
|
+
},
|
|
244
|
+
"execution_count": 9,
|
|
245
|
+
"metadata": {},
|
|
246
|
+
"output_type": "execute_result"
|
|
247
|
+
}
|
|
248
|
+
],
|
|
249
|
+
"source": [
|
|
250
|
+
"hm_with_emul = HistoryMatching(\n",
|
|
251
|
+
" observations=observations,\n",
|
|
252
|
+
" threshold=3.0,\n",
|
|
253
|
+
" emulator=gp\n",
|
|
254
|
+
")\n",
|
|
255
|
+
"\n",
|
|
256
|
+
"pred_means, pred_vars = hm_with_emul.emulator_predict(x_new)\n",
|
|
257
|
+
"hm_with_emul.calculate_implausibility(pred_means, pred_vars)"
|
|
258
|
+
]
|
|
259
|
+
},
|
|
260
|
+
{
|
|
261
|
+
"cell_type": "markdown",
|
|
262
|
+
"metadata": {},
|
|
263
|
+
"source": [
|
|
264
|
+
"## 3. Iterative HistoryMatchingWorkflow\n",
|
|
265
|
+
"\n",
|
|
266
|
+
"We also have a separate class that implements an iterative sample-predict-refit workflow:\n",
|
|
267
|
+
"- sample `n_test_samples` to test from the NROY space\n",
|
|
268
|
+
"- use emulator to filter out implausible samples and update the NROY space\n",
|
|
269
|
+
"- run `n_simulations` predictions for the sampled parameters using the simulator\n",
|
|
270
|
+
"- refit the emulator using the simulated data\n",
|
|
271
|
+
"\n",
|
|
272
|
+
"The object maintains and updates the internal state each time `run()` is called so this can be done as many times as the user wants."
|
|
273
|
+
]
|
|
274
|
+
},
|
|
275
|
+
{
|
|
276
|
+
"cell_type": "code",
|
|
277
|
+
"execution_count": 10,
|
|
278
|
+
"metadata": {},
|
|
279
|
+
"outputs": [
|
|
280
|
+
{
|
|
281
|
+
"name": "stderr",
|
|
282
|
+
"output_type": "stream",
|
|
283
|
+
"text": [
|
|
284
|
+
"Running simulations: 100%|██████████| 20/20 [00:00<00:00, 1140.05it/s]"
|
|
285
|
+
]
|
|
286
|
+
},
|
|
287
|
+
{
|
|
288
|
+
"name": "stdout",
|
|
289
|
+
"output_type": "stream",
|
|
290
|
+
"text": [
|
|
291
|
+
"Successfully completed 20/20 simulations (100.0%)\n"
|
|
292
|
+
]
|
|
293
|
+
},
|
|
294
|
+
{
|
|
295
|
+
"name": "stderr",
|
|
296
|
+
"output_type": "stream",
|
|
297
|
+
"text": [
|
|
298
|
+
"\n"
|
|
299
|
+
]
|
|
300
|
+
}
|
|
301
|
+
],
|
|
302
|
+
"source": [
|
|
303
|
+
"hmw = HistoryMatchingWorkflow(\n",
|
|
304
|
+
" simulator=simulator,\n",
|
|
305
|
+
" emulator=gp,\n",
|
|
306
|
+
" observations=observations,\n",
|
|
307
|
+
" threshold=3.0,\n",
|
|
308
|
+
" train_x=x,\n",
|
|
309
|
+
" train_y=y\n",
|
|
310
|
+
")\n",
|
|
311
|
+
"\n",
|
|
312
|
+
"test_parameters, impl_scores = hmw.run(n_simulations=20, n_test_samples=100)"
|
|
313
|
+
]
|
|
314
|
+
},
|
|
315
|
+
{
|
|
316
|
+
"cell_type": "code",
|
|
317
|
+
"execution_count": 11,
|
|
318
|
+
"metadata": {},
|
|
319
|
+
"outputs": [
|
|
320
|
+
{
|
|
321
|
+
"data": {
|
|
322
|
+
"text/plain": [
|
|
323
|
+
"(torch.Size([100, 2]), torch.Size([100, 1]))"
|
|
324
|
+
]
|
|
325
|
+
},
|
|
326
|
+
"execution_count": 11,
|
|
327
|
+
"metadata": {},
|
|
328
|
+
"output_type": "execute_result"
|
|
329
|
+
}
|
|
330
|
+
],
|
|
331
|
+
"source": [
|
|
332
|
+
"test_parameters.shape, impl_scores.shape"
|
|
333
|
+
]
|
|
334
|
+
},
|
|
335
|
+
{
|
|
336
|
+
"cell_type": "markdown",
|
|
337
|
+
"metadata": {},
|
|
338
|
+
"source": [
|
|
339
|
+
"We can call `run()` as many times as we want, the class stores states from previous runs."
|
|
340
|
+
]
|
|
341
|
+
},
|
|
342
|
+
{
|
|
343
|
+
"cell_type": "code",
|
|
344
|
+
"execution_count": 12,
|
|
345
|
+
"metadata": {},
|
|
346
|
+
"outputs": [
|
|
347
|
+
{
|
|
348
|
+
"name": "stderr",
|
|
349
|
+
"output_type": "stream",
|
|
350
|
+
"text": [
|
|
351
|
+
"Running simulations: 100%|██████████| 20/20 [00:00<00:00, 1008.67it/s]"
|
|
352
|
+
]
|
|
353
|
+
},
|
|
354
|
+
{
|
|
355
|
+
"name": "stdout",
|
|
356
|
+
"output_type": "stream",
|
|
357
|
+
"text": [
|
|
358
|
+
"Successfully completed 20/20 simulations (100.0%)\n"
|
|
359
|
+
]
|
|
360
|
+
},
|
|
361
|
+
{
|
|
362
|
+
"name": "stderr",
|
|
363
|
+
"output_type": "stream",
|
|
364
|
+
"text": [
|
|
365
|
+
"\n"
|
|
366
|
+
]
|
|
367
|
+
}
|
|
368
|
+
],
|
|
369
|
+
"source": [
|
|
370
|
+
"test_parameters, impl_scores = hmw.run(n_simulations=20, n_test_samples=100)"
|
|
371
|
+
]
|
|
372
|
+
},
|
|
373
|
+
{
|
|
374
|
+
"cell_type": "markdown",
|
|
375
|
+
"metadata": {},
|
|
376
|
+
"source": [
|
|
377
|
+
"## 4. Integration with dashboard"
|
|
378
|
+
]
|
|
379
|
+
},
|
|
380
|
+
{
|
|
381
|
+
"cell_type": "code",
|
|
382
|
+
"execution_count": 13,
|
|
383
|
+
"metadata": {},
|
|
384
|
+
"outputs": [],
|
|
385
|
+
"source": [
|
|
386
|
+
"dashboard = HistoryMatchingDashboard(\n",
|
|
387
|
+
" samples=test_parameters,\n",
|
|
388
|
+
" impl_scores=impl_scores,\n",
|
|
389
|
+
" param_names=simulator.param_names, \n",
|
|
390
|
+
" output_names=simulator.output_names, \n",
|
|
391
|
+
" )"
|
|
392
|
+
]
|
|
393
|
+
},
|
|
394
|
+
{
|
|
395
|
+
"cell_type": "code",
|
|
396
|
+
"execution_count": 14,
|
|
397
|
+
"metadata": {},
|
|
398
|
+
"outputs": [
|
|
399
|
+
{
|
|
400
|
+
"data": {
|
|
401
|
+
"application/vnd.jupyter.widget-view+json": {
|
|
402
|
+
"model_id": "c0a1f4ff869a4acf86ed20bf20689055",
|
|
403
|
+
"version_major": 2,
|
|
404
|
+
"version_minor": 0
|
|
405
|
+
},
|
|
406
|
+
"text/plain": [
|
|
407
|
+
"HTML(value='<h2>History Matching Dashboard</h2>')"
|
|
408
|
+
]
|
|
409
|
+
},
|
|
410
|
+
"metadata": {},
|
|
411
|
+
"output_type": "display_data"
|
|
412
|
+
},
|
|
413
|
+
{
|
|
414
|
+
"data": {
|
|
415
|
+
"application/vnd.jupyter.widget-view+json": {
|
|
416
|
+
"model_id": "f83c37cf211246d6a8753961a7c02639",
|
|
417
|
+
"version_major": 2,
|
|
418
|
+
"version_minor": 0
|
|
419
|
+
},
|
|
420
|
+
"text/plain": [
|
|
421
|
+
"VBox(children=(HBox(children=(Dropdown(description='Plot Type:', options=('Parameter vs Implausibility', 'Pair…"
|
|
422
|
+
]
|
|
423
|
+
},
|
|
424
|
+
"metadata": {},
|
|
425
|
+
"output_type": "display_data"
|
|
426
|
+
}
|
|
427
|
+
],
|
|
428
|
+
"source": [
|
|
429
|
+
"dashboard.display()"
|
|
430
|
+
]
|
|
431
|
+
}
|
|
432
|
+
],
|
|
433
|
+
"metadata": {
|
|
434
|
+
"kernelspec": {
|
|
435
|
+
"display_name": ".venv",
|
|
436
|
+
"language": "python",
|
|
437
|
+
"name": "python3"
|
|
438
|
+
},
|
|
439
|
+
"language_info": {
|
|
440
|
+
"codemirror_mode": {
|
|
441
|
+
"name": "ipython",
|
|
442
|
+
"version": 3
|
|
443
|
+
},
|
|
444
|
+
"file_extension": ".py",
|
|
445
|
+
"mimetype": "text/x-python",
|
|
446
|
+
"name": "python",
|
|
447
|
+
"nbconvert_exporter": "python",
|
|
448
|
+
"pygments_lexer": "ipython3",
|
|
449
|
+
"version": "3.12.4"
|
|
450
|
+
}
|
|
451
|
+
},
|
|
452
|
+
"nbformat": 4,
|
|
453
|
+
"nbformat_minor": 2
|
|
454
|
+
}
|