{ "cells": [ { "cell_type": "code", "execution_count": 25, "metadata": {}, "outputs": [], "source": [ "import numpy as np\n", "import torch\n", "from torch import Tensor\n", "\n", "from matplotlib import pyplot as plt\n", "\n", "from ax.modelbridge.factory import get_GPEI, get_botorch\n", "from ax.modelbridge.registry import Models, TorchModelBridge\n", "from ax.models.torch.botorch import BotorchModel\n", "\n", "from botorch.sampling import SobolQMCNormalSampler\n", "from botorch.models.model import Model\n", "from botorch.acquisition.acquisition import AcquisitionFunction\n", "from botorch.acquisition import get_acquisition_function\n", "from botorch.acquisition.objective import ConstrainedMCObjective\n", "from botorch.utils import get_objective_weights_transform, get_outcome_constraint_transforms\n", "\n", "from ax import (\n", " Data,\n", " Metric,\n", " Experiment,\n", " Objective,\n", " OutcomeConstraint,\n", " OptimizationConfig,\n", " ComparisonOp,\n", " ParameterType, \n", " RangeParameter,\n", " SearchSpace, \n", " OutcomeConstraint\n", ")\n", "\n", "from ax.plot.exp_utils import exp_to_df\n", "from ax.service.utils.best_point import get_best_parameters\n", "\n", "from albo.objective import ClassicAlboMCObjective\n", "from albo.acquisition import AlboAcquisitionFactory\n", "from albo.utils import get_untransformed_trace" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Toy problem from Gramacy et. al" ] }, { "cell_type": "code", "execution_count": 26, "metadata": {}, "outputs": [], "source": [ "def gramacy(x):\n", " \"\"\"Gramacy problem function\n", " \"\"\"\n", " x1 = x[:, 0]\n", " x2 = x[:, 1]\n", " f = x1 + x2\n", " c1 = (3./2) - x1 - 2.*x2 - (1./2) * np.sin(2. * np.pi * (x1**2 - 2.*x2))\n", " c2 = x1**2 + x2**2 - 3./2\n", " return np.stack([f, c1, c2], axis=1)\n", "\n", "bounds = np.array([[0.0, 0.0], [1.0, 1.0]])" ] }, { "cell_type": "code", "execution_count": 3, "metadata": {}, "outputs": [], "source": [ "def make_feasibility_plot_2d(\n", " ax,\n", " fcn,\n", " bounds,\n", " nx: int = 100,\n", " ny: int = 100,\n", " levels=None,\n", " levels_fmt='%2.1f'\n", "):\n", " x_bounds = bounds[:, 0]\n", " x = np.linspace(x_bounds[0], x_bounds[1], num=nx)\n", "\n", " y_bounds = bounds[:, 1]\n", " y = np.linspace(y_bounds[0], y_bounds[1], num=ny)\n", "\n", " x_grid, y_grid = np.meshgrid(x, y)\n", " x_ = x_grid.flatten()\n", " y_ = y_grid.flatten()\n", "\n", " X = np.stack((x_, y_), axis=1)\n", " Z = fcn(X)\n", " \n", " contours = list()\n", " for i in range(Z.shape[1]):\n", " c = Z[:, i]\n", " c_grid = c.reshape((len(x), len(y)))\n", "\n", " if i > 0:\n", " cfill = ax.contourf(x_grid, y_grid, c_grid, levels=[0.0, np.inf], colors='lightgray')\n", " clines = ax.contour(x_grid, y_grid, c_grid, levels=[0.0])\n", " contours.append((cfill, clines))\n", " else:\n", " clines = ax.contour(x_grid, y_grid, c_grid, levels=levels)\n", " ax.clabel(clines, fmt=levels_fmt, colors='k')\n", " contours.append((clines))\n", "\n", " return contours" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Lets visualize Gramacy toy problem. The objective function is shown by level sets, and the feasible region is not shaded. There three local optima and the location of global optimum is shown by the red marker." ] }, { "cell_type": "code", "execution_count": 30, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "Text(0, 0.5, 'y')" ] }, "execution_count": 30, "metadata": {}, "output_type": "execute_result" }, { "data": { "image/png": "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\n", "text/plain": [ "
" ] }, "metadata": { "needs_background": "light" }, "output_type": "display_data" } ], "source": [ "fh = plt.figure(figsize=[6, 6])\n", "axes = fh.subplots()\n", "contours = make_feasibility_plot_2d(axes, gramacy, bounds)\n", "local_optimizers = {'x': [0.1954, 0.7197, 0.0], 'y': [0.4044, 0.1411, 0.75]}\n", "f_opt = 0.599788\n", "axes.scatter(local_optimizers['x'], local_optimizers['y'], marker='*', zorder=10, color='k', s=50)\n", "axes.scatter(local_optimizers['x'][:1], local_optimizers['y'][:1], marker='*', zorder=10, color='r', s=100)\n", "axes.set_xlim([0, 1])\n", "axes.set_ylim([0, 1])\n", "axes.set_title('Gramacy toy problem')\n", "axes.set_xlabel('x')\n", "axes.set_ylabel('y')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Setup optimization problem for AX" ] }, { "cell_type": "code", "execution_count": 5, "metadata": {}, "outputs": [], "source": [ "def gramacy_evaluation_fcn(parametrization):\n", " \"\"\"Evaluation function for Gramacy problem\n", " \"\"\"\n", " x = parametrization.get('x')\n", " y = parametrization.get('y')\n", " X = np.array([[x, y]])\n", " z = gramacy(X)\n", " \n", " return {\n", " 'f': (z[0, 0], 0.0), \n", " 'c1': (z[0, 1], 0.0), \n", " 'c2': (z[0, 2], 0.0)\n", " }\n", "\n", "# def get_evaluations(arms):\n", "# return {arm.name: gramacy_evaluation_fcn(arm.parameters) for arm in arms}\n", "\n", "search_space = SearchSpace(\n", " parameters=[\n", " RangeParameter(name='x', parameter_type=ParameterType.FLOAT, lower=0.0, upper=1.0),\n", " RangeParameter(name='y', parameter_type=ParameterType.FLOAT, lower=0.0, upper=1.0)\n", " ]\n", ")\n", "\n", "objective = Objective(metric=Metric(name='f'), minimize=True)\n", "constraint1 = OutcomeConstraint(metric=Metric(name='c1'), op=ComparisonOp.LEQ, bound=0.0, relative=False)\n", "constraint2 = OutcomeConstraint(metric=Metric(name='c2'), op=ComparisonOp.LEQ, bound=0.0, relative=False)\n", "\n", "optimization_config = OptimizationConfig(\n", " objective=objective, \n", " outcome_constraints=[\n", " constraint1, \n", " constraint2\n", " ]\n", ")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Setup experiment with ALBO objective\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Create a new experiment" ] }, { "cell_type": "code", "execution_count": 6, "metadata": {}, "outputs": [], "source": [ "def create_experiment(name=None):\n", " return Experiment(\n", " name=name,\n", " search_space=search_space,\n", " optimization_config=optimization_config\n", " )" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Use a randomized policy for initial exploration" ] }, { "cell_type": "code", "execution_count": 7, "metadata": {}, "outputs": [], "source": [ "def random_init(exp, n=5):\n", " sobol = Models.SOBOL(search_space=exp.search_space)\n", " gr = sobol.gen(n=n)\n", " trial = exp.new_batch_trial()\n", " trial.add_arms_and_weights(gr.arms)\n", " trial.mark_running(no_runner_required=True)\n", " evaluations = {arm.name: gramacy_evaluation_fcn(arm.parameters) for arm in trial.arms}\n", " data = Data.from_evaluations(evaluations, trial.index)\n", " exp.attach_data(data)\n", " trial.mark_completed()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Next we use ALBO objective to guide optimization. In the first phase we use `qExpectedImprovement` acquisition function to balance exploration and exploitation. In the second phase we turn to pure exploitation with `qSimpleRegret`. At this step ALBO objective helps to drill down to the edge of the feasible region." ] }, { "cell_type": "code", "execution_count": 8, "metadata": {}, "outputs": [], "source": [ "def get_albo_acqf_constructor(acqf_name=\"qEI\", penalty_rate=10.0, num_iter_inner=10, **kw):\n", " # Using classical penalty function \n", " albo_objective_constructor = ClassicAlboMCObjective\n", " \n", " # number of mults should be equal to number of constraints\n", " init_mults = torch.tensor([1.0, 1.0], dtype=torch.double)\n", " bounds = torch.tensor([[0.0, 0.0], [1.0, 1.0]], dtype=torch.double)\n", " \n", " return AlboAcquisitionFactory(\n", " albo_objective_constructor=albo_objective_constructor,\n", " acquisition_function_name=acqf_name,\n", " bounds=bounds,\n", " init_mults=init_mults,\n", " init_penalty_rate=penalty_rate,\n", " num_iter=num_iter_inner,\n", " num_restarts=32\n", " )" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Compare to ConstrainedMCObjective " ] }, { "cell_type": "code", "execution_count": 9, "metadata": {}, "outputs": [], "source": [ "class CmcoAcquisitionConstructor(object):\n", " def __init__(self, acqf_name, eta=0.0001, infeasible_cost=0.0):\n", " self.acqf_name = acqf_name\n", " self.eta = eta\n", " self.infeasible_cost = infeasible_cost\n", " \n", " def __call__(self, model, objective_weights, outcome_constraints, X_observed, **kw):\n", " objective_callable = get_objective_weights_transform(objective_weights)\n", " constaints_callable_list = get_outcome_constraint_transforms(outcome_constraints)\n", " objective = ConstrainedMCObjective(\n", " objective=objective_callable,\n", " constraints=constaints_callable_list,\n", " eta=self.eta,\n", " infeasible_cost=self.infeasible_cost\n", " \n", " )\n", " acqf = get_acquisition_function(self.acqf_name, model, objective, X_observed)\n", " return acqf\n", "\n", "def get_cmco_acqf_constructor(acqf_name=\"qEI\", eta=0.0001, infeasible_cost=0.0, **kwargs):\n", " cmco_acqf_constructor= CmcoAcquisitionConstructor(acqf_name, eta, infeasible_cost)\n", " return cmco_acqf_constructor" ] }, { "cell_type": "code", "execution_count": 10, "metadata": {}, "outputs": [], "source": [ "def get_best_feasible_point(experiment, tol=0.0):\n", " \"\"\"Find best feasible arm\n", " \"\"\"\n", " df = exp_to_df(experiment)\n", " df['u'] = np.where(np.logical_and(df['c1'] < tol, df['c2'] < tol), df['f'], np.inf).astype(np.float)\n", " best_row = df.loc[df['u'].idxmin()]\n", " trial_index = best_row['trial_index']\n", " arm_name = best_row['arm_name']\n", " f = best_row['f']\n", " c1 = best_row['c1']\n", " c2 = best_row['c2']\n", " return dict(trial_index=trial_index, arm_name=arm_name, f=f, c1=c1, c2=c2)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Main optimization loop" ] }, { "cell_type": "code", "execution_count": 11, "metadata": {}, "outputs": [], "source": [ "def optimize(exp, steps, verbose=True): \n", " for step in steps: \n", " for i in range(step['num_iter']):\n", " # Create instance of acquisition function over ALBO objective\n", " if step['method'] == 'ALBO':\n", " acqf_constructor = get_albo_acqf_constructor(**step['params'])\n", " elif step['method'] == 'CMCO':\n", " acqf_constructor = get_cmco_acqf_constructor(**step['params'])\n", " else:\n", " raise ValueError()\n", "\n", " # Create BoTorch model with a custom acquisition function \n", " model = get_botorch(\n", " experiment=exp,\n", " search_space=search_space,\n", " data=exp.fetch_data(),\n", " acqf_constructor=acqf_constructor\n", " )\n", "\n", " generator_run = model.gen(1)\n", " trial = exp.new_batch_trial(generator_run=generator_run)\n", " trial.mark_running(no_runner_required=True)\n", " evaluations = {arm.name: gramacy_evaluation_fcn(arm.parameters) for arm in trial.arms}\n", " data = Data.from_evaluations(evaluations, trial.index)\n", " exp.attach_data(data)\n", " trial.mark_completed()\n", " \n", " # Print\n", " if verbose:\n", " print(\n", " step['method'],\n", " step['params']['acqf_name'],\n", " i,\n", " 'candidate=(%f, %f)' % (trial.arms[0].parameters['x'], trial.arms[0].parameters['y'])\n", " )\n", " \n", " return model, acqf_constructor" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Run optimization experiment with ALBO objective" ] }, { "cell_type": "code", "execution_count": 12, "metadata": {}, "outputs": [], "source": [ "steps_albo = [\n", " {\n", " \"method\": \"ALBO\",\n", " \"num_iter\": 20,\n", " \"params\": {\n", " \"acqf_name\": \"qEI\",\n", " \"penalty_rate\": 10.0,\n", " \"num_iter_inner\": 10\n", " }\n", " },\n", " {\n", " \"method\": \"ALBO\",\n", " \"num_iter\": 5,\n", " \"params\": {\n", " \"acqf_name\": \"qSR\",\n", " \"penalty_rate\": 10.0,\n", " \"num_iter_inner\": 10\n", " }\n", " }\n", "]" ] }, { "cell_type": "code", "execution_count": 13, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "ALBO qEI 0 candidate=(0.000000, 1.000000)\n", "ALBO qEI 1 candidate=(0.000000, 0.804245)\n", "ALBO qEI 2 candidate=(0.000000, 0.644632)\n", "ALBO qEI 3 candidate=(0.000000, 0.000000)\n", "ALBO qEI 4 candidate=(0.000000, 0.742770)\n", "ALBO qEI 5 candidate=(0.000000, 0.332442)\n", "ALBO qEI 6 candidate=(0.000000, 0.400784)\n", "ALBO qEI 7 candidate=(0.000000, 0.433443)\n", "ALBO qEI 8 candidate=(0.188279, 0.405457)\n", "ALBO qEI 9 candidate=(0.140333, 0.392043)\n", "ALBO qEI 10 candidate=(0.167348, 0.419620)\n", "ALBO qEI 11 candidate=(0.205408, 0.403433)\n", "ALBO qEI 12 candidate=(0.196384, 0.401749)\n", "ALBO qEI 13 candidate=(0.604451, 0.000000)\n", "ALBO qEI 14 candidate=(0.032964, 0.382788)\n", "ALBO qEI 15 candidate=(0.351507, 0.765261)\n", "ALBO qEI 16 candidate=(0.420979, 0.309023)\n", "ALBO qEI 17 candidate=(0.393395, 0.762988)\n", "ALBO qEI 18 candidate=(0.072027, 0.022196)\n", "ALBO qEI 19 candidate=(0.219598, 0.623286)\n", "ALBO qSR 0 candidate=(0.195441, 0.404362)\n", "ALBO qSR 1 candidate=(0.195417, 0.404386)\n", "ALBO qSR 2 candidate=(0.195410, 0.404396)\n", "ALBO qSR 3 candidate=(0.195405, 0.404405)\n", "ALBO qSR 4 candidate=(0.195393, 0.404408)\n" ] } ], "source": [ "exp_albo = create_experiment(name=\"exp_albo\")\n", "random_init(exp_albo, n=5)\n", "model, acqf_constructor = optimize(exp_albo, steps_albo, verbose=True)" ] }, { "cell_type": "code", "execution_count": 14, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Best feasible observed point {'x': 0.19539297391437763, 'y': 0.40440797976438814}\n", "Best feasible objective 0.599801\n", "Utility gap 0.000013\n", "Constraints c1=-0.000011, c2=-1.298276\n" ] }, { "name": "stderr", "output_type": "stream", "text": [ "/Users/Dasha/opt/anaconda3/envs/albo/lib/python3.7/site-packages/pandas/core/frame.py:9203: FutureWarning:\n", "\n", "merging between different levels is deprecated and will be removed in a future version. (2 levels on the left,1 on the right)\n", "\n", "/Users/Dasha/opt/anaconda3/envs/albo/lib/python3.7/site-packages/ipykernel_launcher.py:5: DeprecationWarning:\n", "\n", "`np.float` is a deprecated alias for the builtin `float`. To silence this warning, use `float` by itself. Doing this will not modify any behavior and is safe. If you specifically wanted the numpy scalar type, use `np.float64` here.\n", "Deprecated in NumPy 1.20; for more details and guidance: https://numpy.org/devdocs/release/1.20.0-notes.html#deprecations\n", "\n" ] } ], "source": [ "best_point = get_best_feasible_point(exp_albo)\n", "best_arm = exp_albo.arms_by_name.get(best_point['arm_name'])\n", "print ('Best feasible observed point', best_arm.parameters)\n", "print ('Best feasible objective', '%f' % best_point['f'])\n", "print ('Utility gap', '%f' % (best_point['f'] - f_opt))\n", "print ('Constraints', 'c1=%f, c2=%f' % (best_point['c1'], best_point['c2']))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "View full optimization trace" ] }, { "cell_type": "code", "execution_count": 15, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
indexarm_namec1c2ftrial_indexxy
000_00.150326-0.9321150.94097402.203187e-017.206557e-01
110_10.802162-1.0497430.89533106.049049e-012.904257e-01
220_2-1.2368050.1964951.84198809.168515e-019.251370e-01
330_31.403217-1.4061980.40227502.814180e-011.208565e-01
440_4-0.526692-0.6138831.27110104.377283e-018.333731e-01
571_0-0.5-0.51.010.000000e+001.000000e+00
6192_0-0.423535-0.8531890.80424521.940099e-148.042454e-01
7233_00.695597-1.0844490.64463231.848817e-126.446321e-01
8244_01.5-1.50.043.740707e-159.985239e-15
9255_00.059829-0.9482930.7427750.000000e+007.427696e-01
10266_00.404928-1.3894820.33244261.513698e-143.324424e-01
11277_00.224449-1.3393720.40078471.278405e-154.007839e-01
12288_00.262002-1.3121270.43344389.275048e-164.334427e-01
13299_00.007193-1.3001560.59373691.882794e-014.054566e-01
14510_00.077624-1.3266090.532376101.403333e-013.920430e-01
15611_00.029966-1.2959140.586968111.673477e-014.196201e-01
16812_0-0.010151-1.2950490.608842122.054083e-014.034334e-01
17913_00.002316-1.3000310.598133131.963841e-014.017491e-01
181014_00.521244-1.1346390.604451146.044509e-011.968635e-16
191115_00.20353-1.3523860.415752153.296375e-023.827884e-01
201216_0-0.106114-0.7908181.116768163.515070e-017.652610e-01
211317_00.642632-1.2272820.730001174.209785e-013.090229e-01
221418_0-0.057514-0.763091.156383183.933947e-017.629881e-01
231519_01.505503-1.4943190.094224197.202736e-022.219627e-02
241620_00.50773-1.0632910.842884202.195978e-016.232864e-01
251721_0-0.000012-1.2982940.599803211.954409e-014.043620e-01
261822_0-0.000013-1.2982840.599803221.954171e-014.043862e-01
272023_0-0.000016-1.2982790.599805231.954096e-014.043955e-01
282124_0-0.000022-1.2982730.599811241.954055e-014.044050e-01
292225_0-0.000011-1.2982760.599801251.953930e-014.044080e-01
\n", "
" ], "text/plain": [ " index arm_name c1 c2 f trial_index x \\\n", "0 0 0_0 0.150326 -0.932115 0.940974 0 2.203187e-01 \n", "1 1 0_1 0.802162 -1.049743 0.895331 0 6.049049e-01 \n", "2 2 0_2 -1.236805 0.196495 1.841988 0 9.168515e-01 \n", "3 3 0_3 1.403217 -1.406198 0.402275 0 2.814180e-01 \n", "4 4 0_4 -0.526692 -0.613883 1.271101 0 4.377283e-01 \n", "5 7 1_0 -0.5 -0.5 1.0 1 0.000000e+00 \n", "6 19 2_0 -0.423535 -0.853189 0.804245 2 1.940099e-14 \n", "7 23 3_0 0.695597 -1.084449 0.644632 3 1.848817e-12 \n", "8 24 4_0 1.5 -1.5 0.0 4 3.740707e-15 \n", "9 25 5_0 0.059829 -0.948293 0.74277 5 0.000000e+00 \n", "10 26 6_0 0.404928 -1.389482 0.332442 6 1.513698e-14 \n", "11 27 7_0 0.224449 -1.339372 0.400784 7 1.278405e-15 \n", "12 28 8_0 0.262002 -1.312127 0.433443 8 9.275048e-16 \n", "13 29 9_0 0.007193 -1.300156 0.593736 9 1.882794e-01 \n", "14 5 10_0 0.077624 -1.326609 0.532376 10 1.403333e-01 \n", "15 6 11_0 0.029966 -1.295914 0.586968 11 1.673477e-01 \n", "16 8 12_0 -0.010151 -1.295049 0.608842 12 2.054083e-01 \n", "17 9 13_0 0.002316 -1.300031 0.598133 13 1.963841e-01 \n", "18 10 14_0 0.521244 -1.134639 0.604451 14 6.044509e-01 \n", "19 11 15_0 0.20353 -1.352386 0.415752 15 3.296375e-02 \n", "20 12 16_0 -0.106114 -0.790818 1.116768 16 3.515070e-01 \n", "21 13 17_0 0.642632 -1.227282 0.730001 17 4.209785e-01 \n", "22 14 18_0 -0.057514 -0.76309 1.156383 18 3.933947e-01 \n", "23 15 19_0 1.505503 -1.494319 0.094224 19 7.202736e-02 \n", "24 16 20_0 0.50773 -1.063291 0.842884 20 2.195978e-01 \n", "25 17 21_0 -0.000012 -1.298294 0.599803 21 1.954409e-01 \n", "26 18 22_0 -0.000013 -1.298284 0.599803 22 1.954171e-01 \n", "27 20 23_0 -0.000016 -1.298279 0.599805 23 1.954096e-01 \n", "28 21 24_0 -0.000022 -1.298273 0.599811 24 1.954055e-01 \n", "29 22 25_0 -0.000011 -1.298276 0.599801 25 1.953930e-01 \n", "\n", " y \n", "0 7.206557e-01 \n", "1 2.904257e-01 \n", "2 9.251370e-01 \n", "3 1.208565e-01 \n", "4 8.333731e-01 \n", "5 1.000000e+00 \n", "6 8.042454e-01 \n", "7 6.446321e-01 \n", "8 9.985239e-15 \n", "9 7.427696e-01 \n", "10 3.324424e-01 \n", "11 4.007839e-01 \n", "12 4.334427e-01 \n", "13 4.054566e-01 \n", "14 3.920430e-01 \n", "15 4.196201e-01 \n", "16 4.034334e-01 \n", "17 4.017491e-01 \n", "18 1.968635e-16 \n", "19 3.827884e-01 \n", "20 7.652610e-01 \n", "21 3.090229e-01 \n", "22 7.629881e-01 \n", "23 2.219627e-02 \n", "24 6.232864e-01 \n", "25 4.043620e-01 \n", "26 4.043862e-01 \n", "27 4.043955e-01 \n", "28 4.044050e-01 \n", "29 4.044080e-01 " ] }, "execution_count": 15, "metadata": {}, "output_type": "execute_result" } ], "source": [ "exp_to_df(exp_albo).sort_values(by='trial_index').reset_index()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "To get the final values for Lagrange multipliers we need to untransform them from standardized space used by BoTorch model." ] }, { "cell_type": "code", "execution_count": 16, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Lagrange multipliers: lamdba1 = 0.868649, lambda2 = 0.000000\n" ] } ], "source": [ "std_f = model.transforms['StandardizeY'].Ystd['f']\n", "std_c1 = model.transforms['StandardizeY'].Ystd['c1']\n", "std_c2 = model.transforms['StandardizeY'].Ystd['c1']\n", "lagrange_mults = acqf_constructor.albo_objective.lagrange_mults\n", "l1 = lagrange_mults[0].item() * std_f / std_c1\n", "l2 = lagrange_mults[1].item() * std_f / std_c2\n", "print('Lagrange multipliers: lamdba1 = %f, lambda2 = %f' % (l1, l2))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Experiment with ConstrainedMCObjective" ] }, { "cell_type": "code", "execution_count": 17, "metadata": {}, "outputs": [], "source": [ "steps_cmco = [\n", " {\n", " \"method\": \"CMCO\",\n", " \"num_iter\": 20,\n", " \"params\": {\n", " \"acqf_name\": \"qEI\",\n", " \"penalty_rate\": 10.0,\n", " \"num_iter_inner\": 10\n", " }\n", " },\n", " {\n", " \"method\": \"CMCO\",\n", " \"num_iter\": 5,\n", " \"params\": {\n", " \"acqf_name\": \"qSR\",\n", " \"penalty_rate\": 10.0,\n", " \"num_iter_inner\": 10\n", " }\n", " }\n", "]" ] }, { "cell_type": "code", "execution_count": 18, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "CMCO qEI 0 candidate=(0.000000, 0.492875)\n", "CMCO qEI 1 candidate=(0.000000, 0.649542)\n", "CMCO qEI 2 candidate=(0.000000, 0.000195)\n", "CMCO qEI 3 candidate=(0.998411, 0.000000)\n", "CMCO qEI 4 candidate=(0.169625, 0.457315)\n", "CMCO qEI 5 candidate=(0.207163, 0.481197)\n", "CMCO qEI 6 candidate=(0.228110, 0.424283)\n", "CMCO qEI 7 candidate=(0.199814, 0.405497)\n", "CMCO qEI 8 candidate=(0.000000, 0.330487)\n", "CMCO qEI 9 candidate=(0.452850, 0.000034)\n", "CMCO qEI 10 candidate=(0.209081, 0.377556)\n", "CMCO qEI 11 candidate=(0.875885, 0.460283)\n", "CMCO qEI 12 candidate=(0.248025, 0.082956)\n", "CMCO qEI 13 candidate=(0.904308, 0.509798)\n", "CMCO qEI 14 candidate=(0.000000, 0.395305)\n", "CMCO qEI 15 candidate=(0.197836, 0.403626)\n", "CMCO qEI 16 candidate=(0.563732, 0.000000)\n", "CMCO qEI 17 candidate=(0.335197, 0.055379)\n", "CMCO qEI 18 candidate=(0.932125, 0.898552)\n", "CMCO qEI 19 candidate=(0.383603, 0.767522)\n", "CMCO qSR 0 candidate=(0.197443, 0.403305)\n", "CMCO qSR 1 candidate=(0.197330, 0.403274)\n", "CMCO qSR 2 candidate=(0.197249, 0.403243)\n", "CMCO qSR 3 candidate=(0.197224, 0.403229)\n", "CMCO qSR 4 candidate=(0.197179, 0.403238)\n" ] } ], "source": [ "exp_cmco = create_experiment(name=\"exp\")\n", "random_init(exp_cmco, n=5)\n", "model, acqf_constructor = optimize(exp_cmco, steps_cmco, verbose=True)" ] }, { "cell_type": "code", "execution_count": 19, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Best feasible observed point {'x': 0.19717873982203032, 'y': 0.40323823448737794}\n", "Best feasible objective 0.600417\n", "Utility gap 0.000629\n", "Constraints c1=-0.000602, c2=-1.298519\n" ] }, { "name": "stderr", "output_type": "stream", "text": [ "/Users/Dasha/opt/anaconda3/envs/albo/lib/python3.7/site-packages/pandas/core/frame.py:9203: FutureWarning:\n", "\n", "merging between different levels is deprecated and will be removed in a future version. (2 levels on the left,1 on the right)\n", "\n", "/Users/Dasha/opt/anaconda3/envs/albo/lib/python3.7/site-packages/ipykernel_launcher.py:5: DeprecationWarning:\n", "\n", "`np.float` is a deprecated alias for the builtin `float`. To silence this warning, use `float` by itself. Doing this will not modify any behavior and is safe. If you specifically wanted the numpy scalar type, use `np.float64` here.\n", "Deprecated in NumPy 1.20; for more details and guidance: https://numpy.org/devdocs/release/1.20.0-notes.html#deprecations\n", "\n" ] } ], "source": [ "best_point = get_best_feasible_point(exp_cmco)\n", "best_arm = exp_cmco.arms_by_name.get(best_point['arm_name'])\n", "print ('Best feasible observed point', best_arm.parameters)\n", "print ('Best feasible objective', '%f' % best_point['f'])\n", "print ('Utility gap', '%f' % (best_point['f'] - f_opt))\n", "print ('Constraints', 'c1=%f, c2=%f' % (best_point['c1'], best_point['c2']))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Repeated experiments for many runs" ] }, { "cell_type": "code", "execution_count": 20, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "0\n", "1\n", "2\n", "3\n", "4\n", "5\n", "6\n", "7\n", "8\n", "9\n", "10\n", "11\n", "12\n", "13\n", "14\n" ] }, { "ename": "KeyboardInterrupt", "evalue": "", "output_type": "error", "traceback": [ "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", "\u001b[0;31mKeyboardInterrupt\u001b[0m Traceback (most recent call last)", "\u001b[0;32m/var/folders/2r/q40kr1qs70x8ft3x_n72r4lr0000gp/T/ipykernel_18092/3901540911.py\u001b[0m in \u001b[0;36m\u001b[0;34m\u001b[0m\n\u001b[1;32m 7\u001b[0m \u001b[0mexp_albo\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mcreate_experiment\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mname\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;34m\"exp_albo\"\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 8\u001b[0m \u001b[0mrandom_init\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mexp_albo\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mn\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;36m5\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 9\u001b[0;31m \u001b[0moptimize\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mexp_albo\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0msteps_albo\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mverbose\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;32mFalse\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 10\u001b[0m \u001b[0mexps_albo\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mappend\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mexp_albo\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 11\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n", "\u001b[0;32m/var/folders/2r/q40kr1qs70x8ft3x_n72r4lr0000gp/T/ipykernel_18092/1230981476.py\u001b[0m in \u001b[0;36moptimize\u001b[0;34m(exp, steps, verbose)\u001b[0m\n\u001b[1;32m 18\u001b[0m )\n\u001b[1;32m 19\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 20\u001b[0;31m \u001b[0mgenerator_run\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mmodel\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mgen\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;36m1\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 21\u001b[0m \u001b[0mtrial\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mexp\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mnew_batch_trial\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mgenerator_run\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mgenerator_run\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 22\u001b[0m \u001b[0mtrial\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mmark_running\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mno_runner_required\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;32mTrue\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", "\u001b[0;32m~/opt/anaconda3/envs/albo/lib/python3.7/site-packages/ax/modelbridge/base.py\u001b[0m in \u001b[0;36mgen\u001b[0;34m(self, n, search_space, optimization_config, pending_observations, fixed_features, model_gen_options)\u001b[0m\n\u001b[1;32m 607\u001b[0m \u001b[0mpending_observations\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mpending_observations\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 608\u001b[0m \u001b[0mfixed_features\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mfixed_features\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 609\u001b[0;31m \u001b[0mmodel_gen_options\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mmodel_gen_options\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 610\u001b[0m )\n\u001b[1;32m 611\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n", "\u001b[0;32m~/opt/anaconda3/envs/albo/lib/python3.7/site-packages/ax/modelbridge/array.py\u001b[0m in \u001b[0;36m_gen\u001b[0;34m(self, n, search_space, pending_observations, fixed_features, model_gen_options, optimization_config)\u001b[0m\n\u001b[1;32m 210\u001b[0m \u001b[0mmodel_gen_options\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mmodel_gen_options\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 211\u001b[0m \u001b[0mrounding_func\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mtransform_callback\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mparameters\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mtransforms\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 212\u001b[0;31m \u001b[0mtarget_fidelities\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mtarget_fidelities\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 213\u001b[0m )\n\u001b[1;32m 214\u001b[0m \u001b[0;31m# Transform array to observations\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", "\u001b[0;32m~/opt/anaconda3/envs/albo/lib/python3.7/site-packages/ax/modelbridge/torch.py\u001b[0m in \u001b[0;36m_model_gen\u001b[0;34m(self, n, bounds, objective_weights, outcome_constraints, linear_constraints, fixed_features, pending_observations, model_gen_options, rounding_func, target_fidelities)\u001b[0m\n\u001b[1;32m 212\u001b[0m \u001b[0mmodel_gen_options\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mmodel_gen_options\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 213\u001b[0m \u001b[0mrounding_func\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mtensor_rounding_func\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 214\u001b[0;31m \u001b[0mtarget_fidelities\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mtarget_fidelities\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 215\u001b[0m )\n\u001b[1;32m 216\u001b[0m return (\n", "\u001b[0;32m~/opt/anaconda3/envs/albo/lib/python3.7/site-packages/ax/models/torch/botorch.py\u001b[0m in \u001b[0;36mgen\u001b[0;34m(self, n, bounds, objective_weights, outcome_constraints, linear_constraints, fixed_features, pending_observations, model_gen_options, rounding_func, target_fidelities)\u001b[0m\n\u001b[1;32m 355\u001b[0m \u001b[0mX_observed\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mX_observed\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 356\u001b[0m \u001b[0mX_pending\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mX_pending\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 357\u001b[0;31m \u001b[0;34m**\u001b[0m\u001b[0macf_options\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 358\u001b[0m )\n\u001b[1;32m 359\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n", "\u001b[0;32m~/Desktop/КурсачРеп/albo/experiments/gramacy_toy/albo/acquisition.py\u001b[0m in \u001b[0;36m__call__\u001b[0;34m(self, model, objective_weights, outcome_constraints, X_observed, X_pending, mc_samples, qmc, seed, **kwargs)\u001b[0m\n\u001b[1;32m 120\u001b[0m \u001b[0;31m# and store the fitted albo objective and the trace of inner loop optimization\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 121\u001b[0m \u001b[0;31m# (for debugging and visualization).\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 122\u001b[0;31m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0malbo_objective\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mtrace_inner\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mfit_albo_objective\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 123\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 124\u001b[0m \u001b[0;31m# Create an acquisition function over the fitted AL objective\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", "\u001b[0;32m~/Desktop/КурсачРеп/albo/experiments/gramacy_toy/albo/acquisition.py\u001b[0m in \u001b[0;36mfit_albo_objective\u001b[0;34m(self)\u001b[0m\n\u001b[1;32m 192\u001b[0m \u001b[0mq\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;36m1\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 193\u001b[0m \u001b[0mnum_restarts\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mnum_restarts\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 194\u001b[0;31m \u001b[0mraw_samples\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mraw_samples\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 195\u001b[0m )\n\u001b[1;32m 196\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n", "\u001b[0;32m~/opt/anaconda3/envs/albo/lib/python3.7/site-packages/botorch/optim/optimize.py\u001b[0m in \u001b[0;36moptimize_acqf\u001b[0;34m(acq_function, bounds, q, num_restarts, raw_samples, options, inequality_constraints, equality_constraints, fixed_features, post_processing_func, batch_initial_conditions, return_best_only, sequential)\u001b[0m\n\u001b[1;32m 170\u001b[0m \u001b[0minequality_constraints\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0minequality_constraints\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 171\u001b[0m \u001b[0mequality_constraints\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mequality_constraints\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 172\u001b[0;31m \u001b[0mfixed_features\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mfixed_features\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 173\u001b[0m )\n\u001b[1;32m 174\u001b[0m \u001b[0mbatch_candidates_list\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mappend\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mbatch_candidates_curr\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", "\u001b[0;32m~/opt/anaconda3/envs/albo/lib/python3.7/site-packages/botorch/gen.py\u001b[0m in \u001b[0;36mgen_candidates_scipy\u001b[0;34m(initial_conditions, acquisition_function, lower_bounds, upper_bounds, inequality_constraints, equality_constraints, options, fixed_features)\u001b[0m\n\u001b[1;32m 123\u001b[0m \u001b[0mbounds\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mbounds\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 124\u001b[0m \u001b[0mconstraints\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mconstraints\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 125\u001b[0;31m \u001b[0moptions\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;34m{\u001b[0m\u001b[0mk\u001b[0m\u001b[0;34m:\u001b[0m \u001b[0mv\u001b[0m \u001b[0;32mfor\u001b[0m \u001b[0mk\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mv\u001b[0m \u001b[0;32min\u001b[0m \u001b[0moptions\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mitems\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0mk\u001b[0m \u001b[0;34m!=\u001b[0m \u001b[0;34m\"method\"\u001b[0m\u001b[0;34m}\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 126\u001b[0m )\n\u001b[1;32m 127\u001b[0m candidates = fix_features(\n", "\u001b[0;32m~/opt/anaconda3/envs/albo/lib/python3.7/site-packages/scipy/optimize/_minimize.py\u001b[0m in \u001b[0;36mminimize\u001b[0;34m(fun, x0, args, method, jac, hess, hessp, bounds, constraints, tol, callback, options)\u001b[0m\n\u001b[1;32m 622\u001b[0m \u001b[0;32melif\u001b[0m \u001b[0mmeth\u001b[0m \u001b[0;34m==\u001b[0m \u001b[0;34m'l-bfgs-b'\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 623\u001b[0m return _minimize_lbfgsb(fun, x0, args, jac, bounds,\n\u001b[0;32m--> 624\u001b[0;31m callback=callback, **options)\n\u001b[0m\u001b[1;32m 625\u001b[0m \u001b[0;32melif\u001b[0m \u001b[0mmeth\u001b[0m \u001b[0;34m==\u001b[0m \u001b[0;34m'tnc'\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 626\u001b[0m return _minimize_tnc(fun, x0, args, jac, bounds, callback=callback,\n", "\u001b[0;32m~/opt/anaconda3/envs/albo/lib/python3.7/site-packages/scipy/optimize/lbfgsb.py\u001b[0m in \u001b[0;36m_minimize_lbfgsb\u001b[0;34m(fun, x0, args, jac, bounds, disp, maxcor, ftol, gtol, eps, maxfun, maxiter, iprint, callback, maxls, finite_diff_rel_step, **unknown_options)\u001b[0m\n\u001b[1;32m 358\u001b[0m \u001b[0;31m# until the completion of the current minimization iteration.\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 359\u001b[0m \u001b[0;31m# Overwrite f and g:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 360\u001b[0;31m \u001b[0mf\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mg\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mfunc_and_grad\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mx\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 361\u001b[0m \u001b[0;32melif\u001b[0m \u001b[0mtask_str\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mstartswith\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34mb'NEW_X'\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 362\u001b[0m \u001b[0;31m# new iteration\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", "\u001b[0;32m~/opt/anaconda3/envs/albo/lib/python3.7/site-packages/scipy/optimize/_differentiable_functions.py\u001b[0m in \u001b[0;36mfun_and_grad\u001b[0;34m(self, x)\u001b[0m\n\u001b[1;32m 265\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0;32mnot\u001b[0m \u001b[0mnp\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0marray_equal\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mx\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mx\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 266\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_update_x_impl\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mx\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 267\u001b[0;31m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_update_fun\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 268\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_update_grad\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 269\u001b[0m \u001b[0;32mreturn\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mf\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mg\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", "\u001b[0;32m~/opt/anaconda3/envs/albo/lib/python3.7/site-packages/scipy/optimize/_differentiable_functions.py\u001b[0m in \u001b[0;36m_update_fun\u001b[0;34m(self)\u001b[0m\n\u001b[1;32m 231\u001b[0m \u001b[0;32mdef\u001b[0m \u001b[0m_update_fun\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 232\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0;32mnot\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mf_updated\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 233\u001b[0;31m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_update_fun_impl\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 234\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mf_updated\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;32mTrue\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 235\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n", "\u001b[0;32m~/opt/anaconda3/envs/albo/lib/python3.7/site-packages/scipy/optimize/_differentiable_functions.py\u001b[0m in \u001b[0;36mupdate_fun\u001b[0;34m()\u001b[0m\n\u001b[1;32m 135\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 136\u001b[0m \u001b[0;32mdef\u001b[0m \u001b[0mupdate_fun\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 137\u001b[0;31m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mf\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mfun_wrapped\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mx\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 138\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 139\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_update_fun_impl\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mupdate_fun\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", "\u001b[0;32m~/opt/anaconda3/envs/albo/lib/python3.7/site-packages/scipy/optimize/_differentiable_functions.py\u001b[0m in \u001b[0;36mfun_wrapped\u001b[0;34m(x)\u001b[0m\n\u001b[1;32m 132\u001b[0m \u001b[0;31m# Overwriting results in undefined behaviour because\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 133\u001b[0m \u001b[0;31m# fun(self.x) will change self.x, with the two no longer linked.\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 134\u001b[0;31m \u001b[0;32mreturn\u001b[0m \u001b[0mfun\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mnp\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mcopy\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mx\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m*\u001b[0m\u001b[0margs\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 135\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 136\u001b[0m \u001b[0;32mdef\u001b[0m \u001b[0mupdate_fun\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", "\u001b[0;32m~/opt/anaconda3/envs/albo/lib/python3.7/site-packages/scipy/optimize/optimize.py\u001b[0m in \u001b[0;36m__call__\u001b[0;34m(self, x, *args)\u001b[0m\n\u001b[1;32m 72\u001b[0m \u001b[0;32mdef\u001b[0m \u001b[0m__call__\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mx\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m*\u001b[0m\u001b[0margs\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 73\u001b[0m \u001b[0;34m\"\"\" returns the the function value \"\"\"\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 74\u001b[0;31m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_compute_if_needed\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mx\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m*\u001b[0m\u001b[0margs\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 75\u001b[0m \u001b[0;32mreturn\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_value\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 76\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n", "\u001b[0;32m~/opt/anaconda3/envs/albo/lib/python3.7/site-packages/scipy/optimize/optimize.py\u001b[0m in \u001b[0;36m_compute_if_needed\u001b[0;34m(self, x, *args)\u001b[0m\n\u001b[1;32m 66\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0;32mnot\u001b[0m \u001b[0mnp\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mall\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mx\u001b[0m \u001b[0;34m==\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mx\u001b[0m\u001b[0;34m)\u001b[0m \u001b[0;32mor\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_value\u001b[0m \u001b[0;32mis\u001b[0m \u001b[0;32mNone\u001b[0m \u001b[0;32mor\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mjac\u001b[0m \u001b[0;32mis\u001b[0m \u001b[0;32mNone\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 67\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mx\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mnp\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0masarray\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mx\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mcopy\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 68\u001b[0;31m \u001b[0mfg\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mfun\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mx\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m*\u001b[0m\u001b[0margs\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 69\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mjac\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mfg\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;36m1\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 70\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_value\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mfg\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;36m0\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", "\u001b[0;32m~/opt/anaconda3/envs/albo/lib/python3.7/site-packages/botorch/gen.py\u001b[0m in \u001b[0;36mf\u001b[0;34m(x)\u001b[0m\n\u001b[1;32m 112\u001b[0m \u001b[0mloss\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;34m-\u001b[0m\u001b[0macquisition_function\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mX_fix\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0msum\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 113\u001b[0m \u001b[0;31m# compute gradient w.r.t. the inputs (does not accumulate in leaves)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 114\u001b[0;31m \u001b[0mgradf\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0m_arrayify\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mtorch\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mautograd\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mgrad\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mloss\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mX\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;36m0\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mcontiguous\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mview\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m-\u001b[0m\u001b[0;36m1\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 115\u001b[0m \u001b[0mfval\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mloss\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mitem\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 116\u001b[0m \u001b[0;32mreturn\u001b[0m \u001b[0mfval\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mgradf\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", "\u001b[0;32m~/opt/anaconda3/envs/albo/lib/python3.7/site-packages/torch/autograd/__init__.py\u001b[0m in \u001b[0;36mgrad\u001b[0;34m(outputs, inputs, grad_outputs, retain_graph, create_graph, only_inputs, allow_unused, is_grads_batched)\u001b[0m\n\u001b[1;32m 275\u001b[0m return Variable._execution_engine.run_backward( # Calls into the C++ engine to run the backward pass\n\u001b[1;32m 276\u001b[0m \u001b[0moutputs\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mgrad_outputs_\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mretain_graph\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mcreate_graph\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0minputs\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 277\u001b[0;31m allow_unused, accumulate_grad=False) # Calls into the C++ engine to run the backward pass\n\u001b[0m\u001b[1;32m 278\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 279\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n", "\u001b[0;32m~/opt/anaconda3/envs/albo/lib/python3.7/site-packages/torch/autograd/function.py\u001b[0m in \u001b[0;36mapply\u001b[0;34m(self, *args)\u001b[0m\n\u001b[1;32m 241\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 242\u001b[0m \u001b[0;32mclass\u001b[0m \u001b[0mBackwardCFunction\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0m_C\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_FunctionBase\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mFunctionCtx\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0m_HookMixin\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 243\u001b[0;31m \u001b[0;32mdef\u001b[0m \u001b[0mapply\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m*\u001b[0m\u001b[0margs\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 244\u001b[0m \u001b[0;31m# _forward_cls is defined by derived class\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 245\u001b[0m \u001b[0;31m# The user should define either backward or vjp but never both.\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", "\u001b[0;31mKeyboardInterrupt\u001b[0m: " ] } ], "source": [ "n_runs = 100\n", "exps_albo = []\n", "exps_cmco = []\n", "for i in range(n_runs):\n", " print(i)\n", " \n", " exp_albo = create_experiment(name=\"exp_albo\")\n", " random_init(exp_albo, n=5)\n", " optimize(exp_albo, steps_albo, verbose=False)\n", " exps_albo.append(exp_albo)\n", " \n", " exp_cmco = create_experiment(name=\"exp_cmco\")\n", " random_init(exp_cmco, n=5)\n", " optimize(exp_cmco, steps_cmco, verbose=False)\n", " exps_cmco.append(exp_cmco)" ] }, { "cell_type": "code", "execution_count": 24, "metadata": {}, "outputs": [], "source": [ "# import multiprocessing\n", "# from multiprocessing import Array\n", "# from tqdm import tqdm\n", "\n", "\n", "# def experiment(exps_albo_cool, exps_cmco_cool):\n", "# exp_albo = create_experiment(name=\"exp_albo\")\n", "# random_init(exp_albo, n=5)\n", "# optimize(exp_albo, steps_albo, verbose=False)\n", "# exps_albo_cool.append(exp_albo)\n", " \n", "# exp_cmco = create_experiment(name=\"exp_cmco\")\n", "# random_init(exp_cmco, n=5)\n", "# optimize(exp_cmco, steps_cmco, verbose=False)\n", "# exps_cmco_cool.append(exp_cmco)\n", "\n", "# if __name__ == '__main__':\n", "# exps_albo_cool = Array()\n", "# exps_cmco_cool = Array()\n", "\n", "# for _ in tqdm(range(10)):\n", "# processes_list = []\n", "# for i in range(10):\n", "# p = multiprocessing.Process(target=experiment, args =(exps_albo_cool, exps_cmco_cool))\n", "# p.start()\n", "# processes_list.append(p)\n", "# for p in processes_list:\n", "# p.join()\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Plot results of optimization" ] }, { "cell_type": "code", "execution_count": 22, "metadata": {}, "outputs": [], "source": [ "def plot_trace_median(ax, exps, n_iter_total, tol=0.0, label=None):\n", " n_runs = len(exps)\n", " u = np.zeros((n_runs, n_iter_total))\n", " for i, exp in enumerate(exps):\n", " df = exp_to_df(exp)\n", " u[i, :] = np.minimum.accumulate(np.where(np.logical_and(df['c1'] < tol, df['c2'] < tol), df['f'] - f_opt, 100))\n", " u_median = np.median(u, axis=0)\n", " every_3_1 = np.array(list((x + 1) % 2 == 0 for x in range(n_iter_total)))\n", " u_q75 = np.where(every_3_1, np.quantile(u, 0.75, 0), 0)\n", " u_q25 = np.where(every_3_1, np.quantile(u, 0.25, 0), 0)\n", " ax1.errorbar(\n", " np.arange(n_iter_total) + 1,\n", " u_median,\n", " np.array([u_median - u_q25, u_q75 - u_median]),\n", " linewidth=3,\n", " elinewidth=1,\n", " capsize=3,\n", " label=label\n", " )\n", " ax1.set_yscale('log')\n", " ax1.grid()\n", " ax1.set_title('Utility gap')\n", " ax1.set_xlim([0, n_iter_total])\n", " ax1.set_xlabel('iterations')\n", " \n", " \n", "def plot_scatter_best(ax, exps, tol=0.0): \n", " n_runs = len(exps)\n", " best_feasible_points = np.zeros((n_runs, 2))\n", " for i, exp in enumerate(exps):\n", " best_point = get_best_feasible_point(exp, tol)\n", " bp = exp.arms_by_name.get(best_point['arm_name']).parameters\n", " best_feasible_points[i, :] = np.array([bp['x'], bp['y']]) \n", " ax.scatter(best_feasible_points[:, 0], best_feasible_points[:, 1], zorder=10, c='b', s=3)" ] }, { "cell_type": "code", "execution_count": 23, "metadata": {}, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "/Users/Dasha/opt/anaconda3/envs/albo/lib/python3.7/site-packages/pandas/core/frame.py:9203: FutureWarning:\n", "\n", "merging between different levels is deprecated and will be removed in a future version. (2 levels on the left,1 on the right)\n", "\n", "/Users/Dasha/opt/anaconda3/envs/albo/lib/python3.7/site-packages/pandas/core/frame.py:9203: FutureWarning:\n", "\n", "merging between different levels is deprecated and will be removed in a future version. (2 levels on the left,1 on the right)\n", "\n", "/Users/Dasha/opt/anaconda3/envs/albo/lib/python3.7/site-packages/pandas/core/frame.py:9203: FutureWarning:\n", "\n", "merging between different levels is deprecated and will be removed in a future version. (2 levels on the left,1 on the right)\n", "\n", "/Users/Dasha/opt/anaconda3/envs/albo/lib/python3.7/site-packages/ipykernel_launcher.py:5: DeprecationWarning:\n", "\n", "`np.float` is a deprecated alias for the builtin `float`. To silence this warning, use `float` by itself. Doing this will not modify any behavior and is safe. If you specifically wanted the numpy scalar type, use `np.float64` here.\n", "Deprecated in NumPy 1.20; for more details and guidance: https://numpy.org/devdocs/release/1.20.0-notes.html#deprecations\n", "\n" ] }, { "data": { "text/plain": [ "Text(0.5, 1.0, 'Best feasible point, CMCO')" ] }, "execution_count": 23, "metadata": {}, "output_type": "execute_result" }, { "data": { "image/png": "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S2HtVxtQVUTE63BMCxWmLdbWFcS4RjwEY/Y7Dzj+vIlJ9bZt2xg9ejS9evVi6NChXHbZZaxevRoR4Te/+U1FuV27dhEdHc3dd99dsez1119n4MCBDBo0iCFDhvDMM88AoKo8/vjj9OnTh8zMTEaMGMGKFSuaFKfxVrovlbyv870OwxhTD+m+FI4dKWbX5j1eh2JasDBNrI93BdlkLdYmwFSV73znOwwfPpw1a9awaNEinnzySXbu3EnPnj2ZNGlSRdm3336brKysiteffPIJzz//PJ9++inLli1j7ty5JCUlAfDiiy8ye/ZslixZQl5eHg899BBXXnklRUVFQT9GExjpvhR2rN+NqnodijGmDv4jgxjTXMIysU5NiCEu2gm9sKiE/UeKPY7ItCTTp08nOjqau+66q2LZ4MGD6dq1K/Hx8fTv35+FCxcCMH78eL73ve9VlHvyySd55pln6NKlCwCxsbHccccdADz99NP85S9/IT7e+cPwkksu4ayzzuKtt94K1qGZAEvrkcKRwiL27TzgdSjGmDqk9XDui7Abjk1zCss+1iJCRnI8+TsOAk4/66Q2SR5HZZrFGOf/tep8h7WXr1/Z/dUuXr58OUOHDq1xtdGjRzNu3Dg6duxIZGQkXbp0YcuWLbWue+DAAQ4dOsRJJ504fuqpp55q3UHCWMWkE3lbSE633yBjQllSx0Ri2kTbfRGmWYVlizVYP2vjnVGjRjF16lTGjRvH97//fa/DMR5K62mXlo0JFyJCWo8US6xNs7LE2phKsrKyWLRoUY3vx8TEMHToUJ599lm++93v1mvddu3a0bZtW9auXXvC8kWLFp3QR9uElw6dk4iKibRLy8aEiXRfKmuWrfc6DNOChWVXEKg8lrXdwNhiud01CgsLSUyso0PImKQau3c0xAUXXMCvfvUrXn75Ze68804Ali5dytatWyvK3H///Zx//vl06NDhhHUfeughHnjgASZNmkSnTp04duwYr7/+OrfffjsPPPAA99xzD2+//TZt2rThs88+Y9asWbz00ktNjtl4IyIygtRuHWzSCWPCRLovhcVTlnOs6BgxcTFeh2NaoKAl1iJyEvBrIElVv1tX+br4T2u+aY+1WJvAERHee+89fvazn/H0008TFxeHz+fj8ccfryiTlZVVbUvzZZddxvbt27nooosqxkr94Q9/CMBPf/pT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\n", "text/plain": [ "
" ] }, "metadata": { "needs_background": "light" }, "output_type": "display_data" } ], "source": [ "fh = plt.figure(figsize=[12, 4])\n", "ax1, ax2, ax3 = fh.subplots(1, 3)\n", "\n", "plot_trace_median(ax1, exps_albo, n_iter_total=30, label='ALBO')\n", "plot_trace_median(ax1, exps_cmco, n_iter_total=30, label='CMCO')\n", "ax1.legend()\n", "ax1.grid()\n", "\n", "contours2 = make_feasibility_plot_2d(ax2, gramacy, bounds=bounds)\n", "ax2.scatter(local_optimizers['x'][:1], local_optimizers['y'][:1], marker='*', zorder=10, color='r', s=150)\n", "plot_scatter_best(ax2, exps_albo)\n", "ax2.set_xlim([0.18, 0.22])\n", "ax2.set_ylim([0.40, 0.41])\n", "ax2.set_title('Best feasible point, ALBO')\n", "\n", "contours3 = make_feasibility_plot_2d(ax3, gramacy, bounds=bounds)\n", "ax3.scatter(local_optimizers['x'][:1], local_optimizers['y'][:1], marker='*', zorder=10, color='r', s=150)\n", "plot_scatter_best(ax3, exps_cmco)\n", "ax3.set_xlim([0.18, 0.22])\n", "ax3.set_ylim([0.40, 0.41])\n", "ax3.set_title('Best feasible point, CMCO')" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [] } ], "metadata": { "kernelspec": { "display_name": "Python 3 (ipykernel)", "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.13" } }, "nbformat": 4, "nbformat_minor": 1 }