pypi optuna 2.5.0
v2.5.0

latest releases: 4.2.0, 4.1.0, 4.0.0...
3 years ago

This is the release note of v2.5.0.

Highlights

Ask-and-Tell

The ask-and-tell interface is a new complement to Study.optimize. It allows users to construct Trial instances without the need of an objective function callback, giving more flexibility in how to define search spaces, ask for suggested hyperparameters and how to evaluate objective functions. The interface is made out of two methods, Study.ask and Study.tell.

  • Study.ask returns a new Trial object.
  • Study.tell takes either a Trial object or a trial number along with the result of that trial, i.e. a value and/or the state, and saves it. Since Study.tell accepts a trial number, a trial object can be disposed after parameters have been suggested. This allows objective function evaluations on a different thread or process.
import optuna
from optuna.trial import TrialState

study = optuna.create_study()

# Use a Python for-loop to iteratively optimize the study.
for _ in range(100):  
    trial = study.ask()  # `trial` is a `Trial` and not a `FrozenTrial`. 

    # Objective function, in this case not as a function but at global scope.
    x = trial.suggest_float("x", -1, 1)
    y = x ** 2

    study.tell(trial, y)

    # Or, tell by trial number. This is equivalent to `study.tell(trial, y)`.
    # study.tell(trial.number, y)

    # Or, prune if the trial seems unpromising. 
    # study.tell(trial, state=TrialState.PRUNED)

assert len(study.trials) == 100

Heartbeat

Now, Optuna supports monitoring trial heartbeats with RDB storages. For example, if a process running a trial is killed by a scheduler in a cluster environment, Optuna will automatically change the state of the trial that was running on that process to TrialState.FAIL from TrialState.RUNNING.

# Consider running this script on several processes. 
import optuna

def objective(trial):
    (Very time-consuming computation)

# Recording heartbeats every 60 seconds.
# Other processes' trials where more than 120 seconds have passed 
# since the last heartbeat was recorded will be automatically failed.
storage = optuna.storages.RDBStorage(url=..., heartbeat_interval=60, grace_period=120)
study = optuna.create_study(storage=storage)
study.optimize(objective, n_trials=100)

Constrained NSGA-II

NSGA-II experimentally supports constrained optimization. Users can introduce constraints with the new constraints_func argument of NSGAIISampler.__init__.

The following is an example using this argument, a bi-objective version of the knapsack problem. We have 100 pairs of items and two knapsacks, and would like to maximize the profits of items within the weight limitation.

import numpy as np
import optuna

# Define bi-objective knapsack problem.
n_items = 100
n_knapsacks = 2
feasible_rate = 0.5
seed = 1

rng = np.random.RandomState(seed=seed)
weights = rng.randint(10, 101, size=(n_knapsacks, n_items))
profits = rng.randint(10, 101, size=(n_knapsacks, n_items))
constraints = (np.sum(weights, axis=1) * feasible_rate).astype(np.int)

def objective(trial):
    xs = np.array([trial.suggest_categorical(f"x_{i}", (0, 1)) for i in range(weights.shape[1])])
    total_weights = np.sum(weights * xs, axis=1)
    total_profits = np.sum(profits * xs, axis=1)

  # Constraints which are considered feasible if less than or equal to zero.
    constraints_violation = total_weights - constraints
    trial.set_user_attr("constraint", constraints_violation.tolist())

    return total_profits.tolist()

def constraints_func(trial):
    return trial.user_attrs["constraint"]

sampler = optuna.samplers.NSGAIISampler(population_size=10, constraints_func=constraints_func)

study = optuna.create_study(directions=["maximize"] * n_knapsacks, sampler=sampler)
study.optimize(objective, n_trials=200)

cnsga2-knapsack-anim

New Features

  • Ask-and-Tell API (Study.ask, Study.tell) (#2158)
  • Add constraints_func argument to NSGA-II (#2175)
  • Add heartbeat functionality using threading (#2190)
  • Add Study.add_trials to simplify creating customized study (#2261)

Enhancements

  • Support log scale in parallel coordinate (#2164, thanks @tohmae!)
  • Warn if constraints are missing in constrained NSGA-II (#2205)
  • Immediately persist suggested parameters with _CachedStorage (#2214)
  • Include the upper bound of uniform/loguniform distributions (#2223)

Bug Fixes

  • Call base sampler's after_trial in PartialFixedSampler (#2209)
  • Fix trials_dataframe for multi-objective optimization with fail or pruned trials (#2265)
  • Fix calculate_weights_below method of MOTPESampler (#2274, thanks @y0z!)

Installation

  • Remove version constraint for AllenNLP and run allennlp_*.py on GitHub Actions (#2226)
  • Pin mypy==0.790 (#2259)
  • Temporarily avoid AllenNLP v2 (#2276)

Documentation

  • Add callback & (add|enqueue)_trial recipe (#2125)
  • Make create_trial's documentation and tests richer (#2126)
  • Move import lines of the callback recipe (A follow-up of #2125) (#2221)
  • Fix optuna/samplers/_base.py typo (#2239)
  • Introduce optuna-dashboard on README (#2224)

Examples

  • Refactor examples/multi_objective/pytorch_simple.py (#2230)
  • Move BoTorch example to examples/multi_objective directory (#2244)
  • Refactor examples/multi_objective/botorch_simple.py (#2245, thanks @nzw0301!)
  • Fix typo in examples/mlflow (#2258, thanks @nzw0301!)

Tests

  • Make create_trial's documentation and tests richer (#2126)
  • Fix unit test of median pruner (#2171)
  • SkoptSampler acquisition function in test to more likely converge (#2194)
  • Diet tests/test_study.py (#2218)
  • Diet tests/test_trial.py (#2219)
  • Shorten the names of trial tests (#2228)
  • Move STORAGE_MODES to testing/storage.py (#2231)
  • Remove duplicate test on study_tests/test_optimize.py (#2232)
  • Add init files in test directories (#2257)

Code Fixes

  • Code quality improvements (#2009, thanks @srijan-deepsource!)
  • Refactor CMA-ES sampler with search space transform (#2193)
  • BoTorchSampler minor code fix reducing dictionary lookup and clearer type behavior (#2195)
  • Fix bad warning message in BoTorchSampler (#2197)
  • Use study.get_trials instead of study._storage.get_all_trials (#2208)
  • Ensure uniform and loguniform distributions less than high boundary (#2243)

Continuous Integration

  • Add RDBStorage tests in github actions (#2200)
  • Publish distributions to TestPyPI on each day (#2220)
  • Rename GitHub Actions jobs for (Test)PyPI uploads (#2254)

Other

  • Fix the syntax of pypi-publish.yml (#2187)
  • Fix mypy local fails in tests/test_deprecated.py and tests/test_experimental.py (#2191)
  • Add an explanation of "no period in the PR title" to CONTRIBUTING.md (#2192)
  • Bump up version number to 2.5.0.dev (#2238)
  • Fix mypy version to 0.790 (Follow-up of 2259) (#2260)
  • Bump up version number to v2.5.0 (#2282)

Thanks to All the Contributors!

This release was made possible by authors, and everyone who participated in reviews and discussions.

@Crissman, @HideakiImamura, @c-bata, @crcrpar, @g-votte, @himkt, @hvy, @keisuke-umezawa, @not522, @nzw0301, @sile, @srijan-deepsource, @tohmae, @toshihikoyanase, @y0z, @ytsmiling

Don't miss a new optuna release

NewReleases is sending notifications on new releases.