autoemulate 0.3.2__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.
Files changed (89) hide show
  1. {autoemulate-0.3.2 → autoemulate-0.4.0}/PKG-INFO +4 -2
  2. {autoemulate-0.3.2 → autoemulate-0.4.0}/README.md +1 -1
  3. {autoemulate-0.3.2 → autoemulate-0.4.0}/autoemulate/compare.py +1 -12
  4. {autoemulate-0.3.2 → autoemulate-0.4.0}/autoemulate/emulators/__init__.py +0 -12
  5. {autoemulate-0.3.2 → autoemulate-0.4.0}/autoemulate/experimental/data/utils.py +3 -3
  6. autoemulate-0.4.0/autoemulate/experimental/emulators/gradient_boosting.py +80 -0
  7. {autoemulate-0.3.2 → autoemulate-0.4.0}/autoemulate/experimental/emulators/lightgbm.py +1 -1
  8. {autoemulate-0.3.2 → autoemulate-0.4.0}/autoemulate/experimental/emulators/neural_processes/conditional_neural_process.py +2 -2
  9. autoemulate-0.4.0/autoemulate/experimental/exploratory/hm_refactor.ipynb +454 -0
  10. autoemulate-0.4.0/autoemulate/experimental/history_matching.py +487 -0
  11. {autoemulate-0.3.2 → autoemulate-0.4.0}/autoemulate/experimental/learners/base.py +2 -65
  12. autoemulate-0.4.0/autoemulate/experimental/sensitivity_analysis.py +258 -0
  13. autoemulate-0.4.0/autoemulate/experimental/simulations/base.py +175 -0
  14. autoemulate-0.4.0/autoemulate/experimental/simulations/epidemic.py +40 -0
  15. autoemulate-0.4.0/autoemulate/experimental/simulations/projectile.py +76 -0
  16. {autoemulate-0.3.2 → autoemulate-0.4.0}/autoemulate/history_matching_dashboard.py +17 -8
  17. autoemulate-0.4.0/autoemulate/mcmc.py +348 -0
  18. autoemulate-0.4.0/autoemulate/mcmc_dashboard.py +818 -0
  19. {autoemulate-0.3.2 → autoemulate-0.4.0}/autoemulate/sensitivity_analysis.py +22 -9
  20. {autoemulate-0.3.2 → autoemulate-0.4.0}/autoemulate/simulations/epidemic.py +30 -0
  21. {autoemulate-0.3.2 → autoemulate-0.4.0}/autoemulate/simulations/projectile.py +30 -0
  22. {autoemulate-0.3.2 → autoemulate-0.4.0}/pyproject.toml +4 -2
  23. {autoemulate-0.3.2 → autoemulate-0.4.0}/LICENSE +0 -0
  24. {autoemulate-0.3.2 → autoemulate-0.4.0}/autoemulate/__init__.py +0 -0
  25. {autoemulate-0.3.2 → autoemulate-0.4.0}/autoemulate/cross_validate.py +0 -0
  26. {autoemulate-0.3.2 → autoemulate-0.4.0}/autoemulate/data_splitting.py +0 -0
  27. {autoemulate-0.3.2 → autoemulate-0.4.0}/autoemulate/datasets.py +0 -0
  28. {autoemulate-0.3.2 → autoemulate-0.4.0}/autoemulate/emulators/conditional_neural_process.py +0 -0
  29. {autoemulate-0.3.2 → autoemulate-0.4.0}/autoemulate/emulators/conditional_neural_process_attn.py +0 -0
  30. {autoemulate-0.3.2 → autoemulate-0.4.0}/autoemulate/emulators/gaussian_process.py +0 -0
  31. {autoemulate-0.3.2 → autoemulate-0.4.0}/autoemulate/emulators/gaussian_process_mogp.py +0 -0
  32. {autoemulate-0.3.2 → autoemulate-0.4.0}/autoemulate/emulators/gaussian_process_mt.py +0 -0
  33. {autoemulate-0.3.2 → autoemulate-0.4.0}/autoemulate/emulators/gaussian_process_sklearn.py +0 -0
  34. {autoemulate-0.3.2 → autoemulate-0.4.0}/autoemulate/emulators/gaussian_process_utils/__init__.py +0 -0
  35. {autoemulate-0.3.2 → autoemulate-0.4.0}/autoemulate/emulators/gaussian_process_utils/early_stopping_criterion.py +0 -0
  36. {autoemulate-0.3.2 → autoemulate-0.4.0}/autoemulate/emulators/gaussian_process_utils/poly_mean.py +0 -0
  37. {autoemulate-0.3.2 → autoemulate-0.4.0}/autoemulate/emulators/gaussian_process_utils/polynomial_features.py +0 -0
  38. {autoemulate-0.3.2 → autoemulate-0.4.0}/autoemulate/emulators/gradient_boosting.py +0 -0
  39. {autoemulate-0.3.2 → autoemulate-0.4.0}/autoemulate/emulators/light_gbm.py +0 -0
  40. {autoemulate-0.3.2 → autoemulate-0.4.0}/autoemulate/emulators/neural_net_sk.py +0 -0
  41. {autoemulate-0.3.2 → autoemulate-0.4.0}/autoemulate/emulators/neural_networks/__init__.py +0 -0
  42. {autoemulate-0.3.2 → autoemulate-0.4.0}/autoemulate/emulators/neural_networks/cnp_module.py +0 -0
  43. {autoemulate-0.3.2 → autoemulate-0.4.0}/autoemulate/emulators/neural_networks/cnp_module_attn.py +0 -0
  44. {autoemulate-0.3.2 → autoemulate-0.4.0}/autoemulate/emulators/neural_networks/datasets.py +0 -0
  45. {autoemulate-0.3.2 → autoemulate-0.4.0}/autoemulate/emulators/neural_networks/gp_module.py +0 -0
  46. {autoemulate-0.3.2 → autoemulate-0.4.0}/autoemulate/emulators/neural_networks/losses.py +0 -0
  47. {autoemulate-0.3.2 → autoemulate-0.4.0}/autoemulate/emulators/polynomials.py +0 -0
  48. {autoemulate-0.3.2 → autoemulate-0.4.0}/autoemulate/emulators/radial_basis_functions.py +0 -0
  49. {autoemulate-0.3.2 → autoemulate-0.4.0}/autoemulate/emulators/random_forest.py +0 -0
  50. {autoemulate-0.3.2 → autoemulate-0.4.0}/autoemulate/emulators/support_vector_machines.py +0 -0
  51. {autoemulate-0.3.2 → autoemulate-0.4.0}/autoemulate/experimental/__init__.py +0 -0
  52. {autoemulate-0.3.2 → autoemulate-0.4.0}/autoemulate/experimental/compare.py +0 -0
  53. {autoemulate-0.3.2 → autoemulate-0.4.0}/autoemulate/experimental/data/preprocessors.py +0 -0
  54. {autoemulate-0.3.2 → autoemulate-0.4.0}/autoemulate/experimental/device.py +0 -0
  55. {autoemulate-0.3.2 → autoemulate-0.4.0}/autoemulate/experimental/emulators/__init__.py +0 -0
  56. {autoemulate-0.3.2 → autoemulate-0.4.0}/autoemulate/experimental/emulators/base.py +0 -0
  57. {autoemulate-0.3.2 → autoemulate-0.4.0}/autoemulate/experimental/emulators/gaussian_process/__init__.py +0 -0
  58. {autoemulate-0.3.2 → autoemulate-0.4.0}/autoemulate/experimental/emulators/gaussian_process/exact.py +0 -0
  59. {autoemulate-0.3.2 → autoemulate-0.4.0}/autoemulate/experimental/emulators/random_forest.py +0 -0
  60. {autoemulate-0.3.2 → autoemulate-0.4.0}/autoemulate/experimental/emulators/svm.py +0 -0
  61. {autoemulate-0.3.2 → autoemulate-0.4.0}/autoemulate/experimental/exploratory/active_matter/README.md +0 -0
  62. {autoemulate-0.3.2 → autoemulate-0.4.0}/autoemulate/experimental/exploratory/active_matter/active_matter.ipynb +0 -0
  63. {autoemulate-0.3.2 → autoemulate-0.4.0}/autoemulate/experimental/learners/__init__.py +0 -0
  64. {autoemulate-0.3.2 → autoemulate-0.4.0}/autoemulate/experimental/learners/membership.py +0 -0
  65. {autoemulate-0.3.2 → autoemulate-0.4.0}/autoemulate/experimental/learners/pool.py +0 -0
  66. {autoemulate-0.3.2 → autoemulate-0.4.0}/autoemulate/experimental/learners/stream.py +0 -0
  67. {autoemulate-0.3.2 → autoemulate-0.4.0}/autoemulate/experimental/model_selection.py +0 -0
  68. {autoemulate-0.3.2 → autoemulate-0.4.0}/autoemulate/experimental/simulations/__init__.py +0 -0
  69. {autoemulate-0.3.2 → autoemulate-0.4.0}/autoemulate/experimental/tuner.py +0 -0
  70. {autoemulate-0.3.2 → autoemulate-0.4.0}/autoemulate/experimental/types.py +0 -0
  71. {autoemulate-0.3.2 → autoemulate-0.4.0}/autoemulate/experimental_design.py +0 -0
  72. {autoemulate-0.3.2 → autoemulate-0.4.0}/autoemulate/history_matching.py +0 -0
  73. {autoemulate-0.3.2 → autoemulate-0.4.0}/autoemulate/hyperparam_searching.py +0 -0
  74. {autoemulate-0.3.2 → autoemulate-0.4.0}/autoemulate/logging_config.py +0 -0
  75. {autoemulate-0.3.2 → autoemulate-0.4.0}/autoemulate/metrics.py +0 -0
  76. {autoemulate-0.3.2 → autoemulate-0.4.0}/autoemulate/model_processing.py +0 -0
  77. {autoemulate-0.3.2 → autoemulate-0.4.0}/autoemulate/model_registry.py +0 -0
  78. {autoemulate-0.3.2 → autoemulate-0.4.0}/autoemulate/plotting.py +0 -0
  79. {autoemulate-0.3.2 → autoemulate-0.4.0}/autoemulate/preprocess_target.py +0 -0
  80. {autoemulate-0.3.2 → autoemulate-0.4.0}/autoemulate/printing.py +0 -0
  81. {autoemulate-0.3.2 → autoemulate-0.4.0}/autoemulate/save.py +0 -0
  82. {autoemulate-0.3.2 → autoemulate-0.4.0}/autoemulate/simulations/__init__.py +0 -0
  83. {autoemulate-0.3.2 → autoemulate-0.4.0}/autoemulate/simulations/base.py +0 -0
  84. {autoemulate-0.3.2 → autoemulate-0.4.0}/autoemulate/simulations/circ_utils.py +0 -0
  85. {autoemulate-0.3.2 → autoemulate-0.4.0}/autoemulate/simulations/flow_functions.py +0 -0
  86. {autoemulate-0.3.2 → autoemulate-0.4.0}/autoemulate/simulations/naghavi_cardiac_ModularCirc.py +0 -0
  87. {autoemulate-0.3.2 → autoemulate-0.4.0}/autoemulate/simulations/reaction_diffusion.py +0 -0
  88. {autoemulate-0.3.2 → autoemulate-0.4.0}/autoemulate/utils.py +0 -0
  89. {autoemulate-0.3.2 → 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.2
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)
@@ -12,6 +12,7 @@ Classifier: Programming Language :: Python :: 3.11
12
12
  Classifier: Programming Language :: Python :: 3.12
13
13
  Provides-Extra: docs
14
14
  Requires-Dist: anytree (>=2.12.1,<3.0.0)
15
+ Requires-Dist: corner (>=2.2.3,<3.0.0)
15
16
  Requires-Dist: gpytorch (>=1.12,<2.0)
16
17
  Requires-Dist: iprogress (>=0.4,<0.5)
17
18
  Requires-Dist: ipywidgets (>=8.1.2,<9.0.0)
@@ -21,6 +22,7 @@ Requires-Dist: matplotlib (>=3.7.2,<4.0.0)
21
22
  Requires-Dist: mogp-emulator (>=0.7.2,<0.8.0)
22
23
  Requires-Dist: numpy (>=1.24,<2.0)
23
24
  Requires-Dist: pandas (>=2.1,<3.0)
25
+ Requires-Dist: pyro-ppl (>=1.9.1,<2.0.0)
24
26
  Requires-Dist: salib (>=1.5.1,<2.0.0)
25
27
  Requires-Dist: scikit-learn (>=1.3.0,<1.6.0)
26
28
  Requires-Dist: scipy (>=1.11.3,<2.0.0)
@@ -41,7 +43,7 @@ Description-Content-Type: text/markdown
41
43
  [![Documentation](https://img.shields.io/badge/documentation-blue)](https://alan-turing-institute.github.io/autoemulate/)
42
44
 
43
45
  <!-- SPHINX-START -->
44
- 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, Gaussian Processes and Conditional Neural Processes to find the best emulator for a simulation.
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.
45
47
 
46
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.
47
49
 
@@ -7,7 +7,7 @@
7
7
  [![Documentation](https://img.shields.io/badge/documentation-blue)](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, Gaussian Processes and Conditional Neural Processes to find the best emulator for a simulation.
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 or dict
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, (torch.Tensor, np.ndarray)) and isinstance(
33
- y, (torch.Tensor, np.ndarray)
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, (torch.Tensor, np.ndarray)) and y is None:
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, (spmatrix, list))
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
+ }