sgbaird commited on
Commit
b0c702c
1 Parent(s): f618644

Refactor evaluate function in app.py to include parameter scaling and unscaled evaluation

Browse files
Files changed (1) hide show
  1. app.py +95 -34
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
- param_info["name"]: MinMaxScaler()
49
- for param_info in PARAM_BOUNDS
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
- f1: float
79
 
80
  @field_validator("*")
81
  def check_bounds(cls, v: int, info: ValidationInfo) -> int:
82
  param = next(
83
- (item for item in PARAM_BOUNDS if item["name"] == info.field_name),
84
  None,
85
  )
86
  if param is None:
@@ -110,31 +141,54 @@ class BlindedParameterization(BaseModel):
110
  )
111
 
112
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
113
  def evaluate(*args):
114
- # Create a DataFrame with the parameter names and scaled values
115
- params_df = pd.DataFrame([args], columns=[param["name"] for param in PARAM_BOUNDS])
116
-
117
- # error checking
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
- # Convert list of dictionaries to list of lists
 
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"f1" if key == "train_frac" else f"x{numeric_index}"
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 less than 0.2, the result is considered "bad" no matter how good
205
- the other values are. If `y2` is less than 0.7, the result is considered
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()