{
  "cells": [
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "collapsed": false
      },
      "outputs": [],
      "source": [
        "%matplotlib inline"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\n# Python API basics\n\nThis short tutorial will show you the basics to use Or\u00edon in python. We will optimize a simple\n1-d ``rosenbrock`` function with random search and TPE and visualize the regret curve to compare\nthe algorithms.\n\nWe first import the only function needed, :func:`build experiment <orion.client.build_experiment>`.\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "collapsed": false
      },
      "outputs": [],
      "source": [
        "from orion.client import build_experiment"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "We configure the database with PickledDB so that the results are saved locally on disk. This\nenables resuming the experiment and running parallel workers.\n\n.. TODO Replace with just nothing when pickleddb becomes the default.\n\n\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "collapsed": false
      },
      "outputs": [],
      "source": [
        "storage = {\n    \"type\": \"legacy\",\n    \"database\": {\n        \"type\": \"pickleddb\",\n        \"host\": \"./db.pkl\",\n    },\n}"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "We define the search space for the optimization. Here, the optimization algorithm may explore\nreal values for ``x`` between 0 and 30 only. See documentation of `search-space` for more\ninformation.\n\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "collapsed": false
      },
      "outputs": [],
      "source": [
        "space = {\"x\": \"uniform(0, 30)\"}"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "We then build the experiment with the name ``random-rosenbrock``. The name is by Or\u00edon as\nan `id` for the experiment. Each experiment must have a unique name.\n\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "collapsed": false
      },
      "outputs": [],
      "source": [
        "experiment = build_experiment(\n    \"random-rosenbrock\",\n    space=space,\n    storage=storage,\n)"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "For this example we use a 1-d rosenbrock function. We must return a list of results,\nfor Or\u00edon. Results must have the format\n``{name: <str>: type: <'objective', 'constraint' or 'gradient'>, value=<float>}`` otherwise\na ``ValueError`` will be raised. At least one of the results must have the type ``objective``,\nthe metric that is minimized by the algorithm.\n\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "collapsed": false
      },
      "outputs": [],
      "source": [
        "def rosenbrock(x, noise=None):\n    \"\"\"Evaluate partial information of a quadratic.\"\"\"\n    y = x - 34.56789\n    z = 4 * y ** 2 + 23.4\n\n    return [{\"name\": \"objective\", \"type\": \"objective\", \"value\": z}]"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "We then pass the function ``rosenbrock`` to\n:meth:`workon() <orion.client.experiment.ExperimentClient.workon>`. This method\nwill iteratively try new sets of hyperparameters suggested by the optimization algorithm\nuntil it reaches 20 trials.\n\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "collapsed": false
      },
      "outputs": [],
      "source": [
        "experiment.workon(rosenbrock, max_trials=20)"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "Now let's plot the regret curve to see how well went the optimization.\n\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "collapsed": false
      },
      "outputs": [],
      "source": [
        "experiment.plot.regret().show()"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        ".. This file is produced by docs/scripts/build_database_and_plots.py\n\n.. raw:: html\n    :file: ../_static/random-rosenbrock_regret.html\n\nWe have here on the x-axis the trials order by suggestion time, that is the order they\nwere tried inside the ``workon`` loop. The y-axis is the objective of the trials, the lower the\nbetter. The red curve represents the regret, the best achieved objective at time `x`, and the\nblue dots are the objectives of the different trials.\n\nFortunately, we can see looking at the regret curve that the best results converge close to the\nminimum. That means the optimization was at least reasonably good. On the other-hand, looking at\nthe trials we see that the algorithm made suggestions far from optimal from the beginning\nto the end of the optimization. That is to be expected, by default Or\u00edon uses random search. All\ntrials were randomly sampled. Let's try next a different algorithm to observe a proper convergence\nbehavior.\n\nLet's use a\n`Tree Parzen Estimator\n<https://papers.nips.cc/paper/2011/hash/86e8f7ab32cfd12577bc2619bc635690-Abstract.html>`_\nthat can easily find the optimal solution. We specify the algorithm configuration t\n:func:`build experiment <orion.client.build_experiment>`\n\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "collapsed": false
      },
      "outputs": [],
      "source": [
        "experiment = build_experiment(\n    \"tpe-rosenbrock\",\n    space=space,\n    algorithms={\"tpe\": {\"n_initial_points\": 5}},\n    storage=storage,\n)"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "We then again run the optimization for 20 trials and plot the regret.\n\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "collapsed": false
      },
      "outputs": [],
      "source": [
        "experiment.workon(rosenbrock, max_trials=20)\n\nexperiment.plot.regret().show()"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        ".. This file is produced by docs/scripts/build_database_and_plots.py\n\n.. raw:: html\n    :file: ../_static/tpe-rosenbrock_regret.html\n\nWe can see the stark difference with the results of the random search. After the first 5 random\npoints (see tpe's configuration above), the TPE already identified the optimal region for `x`\nand explored this subspace.\n\n## Further readings\n\nUser guides:\n\n- `Search space <search-space>`\n- `Algorithms <Setup Algorithms>`\n- `Visualizations <visualizations>`\n\nAPI:\n\n- :func:`orion.client.build_experiment`\n- :func:`orion.client.get_experiment`\n- :class:`orion.client.experiment.ExperimentClient`\n\n"
      ]
    }
  ],
  "metadata": {
    "kernelspec": {
      "display_name": "Python 3",
      "language": "python",
      "name": "python3"
    },
    "language_info": {
      "codemirror_mode": {
        "name": "ipython",
        "version": 3
      },
      "file_extension": ".py",
      "mimetype": "text/x-python",
      "name": "python",
      "nbconvert_exporter": "python",
      "pygments_lexer": "ipython3",
      "version": "3.7.9"
    }
  },
  "nbformat": 4,
  "nbformat_minor": 0
}