ennbo 0.1.0__py3-none-any.whl → 0.1.7__py3-none-any.whl
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.
- enn/__init__.py +25 -13
- enn/benchmarks/__init__.py +3 -0
- enn/benchmarks/ackley.py +5 -0
- enn/benchmarks/ackley_class.py +17 -0
- enn/benchmarks/ackley_core.py +12 -0
- enn/benchmarks/double_ackley.py +24 -0
- enn/enn/candidates.py +14 -0
- enn/enn/conditional_posterior_draw_internals.py +15 -0
- enn/enn/draw_internals.py +15 -0
- enn/enn/enn.py +16 -229
- enn/enn/enn_class.py +423 -0
- enn/enn/enn_conditional.py +325 -0
- enn/enn/enn_fit.py +77 -76
- enn/enn/enn_hash.py +79 -0
- enn/enn/enn_index.py +92 -0
- enn/enn/enn_like_protocol.py +35 -0
- enn/enn/enn_normal.py +3 -3
- enn/enn/enn_params.py +3 -9
- enn/enn/enn_params_class.py +24 -0
- enn/enn/enn_util.py +79 -37
- enn/enn/neighbor_data.py +14 -0
- enn/enn/neighbors.py +14 -0
- enn/enn/posterior_flags.py +8 -0
- enn/enn/weighted_stats.py +14 -0
- enn/turbo/components/__init__.py +41 -0
- enn/turbo/components/acquisition.py +13 -0
- enn/turbo/components/acquisition_optimizer_protocol.py +19 -0
- enn/turbo/components/builder.py +22 -0
- enn/turbo/components/chebyshev_incumbent_selector.py +76 -0
- enn/turbo/components/enn_surrogate.py +115 -0
- enn/turbo/components/gp_surrogate.py +144 -0
- enn/turbo/components/hnr_acq_optimizer.py +83 -0
- enn/turbo/components/incumbent_selector.py +11 -0
- enn/turbo/components/incumbent_selector_protocol.py +16 -0
- enn/turbo/components/no_incumbent_selector.py +21 -0
- enn/turbo/components/no_surrogate.py +49 -0
- enn/turbo/components/pareto_acq_optimizer.py +49 -0
- enn/turbo/components/posterior_result.py +12 -0
- enn/turbo/components/protocols.py +13 -0
- enn/turbo/components/random_acq_optimizer.py +21 -0
- enn/turbo/components/scalar_incumbent_selector.py +39 -0
- enn/turbo/components/surrogate_protocol.py +32 -0
- enn/turbo/components/surrogate_result.py +12 -0
- enn/turbo/components/surrogates.py +5 -0
- enn/turbo/components/thompson_acq_optimizer.py +49 -0
- enn/turbo/components/trust_region_protocol.py +24 -0
- enn/turbo/components/ucb_acq_optimizer.py +49 -0
- enn/turbo/config/__init__.py +87 -0
- enn/turbo/config/acq_type.py +8 -0
- enn/turbo/config/acquisition.py +26 -0
- enn/turbo/config/base.py +4 -0
- enn/turbo/config/candidate_gen_config.py +49 -0
- enn/turbo/config/candidate_rv.py +7 -0
- enn/turbo/config/draw_acquisition_config.py +14 -0
- enn/turbo/config/enn_index_driver.py +6 -0
- enn/turbo/config/enn_surrogate_config.py +42 -0
- enn/turbo/config/enums.py +7 -0
- enn/turbo/config/factory.py +118 -0
- enn/turbo/config/gp_surrogate_config.py +14 -0
- enn/turbo/config/hnr_optimizer_config.py +7 -0
- enn/turbo/config/init_config.py +17 -0
- enn/turbo/config/init_strategies/__init__.py +9 -0
- enn/turbo/config/init_strategies/hybrid_init.py +23 -0
- enn/turbo/config/init_strategies/init_strategy.py +19 -0
- enn/turbo/config/init_strategies/lhd_only_init.py +24 -0
- enn/turbo/config/morbo_tr_config.py +82 -0
- enn/turbo/config/nds_optimizer_config.py +7 -0
- enn/turbo/config/no_surrogate_config.py +14 -0
- enn/turbo/config/no_tr_config.py +31 -0
- enn/turbo/config/optimizer_config.py +72 -0
- enn/turbo/config/pareto_acquisition_config.py +14 -0
- enn/turbo/config/raasp_driver.py +6 -0
- enn/turbo/config/raasp_optimizer_config.py +7 -0
- enn/turbo/config/random_acquisition_config.py +14 -0
- enn/turbo/config/rescalarize.py +7 -0
- enn/turbo/config/surrogate.py +12 -0
- enn/turbo/config/trust_region.py +34 -0
- enn/turbo/config/turbo_tr_config.py +71 -0
- enn/turbo/config/ucb_acquisition_config.py +14 -0
- enn/turbo/config/validation.py +45 -0
- enn/turbo/hypervolume.py +30 -0
- enn/turbo/impl_helpers.py +68 -0
- enn/turbo/morbo_trust_region.py +250 -0
- enn/turbo/no_trust_region.py +58 -0
- enn/turbo/optimizer.py +300 -0
- enn/turbo/optimizer_config.py +8 -0
- enn/turbo/proposal.py +46 -39
- enn/turbo/sampling.py +21 -0
- enn/turbo/strategies/__init__.py +9 -0
- enn/turbo/strategies/lhd_only_strategy.py +36 -0
- enn/turbo/strategies/optimization_strategy.py +19 -0
- enn/turbo/strategies/turbo_hybrid_strategy.py +124 -0
- enn/turbo/tr_helpers.py +202 -0
- enn/turbo/turbo_gp.py +9 -2
- enn/turbo/turbo_gp_base.py +0 -1
- enn/turbo/turbo_gp_fit.py +187 -0
- enn/turbo/turbo_gp_noisy.py +0 -1
- enn/turbo/turbo_optimizer_utils.py +98 -0
- enn/turbo/turbo_trust_region.py +129 -63
- enn/turbo/turbo_utils.py +144 -117
- enn/turbo/types/__init__.py +7 -0
- enn/turbo/types/appendable_array.py +85 -0
- enn/turbo/types/gp_data_prep.py +13 -0
- enn/turbo/types/gp_fit_result.py +11 -0
- enn/turbo/types/obs_lists.py +10 -0
- enn/turbo/types/prepare_ask_result.py +14 -0
- enn/turbo/types/tell_inputs.py +14 -0
- {ennbo-0.1.0.dist-info → ennbo-0.1.7.dist-info}/METADATA +22 -14
- ennbo-0.1.7.dist-info/RECORD +111 -0
- enn/enn/__init__.py +0 -4
- enn/turbo/__init__.py +0 -11
- enn/turbo/base_turbo_impl.py +0 -98
- enn/turbo/lhd_only_impl.py +0 -42
- enn/turbo/turbo_config.py +0 -28
- enn/turbo/turbo_enn_impl.py +0 -176
- enn/turbo/turbo_mode.py +0 -10
- enn/turbo/turbo_mode_impl.py +0 -67
- enn/turbo/turbo_one_impl.py +0 -163
- enn/turbo/turbo_optimizer.py +0 -337
- enn/turbo/turbo_zero_impl.py +0 -24
- ennbo-0.1.0.dist-info/RECORD +0 -27
- {ennbo-0.1.0.dist-info → ennbo-0.1.7.dist-info}/WHEEL +0 -0
- {ennbo-0.1.0.dist-info → ennbo-0.1.7.dist-info}/licenses/LICENSE +0 -0
enn/turbo/turbo_enn_impl.py
DELETED
|
@@ -1,176 +0,0 @@
|
|
|
1
|
-
from __future__ import annotations
|
|
2
|
-
|
|
3
|
-
from typing import TYPE_CHECKING, Any, Callable
|
|
4
|
-
|
|
5
|
-
if TYPE_CHECKING:
|
|
6
|
-
import numpy as np
|
|
7
|
-
from numpy.random import Generator
|
|
8
|
-
|
|
9
|
-
from .base_turbo_impl import BaseTurboImpl
|
|
10
|
-
from .turbo_config import TurboConfig
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
class TurboENNImpl(BaseTurboImpl):
|
|
14
|
-
def __init__(self, config: TurboConfig) -> None:
|
|
15
|
-
super().__init__(config)
|
|
16
|
-
self._enn: Any | None = None
|
|
17
|
-
self._fitted_params: Any | None = None
|
|
18
|
-
self._fitted_n_obs: int = 0
|
|
19
|
-
|
|
20
|
-
def get_x_center(
|
|
21
|
-
self,
|
|
22
|
-
x_obs_list: list,
|
|
23
|
-
y_obs_list: list,
|
|
24
|
-
rng: Generator,
|
|
25
|
-
) -> np.ndarray | None:
|
|
26
|
-
import numpy as np
|
|
27
|
-
|
|
28
|
-
from .turbo_utils import argmax_random_tie
|
|
29
|
-
|
|
30
|
-
if len(y_obs_list) == 0:
|
|
31
|
-
return None
|
|
32
|
-
if self._enn is None or self._fitted_params is None:
|
|
33
|
-
return super().get_x_center(x_obs_list, y_obs_list, rng)
|
|
34
|
-
if self._fitted_n_obs != len(x_obs_list):
|
|
35
|
-
raise RuntimeError(
|
|
36
|
-
f"ENN fitted on {self._fitted_n_obs} obs but get_x_center called with {len(x_obs_list)}"
|
|
37
|
-
)
|
|
38
|
-
|
|
39
|
-
y_array = np.asarray(y_obs_list, dtype=float)
|
|
40
|
-
x_array = np.asarray(x_obs_list, dtype=float)
|
|
41
|
-
|
|
42
|
-
k = self._config.k if self._config.k is not None else 10
|
|
43
|
-
num_top = min(k, len(y_array))
|
|
44
|
-
top_indices = np.argpartition(-y_array, num_top - 1)[:num_top]
|
|
45
|
-
|
|
46
|
-
x_top = x_array[top_indices]
|
|
47
|
-
posterior = self._enn.posterior(x_top, params=self._fitted_params)
|
|
48
|
-
mu = posterior.mu[:, 0]
|
|
49
|
-
|
|
50
|
-
best_idx_in_top = argmax_random_tie(mu, rng=rng)
|
|
51
|
-
return x_top[best_idx_in_top]
|
|
52
|
-
|
|
53
|
-
def needs_tr_list(self) -> bool:
|
|
54
|
-
return True
|
|
55
|
-
|
|
56
|
-
def handle_restart(
|
|
57
|
-
self,
|
|
58
|
-
x_obs_list: list,
|
|
59
|
-
y_obs_list: list,
|
|
60
|
-
yvar_obs_list: list,
|
|
61
|
-
init_idx: int,
|
|
62
|
-
num_init: int,
|
|
63
|
-
) -> tuple[bool, int]:
|
|
64
|
-
x_obs_list.clear()
|
|
65
|
-
y_obs_list.clear()
|
|
66
|
-
yvar_obs_list.clear()
|
|
67
|
-
return True, 0
|
|
68
|
-
|
|
69
|
-
def prepare_ask(
|
|
70
|
-
self,
|
|
71
|
-
x_obs_list: list,
|
|
72
|
-
y_obs_list: list,
|
|
73
|
-
yvar_obs_list: list,
|
|
74
|
-
num_dim: int,
|
|
75
|
-
gp_num_steps: int,
|
|
76
|
-
rng: Any | None = None,
|
|
77
|
-
) -> tuple[Any, float | None, float | None, np.ndarray | None]:
|
|
78
|
-
from .proposal import mk_enn
|
|
79
|
-
|
|
80
|
-
k = self._config.k if self._config.k is not None else 10
|
|
81
|
-
self._enn, self._fitted_params = mk_enn(
|
|
82
|
-
x_obs_list,
|
|
83
|
-
y_obs_list,
|
|
84
|
-
yvar_obs_list=yvar_obs_list,
|
|
85
|
-
k=k,
|
|
86
|
-
num_fit_samples=self._config.num_fit_samples,
|
|
87
|
-
num_fit_candidates=self._config.num_fit_candidates,
|
|
88
|
-
rng=rng,
|
|
89
|
-
params_warm_start=self._fitted_params,
|
|
90
|
-
)
|
|
91
|
-
self._fitted_n_obs = len(x_obs_list)
|
|
92
|
-
return None, None, None, None
|
|
93
|
-
|
|
94
|
-
def select_candidates(
|
|
95
|
-
self,
|
|
96
|
-
x_cand: np.ndarray,
|
|
97
|
-
num_arms: int,
|
|
98
|
-
num_dim: int,
|
|
99
|
-
rng: Generator,
|
|
100
|
-
fallback_fn: Callable[[np.ndarray, int], np.ndarray],
|
|
101
|
-
from_unit_fn: Callable[[np.ndarray], np.ndarray],
|
|
102
|
-
) -> np.ndarray:
|
|
103
|
-
import numpy as np
|
|
104
|
-
|
|
105
|
-
from enn.enn.enn_params import ENNParams
|
|
106
|
-
|
|
107
|
-
acq_type = self._config.acq_type
|
|
108
|
-
k = self._config.k
|
|
109
|
-
var_scale = self._config.var_scale
|
|
110
|
-
|
|
111
|
-
if self._enn is None:
|
|
112
|
-
return fallback_fn(x_cand, num_arms)
|
|
113
|
-
|
|
114
|
-
if self._fitted_params is not None:
|
|
115
|
-
params = self._fitted_params
|
|
116
|
-
else:
|
|
117
|
-
k_val = k if k is not None else 10
|
|
118
|
-
params = ENNParams(
|
|
119
|
-
k=k_val, epi_var_scale=var_scale, ale_homoscedastic_scale=0.0
|
|
120
|
-
)
|
|
121
|
-
|
|
122
|
-
posterior = self._enn.posterior(x_cand, params=params)
|
|
123
|
-
mu = posterior.mu[:, 0]
|
|
124
|
-
se = posterior.se[:, 0]
|
|
125
|
-
|
|
126
|
-
if acq_type == "pareto":
|
|
127
|
-
from enn.enn.enn_util import arms_from_pareto_fronts
|
|
128
|
-
|
|
129
|
-
x_arms = arms_from_pareto_fronts(x_cand, mu, se, num_arms, rng)
|
|
130
|
-
elif acq_type == "ucb":
|
|
131
|
-
scores = mu + se
|
|
132
|
-
shuffled_indices = rng.permutation(len(scores))
|
|
133
|
-
shuffled_scores = scores[shuffled_indices]
|
|
134
|
-
top_k_in_shuffled = np.argpartition(-shuffled_scores, num_arms - 1)[
|
|
135
|
-
:num_arms
|
|
136
|
-
]
|
|
137
|
-
idx = shuffled_indices[top_k_in_shuffled]
|
|
138
|
-
x_arms = x_cand[idx]
|
|
139
|
-
elif acq_type == "thompson":
|
|
140
|
-
samples = posterior.sample(num_samples=1, rng=rng)
|
|
141
|
-
scores = samples[:, 0, 0]
|
|
142
|
-
shuffled_indices = rng.permutation(len(scores))
|
|
143
|
-
shuffled_scores = scores[shuffled_indices]
|
|
144
|
-
top_k_in_shuffled = np.argpartition(-shuffled_scores, num_arms - 1)[
|
|
145
|
-
:num_arms
|
|
146
|
-
]
|
|
147
|
-
idx = shuffled_indices[top_k_in_shuffled]
|
|
148
|
-
x_arms = x_cand[idx]
|
|
149
|
-
else:
|
|
150
|
-
raise ValueError(f"Unknown acq_type: {acq_type}")
|
|
151
|
-
|
|
152
|
-
return from_unit_fn(x_arms)
|
|
153
|
-
|
|
154
|
-
def estimate_y(self, x_unit: np.ndarray, y_observed: np.ndarray) -> np.ndarray:
|
|
155
|
-
if self._enn is None or self._fitted_params is None:
|
|
156
|
-
return y_observed
|
|
157
|
-
posterior = self._enn.posterior(x_unit, params=self._fitted_params)
|
|
158
|
-
return posterior.mu[:, 0]
|
|
159
|
-
|
|
160
|
-
def get_mu_sigma(self, x_unit: np.ndarray) -> tuple[np.ndarray, np.ndarray] | None:
|
|
161
|
-
if self._enn is None:
|
|
162
|
-
return None
|
|
163
|
-
k = self._config.k if self._config.k is not None else 10
|
|
164
|
-
from enn.enn.enn_params import ENNParams
|
|
165
|
-
|
|
166
|
-
params = (
|
|
167
|
-
self._fitted_params
|
|
168
|
-
if self._fitted_params is not None
|
|
169
|
-
else ENNParams(
|
|
170
|
-
k=k, epi_var_scale=self._config.var_scale, ale_homoscedastic_scale=0.0
|
|
171
|
-
)
|
|
172
|
-
)
|
|
173
|
-
posterior = self._enn.posterior(x_unit, params=params, observation_noise=False)
|
|
174
|
-
mu = posterior.mu[:, 0]
|
|
175
|
-
sigma = posterior.se[:, 0]
|
|
176
|
-
return mu, sigma
|
enn/turbo/turbo_mode.py
DELETED
enn/turbo/turbo_mode_impl.py
DELETED
|
@@ -1,67 +0,0 @@
|
|
|
1
|
-
from __future__ import annotations
|
|
2
|
-
|
|
3
|
-
from typing import TYPE_CHECKING, Any, Callable, Protocol
|
|
4
|
-
|
|
5
|
-
if TYPE_CHECKING:
|
|
6
|
-
import numpy as np
|
|
7
|
-
from numpy.random import Generator
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
class TurboModeImpl(Protocol):
|
|
11
|
-
def get_x_center(
|
|
12
|
-
self,
|
|
13
|
-
x_obs_list: list,
|
|
14
|
-
y_obs_list: list,
|
|
15
|
-
rng: Generator,
|
|
16
|
-
) -> np.ndarray | None: ...
|
|
17
|
-
|
|
18
|
-
def needs_tr_list(self) -> bool: ...
|
|
19
|
-
|
|
20
|
-
def create_trust_region(self, num_dim: int, num_arms: int) -> Any: ...
|
|
21
|
-
|
|
22
|
-
def try_early_ask(
|
|
23
|
-
self,
|
|
24
|
-
num_arms: int,
|
|
25
|
-
x_obs_list: list,
|
|
26
|
-
draw_initial_fn: Callable[[int], np.ndarray],
|
|
27
|
-
get_init_lhd_points_fn: Callable[[int], np.ndarray | None],
|
|
28
|
-
) -> np.ndarray | None: ...
|
|
29
|
-
|
|
30
|
-
def handle_restart(
|
|
31
|
-
self,
|
|
32
|
-
x_obs_list: list,
|
|
33
|
-
y_obs_list: list,
|
|
34
|
-
yvar_obs_list: list,
|
|
35
|
-
init_idx: int,
|
|
36
|
-
num_init: int,
|
|
37
|
-
) -> tuple[bool, int]: ...
|
|
38
|
-
|
|
39
|
-
def prepare_ask(
|
|
40
|
-
self,
|
|
41
|
-
x_obs_list: list,
|
|
42
|
-
y_obs_list: list,
|
|
43
|
-
yvar_obs_list: list,
|
|
44
|
-
num_dim: int,
|
|
45
|
-
gp_num_steps: int,
|
|
46
|
-
rng: Generator | Any | None = None,
|
|
47
|
-
) -> tuple[Any, float | None, float | None, np.ndarray | None]: ...
|
|
48
|
-
|
|
49
|
-
def select_candidates(
|
|
50
|
-
self,
|
|
51
|
-
x_cand: np.ndarray,
|
|
52
|
-
num_arms: int,
|
|
53
|
-
num_dim: int,
|
|
54
|
-
rng: Generator,
|
|
55
|
-
fallback_fn: Callable[[np.ndarray, int], np.ndarray],
|
|
56
|
-
from_unit_fn: Callable[[np.ndarray], np.ndarray],
|
|
57
|
-
) -> np.ndarray: ...
|
|
58
|
-
|
|
59
|
-
def update_trust_region(
|
|
60
|
-
self,
|
|
61
|
-
tr_state: Any,
|
|
62
|
-
y_obs_list: list,
|
|
63
|
-
x_center: np.ndarray | None = None,
|
|
64
|
-
k: int | None = None,
|
|
65
|
-
) -> None: ...
|
|
66
|
-
|
|
67
|
-
def estimate_y(self, x_unit: np.ndarray, y_observed: np.ndarray) -> np.ndarray: ...
|
enn/turbo/turbo_one_impl.py
DELETED
|
@@ -1,163 +0,0 @@
|
|
|
1
|
-
from __future__ import annotations
|
|
2
|
-
|
|
3
|
-
from typing import TYPE_CHECKING, Any, Callable
|
|
4
|
-
|
|
5
|
-
if TYPE_CHECKING:
|
|
6
|
-
import numpy as np
|
|
7
|
-
from numpy.random import Generator
|
|
8
|
-
|
|
9
|
-
from .base_turbo_impl import BaseTurboImpl
|
|
10
|
-
from .turbo_config import TurboConfig
|
|
11
|
-
from .turbo_utils import gp_thompson_sample
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
class TurboOneImpl(BaseTurboImpl):
|
|
15
|
-
def __init__(self, config: TurboConfig) -> None:
|
|
16
|
-
super().__init__(config)
|
|
17
|
-
self._gp_model: Any | None = None
|
|
18
|
-
self._gp_y_mean: float = 0.0
|
|
19
|
-
self._gp_y_std: float = 1.0
|
|
20
|
-
self._fitted_n_obs: int = 0
|
|
21
|
-
|
|
22
|
-
def get_x_center(
|
|
23
|
-
self,
|
|
24
|
-
x_obs_list: list,
|
|
25
|
-
y_obs_list: list,
|
|
26
|
-
rng: Generator,
|
|
27
|
-
) -> np.ndarray | None:
|
|
28
|
-
import numpy as np
|
|
29
|
-
import torch
|
|
30
|
-
|
|
31
|
-
from .turbo_utils import argmax_random_tie
|
|
32
|
-
|
|
33
|
-
if len(y_obs_list) == 0:
|
|
34
|
-
return None
|
|
35
|
-
if self._gp_model is None:
|
|
36
|
-
return super().get_x_center(x_obs_list, y_obs_list, rng)
|
|
37
|
-
if self._fitted_n_obs != len(x_obs_list):
|
|
38
|
-
raise RuntimeError(
|
|
39
|
-
f"GP fitted on {self._fitted_n_obs} obs but get_x_center called with {len(x_obs_list)}"
|
|
40
|
-
)
|
|
41
|
-
|
|
42
|
-
x_array = np.asarray(x_obs_list, dtype=float)
|
|
43
|
-
x_torch = torch.as_tensor(x_array, dtype=torch.float64)
|
|
44
|
-
with torch.no_grad():
|
|
45
|
-
posterior = self._gp_model.posterior(x_torch)
|
|
46
|
-
mu = posterior.mean.cpu().numpy().ravel()
|
|
47
|
-
|
|
48
|
-
best_idx = argmax_random_tie(mu, rng=rng)
|
|
49
|
-
return x_array[best_idx]
|
|
50
|
-
|
|
51
|
-
def needs_tr_list(self) -> bool:
|
|
52
|
-
return True
|
|
53
|
-
|
|
54
|
-
def try_early_ask(
|
|
55
|
-
self,
|
|
56
|
-
num_arms: int,
|
|
57
|
-
x_obs_list: list,
|
|
58
|
-
draw_initial_fn: Callable[[int], np.ndarray],
|
|
59
|
-
get_init_lhd_points_fn: Callable[[int], np.ndarray | None],
|
|
60
|
-
) -> np.ndarray | None:
|
|
61
|
-
if len(x_obs_list) == 0:
|
|
62
|
-
return get_init_lhd_points_fn(num_arms)
|
|
63
|
-
return None
|
|
64
|
-
|
|
65
|
-
def handle_restart(
|
|
66
|
-
self,
|
|
67
|
-
x_obs_list: list,
|
|
68
|
-
y_obs_list: list,
|
|
69
|
-
yvar_obs_list: list,
|
|
70
|
-
init_idx: int,
|
|
71
|
-
num_init: int,
|
|
72
|
-
) -> tuple[bool, int]:
|
|
73
|
-
x_obs_list.clear()
|
|
74
|
-
y_obs_list.clear()
|
|
75
|
-
yvar_obs_list.clear()
|
|
76
|
-
return True, 0
|
|
77
|
-
|
|
78
|
-
def prepare_ask(
|
|
79
|
-
self,
|
|
80
|
-
x_obs_list: list,
|
|
81
|
-
y_obs_list: list,
|
|
82
|
-
yvar_obs_list: list,
|
|
83
|
-
num_dim: int,
|
|
84
|
-
gp_num_steps: int,
|
|
85
|
-
rng: Any | None = None,
|
|
86
|
-
) -> tuple[Any, float | None, float | None, np.ndarray | None]:
|
|
87
|
-
import numpy as np
|
|
88
|
-
|
|
89
|
-
from .turbo_utils import fit_gp
|
|
90
|
-
|
|
91
|
-
if len(x_obs_list) == 0:
|
|
92
|
-
return None, None, None, None
|
|
93
|
-
self._gp_model, _likelihood, gp_y_mean_fitted, gp_y_std_fitted = fit_gp(
|
|
94
|
-
x_obs_list,
|
|
95
|
-
y_obs_list,
|
|
96
|
-
num_dim,
|
|
97
|
-
yvar_obs_list=yvar_obs_list if yvar_obs_list else None,
|
|
98
|
-
num_steps=gp_num_steps,
|
|
99
|
-
)
|
|
100
|
-
self._fitted_n_obs = len(x_obs_list)
|
|
101
|
-
if gp_y_mean_fitted is not None:
|
|
102
|
-
self._gp_y_mean = gp_y_mean_fitted
|
|
103
|
-
if gp_y_std_fitted is not None:
|
|
104
|
-
self._gp_y_std = gp_y_std_fitted
|
|
105
|
-
weights = None
|
|
106
|
-
if self._gp_model is not None:
|
|
107
|
-
weights = (
|
|
108
|
-
self._gp_model.covar_module.base_kernel.lengthscale.cpu()
|
|
109
|
-
.detach()
|
|
110
|
-
.numpy()
|
|
111
|
-
.ravel()
|
|
112
|
-
)
|
|
113
|
-
# First line helps stabilize second line.
|
|
114
|
-
weights = weights / weights.mean()
|
|
115
|
-
weights = weights / np.prod(np.power(weights, 1.0 / len(weights)))
|
|
116
|
-
return self._gp_model, gp_y_mean_fitted, gp_y_std_fitted, weights
|
|
117
|
-
|
|
118
|
-
def select_candidates(
|
|
119
|
-
self,
|
|
120
|
-
x_cand: np.ndarray,
|
|
121
|
-
num_arms: int,
|
|
122
|
-
num_dim: int,
|
|
123
|
-
rng: Generator,
|
|
124
|
-
fallback_fn: Callable[[np.ndarray, int], np.ndarray],
|
|
125
|
-
from_unit_fn: Callable[[np.ndarray], np.ndarray],
|
|
126
|
-
) -> np.ndarray:
|
|
127
|
-
if self._gp_model is None:
|
|
128
|
-
return fallback_fn(x_cand, num_arms)
|
|
129
|
-
|
|
130
|
-
idx = gp_thompson_sample(
|
|
131
|
-
self._gp_model,
|
|
132
|
-
x_cand,
|
|
133
|
-
num_arms,
|
|
134
|
-
rng,
|
|
135
|
-
self._gp_y_mean,
|
|
136
|
-
self._gp_y_std,
|
|
137
|
-
)
|
|
138
|
-
return from_unit_fn(x_cand[idx])
|
|
139
|
-
|
|
140
|
-
def estimate_y(self, x_unit: np.ndarray, y_observed: np.ndarray) -> np.ndarray:
|
|
141
|
-
import torch
|
|
142
|
-
|
|
143
|
-
if self._gp_model is None:
|
|
144
|
-
return y_observed
|
|
145
|
-
x_torch = torch.as_tensor(x_unit, dtype=torch.float64)
|
|
146
|
-
with torch.no_grad():
|
|
147
|
-
posterior = self._gp_model.posterior(x_torch)
|
|
148
|
-
mu = posterior.mean.cpu().numpy().ravel()
|
|
149
|
-
return self._gp_y_mean + self._gp_y_std * mu
|
|
150
|
-
|
|
151
|
-
def get_mu_sigma(self, x_unit: np.ndarray) -> tuple[np.ndarray, np.ndarray] | None:
|
|
152
|
-
import torch
|
|
153
|
-
|
|
154
|
-
if self._gp_model is None:
|
|
155
|
-
return None
|
|
156
|
-
x_torch = torch.as_tensor(x_unit, dtype=torch.float64)
|
|
157
|
-
with torch.no_grad():
|
|
158
|
-
posterior = self._gp_model.posterior(x_torch)
|
|
159
|
-
mu_std = posterior.mean.cpu().numpy().ravel()
|
|
160
|
-
sigma_std = posterior.variance.cpu().numpy().ravel() ** 0.5
|
|
161
|
-
mu = self._gp_y_mean + self._gp_y_std * mu_std
|
|
162
|
-
sigma = self._gp_y_std * sigma_std
|
|
163
|
-
return mu, sigma
|