|
from joblib import load |
|
import pandas as pd |
|
import random |
|
from pydantic import BaseModel, ValidationInfo, field_validator |
|
|
|
PARAM_CONSTRAINTS = { |
|
"N": {"type": "range", "bounds": [1, 10]}, |
|
"alpha": {"type": "range", "bounds": [0.0, 1.0]}, |
|
"d_model": {"type": "range", "bounds": [100, 1024]}, |
|
"dim_feedforward": {"type": "range", "bounds": [1024, 4096]}, |
|
"dropout": {"type": "range", "bounds": [0.0, 1.0]}, |
|
"emb_scaler": {"type": "range", "bounds": [0.0, 1.0]}, |
|
"eps": {"type": "range", "bounds": [1e-7, 1e-4]}, |
|
"epochs_step": {"type": "range", "bounds": [5, 20]}, |
|
"fudge": {"type": "range", "bounds": [0.0, 0.1]}, |
|
"heads": {"type": "range", "bounds": [1, 10]}, |
|
"k": {"type": "range", "bounds": [2, 10]}, |
|
"lr": {"type": "range", "bounds": [1e-4, 6e-3]}, |
|
"pe_resolution": {"type": "range", "bounds": [2500, 10000]}, |
|
"ple_resolution": {"type": "range", "bounds": [2500, 10000]}, |
|
"pos_scaler": {"type": "range", "bounds": [0.0, 1.0]}, |
|
"weight_decay": {"type": "range", "bounds": [0.0, 1.0]}, |
|
"batch_size": {"type": "range", "bounds": [32, 256]}, |
|
"out_hidden4": {"type": "range", "bounds": [32, 512]}, |
|
"betas1": {"type": "range", "bounds": [0.5, 0.9999]}, |
|
"betas2": {"type": "range", "bounds": [0.5, 0.9999]}, |
|
"bias": {"type": "choice", "values": [False, True]}, |
|
"criterion": {"type": "choice", "values": ["RobustL1", "RobustL2"]}, |
|
"elem_prop": {"type": "choice", "values": ["mat2vec", "magpie", "onehot"]}, |
|
"train_frac": {"type": "range", "bounds": [0.01, 1.0]}, |
|
} |
|
|
|
|
|
class Parameterization(BaseModel): |
|
N: int |
|
alpha: float |
|
d_model: int |
|
dim_feedforward: int |
|
dropout: float |
|
emb_scaler: float |
|
epochs_step: int |
|
eps: float |
|
fudge: float |
|
heads: int |
|
k: int |
|
lr: float |
|
pe_resolution: int |
|
ple_resolution: int |
|
pos_scaler: float |
|
weight_decay: int |
|
batch_size: int |
|
out_hidden4: int |
|
betas1: float |
|
betas2: float |
|
losscurve: bool |
|
learningcurve: bool |
|
bias: bool |
|
criterion: str |
|
elem_prop: str |
|
train_frac: float |
|
|
|
@field_validator("*") |
|
def check_constraints(cls, v: int, info: ValidationInfo) -> int: |
|
param = PARAM_CONSTRAINTS.get(info.field_name) |
|
if param is None: |
|
return v |
|
|
|
if param["type"] == "range": |
|
min_val, max_val = param["bounds"] |
|
if not min_val <= v <= max_val: |
|
raise ValueError( |
|
f"{info.field_name} must be between {min_val} and {max_val}" |
|
) |
|
elif param["type"] == "choice": |
|
if v not in param["values"]: |
|
raise ValueError(f"{info.field_name} must be one of {param['values']}") |
|
|
|
if ( |
|
info.field_name in ("betas1", "betas2") |
|
and "betas1" in field.owner |
|
and "betas2" in field.owner |
|
): |
|
if field.owner["betas1"] > field.owner["betas2"]: |
|
raise ValueError("betas1 must be less than or equal to betas2") |
|
if ( |
|
info.field_name in ("emb_scaler", "pos_scaler") |
|
and "emb_scaler" in field.owner |
|
and "pos_scaler" in field.owner |
|
): |
|
if field.owner["emb_scaler"] + field.owner["pos_scaler"] > 1.0: |
|
raise ValueError( |
|
"The sum of emb_scaler and pos_scaler must be less than or equal to 1.0" |
|
) |
|
|
|
return v |
|
|
|
|
|
class CrabNetSurrogateModel(object): |
|
def __init__(self, fpath="surrogate_models.pkl"): |
|
self.models = load(fpath) |
|
pass |
|
|
|
def prepare_params_for_eval(self, raw_params: Parameterization): |
|
raw_params["bias"] = int(raw_params["bias"]) |
|
raw_params["use_RobustL1"] = raw_params["criterion"] == "RobustL1" |
|
raw_params["criterion"] = None |
|
|
|
raw_params["losscurve"] = None |
|
raw_params["learningcurve"] = None |
|
|
|
elem_prop = raw_params["elem_prop"] |
|
raw_params["elem_prop_magpie"] = 0 |
|
raw_params["elem_prop_mat2vec"] = 0 |
|
raw_params["elem_prop_onehot"] = 0 |
|
raw_params[f"elem_prop_{elem_prop}"] = 1 |
|
raw_params["elem_prop"] = None |
|
|
|
return raw_params |
|
|
|
def surrogate_evaluate(self, params: Parameterization): |
|
|
|
parameters = self.prepare_params_for_eval(params) |
|
parameters = pd.DataFrame([parameters]) |
|
|
|
percentile = random.uniform(0, 1) |
|
|
|
mae = self.models["mae"].predict(parameters.assign(mae_rank=[percentile])) |
|
rmse = self.models["rmse"].predict(parameters.assign(rmse_rank=[percentile])) |
|
runtime = self.models["runtime"].predict( |
|
parameters.assign(runtime_rank=[percentile]) |
|
) |
|
model_size = self.models["model_size"].predict(parameters) |
|
|
|
return mae, rmse, runtime, model_size |
|
|