-
-
Notifications
You must be signed in to change notification settings - Fork 234
/
Copy pathmulti_objective_model.py
105 lines (79 loc) · 3.17 KB
/
multi_objective_model.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
from __future__ import annotations
from typing import TypeVar
import numpy as np
from smac.model.abstract_model import AbstractModel
__copyright__ = "Copyright 2025, Leibniz University Hanover, Institute of AI"
__license__ = "3-clause BSD"
Self = TypeVar("Self", bound="MultiObjectiveModel")
class MultiObjectiveModel(AbstractModel):
"""Wrapper for the surrogate model to predict multiple objectives.
Parameters
----------
models : AbstractModel | list[AbstractModel]
Which model should be used. If it is a list, then it must provide as many models as objectives.
If it is a single model only, the model is used for all objectives.
objectives : list[str]
Which objectives should be used.
seed : int
"""
def __init__(
self,
models: AbstractModel | list[AbstractModel],
objectives: list[str],
seed: int = 0,
) -> None:
self._n_objectives = len(objectives)
if isinstance(models, list):
assert len(models) == len(objectives)
# Make sure the configspace is the same
configspace = models[0]._configspace
for m in models:
assert configspace == m._configspace
self._models = models
else:
configspace = models._configspace
self._models = [models for _ in range(self._n_objectives)]
super().__init__(
configspace=configspace,
instance_features=None,
pca_components=None,
seed=seed,
)
@property
def is_trained(self) -> bool:
"""Whether the model is trained or not."""
return self._is_trained
@property
def models(self) -> list[AbstractModel]:
"""The internally used surrogate models."""
return self._models
def predict_marginalized(self, X: np.ndarray) -> tuple[np.ndarray, np.ndarray]: # noqa: D102
mean = np.zeros((X.shape[0], self._n_objectives))
var = np.zeros((X.shape[0], self._n_objectives))
for i, estimator in enumerate(self._models):
m, v = estimator.predict_marginalized(X)
mean[:, i] = m.flatten()
var[:, i] = v.flatten()
return mean, var
def _train(self: Self, X: np.ndarray, Y: np.ndarray) -> Self:
if len(self._models) == 0:
raise ValueError("The list of surrogate models is empty.")
for i, model in enumerate(self._models):
model.train(X, Y[:, i])
self._is_trained = all(model.is_trained for model in self._models)
return self
def _predict(
self,
X: np.ndarray,
covariance_type: str | None = "diagonal",
) -> tuple[np.ndarray, np.ndarray | None]:
if covariance_type != "diagonal":
raise ValueError("`covariance_type` can only take `diagonal` for this model.")
mean = np.zeros((X.shape[0], self._n_objectives))
var = np.zeros((X.shape[0], self._n_objectives))
for i, estimator in enumerate(self._models):
m, v = estimator.predict(X)
assert v is not None
mean[:, i] = m.flatten()
var[:, i] = v.flatten()
return mean, var