Skip to content

Commit

Permalink
Add documentation
Browse files Browse the repository at this point in the history
  • Loading branch information
bouthilx committed Oct 21, 2019
1 parent 33fd55a commit 1cf4afd
Show file tree
Hide file tree
Showing 10 changed files with 211 additions and 43 deletions.
1 change: 1 addition & 0 deletions docs/src/code/client.rst
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ Client helper functions
:maxdepth: 1
:caption: Modules

client/experiment
client/manual

.. automodule:: orion.client
Expand Down
5 changes: 5 additions & 0 deletions docs/src/code/client/experiment.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
Experiment client
=================

.. automodule:: orion.client.experiment
:members:
1 change: 1 addition & 0 deletions docs/src/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
:maxdepth: 1

user/pytorch
user/api
user/monitoring
user/searchspace
user/algorithms
Expand Down
2 changes: 2 additions & 0 deletions docs/src/install/database.rst
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
.. _install_database:

**************
Setup Database
**************
Expand Down
2 changes: 2 additions & 0 deletions docs/src/user/algorithms.rst
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
.. _Setup Algorithms:

****************
Setup Algorithms
****************
Expand Down
159 changes: 159 additions & 0 deletions docs/src/user/api.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,159 @@
************
Hunting APIs
************

.. contents::
:depth: 2
:local:


There are two ways of using Oríon for optimization. One is using the commandline interface which
conveniently turn a simple script into a hyper-parameter optimization process at the level of the
command line.
The other is using the python interface which gives total control
over the pipeline of optimization.

Commandline API
===============

Suppose you normally execute your script with the following command

.. code-block:: bash
$ ./main.py --lr 0.1
Using the commandline API you can turn your script into a hyper-parameter process by wrapping it
with Oríon.

.. code-block:: bash
$ orion hunt -n exp-name ./main.py --lr~'loguniform(1e-5, 1.0)'
An experiment called ``exp-name`` will now be created and your script will be called with
the argument ``--lr`` assigned to values sampled by the optimization algorthm.

Configuration of the algorithm can be done inside a yaml file passed to ``--config`` as described in
:ref:`Setup Algorithms`.


Python APIs
===========

The python API is declined in two versions

:ref:`sequential_api`:
A simple method for local sequential optimision.
:ref:`service_api`:
A simple method to get new parameters to try and report results in a distributed manner.
:ref:`framework_api`:
Total control over the hyper-parameter optimization pipeline.


.. _sequential_api:

Sequential API
--------------

Using the helper :py:func:`orion.client.workon`,
you can optimize a function with a single line of code.

.. code-block:: python
from orion.client import workon
def foo(x):
return [dict(
name='dummy_objective',
type='objective',
value=1)]
experiment = workon(foo, space=dict(x='uniform(-50,50)'))
The experiment object returned is can be used to fetch the database of trials
and analyze the optimization process. Note that the storage for `workon` is
in-memory and requires no setup. This means however that :py:func:`orion.client.workon`
cannot be used for parallel optimisation.

.. _service_api:

Service API
-----------

Experiments are created using the helper function
:py:func:`orion.client.create_experiment`. You can then sample new trials with
:py:meth:`experiment.suggest() <orion.client.experiment.ExperimentClient.suggest>`.
The parameters of the trials are provided as a dictionary with
:py:meth:`trial.params <orion.core.worker.trial.Trial.params>`.
Once the trial is completed, results can be reported to the experiment with
:py:meth:`experiment.observe() <orion.client.experiment.ExperimentClient.observe>`.
Note that this should be the final result of the trial. When observe is called, the trial
reservation is released and its status is set to completed. Observing twice the same trial will
raise a RuntimeError because the trial is not reserved anymore.

.. code-block:: python
from orion.client import create_experiment
experiment = create_experiment(
name='foo',
space=dict(x='uniform(-50,50)'))
trial = experiment.suggest()
# Do something using trial.params['x']
results = [dict(
name='dummy_objective',
type='objective',
value=dummy_objective)]
experiment.observe(trial, results)
The storage used by the experiment can be specified as an argument to
:py:func:`create_experiment(storage={}) <orion.client.create_experiment>`
or in a global configuration file as described in :ref:`install_database`.

To distribute the hyper-parameter optimisation in many workers, simply execute your script in
parallel where you want to execute your trials. The method
:py:meth:`experiment.suggest() <orion.client.experiment.ExperimentClient.suggest>`
will take care of synchronizing the local algorithm with all remote instances, making it possible
to distribute the optimization without setting up a master process.

See :py:class:`ExperimentClient <orion.client.experiment.ExperimentClient>`
for more information on the experiment client object.

.. warning::

Code version detection is not currently supported. This means that creating experiments using
different code version will not lead to version increment like it would do with the commandline
API.


.. _framework_api:


Framework API
-------------

.. warning::

This API is not implemented yet. It should be included in v0.2.0.

.. code-block:: python
from orion.client import create_space
from orion.client import create_algo
space = create_space(x='uniform(-50,50)')
algo = create_algo(space, type='ASHA', add some config here)
params = algo.suggest()
results = 'some_results...'
algo.observe(params, results)
16 changes: 5 additions & 11 deletions docs/src/user/library/evc_results.rst
Original file line number Diff line number Diff line change
Expand Up @@ -4,25 +4,19 @@ Iterative Results with EVC
When using the experiment version control (described `here <user/evc>`_),
the experiments are connected in a tree structure which we call the EVC tree.
You can retrieve results from different experiments with the EVC tree similarly
as described in previous section. The only difference
is we need to use :class:`EVCBuilder <orion.core.io.evc_builder.EVCBuilder>` instead of
:class:`ExperimentBuilder <orion.core.io.experiment_builder.ExperimentBuilder>`.
The :class:`EVCBuilder <orion.core.io.evc_builder.EVCBuilder>` will connect the experiment
to the EVC tree, accessible through the
:attr:`node <orion.core.worker.experiment.Experiment.node>` attribute.
All trials of the tree can be fetched
as described in previous section. All trials of the tree can be fetched
with option
:meth:`fetch_trials(with_evc_tree=True) <orion.core.worker.experiment.Experiment.fetch_trials>`,
:meth:`fetch_trials(with_evc_tree=True) <orion.client.experiment.ExperimentClient.fetch_trials>`,
``with_evc_tree=False``` will only fetch the
trials of the specific experiment.

.. code-block:: python
import pprint
from orion.core.io.evc_builder import EVCBuilder
experiment = EVCBuilder().build_view_from(
{"name": "orion-tutorial-with-momentum"})
from orion.client import create_experiment
experiment = create_experiment(name="orion-tutorial-with-momentum")
print(experiment.name)
pprint.pprint(experiment.stats)
Expand Down
42 changes: 18 additions & 24 deletions docs/src/user/library/results.rst
Original file line number Diff line number Diff line change
Expand Up @@ -3,43 +3,39 @@ Results

You can fetch experiments and trials using python code. There is no need to understand the
specific database backend used (such as MongoDB) since you can fetch results using the
:class:`orion.core.worker.experiment.Experiment` object.
The class :class:`orion.core.io.experiment_builder.ExperimentBuilder`
provides simple methods to fetch experiments
:class:`orion.client.experiment.ExperimentClient` object.
The helper function :py:func:`orion.client.create_experiment`
provides a simple way to fetch experiments
using their unique names. You do not need to explicitly open a connection to the database since it
will automatically infer its configuration from the global configuration file as when calling Oríon
in commandline. Otherwise you can pass other arguments to
:meth:`ExperimentBuilder().build_view_from() \
<orion.core.io.experiment_builder.ExperimentBuilder.build_view_from>`.

using the same dictionary structure as in the configuration file.
in commandline. Otherwise you can specify the configuration directly to
:py:func:`create_experiment() <orion.client.create_experiment>`. Take a look at the documentation
for more details on all configuration arguments that are supported.

.. code-block:: python
# Database automatically inferred
ExperimentBuilder().build_view_from(
{"name": "orion-tutorial"})
create_experiment(name="orion-tutorial")
# Database manually set
ExperimentBuilder().build_view_from(
{"name": "orion-tutorial",
"dataset": {
"type": "mongodb",
"name": "myother",
"host": "localhost"}})
create_experiment(
name="orion-tutorial",
storage={
'type': 'legacy',
'database': {
'type': 'mongodb',
'name': 'myother',
'host': 'localhost'}})
For a complete example, here is how you can fetch trials from a given experiment.

.. code-block:: python
import datetime
import pprint
from orion.core.io.experiment_builder import ExperimentBuilder
some_datetime = datetime.datetime.now() - datetime.timedelta(minutes=5)
from orion.client import create_experiment
experiment = ExperimentBuilder().build_view_from({"name": "orion-tutorial"})
experiment = create_experiment(name="orion-tutorial")
pprint.pprint(experiment.stats)
Expand All @@ -56,7 +52,5 @@ For a complete example, here is how you can fetch trials from a given experiment
print(trial.objective)
:class:`<orion.core.worker.experiment.Experiment>` has many methods that allows you to query
:py:class:`ExperimentClient <orion.client.experiment.ExperimentClient>` has many methods that allows you to query
for different trials. You can find them in the code reference section.

.. _`mongodb-like syntax`: https://docs.mongodb.com/manual/reference/method/db.collection.find/
2 changes: 1 addition & 1 deletion src/orion/client/experiment.py
Original file line number Diff line number Diff line change
Expand Up @@ -427,7 +427,7 @@ def workon(self, fct, max_trials=infinity, **kwargs):
----------
fct: callable
Function to optimize. Must take arguments provided by trial.params. Additional constant
parameter can be passed as **kwargs to `workon`. Function must return the final
parameter can be passed as ``**kwargs`` to `workon`. Function must return the final
objective.
max_trials: int, optional
Maximum number of trials to execute within `workon`. If the experiment or algorithm
Expand Down
24 changes: 17 additions & 7 deletions src/orion/client/manual.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,24 @@
and link them with a particular existing experiment.
"""
import orion.core.io.experiment_builder as experiment_builder
import logging

from orion.client import create_experiment
from orion.core.utils import format_trials


log = logging.getLogger(__name__)


def insert_trials(experiment_name, points, raise_exc=True):
"""Insert sets of parameters manually, defined in `points`, as new trials
for the experiment name, `experiment_name`.
.. warning::
This function is deprecated and will be removed in 0.3.0.
You should use ExperimentClient.insert() instead.
:param experiment_name: Name of the experiment which the new trials are
going to be associated with
:param points: list of tuples in agreement with experiment's parameter space
Expand All @@ -31,13 +41,15 @@ def insert_trials(experiment_name, points, raise_exc=True):
the database.
"""
experiment_view = experiment_builder.build_view(name=experiment_name)
log.warning('insert_trials() is deprecated and will be removed in 0.3.0. '
'You should use ExperimentClient.insert() instead.')
experiment = create_experiment(experiment_name)

valid_points = []

for point in points:
try:
assert point in experiment_view.space
assert point in experiment.space
valid_points.append(point)
except AssertionError:
if raise_exc:
Expand All @@ -47,10 +59,8 @@ def insert_trials(experiment_name, points, raise_exc=True):
return

new_trials = list(
map(lambda data: format_trials.tuple_to_trial(data, experiment_view.space),
map(lambda data: format_trials.tuple_to_trial(data, experiment.space),
valid_points))

experiment = experiment_builder.build(name=experiment_view.name,
version=experiment_view.version)
for new_trial in new_trials:
experiment.register_trial(new_trial)
experiment.insert(new_trial.params)

0 comments on commit 1cf4afd

Please sign in to comment.