pip install hyperopt★Core library (pulls in numpy, scipy, networkx, tqdm).pip install "hyperopt[mongotrials]"Extra for the Mongo-backed distributed backend.from hyperopt import fmin, tpe, hp, Trials★The four names you reach for every time.from hyperopt import STATUS_OK, space_eval★Return-status flag + the index decoder.import numpy as npNeeded forlog()bounds &rstate.
space = {"x": hp.uniform("x", -5, 5)}★1 · describe the space withhp.*.def objective(p): return (p["x"]-2)**2★2 · map a config to a loss.best = fmin(objective, space, algo=tpe.suggest, max_evals=100)★3 · search — returns the argmin.space_eval(space, best)★4 · decode indices → real values (always do this).
hp.uniform("x", low, high)Continuous float, flat over the range.hp.loguniform("lr", np.log(1e-4), np.log(1e-1))★Log scale — bounds are in log space.hp.quniform("n", 1, 100, 1)Quantized float (returns a float — cast to int).hp.choice("opt", ["adam", "sgd"])★Categorical — best gives its index.hp.randint("k", 10)Integer in[0, 10).
hp.normal("m", mu, sigma)Gaussian — unbounded, centered onmu.hp.lognormal("s", mu, sigma)Positive, heavy-tailed.hp.uniformint("u", low, high)Integer, uniform & inclusive.hp.qloguniform · hp.qnormal · hp.qlognormalQuantized log / normal variants.hp.pchoice("c", [(0.3, "a"), (0.7, "b")])Weighted categorical (custom prior probabilities).
hp.choice("model", [svm_branch, rf_branch])★Each branch is a dict with its own hp.* params.{"type": "svm", "C": hp.loguniform("C", …)}Sub-params only sampled when the branch is chosen.hp.choice("a", [("c1", hp.uniform(…)), ("c2", …)])Tuple branches work too — unpack in the objective.# every hp label must be globally UNIQUEruleReusing a label across branches silently breaks the space.
def objective(params): …★One arg — the sampled point (dict / list / value).return loss★Simplest protocol: a single float to minimize.return -accuracyfmin only minimizes — negate to maximize.params["lr"], params["model"]["C"]Read hyperparameters (nested for conditional spaces).
return {"loss": L, "status": STATUS_OK}★The two required keys of the rich protocol."status": STATUS_FAILFlag a bad config so it's ignored, not counted as best."loss_variance": v · "true_loss": tOptional stats for noisy / held-out losses."attachments": {"model": pickled}Stash big artefacts on the trial (retrieve later).
fmin(fn, space, algo=tpe.suggest, max_evals=100)★The four essentials — returnsbest(the argmin).trials=Trials()★Pass one to keep the full evaluation history.rstate=np.random.default_rng(42)Seed for reproducible runs.return_argmin=FalseReturn the best trial instead of the argmin dict.
timeout=300Stop after 300 s of wall-clock.loss_threshold=0.01Stop once any trial beats this loss.early_stop_fn=no_progress_loss(20)★Stop after 20 evals with no improvement.points_to_evaluate=[{"x": 2.0}]Warm-start with known-good configs.show_progressbar=False, verbose=FalseQuiet the tqdm bar / logging.
tpe.suggest★Tree-of-Parzen-Estimators — the smart default.rand.suggestRandom search — the honest baseline.anneal.suggestSimulated annealing — simple adaptive search.atpe.suggestAdaptive TPE (auto-tunes TPE's own knobs).mix.suggestMix algorithms probabilistically.
from hyperopt import partialWrap the suggester to set its params.algo=partial(tpe.suggest, n_startup_jobs=20)★Random warm-up trials before TPE kicks in.partial(tpe.suggest, gamma=0.25)The good/bad split quantile.partial(tpe.suggest, n_EI_candidates=24)Candidates scored by expected improvement each step.
space_eval(space, best)★hp.choiceputs an index inbest— this decodes it.trials.argminSame argmin dict fmin returns (still indices).trials.best_trial["result"]["loss"]The winning loss value.space_eval(space, trials.argmin)Full real-valued winning config.
trials = Trials()★In-memory database of every evaluation.trials.losses()List of losses in trial order — plot the curve.trials.best_trial★Full record of the winning trial.trials.resultsEvery return dict you produced.trials.vals · trials.trialsSampled param values · raw trial documents.
for t in trials.trials: t["result"], t["misc"]["vals"]Per-trial result + the values that produced it.trials.statuses()OK / FAIL per trial.pd.DataFrame(trials.vals)Turn the search history into a DataFrame.trials.trial_attachments(trial)Retrieve stashed artefacts (models, arrays).
from hyperopt.early_stop import no_progress_loss★The built-in patience stopper.early_stop_fn=no_progress_loss(30)Halt after 30 evals without improvement.def stop(trials, *a): return cond, {}Custom stopper — returns(stop?, state).timeout=600 · loss_threshold=0.0Or bound by wall-clock / target loss.
pickle.dump(trials, f)ATrialsobject pickles cleanly.trials_save_file="t.pkl"Let fmin checkpoint the trials itself.fmin(…, trials=old, max_evals=len(old)+50)★Resume: reuse trials & raise the budget.points_to_evaluate=prev_bestCarry known-good configs into a new run.
from hyperopt import SparkTrials★Run trials across a Spark cluster.spark_trials = SparkTrials(parallelism=8)Up to 8 concurrent trials.fmin(…, trials=spark_trials)★Same fmin — just swap the trials backend.# TPE is sequential; parallelism trades off infoHigher parallelism ≈ more random-like search.
from hyperopt.mongoexp import MongoTrialsAsync distributed search via a MongoDB queue.MongoTrials("mongo://host:27017/db/jobs", exp_key="e1")Point trials at a Mongo collection.$ hyperopt-mongo-worker --mongo=host:27017/dbLaunch workers that pull & evaluate jobs.# objective must be importable, not a closurenoteWorkers re-import your function by reference.
return -cross_val_score(clf, X, y).mean()★Minimize negative CV score = maximize accuracy.clf = SVC(C=p["C"], gamma=p["gamma"])Build the estimator from the sampled config.from hpsklearn import HyperoptEstimatorAuto-sklearn-style wrapper over Hyperopt.# xgboost: cast quniform depth to intint(p["max_depth"])— quniform returns a float.
hp.choice → index in best★Alwaysspace_eval; never index the list yourself.fmin minimizes only★Return-metricto maximize.loguniform bounds are log-space★Passnp.log(lo), np.log(hi), not raw values.labels must be globally uniqueDuplicatehp.*labels corrupt the space.quniform returns a floatCast toint()for counts / depths.