.. DO NOT EDIT. .. THIS FILE WAS AUTOMATICALLY GENERATED BY SPHINX-GALLERY. .. TO MAKE CHANGES, EDIT THE SOURCE PYTHON FILE: .. "generated/recipes/001_first.py" .. LINE NUMBERS ARE GIVEN BELOW. .. only:: html .. note:: :class: sphx-glr-download-link-note :ref:`Go to the end ` to download the full example code. .. rst-class:: sphx-glr-example-title .. _sphx_glr_generated_recipes_001_first.py: .. _first: How to Implement Your Sampler with OptunaHub =========================================================== OptunaHub is an Optuna package registry, which is a platform to share algorithms developed by contributors. This recipe shows how to implement your own algorithm with OptunaHub. Here, we show how to implement your own sampler, i.e., optimizaiton algorithm. If you want to implement algorithms other than a sampler, please refer to the other recipes. - :doc:`003_pruner` - :doc:`004_visualization` Usually, Optuna provides ``BaseSampler`` class to implement your own sampler. However, it is a bit complicated to implement a sampler from scratch. Instead, in OptunaHub, you can use `optunahub.samplers.SimpleBaseSampler `__ class, which is a sampler template that can be easily extended. You need to install ``optuna`` to implement your own sampler, and ``optunahub`` to use the template ``SimpleBaseSampler``. .. code-block:: bash $ pip install optuna optunahub .. GENERATED FROM PYTHON SOURCE LINES 29-30 First of all, import ``optuna``, ``optunahub``, and other required modules. .. GENERATED FROM PYTHON SOURCE LINES 30-40 .. code-block:: Python from __future__ import annotations from typing import Any import numpy as np import optuna import optunahub .. GENERATED FROM PYTHON SOURCE LINES 41-43 Next, define your own sampler class by inheriting ``SimpleBaseSampler`` class. In this example, we implement a sampler that returns a random value. .. GENERATED FROM PYTHON SOURCE LINES 43-85 .. code-block:: Python class MySampler(optunahub.samplers.SimpleBaseSampler): # By default, search space will be estimated automatically like Optuna's built-in samplers. # You can fix the search spacd by `search_space` argument of `SimpleSampler` class. def __init__( self, search_space: dict[str, optuna.distributions.BaseDistribution] | None = None ) -> None: super().__init__(search_space) self._rng = np.random.RandomState() # You need to implement sample_relative method. # This method returns a dictionary of hyperparameters. # The keys of the dictionary are the names of the hyperparameters, which must be the same as the keys of the search_space argument. # The values of the dictionary are the values of the hyperparameters. # In this example, sample_relative method returns a dictionary of randomly sampled hyperparameters. def sample_relative( self, study: optuna.study.Study, trial: optuna.trial.FrozenTrial, search_space: dict[str, optuna.distributions.BaseDistribution], ) -> dict[str, Any]: # search_space argument must be identical to search_space argument input to __init__ method. # This method is automatically invoked by Optuna and SimpleBaseSampler. # If search space is empty, all parameter values are sampled randomly by SimpleBaseSampler. if search_space == {}: return {} params = {} # type: dict[str, Any] for n, d in search_space.items(): if isinstance(d, optuna.distributions.FloatDistribution): params[n] = self._rng.uniform(d.low, d.high) elif isinstance(d, optuna.distributions.IntDistribution): params[n] = self._rng.randint(d.low, d.high) elif isinstance(d, optuna.distributions.CategoricalDistribution): params[n] = d.choices[self._rng.randint(len(d.choices))] else: raise NotImplementedError return params .. GENERATED FROM PYTHON SOURCE LINES 86-87 Here, as an example, the objective function is defined as follows. .. GENERATED FROM PYTHON SOURCE LINES 87-96 .. code-block:: Python def objective(trial: optuna.trial.Trial) -> float: x = trial.suggest_float("x", -10, 10) y = trial.suggest_int("y", -10, 10) z = trial.suggest_categorical("z", ["a", "b", "c"]) return x**2 + y**2 + {"a": -10, "b": 0, "c": 10}[z] ** 2 .. GENERATED FROM PYTHON SOURCE LINES 97-99 This sampler can be used in the same way as other Optuna samplers. In the following example, we create a study and optimize it using ``MySampler`` class. .. GENERATED FROM PYTHON SOURCE LINES 99-103 .. code-block:: Python sampler = MySampler() study = optuna.create_study(sampler=sampler) study.optimize(objective, n_trials=100) .. GENERATED FROM PYTHON SOURCE LINES 104-105 The best parameters can be fetched as follows. .. GENERATED FROM PYTHON SOURCE LINES 105-110 .. code-block:: Python best_params = study.best_params best_value = study.best_value print(f"Best params: {best_params}, Best value: {best_value}") .. rst-class:: sphx-glr-script-out .. code-block:: none Best params: {'x': -0.2841009445692535, 'y': 0, 'z': 'b'}, Best value: 0.08071334670514205 .. GENERATED FROM PYTHON SOURCE LINES 111-112 We can see that ``best_params`` value found by Optuna is close to the optimal value ``{"x":0, "y": 0, "z": "b"}``. .. GENERATED FROM PYTHON SOURCE LINES 114-118 In the above examples, search space is estimated at the first trial and updated dynamically through optimization. If your sampler requires the search space to be fixed before optimization, you can pass the search space to the sampler at initialization. Passing the search space also allows the sampler to avoid the overhead of estimating the search space. See `the documentation `__ for more information about the ``optuna.distributions`` to define search space. .. GENERATED FROM PYTHON SOURCE LINES 118-128 .. code-block:: Python sampler = MySampler( search_space={ "x": optuna.distributions.FloatDistribution(-10, 10), "y": optuna.distributions.IntDistribution(-10, 10), "z": optuna.distributions.CategoricalDistribution(["a", "b", "c"]), } ) study = optuna.create_study(sampler=sampler) study.optimize(objective, n_trials=100) .. GENERATED FROM PYTHON SOURCE LINES 129-132 In the next recipe, we will show how to register your sampler to OptunaHub. Let's move on to :doc:`002_registration`. See `the User-Defined Sampler documentation `_ for more information to implement a sampler. .. rst-class:: sphx-glr-timing **Total running time of the script:** (0 minutes 0.093 seconds) .. _sphx_glr_download_generated_recipes_001_first.py: .. only:: html .. container:: sphx-glr-footer sphx-glr-footer-example .. container:: sphx-glr-download sphx-glr-download-jupyter :download:`Download Jupyter notebook: 001_first.ipynb <001_first.ipynb>` .. container:: sphx-glr-download sphx-glr-download-python :download:`Download Python source code: 001_first.py <001_first.py>` .. container:: sphx-glr-download sphx-glr-download-zip :download:`Download zipped: 001_first.zip <001_first.zip>` .. only:: html .. rst-class:: sphx-glr-signature `Gallery generated by Sphinx-Gallery `_