{ "cells": [ { "cell_type": "markdown", "id": "77765219", "metadata": { "collapsed": true, "customInput": null, "originalKey": "ac61b043-8ebf-43b9-9fa5-ed9a42a184ce", "papermill": { "duration": 0.006374, "end_time": "2024-09-23T20:32:57.749446", "exception": false, "start_time": "2024-09-23T20:32:57.743072", "status": "completed" }, "showInput": false, "tags": [] }, "source": [ "# Tune a CNN on MNIST\n", "\n", "This tutorial walks through using Ax to tune two hyperparameters (learning rate and momentum) for a PyTorch CNN on the MNIST dataset trained using SGD with momentum." ] }, { "cell_type": "code", "execution_count": 1, "id": "d4b97dc4", "metadata": { "customInput": null, "customOutput": null, "execution": { "iopub.execute_input": "2024-09-23T20:32:57.763043Z", "iopub.status.busy": "2024-09-23T20:32:57.762468Z", "iopub.status.idle": "2024-09-23T20:33:01.421760Z", "shell.execute_reply": "2024-09-23T20:33:01.420587Z" }, "executionStartTime": 1690415246079, "executionStopTime": 1690415266324, "originalKey": "c2b37f0f-3644-4367-912f-f775082f6676", "papermill": { "duration": 3.685277, "end_time": "2024-09-23T20:33:01.440797", "exception": false, "start_time": "2024-09-23T20:32:57.755520", "status": "completed" }, "requestMsgId": "0b481630-f0f4-436a-a205-a25aa163a364", "showInput": true, "tags": [] }, "outputs": [ { "data": { "text/html": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "name": "stderr", "output_type": "stream", "text": [ "[INFO 09-23 20:33:01] ax.utils.notebook.plotting: Injecting Plotly library into cell. Do not overwrite or delete cell.\n" ] }, { "name": "stderr", "output_type": "stream", "text": [ "[INFO 09-23 20:33:01] ax.utils.notebook.plotting: Please see\n", " (https://ax.dev/tutorials/visualizations.html#Fix-for-plots-that-are-not-rendering)\n", " if visualizations are not rendering.\n" ] }, { "data": { "text/html": [ " \n", " " ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "import torch\n", "\n", "import torch.nn as nn\n", "import torch.nn.functional as F\n", "\n", "from ax.service.ax_client import AxClient, ObjectiveProperties\n", "from ax.service.utils.report_utils import exp_to_df\n", "from ax.utils.notebook.plotting import init_notebook_plotting, render\n", "from ax.utils.tutorials.cnn_utils import evaluate, load_mnist, train\n", "from torch._tensor import Tensor\n", "from torch.utils.data import DataLoader\n", "\n", "init_notebook_plotting()" ] }, { "cell_type": "code", "execution_count": 2, "id": "c092784e", "metadata": { "customInput": null, "customOutput": null, "execution": { "iopub.execute_input": "2024-09-23T20:33:01.524281Z", "iopub.status.busy": "2024-09-23T20:33:01.523765Z", "iopub.status.idle": "2024-09-23T20:33:01.529302Z", "shell.execute_reply": "2024-09-23T20:33:01.528768Z" }, "executionStartTime": 1690415266521, "executionStopTime": 1690415266529, "originalKey": "4d0a27c4-a6ce-4b7d-97eb-1c229aabb375", "papermill": { "duration": 0.049199, "end_time": "2024-09-23T20:33:01.530579", "exception": false, "start_time": "2024-09-23T20:33:01.481380", "status": "completed" }, "requestMsgId": "fd975d25-a185-4b09-a50f-7b2bcd89f93f", "showInput": true, "tags": [] }, "outputs": [], "source": [ "torch.manual_seed(42)\n", "dtype = torch.float\n", "device = torch.device(\"cuda\" if torch.cuda.is_available() else \"cpu\")" ] }, { "cell_type": "markdown", "id": "9003a843", "metadata": { "customInput": null, "originalKey": "10384e51-444c-4265-b56d-ad078d05d2a1", "papermill": { "duration": 0.041071, "end_time": "2024-09-23T20:33:01.613475", "exception": false, "start_time": "2024-09-23T20:33:01.572404", "status": "completed" }, "showInput": false, "tags": [] }, "source": [ "## 1. Load MNIST data\n", "First, we need to load the MNIST data and partition it into training, validation, and test sets.\n", "\n", "Note: this will download the dataset if necessary." ] }, { "cell_type": "code", "execution_count": 3, "id": "ad119fae", "metadata": { "customInput": null, "customOutput": null, "execution": { "iopub.execute_input": "2024-09-23T20:33:01.697397Z", "iopub.status.busy": "2024-09-23T20:33:01.696785Z", "iopub.status.idle": "2024-09-23T20:33:12.096363Z", "shell.execute_reply": "2024-09-23T20:33:12.095592Z" }, "executionStartTime": 1690415266733, "executionStopTime": 1690415266902, "originalKey": "6f0949e2-1064-44b8-99c0-f6ce23df7c63", "papermill": { "duration": 10.443158, "end_time": "2024-09-23T20:33:12.097846", "exception": false, "start_time": "2024-09-23T20:33:01.654688", "status": "completed" }, "requestMsgId": "8ce7dd21-9afb-4379-ad11-4112b4d27f8a", "showInput": true, "tags": [] }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Downloading http://yann.lecun.com/exdb/mnist/train-images-idx3-ubyte.gz\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "Failed to download (trying next):\n", "HTTP Error 403: Forbidden\n", "\n", "Downloading https://ossci-datasets.s3.amazonaws.com/mnist/train-images-idx3-ubyte.gz\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "Downloading https://ossci-datasets.s3.amazonaws.com/mnist/train-images-idx3-ubyte.gz to ./data/MNIST/raw/train-images-idx3-ubyte.gz\n" ] }, { "name": "stderr", "output_type": "stream", "text": [ "\r", " 0%| | 0/9912422 [00:00, ?it/s]" ] }, { "name": "stderr", "output_type": "stream", "text": [ "\r", " 1%| | 98304/9912422 [00:00<00:14, 688096.17it/s]" ] }, { "name": "stderr", "output_type": "stream", "text": [ "\r", " 4%|▎ | 360448/9912422 [00:00<00:07, 1355322.69it/s]" ] }, { "name": "stderr", "output_type": "stream", "text": [ "\r", " 15%|█▍ | 1441792/9912422 [00:00<00:02, 4163814.92it/s]" ] }, { "name": "stderr", "output_type": "stream", "text": [ "\r", " 59%|█████▉ | 5832704/9912422 [00:00<00:00, 14548101.86it/s]" ] }, { "name": "stderr", "output_type": "stream", "text": [ "\r", "100%|██████████| 9912422/9912422 [00:00<00:00, 15283878.71it/s]" ] }, { "name": "stderr", "output_type": "stream", "text": [ "\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "Extracting ./data/MNIST/raw/train-images-idx3-ubyte.gz to ./data/MNIST/raw\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "\n", "Downloading http://yann.lecun.com/exdb/mnist/train-labels-idx1-ubyte.gz\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "Failed to download (trying next):\n", "HTTP Error 403: Forbidden\n", "\n", "Downloading https://ossci-datasets.s3.amazonaws.com/mnist/train-labels-idx1-ubyte.gz\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "Downloading https://ossci-datasets.s3.amazonaws.com/mnist/train-labels-idx1-ubyte.gz to ./data/MNIST/raw/train-labels-idx1-ubyte.gz\n" ] }, { "name": "stderr", "output_type": "stream", "text": [ "\r", " 0%| | 0/28881 [00:00, ?it/s]" ] }, { "name": "stderr", "output_type": "stream", "text": [ "\r", "100%|██████████| 28881/28881 [00:00<00:00, 420093.68it/s]" ] }, { "name": "stderr", "output_type": "stream", "text": [ "\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "Extracting ./data/MNIST/raw/train-labels-idx1-ubyte.gz to ./data/MNIST/raw\n", "\n", "Downloading http://yann.lecun.com/exdb/mnist/t10k-images-idx3-ubyte.gz\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "Failed to download (trying next):\n", "HTTP Error 403: Forbidden\n", "\n", "Downloading https://ossci-datasets.s3.amazonaws.com/mnist/t10k-images-idx3-ubyte.gz\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "Downloading https://ossci-datasets.s3.amazonaws.com/mnist/t10k-images-idx3-ubyte.gz to ./data/MNIST/raw/t10k-images-idx3-ubyte.gz\n" ] }, { "name": "stderr", "output_type": "stream", "text": [ "\r", " 0%| | 0/1648877 [00:00, ?it/s]" ] }, { "name": "stderr", "output_type": "stream", "text": [ "\r", " 6%|▌ | 98304/1648877 [00:00<00:02, 749526.65it/s]" ] }, { "name": "stderr", "output_type": "stream", "text": [ "\r", " 18%|█▊ | 294912/1648877 [00:00<00:01, 1183964.11it/s]" ] }, { "name": "stderr", "output_type": "stream", "text": [ "\r", " 79%|███████▉ | 1310720/1648877 [00:00<00:00, 4066662.28it/s]" ] }, { "name": "stderr", "output_type": "stream", "text": [ "\r", "100%|██████████| 1648877/1648877 [00:00<00:00, 4074549.28it/s]" ] }, { "name": "stderr", "output_type": "stream", "text": [ "\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "Extracting ./data/MNIST/raw/t10k-images-idx3-ubyte.gz to ./data/MNIST/raw\n", "\n", "Downloading http://yann.lecun.com/exdb/mnist/t10k-labels-idx1-ubyte.gz\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "Failed to download (trying next):\n", "HTTP Error 403: Forbidden\n", "\n", "Downloading https://ossci-datasets.s3.amazonaws.com/mnist/t10k-labels-idx1-ubyte.gz\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "Downloading https://ossci-datasets.s3.amazonaws.com/mnist/t10k-labels-idx1-ubyte.gz to ./data/MNIST/raw/t10k-labels-idx1-ubyte.gz\n" ] }, { "name": "stderr", "output_type": "stream", "text": [ "\r", " 0%| | 0/4542 [00:00, ?it/s]" ] }, { "name": "stderr", "output_type": "stream", "text": [ "\r", "100%|██████████| 4542/4542 [00:00<00:00, 10613107.95it/s]" ] }, { "name": "stdout", "output_type": "stream", "text": [ "Extracting ./data/MNIST/raw/t10k-labels-idx1-ubyte.gz to ./data/MNIST/raw\n", "\n" ] }, { "name": "stderr", "output_type": "stream", "text": [ "\n" ] } ], "source": [ "BATCH_SIZE = 512\n", "train_loader, valid_loader, test_loader = load_mnist(batch_size=BATCH_SIZE)" ] }, { "cell_type": "markdown", "id": "31b14a32", "metadata": { "customInput": null, "originalKey": "be39e4d6-f4b1-418b-b8e1-8461db582e0c", "papermill": { "duration": 0.042685, "end_time": "2024-09-23T20:33:12.184031", "exception": false, "start_time": "2024-09-23T20:33:12.141346", "status": "completed" }, "showInput": false, "tags": [] }, "source": [ "## 2. Initialize Client\n", "Create a client object to interface with Ax APIs. By default this runs locally without storage.\n", "\n", " " ] }, { "cell_type": "code", "execution_count": 4, "id": "b8ae685f", "metadata": { "customInput": null, "customOutput": null, "execution": { "iopub.execute_input": "2024-09-23T20:33:12.270938Z", "iopub.status.busy": "2024-09-23T20:33:12.270627Z", "iopub.status.idle": "2024-09-23T20:33:12.275139Z", "shell.execute_reply": "2024-09-23T20:33:12.274551Z" }, "executionStartTime": 1690415267018, "executionStopTime": 1690415267023, "originalKey": "14f154fc-8109-4115-b94a-016daf85bc6f", "papermill": { "duration": 0.04983, "end_time": "2024-09-23T20:33:12.276438", "exception": false, "start_time": "2024-09-23T20:33:12.226608", "status": "completed" }, "requestMsgId": "7e1cd1ff-dc6e-423c-89b1-05762a7bcce2", "showInput": true, "tags": [] }, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "[INFO 09-23 20:33:12] ax.service.ax_client: Starting optimization with verbose logging. To disable logging, set the `verbose_logging` argument to `False`. Note that float values in the logs are rounded to 6 decimal points.\n" ] } ], "source": [ "ax_client = AxClient()" ] }, { "cell_type": "markdown", "id": "a6d6a568", "metadata": { "customInput": null, "originalKey": "f30a11d8-e7e8-4815-93a4-99b4aa531a17", "papermill": { "duration": 0.042915, "end_time": "2024-09-23T20:33:12.362301", "exception": false, "start_time": "2024-09-23T20:33:12.319386", "status": "completed" }, "showInput": false, "tags": [] }, "source": [ "## 3. Set up experiment\n", "An experiment consists of a **search space** (parameters and parameter constraints) and **optimization configuration** (objective name, minimization setting, and outcome constraints)." ] }, { "cell_type": "code", "execution_count": 5, "id": "3e5be01e", "metadata": { "customInput": null, "execution": { "iopub.execute_input": "2024-09-23T20:33:12.449080Z", "iopub.status.busy": "2024-09-23T20:33:12.448766Z", "iopub.status.idle": "2024-09-23T20:33:12.460812Z", "shell.execute_reply": "2024-09-23T20:33:12.460257Z" }, "executionStartTime": 1690415267155, "executionStopTime": 1690415267171, "originalKey": "c6b4fe1b-692a-499e-88c9-50dbefdcfc15", "papermill": { "duration": 0.057125, "end_time": "2024-09-23T20:33:12.462130", "exception": false, "start_time": "2024-09-23T20:33:12.405005", "status": "completed" }, "requestMsgId": "86409a5b-e66a-424e-8ac7-c0623a9c9ccf", "showInput": true, "tags": [] }, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "[INFO 09-23 20:33:12] ax.service.utils.instantiation: Inferred value type of ParameterType.FLOAT for parameter momentum. If that is not the expected value type, you can explicitly specify 'value_type' ('int', 'float', 'bool' or 'str') in parameter dict.\n" ] }, { "name": "stderr", "output_type": "stream", "text": [ "[INFO 09-23 20:33:12] ax.service.utils.instantiation: Created search space: SearchSpace(parameters=[RangeParameter(name='lr', parameter_type=FLOAT, range=[1e-06, 0.4], log_scale=True), RangeParameter(name='momentum', parameter_type=FLOAT, range=[0.0, 1.0])], parameter_constraints=[]).\n" ] }, { "name": "stderr", "output_type": "stream", "text": [ "[INFO 09-23 20:33:12] ax.modelbridge.dispatch_utils: Using Models.BOTORCH_MODULAR since there is at least one ordered parameter and there are no unordered categorical parameters.\n" ] }, { "name": "stderr", "output_type": "stream", "text": [ "[INFO 09-23 20:33:12] ax.modelbridge.dispatch_utils: Calculating the number of remaining initialization trials based on num_initialization_trials=None max_initialization_trials=None num_tunable_parameters=2 num_trials=None use_batch_trials=False\n" ] }, { "name": "stderr", "output_type": "stream", "text": [ "[INFO 09-23 20:33:12] ax.modelbridge.dispatch_utils: calculated num_initialization_trials=5\n" ] }, { "name": "stderr", "output_type": "stream", "text": [ "[INFO 09-23 20:33:12] ax.modelbridge.dispatch_utils: num_completed_initialization_trials=0 num_remaining_initialization_trials=5\n" ] }, { "name": "stderr", "output_type": "stream", "text": [ "[INFO 09-23 20:33:12] ax.modelbridge.dispatch_utils: `verbose`, `disable_progbar`, and `jit_compile` are not yet supported when using `choose_generation_strategy` with ModularBoTorchModel, dropping these arguments.\n" ] }, { "name": "stderr", "output_type": "stream", "text": [ "[INFO 09-23 20:33:12] ax.modelbridge.dispatch_utils: Using Bayesian Optimization generation strategy: GenerationStrategy(name='Sobol+BoTorch', steps=[Sobol for 5 trials, BoTorch for subsequent trials]). Iterations after 5 will take longer to generate due to model-fitting.\n" ] } ], "source": [ "# Create an experiment with required arguments: name, parameters, and objective_name.\n", "ax_client.create_experiment(\n", " name=\"tune_cnn_on_mnist\", # The name of the experiment.\n", " parameters=[\n", " {\n", " \"name\": \"lr\", # The name of the parameter.\n", " \"type\": \"range\", # The type of the parameter (\"range\", \"choice\" or \"fixed\").\n", " \"bounds\": [1e-6, 0.4], # The bounds for range parameters. \n", " # \"values\" The possible values for choice parameters .\n", " # \"value\" The fixed value for fixed parameters.\n", " \"value_type\": \"float\", # Optional, the value type (\"int\", \"float\", \"bool\" or \"str\"). Defaults to inference from type of \"bounds\".\n", " \"log_scale\": True, # Optional, whether to use a log scale for range parameters. Defaults to False.\n", " # \"is_ordered\" Optional, a flag for choice parameters.\n", " },\n", " {\n", " \"name\": \"momentum\", \n", " \"type\": \"range\", \n", " \"bounds\": [0.0, 1.0], \n", " },\n", " ],\n", " objectives={\"accuracy\": ObjectiveProperties(minimize=False)}, # The objective name and minimization setting.\n", " # parameter_constraints: Optional, a list of strings of form \"p1 >= p2\" or \"p1 + p2 <= some_bound\".\n", " # outcome_constraints: Optional, a list of strings of form \"constrained_metric <= some_bound\".\n", ")" ] }, { "cell_type": "markdown", "id": "73b704a8", "metadata": { "customInput": null, "originalKey": "af441a83-50fd-4385-a380-d8ebc570c0e5", "papermill": { "duration": 0.042868, "end_time": "2024-09-23T20:33:12.548352", "exception": false, "start_time": "2024-09-23T20:33:12.505484", "status": "completed" }, "showInput": false, "tags": [] }, "source": [ "## 4. Define how to evaluate trials\n" ] }, { "cell_type": "markdown", "id": "e91c6a08", "metadata": { "customInput": null, "originalKey": "c7630dfd-548b-408a-badf-b6abf79275e2", "papermill": { "duration": 0.042899, "end_time": "2024-09-23T20:33:12.634059", "exception": false, "start_time": "2024-09-23T20:33:12.591160", "status": "completed" }, "showInput": false, "tags": [] }, "source": [ "First we define a simple CNN class to classify the MNIST images" ] }, { "cell_type": "code", "execution_count": 6, "id": "edf1d68f", "metadata": { "customInput": null, "customOutput": null, "execution": { "iopub.execute_input": "2024-09-23T20:33:12.721297Z", "iopub.status.busy": "2024-09-23T20:33:12.720775Z", "iopub.status.idle": "2024-09-23T20:33:12.726000Z", "shell.execute_reply": "2024-09-23T20:33:12.725421Z" }, "executionStartTime": 1690415267282, "executionStopTime": 1690415267286, "originalKey": "e41fea0a-ae71-4e6f-8c0a-6eb6ae143fb0", "papermill": { "duration": 0.05046, "end_time": "2024-09-23T20:33:12.727287", "exception": false, "start_time": "2024-09-23T20:33:12.676827", "status": "completed" }, "requestMsgId": "60f14ec9-eb1b-4e88-95c5-15c91f999c90", "showInput": true, "tags": [] }, "outputs": [], "source": [ "class CNN(nn.Module):\n", " \n", " def __init__(self) -> None:\n", " super().__init__()\n", " self.conv1 = nn.Conv2d(1, 20, kernel_size=5, stride=1)\n", " self.fc1 = nn.Linear(8 * 8 * 20, 64)\n", " self.fc2 = nn.Linear(64, 10)\n", "\n", " def forward(self, x: Tensor) -> Tensor:\n", " x = F.relu(self.conv1(x))\n", " x = F.max_pool2d(x, 3, 3)\n", " x = x.view(-1, 8 * 8 * 20)\n", " x = F.relu(self.fc1(x))\n", " x = self.fc2(x)\n", " return F.log_softmax(x, dim=-1)" ] }, { "cell_type": "markdown", "id": "42a9a16a", "metadata": { "customInput": null, "originalKey": "8ef6bcb9-c492-4874-b8c7-a07f7e6291ad", "papermill": { "duration": 0.043446, "end_time": "2024-09-23T20:33:12.813638", "exception": false, "start_time": "2024-09-23T20:33:12.770192", "status": "completed" }, "showInput": false, "tags": [] }, "source": [ "In this tutorial, we want to optimize classification accuracy on the validation set as a function of the learning rate and momentum. The `train_evaluate` function takes in a parameterization (set of parameter values), computes the classification accuracy, and returns that metric. " ] }, { "cell_type": "code", "execution_count": 7, "id": "eafe2fe7", "metadata": { "customInput": null, "customOutput": null, "execution": { "iopub.execute_input": "2024-09-23T20:33:12.902258Z", "iopub.status.busy": "2024-09-23T20:33:12.901765Z", "iopub.status.idle": "2024-09-23T20:33:12.905998Z", "shell.execute_reply": "2024-09-23T20:33:12.905345Z" }, "executionStartTime": 1690415267388, "executionStopTime": 1690415267395, "originalKey": "a7e4bcc4-7494-429b-bb93-7ad84d0985af", "papermill": { "duration": 0.050234, "end_time": "2024-09-23T20:33:12.907485", "exception": false, "start_time": "2024-09-23T20:33:12.857251", "status": "completed" }, "requestMsgId": "5d486dbf-60cb-453d-8f24-8605f974b0a7", "showInput": true, "tags": [] }, "outputs": [], "source": [ "def train_evaluate(parameterization):\n", " \"\"\"\n", " Train the model and then compute an evaluation metric.\n", "\n", " In this tutorial, the CNN utils package is doing a lot of work\n", " under the hood:\n", " - `train` initializes the network, defines the loss function\n", " and optimizer, performs the training loop, and returns the\n", " trained model.\n", " - `evaluate` computes the accuracy of the model on the\n", " evaluation dataset and returns the metric.\n", "\n", " For your use case, you can define training and evaluation functions\n", " of your choosing.\n", "\n", " \"\"\"\n", " net = CNN()\n", " net = train(\n", " net=net,\n", " train_loader=train_loader,\n", " parameters=parameterization,\n", " dtype=dtype,\n", " device=device,\n", " )\n", "\n", " return evaluate(\n", " net=net, \n", " data_loader=valid_loader, \n", " dtype=dtype, \n", " device=device,\n", " )\n" ] }, { "cell_type": "markdown", "id": "f1707cfb", "metadata": { "customInput": null, "originalKey": "9ab127a8-021f-4ec8-9f4e-f4256a2e322a", "papermill": { "duration": 0.043079, "end_time": "2024-09-23T20:33:12.993422", "exception": false, "start_time": "2024-09-23T20:33:12.950343", "status": "completed" }, "showInput": false, "tags": [] }, "source": [ "## 5. Run optimization loop\n" ] }, { "cell_type": "markdown", "id": "20fb6e6e", "metadata": { "customInput": null, "originalKey": "411a2fb4-e8a3-4414-bc17-09f0b5ba3e74", "papermill": { "duration": 0.043484, "end_time": "2024-09-23T20:33:13.080451", "exception": false, "start_time": "2024-09-23T20:33:13.036967", "status": "completed" }, "showInput": false, "tags": [] }, "source": [ "First we use `attach_trial` to attach a custom trial with manually-chosen parameters. This step is optional, but we include it here to demonstrate adding manual trials and to serve as a baseline model with decent performance. " ] }, { "cell_type": "code", "execution_count": 8, "id": "7d3041d6", "metadata": { "customInput": null, "execution": { "iopub.execute_input": "2024-09-23T20:33:13.168762Z", "iopub.status.busy": "2024-09-23T20:33:13.168172Z", "iopub.status.idle": "2024-09-23T20:33:19.893765Z", "shell.execute_reply": "2024-09-23T20:33:19.893085Z" }, "executionStartTime": 1690415267533, "executionStopTime": 1690415287786, "originalKey": "1388ef55-5642-46ab-b297-c76a73a48aca", "papermill": { "duration": 6.771374, "end_time": "2024-09-23T20:33:19.895134", "exception": false, "start_time": "2024-09-23T20:33:13.123760", "status": "completed" }, "requestMsgId": "b32a4981-ad59-46e1-b701-fa5a5f118d8b", "showInput": true, "tags": [] }, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "[INFO 09-23 20:33:13] ax.core.experiment: Attached custom parameterizations [{'lr': 2.6e-05, 'momentum': 0.58}] as trial 0.\n" ] }, { "name": "stderr", "output_type": "stream", "text": [ "[INFO 09-23 20:33:19] ax.service.ax_client: Completed trial 0 with data: {'accuracy': (0.841833, None)}.\n" ] } ], "source": [ "# Attach the trial\n", "ax_client.attach_trial(\n", " parameters={\"lr\": 0.000026, \"momentum\": 0.58}\n", ")\n", "\n", "# Get the parameters and run the trial \n", "baseline_parameters = ax_client.get_trial_parameters(trial_index=0)\n", "ax_client.complete_trial(trial_index=0, raw_data=train_evaluate(baseline_parameters))" ] }, { "cell_type": "markdown", "id": "6ff3d1fd", "metadata": { "customInput": null, "originalKey": "f0f886a1-c5c8-44bb-b2fd-9fa3f140357a", "papermill": { "duration": 0.043319, "end_time": "2024-09-23T20:33:19.981849", "exception": false, "start_time": "2024-09-23T20:33:19.938530", "status": "completed" }, "showInput": false, "tags": [] }, "source": [ "Now we start the optimization loop.\n", "\n", "At each step, the user queries the client for a new trial then submits the evaluation of that trial back to the client.\n", "\n", "Note that Ax auto-selects an appropriate optimization algorithm based on the search space. For more advanced use cases that require a specific optimization algorithm, pass a `generation_strategy` argument into the `AxClient` constructor. Note that when Bayesian Optimization is used, generating new trials may take a few minutes." ] }, { "cell_type": "code", "execution_count": 9, "id": "8e2a04a2", "metadata": { "customInput": null, "customOutput": null, "execution": { "iopub.execute_input": "2024-09-23T20:33:20.070261Z", "iopub.status.busy": "2024-09-23T20:33:20.069758Z", "iopub.status.idle": "2024-09-23T20:36:32.470558Z", "shell.execute_reply": "2024-09-23T20:36:32.469835Z" }, "executionStartTime": 1690415287908, "executionStopTime": 1690415945107, "originalKey": "bff5d714-1ab3-43d3-b9b3-8c3a53c81dcb", "papermill": { "duration": 192.491895, "end_time": "2024-09-23T20:36:32.517293", "exception": false, "start_time": "2024-09-23T20:33:20.025398", "status": "completed" }, "requestMsgId": "a203534f-85dd-4dfa-9fa6-6aa46a0200a3", "showInput": true, "tags": [] }, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "/tmp/tmp.QqcA7fo0ui/Ax-main/ax/modelbridge/cross_validation.py:463: UserWarning:\n", "\n", "Encountered exception in computing model fit quality: RandomModelBridge does not support prediction.\n", "\n", "[INFO 09-23 20:33:20] ax.service.ax_client: Generated new trial 1 with parameters {'lr': 0.009955, 'momentum': 0.633423} using model Sobol.\n" ] }, { "name": "stderr", "output_type": "stream", "text": [ "[INFO 09-23 20:33:26] ax.service.ax_client: Completed trial 1 with data: {'accuracy': (0.100333, None)}.\n" ] }, { "name": "stderr", "output_type": "stream", "text": [ "/tmp/tmp.QqcA7fo0ui/Ax-main/ax/modelbridge/cross_validation.py:463: UserWarning:\n", "\n", "Encountered exception in computing model fit quality: RandomModelBridge does not support prediction.\n", "\n", "[INFO 09-23 20:33:26] ax.service.ax_client: Generated new trial 2 with parameters {'lr': 9e-05, 'momentum': 0.335441} using model Sobol.\n" ] }, { "name": "stderr", "output_type": "stream", "text": [ "[INFO 09-23 20:33:33] ax.service.ax_client: Completed trial 2 with data: {'accuracy': (0.884333, None)}.\n" ] }, { "name": "stderr", "output_type": "stream", "text": [ "/tmp/tmp.QqcA7fo0ui/Ax-main/ax/modelbridge/cross_validation.py:463: UserWarning:\n", "\n", "Encountered exception in computing model fit quality: RandomModelBridge does not support prediction.\n", "\n", "[INFO 09-23 20:33:33] ax.service.ax_client: Generated new trial 3 with parameters {'lr': 2e-06, 'momentum': 0.902833} using model Sobol.\n" ] }, { "name": "stderr", "output_type": "stream", "text": [ "[INFO 09-23 20:33:40] ax.service.ax_client: Completed trial 3 with data: {'accuracy': (0.678667, None)}.\n" ] }, { "name": "stderr", "output_type": "stream", "text": [ "/tmp/tmp.QqcA7fo0ui/Ax-main/ax/modelbridge/cross_validation.py:463: UserWarning:\n", "\n", "Encountered exception in computing model fit quality: RandomModelBridge does not support prediction.\n", "\n", "[INFO 09-23 20:33:40] ax.service.ax_client: Generated new trial 4 with parameters {'lr': 0.10174, 'momentum': 0.065787} using model Sobol.\n" ] }, { "name": "stderr", "output_type": "stream", "text": [ "[INFO 09-23 20:33:46] ax.service.ax_client: Completed trial 4 with data: {'accuracy': (0.100333, None)}.\n" ] }, { "name": "stderr", "output_type": "stream", "text": [ "/tmp/tmp.QqcA7fo0ui/Ax-main/ax/modelbridge/cross_validation.py:463: UserWarning:\n", "\n", "Encountered exception in computing model fit quality: RandomModelBridge does not support prediction.\n", "\n", "[INFO 09-23 20:33:46] ax.service.ax_client: Generated new trial 5 with parameters {'lr': 0.017004, 'momentum': 0.802601} using model Sobol.\n" ] }, { "name": "stderr", "output_type": "stream", "text": [ "[INFO 09-23 20:33:53] ax.service.ax_client: Completed trial 5 with data: {'accuracy': (0.088167, None)}.\n" ] }, { "name": "stderr", "output_type": "stream", "text": [ "[INFO 09-23 20:33:53] ax.service.ax_client: Generated new trial 6 with parameters {'lr': 3.5e-05, 'momentum': 0.0} using model BoTorch.\n" ] }, { "name": "stderr", "output_type": "stream", "text": [ "[INFO 09-23 20:34:00] ax.service.ax_client: Completed trial 6 with data: {'accuracy': (0.774, None)}.\n" ] }, { "name": "stderr", "output_type": "stream", "text": [ "[INFO 09-23 20:34:00] ax.service.ax_client: Generated new trial 7 with parameters {'lr': 8.3e-05, 'momentum': 1.0} using model BoTorch.\n" ] }, { "name": "stderr", "output_type": "stream", "text": [ "[INFO 09-23 20:34:07] ax.service.ax_client: Completed trial 7 with data: {'accuracy': (0.897667, None)}.\n" ] }, { "name": "stderr", "output_type": "stream", "text": [ "[INFO 09-23 20:34:08] ax.service.ax_client: Generated new trial 8 with parameters {'lr': 4.6e-05, 'momentum': 1.0} using model BoTorch.\n" ] }, { "name": "stderr", "output_type": "stream", "text": [ "[INFO 09-23 20:34:15] ax.service.ax_client: Completed trial 8 with data: {'accuracy': (0.891333, None)}.\n" ] }, { "name": "stderr", "output_type": "stream", "text": [ "[INFO 09-23 20:34:16] ax.service.ax_client: Generated new trial 9 with parameters {'lr': 0.000125, 'momentum': 1.0} using model BoTorch.\n" ] }, { "name": "stderr", "output_type": "stream", "text": [ "[INFO 09-23 20:34:22] ax.service.ax_client: Completed trial 9 with data: {'accuracy': (0.853167, None)}.\n" ] }, { "name": "stderr", "output_type": "stream", "text": [ "[INFO 09-23 20:34:23] ax.service.ax_client: Generated new trial 10 with parameters {'lr': 7.2e-05, 'momentum': 0.726163} using model BoTorch.\n" ] }, { "name": "stderr", "output_type": "stream", "text": [ "[INFO 09-23 20:34:30] ax.service.ax_client: Completed trial 10 with data: {'accuracy': (0.900833, None)}.\n" ] }, { "name": "stderr", "output_type": "stream", "text": [ "[INFO 09-23 20:34:31] ax.service.ax_client: Generated new trial 11 with parameters {'lr': 0.000173, 'momentum': 0.0} using model BoTorch.\n" ] }, { "name": "stderr", "output_type": "stream", "text": [ "[INFO 09-23 20:34:38] ax.service.ax_client: Completed trial 11 with data: {'accuracy': (0.846833, None)}.\n" ] }, { "name": "stderr", "output_type": "stream", "text": [ "[INFO 09-23 20:34:39] ax.service.ax_client: Generated new trial 12 with parameters {'lr': 5.9e-05, 'momentum': 1.0} using model BoTorch.\n" ] }, { "name": "stderr", "output_type": "stream", "text": [ "[INFO 09-23 20:34:46] ax.service.ax_client: Completed trial 12 with data: {'accuracy': (0.892167, None)}.\n" ] }, { "name": "stderr", "output_type": "stream", "text": [ "[INFO 09-23 20:34:47] ax.service.ax_client: Generated new trial 13 with parameters {'lr': 8.7e-05, 'momentum': 0.64011} using model BoTorch.\n" ] }, { "name": "stderr", "output_type": "stream", "text": [ "[INFO 09-23 20:34:54] ax.service.ax_client: Completed trial 13 with data: {'accuracy': (0.8895, None)}.\n" ] }, { "name": "stderr", "output_type": "stream", "text": [ "[INFO 09-23 20:34:55] ax.service.ax_client: Generated new trial 14 with parameters {'lr': 6.1e-05, 'momentum': 0.819741} using model BoTorch.\n" ] }, { "name": "stderr", "output_type": "stream", "text": [ "[INFO 09-23 20:35:02] ax.service.ax_client: Completed trial 14 with data: {'accuracy': (0.906333, None)}.\n" ] }, { "name": "stderr", "output_type": "stream", "text": [ "[INFO 09-23 20:35:03] ax.service.ax_client: Generated new trial 15 with parameters {'lr': 1e-06, 'momentum': 0.0} using model BoTorch.\n" ] }, { "name": "stderr", "output_type": "stream", "text": [ "[INFO 09-23 20:35:10] ax.service.ax_client: Completed trial 15 with data: {'accuracy': (0.15, None)}.\n" ] }, { "name": "stderr", "output_type": "stream", "text": [ "[INFO 09-23 20:35:11] ax.service.ax_client: Generated new trial 16 with parameters {'lr': 3.3e-05, 'momentum': 1.0} using model BoTorch.\n" ] }, { "name": "stderr", "output_type": "stream", "text": [ "[INFO 09-23 20:35:18] ax.service.ax_client: Completed trial 16 with data: {'accuracy': (0.82, None)}.\n" ] }, { "name": "stderr", "output_type": "stream", "text": [ "[INFO 09-23 20:35:19] ax.service.ax_client: Generated new trial 17 with parameters {'lr': 0.000113, 'momentum': 0.591139} using model BoTorch.\n" ] }, { "name": "stderr", "output_type": "stream", "text": [ "[INFO 09-23 20:35:26] ax.service.ax_client: Completed trial 17 with data: {'accuracy': (0.911, None)}.\n" ] }, { "name": "stderr", "output_type": "stream", "text": [ "[INFO 09-23 20:35:27] ax.service.ax_client: Generated new trial 18 with parameters {'lr': 8.5e-05, 'momentum': 0.551459} using model BoTorch.\n" ] }, { "name": "stderr", "output_type": "stream", "text": [ "[INFO 09-23 20:35:34] ax.service.ax_client: Completed trial 18 with data: {'accuracy': (0.888167, None)}.\n" ] }, { "name": "stderr", "output_type": "stream", "text": [ "[INFO 09-23 20:35:36] ax.service.ax_client: Generated new trial 19 with parameters {'lr': 0.000109, 'momentum': 0.719968} using model BoTorch.\n" ] }, { "name": "stderr", "output_type": "stream", "text": [ "[INFO 09-23 20:35:42] ax.service.ax_client: Completed trial 19 with data: {'accuracy': (0.919667, None)}.\n" ] }, { "name": "stderr", "output_type": "stream", "text": [ "[INFO 09-23 20:35:44] ax.service.ax_client: Generated new trial 20 with parameters {'lr': 0.000143, 'momentum': 0.63833} using model BoTorch.\n" ] }, { "name": "stderr", "output_type": "stream", "text": [ "[INFO 09-23 20:35:51] ax.service.ax_client: Completed trial 20 with data: {'accuracy': (0.902667, None)}.\n" ] }, { "name": "stderr", "output_type": "stream", "text": [ "[INFO 09-23 20:35:52] ax.service.ax_client: Generated new trial 21 with parameters {'lr': 9.5e-05, 'momentum': 0.698897} using model BoTorch.\n" ] }, { "name": "stderr", "output_type": "stream", "text": [ "[INFO 09-23 20:35:59] ax.service.ax_client: Completed trial 21 with data: {'accuracy': (0.897333, None)}.\n" ] }, { "name": "stderr", "output_type": "stream", "text": [ "[INFO 09-23 20:36:01] ax.service.ax_client: Generated new trial 22 with parameters {'lr': 0.000133, 'momentum': 0.747599} using model BoTorch.\n" ] }, { "name": "stderr", "output_type": "stream", "text": [ "[INFO 09-23 20:36:07] ax.service.ax_client: Completed trial 22 with data: {'accuracy': (0.930333, None)}.\n" ] }, { "name": "stderr", "output_type": "stream", "text": [ "[INFO 09-23 20:36:09] ax.service.ax_client: Generated new trial 23 with parameters {'lr': 0.000189, 'momentum': 0.672589} using model BoTorch.\n" ] }, { "name": "stderr", "output_type": "stream", "text": [ "[INFO 09-23 20:36:16] ax.service.ax_client: Completed trial 23 with data: {'accuracy': (0.938167, None)}.\n" ] }, { "name": "stderr", "output_type": "stream", "text": [ "[INFO 09-23 20:36:17] ax.service.ax_client: Generated new trial 24 with parameters {'lr': 0.000177, 'momentum': 0.547454} using model BoTorch.\n" ] }, { "name": "stderr", "output_type": "stream", "text": [ "[INFO 09-23 20:36:24] ax.service.ax_client: Completed trial 24 with data: {'accuracy': (0.916667, None)}.\n" ] }, { "name": "stderr", "output_type": "stream", "text": [ "[INFO 09-23 20:36:25] ax.service.ax_client: Generated new trial 25 with parameters {'lr': 0.000269, 'momentum': 0.596213} using model BoTorch.\n" ] }, { "name": "stderr", "output_type": "stream", "text": [ "[INFO 09-23 20:36:32] ax.service.ax_client: Completed trial 25 with data: {'accuracy': (0.936, None)}.\n" ] } ], "source": [ "for i in range(25):\n", " parameters, trial_index = ax_client.get_next_trial()\n", " # Local evaluation here can be replaced with deployment to external system.\n", " ax_client.complete_trial(trial_index=trial_index, raw_data=train_evaluate(parameters))" ] }, { "cell_type": "markdown", "id": "3d9842b2", "metadata": { "customInput": null, "originalKey": "ccd16059-db9f-475b-b527-75afb320e0f4", "papermill": { "duration": 0.045713, "end_time": "2024-09-23T20:36:32.608390", "exception": false, "start_time": "2024-09-23T20:36:32.562677", "status": "completed" }, "showInput": false, "tags": [] }, "source": [ "### How many trials can run in parallel?\n", "By default, Ax restricts number of trials that can run in parallel for some optimization stages, in order to improve the optimization performance and reduce the number of trials that the optimization will require. To check the maximum parallelism for each optimization stage:" ] }, { "cell_type": "code", "execution_count": 10, "id": "d459ee9b", "metadata": { "customInput": null, "customOutput": null, "execution": { "iopub.execute_input": "2024-09-23T20:36:32.700741Z", "iopub.status.busy": "2024-09-23T20:36:32.700444Z", "iopub.status.idle": "2024-09-23T20:36:32.707208Z", "shell.execute_reply": "2024-09-23T20:36:32.706576Z" }, "executionStartTime": 1690415945269, "executionStopTime": 1690415945336, "originalKey": "7182d2f9-912c-464c-b5ad-f65ce6f00017", "papermill": { "duration": 0.054648, "end_time": "2024-09-23T20:36:32.708437", "exception": false, "start_time": "2024-09-23T20:36:32.653789", "status": "completed" }, "requestMsgId": "4cb4ff79-e45b-4c7d-86a1-7f8007eb2c81", "showInput": true, "tags": [] }, "outputs": [ { "data": { "text/plain": [ "[(5, 5), (-1, 3)]" ] }, "execution_count": 10, "metadata": {}, "output_type": "execute_result" } ], "source": [ "ax_client.get_max_parallelism()" ] }, { "cell_type": "markdown", "id": "db6a4cd3", "metadata": { "customInput": null, "originalKey": "e2f429e6-2ec8-4af2-906b-52a36a53d329", "papermill": { "duration": 0.045624, "end_time": "2024-09-23T20:36:32.799388", "exception": false, "start_time": "2024-09-23T20:36:32.753764", "status": "completed" }, "showInput": false, "tags": [] }, "source": [ "The output of this function is a list of tuples of form (number of trials, max parallelism), so the example above means \"the max parallelism is 5 for the first 5 trials and 3 for all subsequent trials.\" This is because the first 5 trials are produced quasi-randomly and can all be evaluated at once, and subsequent trials are produced via Bayesian optimization, which converges on optimal point in fewer trials when parallelism is limited. MaxParallelismReachedException indicates that the parallelism limit has been reached –– refer to the 'Service API Exceptions Meaning and Handling' section at the end of the tutorial for handling.\n", "\n" ] }, { "cell_type": "markdown", "id": "bf21680d", "metadata": { "customInput": null, "originalKey": "86c7aef9-993a-411e-add5-05839b00d3cf", "papermill": { "duration": 0.045483, "end_time": "2024-09-23T20:36:32.890456", "exception": false, "start_time": "2024-09-23T20:36:32.844973", "status": "completed" }, "showInput": false, "tags": [] }, "source": [ "### How to view all existing trials during optimization?" ] }, { "cell_type": "code", "execution_count": 11, "id": "3ebfa49c", "metadata": { "customInput": null, "execution": { "iopub.execute_input": "2024-09-23T20:36:32.982746Z", "iopub.status.busy": "2024-09-23T20:36:32.982464Z", "iopub.status.idle": "2024-09-23T20:36:33.012706Z", "shell.execute_reply": "2024-09-23T20:36:33.012165Z" }, "executionStartTime": 1690415945532, "executionStopTime": 1690415946199, "originalKey": "3fbad5dc-863a-494e-b04f-d7dc1e47936c", "papermill": { "duration": 0.077892, "end_time": "2024-09-23T20:36:33.013989", "exception": false, "start_time": "2024-09-23T20:36:32.936097", "status": "completed" }, "requestMsgId": "905ea8b6-add0-473e-8516-5be6ad7d7658", "showInput": true, "tags": [] }, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "[WARNING 09-23 20:36:32] ax.service.utils.report_utils: Column reason missing for all trials. Not appending column.\n" ] }, { "data": { "text/html": [ "
\n", " | trial_index | \n", "arm_name | \n", "trial_status | \n", "generation_method | \n", "accuracy | \n", "lr | \n", "momentum | \n", "
---|---|---|---|---|---|---|---|
0 | \n", "0 | \n", "0_0 | \n", "COMPLETED | \n", "Manual | \n", "0.841833 | \n", "0.000026 | \n", "0.580000 | \n", "
1 | \n", "1 | \n", "1_0 | \n", "COMPLETED | \n", "Sobol | \n", "0.100333 | \n", "0.009955 | \n", "0.633423 | \n", "
2 | \n", "2 | \n", "2_0 | \n", "COMPLETED | \n", "Sobol | \n", "0.884333 | \n", "0.000090 | \n", "0.335441 | \n", "
3 | \n", "3 | \n", "3_0 | \n", "COMPLETED | \n", "Sobol | \n", "0.678667 | \n", "0.000002 | \n", "0.902833 | \n", "
4 | \n", "4 | \n", "4_0 | \n", "COMPLETED | \n", "Sobol | \n", "0.100333 | \n", "0.101740 | \n", "0.065787 | \n", "
5 | \n", "5 | \n", "5_0 | \n", "COMPLETED | \n", "Sobol | \n", "0.088167 | \n", "0.017004 | \n", "0.802601 | \n", "
6 | \n", "6 | \n", "6_0 | \n", "COMPLETED | \n", "BoTorch | \n", "0.774000 | \n", "0.000035 | \n", "0.000000 | \n", "
7 | \n", "7 | \n", "7_0 | \n", "COMPLETED | \n", "BoTorch | \n", "0.897667 | \n", "0.000083 | \n", "1.000000 | \n", "
8 | \n", "8 | \n", "8_0 | \n", "COMPLETED | \n", "BoTorch | \n", "0.891333 | \n", "0.000046 | \n", "1.000000 | \n", "
9 | \n", "9 | \n", "9_0 | \n", "COMPLETED | \n", "BoTorch | \n", "0.853167 | \n", "0.000125 | \n", "1.000000 | \n", "
10 | \n", "10 | \n", "10_0 | \n", "COMPLETED | \n", "BoTorch | \n", "0.900833 | \n", "0.000072 | \n", "0.726163 | \n", "
11 | \n", "11 | \n", "11_0 | \n", "COMPLETED | \n", "BoTorch | \n", "0.846833 | \n", "0.000173 | \n", "0.000000 | \n", "
12 | \n", "12 | \n", "12_0 | \n", "COMPLETED | \n", "BoTorch | \n", "0.892167 | \n", "0.000059 | \n", "1.000000 | \n", "
13 | \n", "13 | \n", "13_0 | \n", "COMPLETED | \n", "BoTorch | \n", "0.889500 | \n", "0.000087 | \n", "0.640110 | \n", "
14 | \n", "14 | \n", "14_0 | \n", "COMPLETED | \n", "BoTorch | \n", "0.906333 | \n", "0.000061 | \n", "0.819741 | \n", "
15 | \n", "15 | \n", "15_0 | \n", "COMPLETED | \n", "BoTorch | \n", "0.150000 | \n", "0.000001 | \n", "0.000000 | \n", "
16 | \n", "16 | \n", "16_0 | \n", "COMPLETED | \n", "BoTorch | \n", "0.820000 | \n", "0.000033 | \n", "1.000000 | \n", "
17 | \n", "17 | \n", "17_0 | \n", "COMPLETED | \n", "BoTorch | \n", "0.911000 | \n", "0.000113 | \n", "0.591139 | \n", "
18 | \n", "18 | \n", "18_0 | \n", "COMPLETED | \n", "BoTorch | \n", "0.888167 | \n", "0.000085 | \n", "0.551459 | \n", "
19 | \n", "19 | \n", "19_0 | \n", "COMPLETED | \n", "BoTorch | \n", "0.919667 | \n", "0.000109 | \n", "0.719968 | \n", "
20 | \n", "20 | \n", "20_0 | \n", "COMPLETED | \n", "BoTorch | \n", "0.902667 | \n", "0.000143 | \n", "0.638330 | \n", "
21 | \n", "21 | \n", "21_0 | \n", "COMPLETED | \n", "BoTorch | \n", "0.897333 | \n", "0.000095 | \n", "0.698897 | \n", "
22 | \n", "22 | \n", "22_0 | \n", "COMPLETED | \n", "BoTorch | \n", "0.930333 | \n", "0.000133 | \n", "0.747599 | \n", "
23 | \n", "23 | \n", "23_0 | \n", "COMPLETED | \n", "BoTorch | \n", "0.938167 | \n", "0.000189 | \n", "0.672589 | \n", "
24 | \n", "24 | \n", "24_0 | \n", "COMPLETED | \n", "BoTorch | \n", "0.916667 | \n", "0.000177 | \n", "0.547454 | \n", "
25 | \n", "25 | \n", "25_0 | \n", "COMPLETED | \n", "BoTorch | \n", "0.936000 | \n", "0.000269 | \n", "0.596213 | \n", "