<jupyter_start><jupyter_text>Ask-and-Tell InterfaceOptuna has an `Ask-and-Tell` interface, which provides a more flexible interface for hyperparameter optimization.This tutorial explains three use-cases when the ask-and-tell interface is beneficial:- `Apply-optuna-to-an-existing-optimization-problem-with-minimum-modifications`- `Define-and-Run`- `Batch-Optimization` Apply Optuna to an existing optimization problem with minimum modificationsLet's consider the traditional supervised classification problem; you aim to maximize the validation accuracy.To do so, you train `LogisticRegression` as a simple model.<jupyter_code>import numpy as np
from sklearn.datasets import make_classification
from sklearn.linear_model import LogisticRegression
from sklearn.model_selection import train_test_split

import optuna


X, y = make_classification(n_features=10)
X_train, X_test, y_train, y_test = train_test_split(X, y)

C = 0.01
clf = LogisticRegression(C=C)
clf.fit(X_train, y_train)
val_accuracy = clf.score(X_test, y_test)  # the objective<jupyter_output><empty_output><jupyter_text>Then you try to optimize hyperparameters ``C`` and ``solver`` of the classifier by using optuna.When you introduce optuna naively, you define an ``objective`` functionsuch that it takes ``trial`` and calls ``suggest_*`` methods of ``trial`` to sample the hyperparameters:<jupyter_code>def objective(trial):
    X, y = make_classification(n_features=10)
    X_train, X_test, y_train, y_test = train_test_split(X, y)

    C = trial.suggest_loguniform("C", 1e-7, 10.0)
    solver = trial.suggest_categorical("solver", ("lbfgs", "saga"))

    clf = LogisticRegression(C=C, solver=solver)
    clf.fit(X_train, y_train)
    val_accuracy = clf.score(X_test, y_test)

    return val_accuracy


study = optuna.create_study(direction="maximize")
study.optimize(objective, n_trials=10)<jupyter_output><empty_output><jupyter_text>This interface is not flexible enough.For example, if ``objective`` requires additional arguments other than ``trial``,you need to define a class as in`How to define objective functions that have own arguments? `_.The ask-and-tell interface provides a more flexible syntax to optimize hyperparameters.The following example is equivalent to the previous code block.<jupyter_code>study = optuna.create_study(direction="maximize")

n_trials = 10
for _ in range(n_trials):
    trial = study.ask()  # `trial` is a `Trial` and not a `FrozenTrial`.

    C = trial.suggest_loguniform("C", 1e-7, 10.0)
    solver = trial.suggest_categorical("solver", ("lbfgs", "saga"))

    clf = LogisticRegression(C=C, solver=solver)
    clf.fit(X_train, y_train)
    val_accuracy = clf.score(X_test, y_test)

    study.tell(trial, val_accuracy)  # tell the pair of trial and objective value<jupyter_output><empty_output><jupyter_text>The main difference is to use two methods: :func:`optuna.study.Study.ask`and :func:`optuna.study.Study.tell`.:func:`optuna.study.Study.ask` creates a trial that can sample hyperparameters, and:func:`optuna.study.Study.tell` finishes the trial by passing ``trial`` and an objective value.You can apply Optuna's hyperparameter optimization to your original codewithout an ``objective`` function.If you want to make your optimization faster with a pruner, you need to explicitly pass the state of trialto the argument of :func:`optuna.study.Study.tell` method as follows:.. code-block:: python   import numpy as np   from sklearn.datasets import load_iris   from sklearn.linear_model import SGDClassifier   from sklearn.model_selection import train_test_split   import optuna   X, y = load_iris(return_X_y=True)   X_train, X_valid, y_train, y_valid = train_test_split(X, y)   classes = np.unique(y)   n_train_iter = 100    define study with hyperband pruner.   study = optuna.create_study(       direction="maximize",       pruner=optuna.pruners.HyperbandPruner(           min_resource=1, max_resource=n_train_iter, reduction_factor=3       ),   )   for _ in range(20):       trial = study.ask()       alpha = trial.suggest_uniform("alpha", 0.0, 1.0)       clf = SGDClassifier(alpha=alpha)       pruned_trial = False       for step in range(n_train_iter):           clf.partial_fit(X_train, y_train, classes=classes)           intermediate_value = clf.score(X_valid, y_valid)           trial.report(intermediate_value, step)           if trial.should_prune():               pruned_trial = True               break       if pruned_trial:           study.tell(trial, state=optuna.trial.TrialState.PRUNED)   tell the pruned state       else:           score = clf.score(X_valid, y_valid)           study.tell(trial, score)   tell objective value Note:func:`optuna.study.Study.tell` method can take a trial number rather than the trial object.    ``study.tell(trial.number, y)`` is equivalent to ``study.tell(trial, y)``.  Define-and-RunThe ask-and-tell interface supports both `define-by-run` and `define-and-run` APIs.This section shows the example of the `define-and-run` APIin addition to the define-by-run example above.Define distributions for the hyperparameters before calling the:func:`optuna.study.Study.ask` method for define-and-run API.For example,<jupyter_code>distributions = {
    "C": optuna.distributions.LogUniformDistribution(1e-7, 10.0),
    "solver": optuna.distributions.CategoricalDistribution(("lbfgs", "saga")),
}<jupyter_output><empty_output><jupyter_text>Pass ``distributions`` to :func:`optuna.study.Study.ask` method at each call.The retuned ``trial`` contains the suggested hyperparameters.<jupyter_code>study = optuna.create_study(direction="maximize")
n_trials = 10
for _ in range(n_trials):
    trial = study.ask(distributions)  # pass the pre-defined distributions.

    # two hyperparameters are already sampled from the pre-defined distributions
    C = trial.params["C"]
    solver = trial.params["solver"]

    clf = LogisticRegression(C=C, solver=solver)
    clf.fit(X_train, y_train)
    val_accuracy = clf.score(X_test, y_test)

    study.tell(trial, val_accuracy)<jupyter_output><empty_output><jupyter_text>Batch OptimizationThe ask-and-tell interface enables us to optimize a batched objective for faster optimization.For example, parallelizable evaluation, operation over vectors, etc. The following objective takes batched hyperparameters ``xs`` and ``ys`` instead of a singlepair of hyperparameters ``x`` and ``y`` and calculates the objective over the full vectors.<jupyter_code>def batched_objective(xs: np.ndarray, ys: np.ndarray):
    return xs ** 2 + ys<jupyter_output><empty_output><jupyter_text>In the following example, the number of pairs of hyperparameters in a batch is $10$,and ``batched_objective`` is evaluated three times.Thus, the number of trials is $30$.Note that you need to store either ``trial_ids`` or ``trial`` to call:func:`optuna.study.Study.tell` method after the batched evaluations.<jupyter_code>batch_size = 10
study = optuna.create_study(sampler=optuna.samplers.CmaEsSampler())

for _ in range(3):

    # create batch
    trial_ids = []
    x_batch = []
    y_batch = []
    for _ in range(batch_size):
        trial = study.ask()
        trial_ids.append(trial.number)
        x_batch.append(trial.suggest_float("x", -10, 10))
        y_batch.append(trial.suggest_float("y", -10, 10))

    # evaluate batched objective
    x_batch = np.array(x_batch)
    y_batch = np.array(y_batch)
    objectives = batched_objective(x_batch, y_batch)

    # finish all trials in the batch
    for trial_id, objective in zip(trial_ids, objectives):
        study.tell(trial_id, objective)<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.10096217213654936, 'fraction_numerical': 0.007249242124686964, 'mean_word_length': 4.726792452830189, 'pattern_counts': {'":': 2, '<': 29, '<?xml version=': 0, '>': 29, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '7', 'dir': 'jupyter-structured-clean-dedup', 'id': '483950', 'license': 'MIT', 'n_tokens_mistral': 2488, 'n_tokens_neox': 2319, 'n_words': 665, 'path': 'Optuna.docset/Contents/Resources/Documents/_downloads/9e17bbf554dfa22e6c92f27c8c7df53d/009_ask_and_tell.ipynb', 'repo_name': '29Takuya/dash-docset-optuna', 'size': '7587'}