Refactor evaluate function in app.py to include parameter scaling and unscaled evaluation
Browse files
app.py
CHANGED
@@ -44,11 +44,42 @@ example_parameterization = {
|
|
44 |
example_results = model.surrogate_evaluate([example_parameterization])
|
45 |
example_result = example_results[0]
|
46 |
|
47 |
-
scalers
|
48 |
-
|
49 |
-
|
50 |
-
if param_info["type"] == "range"
|
51 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
52 |
|
53 |
|
54 |
class BlindedParameterization(BaseModel):
|
@@ -72,15 +103,15 @@ class BlindedParameterization(BaseModel):
|
|
72 |
x18: float # int
|
73 |
x19: float
|
74 |
x20: float
|
75 |
-
c1: bool
|
76 |
c2: str
|
77 |
c3: str
|
78 |
-
|
79 |
|
80 |
@field_validator("*")
|
81 |
def check_bounds(cls, v: int, info: ValidationInfo) -> int:
|
82 |
param = next(
|
83 |
-
(item for item in
|
84 |
None,
|
85 |
)
|
86 |
if param is None:
|
@@ -110,31 +141,54 @@ class BlindedParameterization(BaseModel):
|
|
110 |
)
|
111 |
|
112 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
113 |
def evaluate(*args):
|
114 |
-
#
|
115 |
-
|
116 |
-
|
117 |
-
#
|
118 |
-
BlindedParameterization(**params_df.to_dict("records")[0])
|
119 |
-
|
120 |
-
# Reverse the scaling for each parameter and reverse the renaming for choice parameters
|
121 |
-
for param_info in PARAM_BOUNDS:
|
122 |
-
key = param_info["name"]
|
123 |
-
if param_info["type"] == "range":
|
124 |
-
scaler = scalers[key]
|
125 |
-
params_df[key] = scaler.inverse_transform(params_df[[key]])
|
126 |
-
elif param_info["type"] == "choice":
|
127 |
-
# Extract the index from the renamed choice and use it to get the original choice
|
128 |
-
choice_index = int(params_df[key].str.split("_").str[-1].iloc[0])
|
129 |
-
params_df[key] = param_info["values"][choice_index]
|
130 |
-
|
131 |
-
# Convert the DataFrame to a list of dictionaries
|
132 |
-
params_list = params_df.to_dict("records")
|
133 |
-
|
134 |
-
# Evaluate the model with the unscaled parameters
|
135 |
-
results = model.surrogate_evaluate(params_list)
|
136 |
|
137 |
-
|
|
|
138 |
results_list = [list(result.values()) for result in results]
|
139 |
return results_list
|
140 |
|
@@ -148,7 +202,7 @@ def get_interface(param_info, numeric_index, choice_index):
|
|
148 |
scaler.fit([[bound] for bound in param_info["bounds"]])
|
149 |
scaled_value = scaler.transform([[default_value]])[0][0]
|
150 |
scaled_bounds = scaler.transform([[bound] for bound in param_info["bounds"]])
|
151 |
-
label = f"
|
152 |
return (
|
153 |
gr.Slider( # Change this line
|
154 |
value=scaled_value,
|
@@ -174,6 +228,9 @@ def get_interface(param_info, numeric_index, choice_index):
|
|
174 |
)
|
175 |
|
176 |
|
|
|
|
|
|
|
177 |
numeric_index = 1
|
178 |
choice_index = 1
|
179 |
inputs = []
|
@@ -201,8 +258,8 @@ iface = gr.Interface(
|
|
201 |
words, repeat calls with the same input arguments will result in different
|
202 |
values for `y1`, `y2`, and `y3`, but the same value for `y4`.
|
203 |
|
204 |
-
If `y1` is
|
205 |
-
the other values are. If `y2` is
|
206 |
"bad" no matter how good the other values are. If `y3` is greater than 1800,
|
207 |
the result is considered "bad" no matter how good the other values are. If `y4`
|
208 |
is greater than 40e6, the result is considered "bad" no matter how good the
|
@@ -213,6 +270,10 @@ iface = gr.Interface(
|
|
213 |
evaluation. However, this also typically means higher quality and relevance
|
214 |
to the optimization campaign goals. `fidelity1` and `y3` are
|
215 |
correlated.
|
|
|
|
|
|
|
|
|
216 |
""",
|
217 |
)
|
218 |
iface.launch()
|
|
|
44 |
example_results = model.surrogate_evaluate([example_parameterization])
|
45 |
example_result = example_results[0]
|
46 |
|
47 |
+
# Initialize and fit scalers for each parameter
|
48 |
+
scalers = {}
|
49 |
+
for param_info in PARAM_BOUNDS:
|
50 |
+
if param_info["type"] == "range":
|
51 |
+
scaler = MinMaxScaler()
|
52 |
+
# Fit the scaler using the parameter bounds
|
53 |
+
scaler.fit([[bound] for bound in param_info["bounds"]])
|
54 |
+
scalers[param_info["name"]] = scaler
|
55 |
+
|
56 |
+
# HACK: Hardcoded
|
57 |
+
BLINDED_PARAM_BOUNDS = [
|
58 |
+
{"name": "x1", "type": "range", "bounds": [0.0, 1.0]},
|
59 |
+
{"name": "x2", "type": "range", "bounds": [0.0, 1.0]},
|
60 |
+
{"name": "x3", "type": "range", "bounds": [0.0, 1.0]},
|
61 |
+
{"name": "x4", "type": "range", "bounds": [0.0, 1.0]},
|
62 |
+
{"name": "x5", "type": "range", "bounds": [0.0, 1.0]},
|
63 |
+
{"name": "x6", "type": "range", "bounds": [0.0, 1.0]},
|
64 |
+
{"name": "x7", "type": "range", "bounds": [0.0, 1.0]},
|
65 |
+
{"name": "x8", "type": "range", "bounds": [0.0, 1.0]},
|
66 |
+
{"name": "x9", "type": "range", "bounds": [0.0, 1.0]},
|
67 |
+
{"name": "x10", "type": "range", "bounds": [0.0, 1.0]},
|
68 |
+
{"name": "x11", "type": "range", "bounds": [0.0, 1.0]},
|
69 |
+
{"name": "x12", "type": "range", "bounds": [0.0, 1.0]},
|
70 |
+
{"name": "x13", "type": "range", "bounds": [0.0, 1.0]},
|
71 |
+
{"name": "x14", "type": "range", "bounds": [0.0, 1.0]},
|
72 |
+
{"name": "x15", "type": "range", "bounds": [0.0, 1.0]},
|
73 |
+
{"name": "x16", "type": "range", "bounds": [0.0, 1.0]},
|
74 |
+
{"name": "x17", "type": "range", "bounds": [0.0, 1.0]},
|
75 |
+
{"name": "x18", "type": "range", "bounds": [0.0, 1.0]},
|
76 |
+
{"name": "x19", "type": "range", "bounds": [0.0, 1.0]},
|
77 |
+
{"name": "x20", "type": "range", "bounds": [0.0, 1.0]},
|
78 |
+
{"name": "c1", "type": "choice", "values": ["c1_0", "c1_1"]},
|
79 |
+
{"name": "c2", "type": "choice", "values": ["c2_0", "c2_1"]},
|
80 |
+
{"name": "c3", "type": "choice", "values": ["c3_0", "c3_1"]},
|
81 |
+
{"name": "fidelity1", "type": "range", "bounds": [0.0, 1.0]},
|
82 |
+
]
|
83 |
|
84 |
|
85 |
class BlindedParameterization(BaseModel):
|
|
|
103 |
x18: float # int
|
104 |
x19: float
|
105 |
x20: float
|
106 |
+
c1: str # bool
|
107 |
c2: str
|
108 |
c3: str
|
109 |
+
fidelity1: float
|
110 |
|
111 |
@field_validator("*")
|
112 |
def check_bounds(cls, v: int, info: ValidationInfo) -> int:
|
113 |
param = next(
|
114 |
+
(item for item in BLINDED_PARAM_BOUNDS if item["name"] == info.field_name),
|
115 |
None,
|
116 |
)
|
117 |
if param is None:
|
|
|
141 |
)
|
142 |
|
143 |
|
144 |
+
# Conversion from original to blinded representation
|
145 |
+
def convert_to_blinded(params):
|
146 |
+
blinded_params = {}
|
147 |
+
numeric_index = 1
|
148 |
+
choice_index = 1
|
149 |
+
for param in PARAM_BOUNDS:
|
150 |
+
if param["type"] == "range":
|
151 |
+
key = f"x{numeric_index}" if param["name"] != "train_frac" else "fidelity1"
|
152 |
+
blinded_params[key] = scalers[param["name"]].transform(
|
153 |
+
[[params[param["name"]]]]
|
154 |
+
)[0][0]
|
155 |
+
numeric_index += 1 if param["name"] != "train_frac" else 0
|
156 |
+
elif param["type"] == "choice":
|
157 |
+
key = f"c{choice_index}"
|
158 |
+
choice_index = param["values"].index(params[param["name"]])
|
159 |
+
blinded_params[key] = f"{key}_{choice_index}"
|
160 |
+
choice_index += 1
|
161 |
+
return blinded_params
|
162 |
+
|
163 |
+
|
164 |
+
# Conversion from blinded to original representation
|
165 |
+
def convert_from_blinded(blinded_params):
|
166 |
+
original_params = {}
|
167 |
+
numeric_index = 1
|
168 |
+
choice_index = 1
|
169 |
+
for param in PARAM_BOUNDS:
|
170 |
+
if param["type"] == "range":
|
171 |
+
key = f"x{numeric_index}" if param["name"] != "train_frac" else "fidelity1"
|
172 |
+
original_params[param["name"]] = scalers[param["name"]].inverse_transform(
|
173 |
+
[[blinded_params[key]]]
|
174 |
+
)[0][0]
|
175 |
+
numeric_index += 1 if param["name"] != "train_frac" else 0
|
176 |
+
elif param["type"] == "choice":
|
177 |
+
key = f"c{choice_index}"
|
178 |
+
choice_value = blinded_params[key].split("_")[-1]
|
179 |
+
original_params[param["name"]] = param["values"][int(choice_value)]
|
180 |
+
choice_index += 1
|
181 |
+
return original_params
|
182 |
+
|
183 |
+
|
184 |
def evaluate(*args):
|
185 |
+
# Assume args are in the order of BLINDED_PARAM_BOUNDS
|
186 |
+
blinded_params = dict(zip([param["name"] for param in BLINDED_PARAM_BOUNDS], args))
|
187 |
+
original_params = convert_from_blinded(blinded_params)
|
188 |
+
BlindedParameterization(**blinded_params) # Validation
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
189 |
|
190 |
+
params_list = [original_params]
|
191 |
+
results = model.surrogate_evaluate(params_list)
|
192 |
results_list = [list(result.values()) for result in results]
|
193 |
return results_list
|
194 |
|
|
|
202 |
scaler.fit([[bound] for bound in param_info["bounds"]])
|
203 |
scaled_value = scaler.transform([[default_value]])[0][0]
|
204 |
scaled_bounds = scaler.transform([[bound] for bound in param_info["bounds"]])
|
205 |
+
label = f"fidelity1" if key == "train_frac" else f"x{numeric_index}"
|
206 |
return (
|
207 |
gr.Slider( # Change this line
|
208 |
value=scaled_value,
|
|
|
228 |
)
|
229 |
|
230 |
|
231 |
+
# test the evaluate function
|
232 |
+
blinded_results = evaluate(*[0.5] * 20, "c1_0", "c2_0", "c3_0", 0.5)
|
233 |
+
|
234 |
numeric_index = 1
|
235 |
choice_index = 1
|
236 |
inputs = []
|
|
|
258 |
words, repeat calls with the same input arguments will result in different
|
259 |
values for `y1`, `y2`, and `y3`, but the same value for `y4`.
|
260 |
|
261 |
+
If `y1` is greater than 0.2, the result is considered "bad" no matter how good
|
262 |
+
the other values are. If `y2` is greater than 0.7, the result is considered
|
263 |
"bad" no matter how good the other values are. If `y3` is greater than 1800,
|
264 |
the result is considered "bad" no matter how good the other values are. If `y4`
|
265 |
is greater than 40e6, the result is considered "bad" no matter how good the
|
|
|
270 |
evaluation. However, this also typically means higher quality and relevance
|
271 |
to the optimization campaign goals. `fidelity1` and `y3` are
|
272 |
correlated.
|
273 |
+
|
274 |
+
Constraints:
|
275 |
+
- `x19` should be less than `x20`.
|
276 |
+
- `x6` and `x15` should sum to no more than 1.0.
|
277 |
""",
|
278 |
)
|
279 |
iface.launch()
|