Spaces:
Running
Running
| """Start a hyperoptimization from a single node""" | |
| import sys | |
| import numpy as np | |
| import pickle as pkl | |
| from pysr import PySRRegressor | |
| import hyperopt | |
| from hyperopt import hp, fmin, tpe, Trials | |
| from hyperopt.fmin import generate_trials_to_calculate | |
| # Change the following code to your file | |
| ################################################################################ | |
| TRIALS_FOLDER = "trials" | |
| NUMBER_TRIALS_PER_RUN = 1 | |
| timeout_in_minutes = 5 | |
| # Test run to compile everything: | |
| binary_operators = ["*", "/", "+", "-"] | |
| unary_operators = ["sin", "cos", "exp", "log"] | |
| julia_project = None | |
| procs = 4 | |
| model = PySRRegressor( | |
| binary_operators=binary_operators, | |
| unary_operators=unary_operators, | |
| timeout_in_seconds=30, | |
| julia_project=julia_project, | |
| procs=procs, | |
| ) | |
| model.fit(np.random.randn(100, 3), np.random.randn(100)) | |
| def run_trial(args): | |
| """Evaluate the model loss using the hyperparams in args | |
| :args: A dictionary containing all hyperparameters | |
| :returns: Dict with status and loss from cross-validation | |
| """ | |
| # The arguments which are integers: | |
| integer_args = [ | |
| "populations", | |
| "niterations", | |
| "ncyclesperiteration", | |
| "npop", | |
| "topn", | |
| "maxsize", | |
| "optimizer_nrestarts", | |
| "optimizer_iterations", | |
| ] | |
| # Set these to int types: | |
| for k, v in args.items(): | |
| if k in integer_args: | |
| args[k] = int(v) | |
| # Duplicate this argument: | |
| args["tournament_selection_n"] = args["topn"] | |
| # Invalid hyperparams: | |
| invalid = args["npop"] < args["topn"] | |
| if invalid: | |
| return dict(status="fail", loss=float("inf")) | |
| args["timeout_in_seconds"] = timeout_in_minutes * 60 | |
| args["julia_project"] = julia_project | |
| args["procs"] = procs | |
| print(f"Running trial with args: {args}") | |
| # Create the dataset: | |
| ntrials = 3 | |
| losses = [] | |
| # Old datasets: | |
| eval_str = [ | |
| "np.cos(2.3 * X[:, 0]) * np.sin(2.3 * X[:, 0] * X[:, 1] * X[:, 2]) - 10.0", | |
| "(np.exp(X[:, 3]*0.3) + 3)/(np.exp(X[:, 1]*0.2) + np.cos(X[:, 0]) + 1.1)", | |
| # "np.sign(X[:, 2])*np.abs(X[:, 2])**2.5 + 5*np.cos(X[:, 3]) - 5", | |
| # "np.exp(X[:, 0]/2) + 12.0 + np.log(np.abs(X[:, 0])*10 + 1)", | |
| # "X[:, 0] * np.sin(2*np.pi * (X[:, 1] * X[:, 2] - X[:, 3] / X[:, 4])) + 3.0", | |
| ] | |
| for expression in eval_str: | |
| expression_losses = [] | |
| for i in range(ntrials): | |
| rstate = np.random.RandomState(i) | |
| X = 3 * rstate.randn(200, 5) | |
| y = eval(expression) | |
| # Normalize y so that losses are fair: | |
| y = (y - np.average(y)) / np.std(y) | |
| # Create the model: | |
| model = PySRRegressor(**args) | |
| # Run the model: | |
| try: | |
| model.fit(X, y) | |
| except RuntimeError: | |
| return dict(status="fail", loss=float("inf")) | |
| # Compute loss: | |
| cur_loss = float(model.get_best()["loss"]) | |
| expression_losses.append(cur_loss) | |
| losses.append(np.median(expression_losses)) | |
| loss = np.average(losses) | |
| print(f"Finished with {loss}", str(args)) | |
| return dict(status="ok", loss=loss) | |
| space = dict( | |
| # model_selection="best", | |
| model_selection=hp.choice("model_selection", ["accuracy"]), | |
| # binary_operators=None, | |
| binary_operators=hp.choice("binary_operators", [binary_operators]), | |
| # unary_operators=None, | |
| unary_operators=hp.choice("unary_operators", [unary_operators]), | |
| # populations=100, | |
| populations=hp.qloguniform("populations", np.log(10), np.log(1000), 1), | |
| # niterations=4, | |
| niterations=hp.choice( | |
| "niterations", [10000] | |
| ), # We will quit automatically based on a clock. | |
| # ncyclesperiteration=100, | |
| ncyclesperiteration=hp.qloguniform( | |
| "ncyclesperiteration", np.log(10), np.log(5000), 1 | |
| ), | |
| # alpha=0.1, | |
| alpha=hp.loguniform("alpha", np.log(0.0001), np.log(1000)), | |
| # annealing=False, | |
| annealing=hp.choice("annealing", [False, True]), | |
| # fractionReplaced=0.01, | |
| fractionReplaced=hp.loguniform("fractionReplaced", np.log(0.0001), np.log(0.5)), | |
| # fractionReplacedHof=0.005, | |
| fractionReplacedHof=hp.loguniform( | |
| "fractionReplacedHof", np.log(0.0001), np.log(0.5) | |
| ), | |
| # npop=100, | |
| npop=hp.qloguniform("npop", np.log(20), np.log(1000), 1), | |
| # parsimony=1e-4, | |
| parsimony=hp.loguniform("parsimony", np.log(0.0001), np.log(0.5)), | |
| # topn=10, | |
| topn=hp.qloguniform("topn", np.log(2), np.log(50), 1), | |
| # weightAddNode=1, | |
| weightAddNode=hp.loguniform("weightAddNode", np.log(0.0001), np.log(100)), | |
| # weightInsertNode=3, | |
| weightInsertNode=hp.loguniform("weightInsertNode", np.log(0.0001), np.log(100)), | |
| # weightDeleteNode=3, | |
| weightDeleteNode=hp.loguniform("weightDeleteNode", np.log(0.0001), np.log(100)), | |
| # weightDoNothing=1, | |
| weightDoNothing=hp.loguniform("weightDoNothing", np.log(0.0001), np.log(100)), | |
| # weightMutateConstant=10, | |
| weightMutateConstant=hp.loguniform( | |
| "weightMutateConstant", np.log(0.0001), np.log(100) | |
| ), | |
| # weightMutateOperator=1, | |
| weightMutateOperator=hp.loguniform( | |
| "weightMutateOperator", np.log(0.0001), np.log(100) | |
| ), | |
| # weightRandomize=1, | |
| weightRandomize=hp.loguniform("weightRandomize", np.log(0.0001), np.log(100)), | |
| # weightSimplify=0.002, | |
| weightSimplify=hp.choice("weightSimplify", [0.002]), # One of these is fixed. | |
| # perturbationFactor=1.0, | |
| perturbationFactor=hp.loguniform("perturbationFactor", np.log(0.0001), np.log(100)), | |
| # maxsize=20, | |
| maxsize=hp.choice("maxsize", [20]), | |
| # warmupMaxsizeBy=0.0, | |
| warmupMaxsizeBy=hp.uniform("warmupMaxsizeBy", 0.0, 0.5), | |
| # useFrequency=True, | |
| useFrequency=hp.choice("useFrequency", [True, False]), | |
| # optimizer_nrestarts=3, | |
| optimizer_nrestarts=hp.quniform("optimizer_nrestarts", 1, 10, 1), | |
| # optimize_probability=1.0, | |
| optimize_probability=hp.uniform("optimize_probability", 0.0, 1.0), | |
| # optimizer_iterations=10, | |
| optimizer_iterations=hp.quniform("optimizer_iterations", 1, 10, 1), | |
| # tournament_selection_p=1.0, | |
| tournament_selection_p=hp.uniform("tournament_selection_p", 0.0, 1.0), | |
| ) | |
| init_vals = [ | |
| dict( | |
| model_selection=0, # 0 means first choice | |
| binary_operators=0, | |
| unary_operators=0, | |
| populations=100.0, | |
| niterations=0, | |
| ncyclesperiteration=100.0, | |
| alpha=0.1, | |
| annealing=0, | |
| # fractionReplaced=0.01, | |
| fractionReplaced=0.01, | |
| # fractionReplacedHof=0.005, | |
| fractionReplacedHof=0.005, | |
| # npop=100, | |
| npop=100.0, | |
| # parsimony=1e-4, | |
| parsimony=1e-4, | |
| # topn=10, | |
| topn=10.0, | |
| # weightAddNode=1, | |
| weightAddNode=1.0, | |
| # weightInsertNode=3, | |
| weightInsertNode=3.0, | |
| # weightDeleteNode=3, | |
| weightDeleteNode=3.0, | |
| # weightDoNothing=1, | |
| weightDoNothing=1.0, | |
| # weightMutateConstant=10, | |
| weightMutateConstant=10.0, | |
| # weightMutateOperator=1, | |
| weightMutateOperator=1.0, | |
| # weightRandomize=1, | |
| weightRandomize=1.0, | |
| # weightSimplify=0.002, | |
| weightSimplify=0, # One of these is fixed. | |
| # perturbationFactor=1.0, | |
| perturbationFactor=1.0, | |
| # maxsize=20, | |
| maxsize=0, | |
| # warmupMaxsizeBy=0.0, | |
| warmupMaxsizeBy=0.0, | |
| # useFrequency=True, | |
| useFrequency=1, | |
| # optimizer_nrestarts=3, | |
| optimizer_nrestarts=3.0, | |
| # optimize_probability=1.0, | |
| optimize_probability=1.0, | |
| # optimizer_iterations=10, | |
| optimizer_iterations=10.0, | |
| # tournament_selection_p=1.0, | |
| tournament_selection_p=0.999, | |
| ) | |
| ] | |
| ################################################################################ | |
| def merge_trials(trials1, trials2_slice): | |
| """Merge two hyperopt trials objects | |
| :trials1: The primary trials object | |
| :trials2_slice: A slice of the trials object to be merged, | |
| obtained with, e.g., trials2.trials[:10] | |
| :returns: The merged trials object | |
| """ | |
| max_tid = 0 | |
| if len(trials1.trials) > 0: | |
| max_tid = max([trial["tid"] for trial in trials1.trials]) | |
| for trial in trials2_slice: | |
| tid = trial["tid"] + max_tid + 1 | |
| local_hyperopt_trial = Trials().new_trial_docs( | |
| tids=[None], specs=[None], results=[None], miscs=[None] | |
| ) | |
| local_hyperopt_trial[0] = trial | |
| local_hyperopt_trial[0]["tid"] = tid | |
| local_hyperopt_trial[0]["misc"]["tid"] = tid | |
| for key in local_hyperopt_trial[0]["misc"]["idxs"].keys(): | |
| local_hyperopt_trial[0]["misc"]["idxs"][key] = [tid] | |
| trials1.insert_trial_docs(local_hyperopt_trial) | |
| trials1.refresh() | |
| return trials1 | |
| loaded_fnames = [] | |
| trials = generate_trials_to_calculate(init_vals) | |
| i = 0 | |
| n = NUMBER_TRIALS_PER_RUN | |
| # Run new hyperparameter trials until killed | |
| while True: | |
| np.random.seed() | |
| # Load up all runs: | |
| import glob | |
| if i > 0: | |
| path = TRIALS_FOLDER + "/*.pkl" | |
| for fname in glob.glob(path): | |
| if fname in loaded_fnames: | |
| continue | |
| trials_obj = pkl.load(open(fname, "rb")) | |
| n_trials = trials_obj["n"] | |
| trials_obj = trials_obj["trials"] | |
| if len(loaded_fnames) == 0: | |
| trials = trials_obj | |
| else: | |
| print("Merging trials") | |
| trials = merge_trials(trials, trials_obj.trials[-n_trials:]) | |
| loaded_fnames.append(fname) | |
| print("Loaded trials", len(loaded_fnames)) | |
| if len(loaded_fnames) == 0: | |
| trials = Trials() | |
| try: | |
| best = fmin( | |
| run_trial, | |
| space=space, | |
| algo=tpe.suggest, | |
| max_evals=n + len(trials.trials), | |
| trials=trials, | |
| verbose=1, | |
| rstate=np.random.default_rng(np.random.randint(1, 10**6)), | |
| ) | |
| except hyperopt.exceptions.AllTrialsFailed: | |
| continue | |
| else: | |
| best = fmin( | |
| run_trial, | |
| space=space, | |
| algo=tpe.suggest, | |
| max_evals=2, | |
| trials=trials, | |
| points_to_evaluate=init_vals, | |
| ) | |
| print("current best", best) | |
| hyperopt_trial = Trials() | |
| # Merge with empty trials dataset: | |
| save_trials = merge_trials(hyperopt_trial, trials.trials[-n:]) | |
| new_fname = TRIALS_FOLDER + "/" + str(np.random.randint(0, sys.maxsize)) + ".pkl" | |
| pkl.dump({"trials": save_trials, "n": n}, open(new_fname, "wb")) | |
| loaded_fnames.append(new_fname) | |
| i += 1 | |