{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Planners Interfaces" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Optimization algorithms in **Olympus** can be accessed via ``Planners`` objects. They have higher- and lower-level methods to allow more/less control of the optimization. " ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The most important methods for any ``Planner`` in **Olympus** are:\n", "- ``optimize``\n", "- ``recommend``\n", "- ``ask`` and ``tell``" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Here we show how these three interfaces can be used to optimize a surface of choice. Let's start by instanciating a specific optimizer and emulator" ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\u001b[0;37m[INFO] Loading emulator using a BayesNeuralNet model for the dataset hplc...\n", "\u001b[0m" ] } ], "source": [ "from olympus import Planner, Emulator, Campaign\n", "\n", "planner = Planner('Hyperopt', goal='maximize')\n", "emulator = Emulator(dataset='hplc', model='BayesNeuralNet')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Optimize" ] }, { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\u001b[0;37m[INFO] Optimize iteration 1\n", "\u001b[0m\u001b[0;37m[INFO] Obtaining parameters from planner...\n", "\u001b[0m\u001b[0;37m[INFO] Obtaining measurement from emulator...\n", "\u001b[0m\u001b[0;37m[INFO] Optimize iteration 2\n", "\u001b[0m\u001b[0;37m[INFO] Obtaining parameters from planner...\n", "\u001b[0m\u001b[0;37m[INFO] Obtaining measurement from emulator...\n", "\u001b[0m\u001b[0;37m[INFO] Optimize iteration 3\n", "\u001b[0m\u001b[0;37m[INFO] Obtaining parameters from planner...\n", "\u001b[0m\u001b[0;37m[INFO] Obtaining measurement from emulator...\n", "\u001b[0m\u001b[0;37m[INFO] Optimize iteration 4\n", "\u001b[0m\u001b[0;37m[INFO] Obtaining parameters from planner...\n", "\u001b[0m\u001b[0;37m[INFO] Obtaining measurement from emulator...\n", "\u001b[0m\u001b[0;37m[INFO] Optimize iteration 5\n", "\u001b[0m\u001b[0;37m[INFO] Obtaining parameters from planner...\n", "\u001b[0m\u001b[0;37m[INFO] Obtaining measurement from emulator...\n", "\u001b[0m" ] } ], "source": [ "# optimise the surface for 5 iterations\n", "campaign = planner.optimize(emulator, num_iter=5, verbose=True)" ] }, { "cell_type": "code", "execution_count": 3, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[3.99634412e-02 5.92366755e-02 5.56513608e-01 1.32164115e+00\n", " 1.28585018e+02 2.29232642e+00] [794.28760118]\n", "[5.21297934e-02 4.11513637e-02 8.28823539e-01 2.12991777e+00\n", " 1.34636851e+02 4.56346874e+00] [190.70192684]\n", "[6.88022674e-02 2.31711378e-02 7.86579842e-01 1.45240663e+00\n", " 1.06799456e+02 3.21836802e+00] [25.05118119]\n", "[3.57485194e-02 1.01848064e-02 4.79433112e-01 1.59496475e+00\n", " 9.11006486e+01 8.93052795e+00] [837.64479039]\n", "[3.19394342e-02 1.03955562e-02 2.87069883e-01 2.24478218e+00\n", " 1.22440051e+02 2.82028857e+00] [2000.172279]\n" ] } ], "source": [ "# print the results\n", "for p, v in zip(campaign.params, campaign.values):\n", " print(p, v)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Recommend" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "As you can see, the ``optimize`` method is very convenient, but does not allow much control in what happens at each step of the optimization. The ``recommend`` method runs instead a single iteration of the optimization, such that you can have access to the parameters and measurements at each iteraion. As an example, we perform the same 10-step optimization as above but using ``recommend`` instead this time." ] }, { "cell_type": "code", "execution_count": 4, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Iter 1\n", "------\n", "Parameters: ParamVector(sample_loop = 0.04214239677999049, additional_volume = 0.053410186023081355, tubing_volume = 0.6886106912572801, sample_flow = 1.2313387694567246, push_speed = 120.33877426478782, wait_time = 9.831562416147625)\n", "Values: ParamVector(peak_area = 182.92490526330087)\n", "\n", "Iter 2\n", "------\n", "Parameters: ParamVector(sample_loop = 0.043293140897302164, additional_volume = 0.048965823324975226, tubing_volume = 0.686463996645267, sample_flow = 1.8937519623656645, push_speed = 98.51430725969507, wait_time = 5.601818498433116)\n", "Values: ParamVector(peak_area = 215.42974384808343)\n", "\n", "Iter 3\n", "------\n", "Parameters: ParamVector(sample_loop = 0.07643185535530703, additional_volume = 0.05667404894922595, tubing_volume = 0.6650598532796427, sample_flow = 1.916183318424112, push_speed = 122.7209899443508, wait_time = 1.510488953562232)\n", "Values: ParamVector(peak_area = 324.8829338472122)\n", "\n", "Iter 4\n", "------\n", "Parameters: ParamVector(sample_loop = 0.03882589187468909, additional_volume = 0.012301890870887077, tubing_volume = 0.278553853395321, sample_flow = 2.2053614339750007, push_speed = 104.96898650189364, wait_time = 9.562302646869888)\n", "Values: ParamVector(peak_area = 2072.8976459933033)\n", "\n", "Iter 5\n", "------\n", "Parameters: ParamVector(sample_loop = 0.009822229434326219, additional_volume = 0.029049327494845626, tubing_volume = 0.8460893640743111, sample_flow = 1.3473238976680675, push_speed = 123.70914753868718, wait_time = 4.0203055504668015)\n", "Values: ParamVector(peak_area = 0.0)\n", "\n" ] } ], "source": [ "max_iter = 5\n", "\n", "# instantiate a Campaign object, which stores the results of the optimization\n", "campaign = Campaign()\n", "\n", "# tell the planner what is the optimization domain\n", "planner.set_param_space(emulator.param_space)\n", "\n", "for i in range(max_iter):\n", " print(f\"Iter {i+1}\\n------\")\n", " \n", " # ask the planner for a new set of parameters\n", " params = planner.recommend(observations=campaign.observations)\n", " print('Parameters:', params)\n", " \n", " # evaluate the merit of the new parameters\n", " values = emulator.run(params.to_array(), return_paramvector=True)\n", " print('Values:', values[0])\n", "\n", " # store parameter and measurement pair in campaign\n", " campaign.add_observation(params, values)\n", " \n", " print()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Ask and Tell" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Finally, one can use the ``ask`` and ``tell`` methods instead of ``recommend``. This allows to control what the planner knows before suggesting the next experiment to run. However, note that not all planners use the history of the optimization when to choose what experiment to propose next." ] }, { "cell_type": "code", "execution_count": 5, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Iter 1\n", "------\n", "Parameters: ParamVector(sample_loop = 0.03549386694005813, additional_volume = 0.03330348781561569, tubing_volume = 0.20541452615744327, sample_flow = 0.9918564339279039, push_speed = 85.3836698503327, wait_time = 7.732563361348338)\n", "Values: ParamVector(peak_area = 0.0)\n", "\n", "Iter 2\n", "------\n", "Parameters: ParamVector(sample_loop = 0.07948685024663711, additional_volume = 0.01405398186830723, tubing_volume = 0.4008361777353059, sample_flow = 1.213248706166157, push_speed = 122.85990779892668, wait_time = 1.9588104184592865)\n", "Values: ParamVector(peak_area = 1087.4971033499935)\n", "\n", "Iter 3\n", "------\n", "Parameters: ParamVector(sample_loop = 0.07459429555877291, additional_volume = 0.04632047521192829, tubing_volume = 0.8636585456822277, sample_flow = 2.4340302954514517, push_speed = 127.34080433592416, wait_time = 9.348306043102033)\n", "Values: ParamVector(peak_area = 0.0)\n", "\n", "Iter 4\n", "------\n", "Parameters: ParamVector(sample_loop = 0.04469537573702059, additional_volume = 0.016678012840125878, tubing_volume = 0.6607858069330779, sample_flow = 1.8523761717851137, push_speed = 138.98260252526268, wait_time = 9.501125947667138)\n", "Values: ParamVector(peak_area = 330.6013244397631)\n", "\n", "Iter 5\n", "------\n", "Parameters: ParamVector(sample_loop = 0.05279966827346898, additional_volume = 0.04876100437059912, tubing_volume = 0.7023206540114464, sample_flow = 1.0172256976081377, push_speed = 138.30474028379786, wait_time = 1.4750453547630402)\n", "Values: ParamVector(peak_area = 70.43434451522799)\n", "\n" ] } ], "source": [ "max_iter = 5\n", "\n", "# instantiate a Campaign object, which stores the results of the optimization\n", "campaign = Campaign()\n", "\n", "# tell the planner what is the optimization domain\n", "planner.set_param_space(emulator.param_space)\n", "\n", "for i in range(max_iter):\n", " print(f\"Iter {i+1}\\n------\")\n", " \n", " # tell the planner about the optimization history\n", " planner.tell(campaign.observations)\n", " \n", " # ask the planner for a new set of parameters\n", " params = planner.ask()\n", " print('Parameters:', params)\n", " \n", " # evaluate the merit of the new parameters\n", " values = emulator.run(params.to_array(), return_paramvector=True)\n", " print('Values:', values[0])\n", "\n", " # store parameter and measurement pair in campaign\n", " campaign.add_observation(params, values)\n", " \n", " print()" ] } ], "metadata": { "kernelspec": { "display_name": "olympus", "language": "python", "name": "olympus" }, "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": 4 }