diff --git a/docs/curriculum/tutorials/featurization/featurization-tutorial.ipynb b/docs/curriculum/tutorials/featurization/featurization-tutorial.ipynb new file mode 100644 index 00000000..c8a812c9 --- /dev/null +++ b/docs/curriculum/tutorials/featurization/featurization-tutorial.ipynb @@ -0,0 +1,558 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Optimizing MAX Phases with Featurization\n", + "\n", + "Some design spaces cannot be reduced to simple, continuous representations that can be fed into Ax. For example, material compositions often span the periodic table and are subject to non-linear constraints like parsimony and electron counting rules that would be impossible to express in an Ax parameters object. One possible solution is to represent the composition as a one dimensional vector of the molar fractions of the materials' constituent elements. However, this representation assumes simple elemental substitution rules, which tyically only hold in limited composition ranges. Additionally, such a representation provides the model with little information about the unerlying physics and has been shown to be a weak predictor of material properties.\n", + "\n", + "Featurization is the process of creating new representations that better describe the input data and are more ammendable to statistical modeling. In the context of material compositions, featurization typically involves creating a weighted combination of teh constituent elements' atomic properties. In this scheme, a material like Al2O3 is represented as a vector by averaging the properties of aluminum and oxygen, weighted by their molar fractions. In this tutorial, the popular featurization package,[`CBFV`](https://pypi.org/project/CBFV/), will be used to perform the featurization task.\n", + "\n", + "---\n", + "\n", + "MAX phase materials are a specialized group of compounds that blend the properties of metals and ceramics. MAX phase compositions are comprised of M, a transition metal; A, a group 13 or 14 element; and X, carbon or nitrogen. MAX phases are of particular interest in high temperature, structural applications. \n", + "\n", + "You have been tasked with finding a new MAX phase composition with a high elastic modulus to be used as a cladding material in a next generation nuclear reactor. A colleague in your lab spent a few weeks looking through the literature and has identified a set of reported MAX phase materials that haven't been tested for modulus, but look promising.\n", + "\n", + "You believe Bayesian optimization can help faciliate this search, and decide to use Honegumi to help construct an optimization script.\n", + "\n", + "To simulate this task, a helper function is provided that automatically pulls and splits the data in a representative way. An explanation of this function is provided in subsequent cells and in line comments. Although optimal values could easily be found using the tabulated data, we will pretend that such data is unknown and use Bayesian optimization to find the optimal material instead." + ] + }, + { + "cell_type": "code", + "execution_count": 36, + "metadata": {}, + "outputs": [], + "source": [ + "import matplotlib.pyplot as plt\n", + "from CBFV import composition\n", + "from matminer.datasets import load_dataset\n", + "\n", + "def generate_data(seed=42):\n", + " \"\"\"\n", + " Constructs training and cadidate data from a benchmark MAX phase dataset by sampling\n", + " 8 points with elastic modulus <= 200 GPa for training and using the remaining data\n", + " as candidates for optimization.\n", + "\n", + " Args:\n", + " seed (int): Random seed for reproducibility. Default is 42.\n", + "\n", + " Returns:\n", + " tuple: A tuple containing two DataFrames:\n", + " - `train`: A DataFrame of 8 sampled points with elastic modulus <= 200 GPa.\n", + " - `candidate`: A DataFrame of the remaining data after sampling.\n", + " \"\"\"\n", + " # load benchmark dataset, pull the formula and elastic modulus\n", + " data = load_dataset(\"m2ax\", pbar=True)[['formula', 'elastic modulus']]\n", + " data.rename(columns={'elastic modulus': 'target'}, inplace=True)\n", + "\n", + " # generate an initial data by sampling 8 points with elastic modulus <= 200 GPa\n", + " train = data[data.target <= 200].sample(n=8, random_state=seed)\n", + " candidates = data.drop(train.index)\n", + "\n", + " return train, candidates" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Featurizing Compositions\n", + "\n", + "In the code cell below, we will featurize the training and candidate materials using the `CBFV` packages. In the interest of keeping the tutorial simple, we will subsample the generated features, keeping every 20th feature." + ] + }, + { + "cell_type": "code", + "execution_count": 37, + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "Reading file /Users/andrewf/miniconda3/envs/ax_env_pip/lib/python3.10/site-packages/matminer/datasets/m2ax.json.gz: 0it [00:00, ?it/s]0, ?it/s]\n", + "Decoding objects from /Users/andrewf/miniconda3/envs/ax_env_pip/lib/python3.10/site-packages/matminer/datasets/m2ax.json.gz: 0it [00:00, ?it/s]\n" + ] + }, + { + "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", + "
formulatarget
89Cr2SnN141
45Ti2TlN200
111Mo2PbN138
174Hf2CdC174
0Sc2AlC140
\n", + "
" + ], + "text/plain": [ + " formula target\n", + "89 Cr2SnN 141\n", + "45 Ti2TlN 200\n", + "111 Mo2PbN 138\n", + "174 Hf2CdC 174\n", + "0 Sc2AlC 140" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "Processing Input Data: 100%|██████████| 8/8 [00:00<00:00, 4279.90it/s]\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\tFeaturizing Compositions...\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "Assigning Features...: 100%|██████████| 8/8 [00:00<00:00, 9592.46it/s]\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\tCreating Pandas Objects...\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "Processing Input Data: 100%|██████████| 215/215 [00:00<00:00, 42091.83it/s]\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\tFeaturizing Compositions...\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "Assigning Features...: 100%|██████████| 215/215 [00:00<00:00, 12453.57it/s]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\tCreating Pandas Objects...\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "\n" + ] + } + ], + "source": [ + "# create training and candidate datasets\n", + "train, candidates = generate_data()\n", + "\n", + "# show the first five compositions in the training set\n", + "display(train.head())\n", + "\n", + "# featurize the compositions, keep every 20th feature for tutorial simplicity\n", + "X_train, y_train, formula, _ = composition.generate_features(train)\n", + "X_train = X_train.iloc[:, ::20]\n", + "\n", + "X_candidates, y_candidates, _, _ = composition.generate_features(candidates)\n", + "X_candidates = X_candidates.iloc[:, ::20]" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Applying Honegumi\n", + "\n", + "We will now use the [Honegumi](https://honegumi.readthedocs.io/en/latest/index.html) website to generate a script that will help us optimize our material composition for elastic modulus. Unlike other tutorials, however, this will require more extensive modifications to the generated script in order to facilitate feeding in predefined candidate solutions. From the description, we observe that our problem is a **single objective** optimization problem with some **existing materials data**. Additionally, as our problem doesn't have a simple continuous representation, typical Sobol generation won't work, so we will want to adjust the generation strategy somewhat, which can be exposed by selecting the **Fully Bayesian** option.\n", + "\n", + "![Featurization Selection](featurization_selection.png)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The Honegumi generated optimization script will provide a framework for our optimization campaign that we can modify to suit our specific problem needs. In the code sections below, we will make several modifications to this generated script to make it compatible with our problem." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Modifying the Code for Our Problem\n", + "We can modify this code to suit our problem with a few simple modifications. Wherever a modification has been made to the code, a comment starting with `# CHANGE:` has been added along with a brief description of the change." + ] + }, + { + "cell_type": "code", + "execution_count": 38, + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[INFO 08-08 15:35:14] 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", + "[INFO 08-08 15:35:14] ax.service.utils.instantiation: Inferred value type of ParameterType.FLOAT for parameter avg_Atomic_Number. If that is not the expected value type, you can explicitly specify 'value_type' ('int', 'float', 'bool' or 'str') in parameter dict.\n", + "[INFO 08-08 15:35:14] ax.service.utils.instantiation: Inferred value type of ParameterType.FLOAT for parameter avg_Allred-Rockow_electronegativity. If that is not the expected value type, you can explicitly specify 'value_type' ('int', 'float', 'bool' or 'str') in parameter dict.\n", + "[INFO 08-08 15:35:14] ax.service.utils.instantiation: Inferred value type of ParameterType.FLOAT for parameter avg_heat_of_vaporization_(kJ/mol)_. If that is not the expected value type, you can explicitly specify 'value_type' ('int', 'float', 'bool' or 'str') in parameter dict.\n", + "[INFO 08-08 15:35:14] ax.service.utils.instantiation: Inferred value type of ParameterType.FLOAT for parameter dev_Pauling_Electronegativity. If that is not the expected value type, you can explicitly specify 'value_type' ('int', 'float', 'bool' or 'str') in parameter dict.\n", + "[INFO 08-08 15:35:14] ax.service.utils.instantiation: Inferred value type of ParameterType.FLOAT for parameter dev_Boiling_Point_(K). If that is not the expected value type, you can explicitly specify 'value_type' ('int', 'float', 'bool' or 'str') in parameter dict.\n", + "[INFO 08-08 15:35:14] ax.service.utils.instantiation: Inferred value type of ParameterType.FLOAT for parameter range_Covalent_Radius. If that is not the expected value type, you can explicitly specify 'value_type' ('int', 'float', 'bool' or 'str') in parameter dict.\n", + "[INFO 08-08 15:35:14] ax.service.utils.instantiation: Inferred value type of ParameterType.FLOAT for parameter range_outer_shell_electrons. If that is not the expected value type, you can explicitly specify 'value_type' ('int', 'float', 'bool' or 'str') in parameter dict.\n", + "[INFO 08-08 15:35:14] ax.service.utils.instantiation: Inferred value type of ParameterType.FLOAT for parameter max_Mendeleev_Number. If that is not the expected value type, you can explicitly specify 'value_type' ('int', 'float', 'bool' or 'str') in parameter dict.\n", + "[INFO 08-08 15:35:14] ax.service.utils.instantiation: Inferred value type of ParameterType.FLOAT for parameter max_Number_of_unfilled_s_valence_electrons. If that is not the expected value type, you can explicitly specify 'value_type' ('int', 'float', 'bool' or 'str') in parameter dict.\n", + "[INFO 08-08 15:35:14] ax.service.utils.instantiation: Inferred value type of ParameterType.FLOAT for parameter min_families. If that is not the expected value type, you can explicitly specify 'value_type' ('int', 'float', 'bool' or 'str') in parameter dict.\n", + "[INFO 08-08 15:35:14] ax.service.utils.instantiation: Inferred value type of ParameterType.FLOAT for parameter min_valence_s. If that is not the expected value type, you can explicitly specify 'value_type' ('int', 'float', 'bool' or 'str') in parameter dict.\n", + "[INFO 08-08 15:35:14] ax.service.utils.instantiation: Inferred value type of ParameterType.FLOAT for parameter mode_Atomic_Number. If that is not the expected value type, you can explicitly specify 'value_type' ('int', 'float', 'bool' or 'str') in parameter dict.\n", + "[INFO 08-08 15:35:14] ax.service.utils.instantiation: Inferred value type of ParameterType.FLOAT for parameter mode_Allred-Rockow_electronegativity. If that is not the expected value type, you can explicitly specify 'value_type' ('int', 'float', 'bool' or 'str') in parameter dict.\n", + "[INFO 08-08 15:35:14] ax.service.utils.instantiation: Inferred value type of ParameterType.FLOAT for parameter mode_heat_of_vaporization_(kJ/mol)_. If that is not the expected value type, you can explicitly specify 'value_type' ('int', 'float', 'bool' or 'str') in parameter dict.\n", + "[INFO 08-08 15:35:14] ax.service.utils.instantiation: Created search space: SearchSpace(parameters=[RangeParameter(name='avg_Atomic_Number', parameter_type=FLOAT, range=[-100000.0, 100000.0]), RangeParameter(name='avg_Allred-Rockow_electronegativity', parameter_type=FLOAT, range=[-100000.0, 100000.0]), RangeParameter(name='avg_heat_of_vaporization_(kJ/mol)_', parameter_type=FLOAT, range=[-100000.0, 100000.0]), RangeParameter(name='dev_Pauling_Electronegativity', parameter_type=FLOAT, range=[-100000.0, 100000.0]), RangeParameter(name='dev_Boiling_Point_(K)', parameter_type=FLOAT, range=[-100000.0, 100000.0]), RangeParameter(name='range_Covalent_Radius', parameter_type=FLOAT, range=[-100000.0, 100000.0]), RangeParameter(name='range_outer_shell_electrons', parameter_type=FLOAT, range=[-100000.0, 100000.0]), RangeParameter(name='max_Mendeleev_Number', parameter_type=FLOAT, range=[-100000.0, 100000.0]), RangeParameter(name='max_Number_of_unfilled_s_valence_electrons', parameter_type=FLOAT, range=[-100000.0, 100000.0]), RangeParameter(name='min_families', parameter_type=FLOAT, range=[-100000.0, 100000.0]), RangeParameter(name='min_valence_s', parameter_type=FLOAT, range=[-100000.0, 100000.0]), RangeParameter(name='mode_Atomic_Number', parameter_type=FLOAT, range=[-100000.0, 100000.0]), RangeParameter(name='mode_Allred-Rockow_electronegativity', parameter_type=FLOAT, range=[-100000.0, 100000.0]), RangeParameter(name='mode_heat_of_vaporization_(kJ/mol)_', parameter_type=FLOAT, range=[-100000.0, 100000.0])], parameter_constraints=[]).\n", + "[INFO 08-08 15:35:14] ax.core.experiment: Attached custom parameterizations [{'avg_Atomic_Number': 26.25, 'avg_Allred-Rockow_electronegativity': 2.0475, 'avg_heat_of_vaporization_(kJ/mol)_': 246.7982, 'dev_Pauling_Electronegativity': 0.48, 'dev_Boiling_Point_(K)': 1025.175, 'range_Covalent_Radius': 0.66, 'range_outer_shell_electrons': 4.0, 'max_Mendeleev_Number': 82.0, 'max_Number_of_unfilled_s_valence_electrons': 1.0, 'min_families': 4.0, 'min_valence_s': 1.0, 'mode_Atomic_Number': 24.0, 'mode_Allred-Rockow_electronegativity': 1.65, 'mode_heat_of_vaporization_(kJ/mol)_': 344.3}] as trial 0.\n", + "[INFO 08-08 15:35:14] ax.service.ax_client: Completed trial 0 with data: {'elastic_modulus': (141, None)}.\n", + "[INFO 08-08 15:35:14] ax.core.experiment: Attached custom parameterizations [{'avg_Atomic_Number': 33.0, 'avg_Allred-Rockow_electronegativity': 1.90375, 'avg_heat_of_vaporization_(kJ/mol)_': 252.2232, 'dev_Pauling_Electronegativity': 0.5525, 'dev_Boiling_Point_(K)': 1328.2, 'range_Covalent_Radius': 0.73, 'range_outer_shell_electrons': 3.0, 'max_Mendeleev_Number': 82.0, 'max_Number_of_unfilled_s_valence_electrons': 0.0, 'min_families': 4.0, 'min_valence_s': 2.0, 'mode_Atomic_Number': 22.0, 'mode_Allred-Rockow_electronegativity': 1.38, 'mode_heat_of_vaporization_(kJ/mol)_': 421.0}] as trial 1.\n", + "[INFO 08-08 15:35:14] ax.service.ax_client: Completed trial 1 with data: {'elastic_modulus': (200, None)}.\n", + "[INFO 08-08 15:35:14] ax.core.experiment: Attached custom parameterizations [{'avg_Atomic_Number': 43.25, 'avg_Allred-Rockow_electronegativity': 1.965, 'avg_heat_of_vaporization_(kJ/mol)_': 344.1232, 'dev_Pauling_Electronegativity': 0.36625, 'dev_Boiling_Point_(K)': 1919.95, 'range_Covalent_Radius': 0.72, 'range_outer_shell_electrons': 4.0, 'max_Mendeleev_Number': 82.0, 'max_Number_of_unfilled_s_valence_electrons': 1.0, 'min_families': 4.0, 'min_valence_s': 1.0, 'mode_Atomic_Number': 42.0, 'mode_Allred-Rockow_electronegativity': 1.47, 'mode_heat_of_vaporization_(kJ/mol)_': 598.0}] as trial 2.\n", + "[INFO 08-08 15:35:14] ax.service.ax_client: Completed trial 2 with data: {'elastic_modulus': (138, None)}.\n", + "[INFO 08-08 15:35:14] ax.core.experiment: Attached custom parameterizations [{'avg_Atomic_Number': 49.5, 'avg_Allred-Rockow_electronegativity': 1.596, 'avg_heat_of_vaporization_(kJ/mol)_': 401.3425, 'dev_Pauling_Electronegativity': 0.42, 'dev_Boiling_Point_(K)': 1466.5, 'range_Covalent_Radius': 0.73, 'range_outer_shell_electrons': 2.0, 'max_Mendeleev_Number': 77.0, 'max_Number_of_unfilled_s_valence_electrons': 0.0, 'min_families': 4.0, 'min_valence_s': 2.0, 'mode_Atomic_Number': 72.0, 'mode_Allred-Rockow_electronegativity': 1.16, 'mode_heat_of_vaporization_(kJ/mol)_': 575.0}] as trial 3.\n", + "[INFO 08-08 15:35:14] ax.service.ax_client: Completed trial 3 with data: {'elastic_modulus': (174, None)}.\n", + "[INFO 08-08 15:35:14] ax.core.experiment: Attached custom parameterizations [{'avg_Atomic_Number': 15.25, 'avg_Allred-Rockow_electronegativity': 1.63425, 'avg_heat_of_vaporization_(kJ/mol)_': 319.4, 'dev_Pauling_Electronegativity': 0.415, 'dev_Boiling_Point_(K)': 793.75, 'range_Covalent_Radius': 0.67, 'range_outer_shell_electrons': 2.0, 'max_Mendeleev_Number': 77.0, 'max_Number_of_unfilled_s_valence_electrons': 0.0, 'min_families': 3.0, 'min_valence_s': 2.0, 'mode_Atomic_Number': 21.0, 'mode_Allred-Rockow_electronegativity': 1.19, 'mode_heat_of_vaporization_(kJ/mol)_': 314.2}] as trial 4.\n", + "[INFO 08-08 15:35:14] ax.service.ax_client: Completed trial 4 with data: {'elastic_modulus': (140, None)}.\n", + "[INFO 08-08 15:35:14] ax.core.experiment: Attached custom parameterizations [{'avg_Atomic_Number': 25.75, 'avg_Allred-Rockow_electronegativity': 1.9875, 'avg_heat_of_vaporization_(kJ/mol)_': 301.1482, 'dev_Pauling_Electronegativity': 0.4875, 'dev_Boiling_Point_(K)': 1202.175, 'range_Covalent_Radius': 0.66, 'range_outer_shell_electrons': 3.0, 'max_Mendeleev_Number': 82.0, 'max_Number_of_unfilled_s_valence_electrons': 0.0, 'min_families': 4.0, 'min_valence_s': 2.0, 'mode_Atomic_Number': 23.0, 'mode_Allred-Rockow_electronegativity': 1.53, 'mode_heat_of_vaporization_(kJ/mol)_': 453.0}] as trial 5.\n", + "[INFO 08-08 15:35:14] ax.service.ax_client: Completed trial 5 with data: {'elastic_modulus': (117, None)}.\n", + "[INFO 08-08 15:35:14] ax.core.experiment: Attached custom parameterizations [{'avg_Atomic_Number': 26.0, 'avg_Allred-Rockow_electronegativity': 1.917, 'avg_heat_of_vaporization_(kJ/mol)_': 335.05, 'dev_Pauling_Electronegativity': 0.2975, 'dev_Boiling_Point_(K)': 858.375, 'range_Covalent_Radius': 0.64, 'range_outer_shell_electrons': 3.0, 'max_Mendeleev_Number': 80.0, 'max_Number_of_unfilled_s_valence_electrons': 1.0, 'min_families': 4.0, 'min_valence_s': 1.0, 'mode_Atomic_Number': 24.0, 'mode_Allred-Rockow_electronegativity': 1.65, 'mode_heat_of_vaporization_(kJ/mol)_': 344.3}] as trial 6.\n", + "[INFO 08-08 15:35:14] ax.service.ax_client: Completed trial 6 with data: {'elastic_modulus': (160, None)}.\n", + "[INFO 08-08 15:35:14] ax.core.experiment: Attached custom parameterizations [{'avg_Atomic_Number': 34.25, 'avg_Allred-Rockow_electronegativity': 1.8825, 'avg_heat_of_vaporization_(kJ/mol)_': 365.6482, 'dev_Pauling_Electronegativity': 0.585, 'dev_Boiling_Point_(K)': 1669.95, 'range_Covalent_Radius': 0.73, 'range_outer_shell_electrons': 3.0, 'max_Mendeleev_Number': 82.0, 'max_Number_of_unfilled_s_valence_electrons': 0.0, 'min_families': 4.0, 'min_valence_s': 2.0, 'mode_Atomic_Number': 40.0, 'mode_Allred-Rockow_electronegativity': 1.32, 'mode_heat_of_vaporization_(kJ/mol)_': 582.0}] as trial 7.\n", + "[INFO 08-08 15:35:14] ax.service.ax_client: Completed trial 7 with data: {'elastic_modulus': (181, None)}.\n", + "[INFO 08-08 15:35:14] ax.service.ax_client: get_model_predictions() has been called when no model is instantiated. Attempting to instantiate the model for the first time.\n", + "[INFO 08-08 15:35:14] ax.service.ax_client: Successfully instantiated a model for the first time.\n", + "[INFO 08-08 15:35:14] ax.core.experiment: Attached custom parameterizations [{'avg_Atomic_Number': 42.5, 'avg_Allred-Rockow_electronegativity': 2.06475, 'avg_heat_of_vaporization_(kJ/mol)_': 415.73045, 'dev_Pauling_Electronegativity': 0.27625, 'dev_Boiling_Point_(K)': 2808.95, 'range_Covalent_Radius': 0.71, 'range_outer_shell_electrons': 3.0, 'max_Mendeleev_Number': 83.0, 'max_Number_of_unfilled_s_valence_electrons': 0.0, 'min_families': 4.0, 'min_valence_s': 2.0, 'mode_Atomic_Number': 74.0, 'mode_Allred-Rockow_electronegativity': 1.47, 'mode_heat_of_vaporization_(kJ/mol)_': 824.0}] as trial 8.\n", + "[INFO 08-08 15:35:14] ax.service.ax_client: Completed trial 8 with data: {'elastic_modulus': (171, None)}.\n", + "/Users/andrewf/miniconda3/envs/ax_env_pip/lib/python3.10/site-packages/linear_operator/utils/cholesky.py:40: NumericalWarning: A not p.d., added jitter of 1.0e-08 to the diagonal\n", + " warnings.warn(\n", + "[INFO 08-08 15:35:14] ax.core.experiment: Attached custom parameterizations [{'avg_Atomic_Number': 29.5, 'avg_Allred-Rockow_electronegativity': 1.7945, 'avg_heat_of_vaporization_(kJ/mol)_': 462.675, 'dev_Pauling_Electronegativity': 0.475, 'dev_Boiling_Point_(K)': 636.375, 'range_Covalent_Radius': 0.71, 'range_outer_shell_electrons': 2.0, 'max_Mendeleev_Number': 79.0, 'max_Number_of_unfilled_s_valence_electrons': 0.0, 'min_families': 4.0, 'min_valence_s': 2.0, 'mode_Atomic_Number': 40.0, 'mode_Allred-Rockow_electronegativity': 1.32, 'mode_heat_of_vaporization_(kJ/mol)_': 582.0}] as trial 9.\n", + "[INFO 08-08 15:35:14] ax.service.ax_client: Completed trial 9 with data: {'elastic_modulus': (218, None)}.\n", + "[INFO 08-08 15:35:14] ax.core.experiment: Attached custom parameterizations [{'avg_Atomic_Number': 46.5, 'avg_Allred-Rockow_electronegativity': 1.8695, 'avg_heat_of_vaporization_(kJ/mol)_': 583.675, 'dev_Pauling_Electronegativity': 0.155, 'dev_Boiling_Point_(K)': 957.125, 'range_Covalent_Radius': 0.69, 'range_outer_shell_electrons': 2.0, 'max_Mendeleev_Number': 79.0, 'max_Number_of_unfilled_s_valence_electrons': 0.0, 'min_families': 4.0, 'min_valence_s': 2.0, 'mode_Atomic_Number': 74.0, 'mode_Allred-Rockow_electronegativity': 1.47, 'mode_heat_of_vaporization_(kJ/mol)_': 824.0}] as trial 10.\n", + "[INFO 08-08 15:35:14] ax.service.ax_client: Completed trial 10 with data: {'elastic_modulus': (216, None)}.\n", + "/Users/andrewf/miniconda3/envs/ax_env_pip/lib/python3.10/site-packages/linear_operator/utils/cholesky.py:40: NumericalWarning: A not p.d., added jitter of 1.0e-08 to the diagonal\n", + " warnings.warn(\n", + "[INFO 08-08 15:35:14] ax.core.experiment: Attached custom parameterizations [{'avg_Atomic_Number': 21.0, 'avg_Allred-Rockow_electronegativity': 1.8995, 'avg_heat_of_vaporization_(kJ/mol)_': 398.175, 'dev_Pauling_Electronegativity': 0.325, 'dev_Boiling_Point_(K)': 611.375, 'range_Covalent_Radius': 0.48, 'range_outer_shell_electrons': 2.0, 'max_Mendeleev_Number': 79.0, 'max_Number_of_unfilled_s_valence_electrons': 0.0, 'min_families': 4.0, 'min_valence_s': 2.0, 'mode_Atomic_Number': 23.0, 'mode_Allred-Rockow_electronegativity': 1.53, 'mode_heat_of_vaporization_(kJ/mol)_': 453.0}] as trial 11.\n", + "[INFO 08-08 15:35:14] ax.service.ax_client: Completed trial 11 with data: {'elastic_modulus': (263, None)}.\n", + "/Users/andrewf/miniconda3/envs/ax_env_pip/lib/python3.10/site-packages/linear_operator/utils/cholesky.py:40: NumericalWarning: A not p.d., added jitter of 1.0e-08 to the diagonal\n", + " warnings.warn(\n", + "[INFO 08-08 15:35:14] ax.core.experiment: Attached custom parameterizations [{'avg_Atomic_Number': 16.0, 'avg_Allred-Rockow_electronegativity': 1.92475, 'avg_heat_of_vaporization_(kJ/mol)_': 160.83045, 'dev_Pauling_Electronegativity': 0.6275, 'dev_Boiling_Point_(K)': 1394.95, 'range_Covalent_Radius': 0.69, 'range_outer_shell_electrons': 3.0, 'max_Mendeleev_Number': 83.0, 'max_Number_of_unfilled_s_valence_electrons': 0.0, 'min_families': 3.0, 'min_valence_s': 2.0, 'mode_Atomic_Number': 21.0, 'mode_Allred-Rockow_electronegativity': 1.19, 'mode_heat_of_vaporization_(kJ/mol)_': 314.2}] as trial 12.\n", + "[INFO 08-08 15:35:14] ax.service.ax_client: Completed trial 12 with data: {'elastic_modulus': (200, None)}.\n", + "/Users/andrewf/miniconda3/envs/ax_env_pip/lib/python3.10/site-packages/linear_operator/utils/cholesky.py:40: NumericalWarning: A not p.d., added jitter of 1.0e-08 to the diagonal\n", + " warnings.warn(\n", + "[INFO 08-08 15:35:15] ax.core.experiment: Attached custom parameterizations [{'avg_Atomic_Number': 20.0, 'avg_Allred-Rockow_electronegativity': 1.7295, 'avg_heat_of_vaporization_(kJ/mol)_': 328.775, 'dev_Pauling_Electronegativity': 0.46, 'dev_Boiling_Point_(K)': 748.375, 'range_Covalent_Radius': 0.67, 'range_outer_shell_electrons': 2.0, 'max_Mendeleev_Number': 79.0, 'max_Number_of_unfilled_s_valence_electrons': 0.0, 'min_families': 3.0, 'min_valence_s': 2.0, 'mode_Atomic_Number': 21.0, 'mode_Allred-Rockow_electronegativity': 1.19, 'mode_heat_of_vaporization_(kJ/mol)_': 314.2}] as trial 13.\n", + "[INFO 08-08 15:35:15] ax.service.ax_client: Completed trial 13 with data: {'elastic_modulus': (175, None)}.\n", + "/Users/andrewf/miniconda3/envs/ax_env_pip/lib/python3.10/site-packages/linear_operator/utils/cholesky.py:40: NumericalWarning: A not p.d., added jitter of 1.0e-08 to the diagonal\n", + " warnings.warn(\n", + "[INFO 08-08 15:35:15] ax.core.experiment: Attached custom parameterizations [{'avg_Atomic_Number': 41.5, 'avg_Allred-Rockow_electronegativity': 1.90975, 'avg_heat_of_vaporization_(kJ/mol)_': 291.23045, 'dev_Pauling_Electronegativity': 0.6575, 'dev_Boiling_Point_(K)': 2278.95, 'range_Covalent_Radius': 0.75, 'range_outer_shell_electrons': 3.0, 'max_Mendeleev_Number': 83.0, 'max_Number_of_unfilled_s_valence_electrons': 0.0, 'min_families': 4.0, 'min_valence_s': 2.0, 'mode_Atomic_Number': 72.0, 'mode_Allred-Rockow_electronegativity': 1.16, 'mode_heat_of_vaporization_(kJ/mol)_': 575.0}] as trial 14.\n", + "[INFO 08-08 15:35:15] ax.service.ax_client: Completed trial 14 with data: {'elastic_modulus': (316, None)}.\n", + "/Users/andrewf/miniconda3/envs/ax_env_pip/lib/python3.10/site-packages/linear_operator/utils/cholesky.py:40: NumericalWarning: A not p.d., added jitter of 1.0e-08 to the diagonal\n", + " warnings.warn(\n", + "[INFO 08-08 15:35:15] ax.core.experiment: Attached custom parameterizations [{'avg_Atomic_Number': 32.75, 'avg_Allred-Rockow_electronegativity': 1.825, 'avg_heat_of_vaporization_(kJ/mol)_': 202.2232, 'dev_Pauling_Electronegativity': 0.56625, 'dev_Boiling_Point_(K)': 1029.95, 'range_Covalent_Radius': 0.72, 'range_outer_shell_electrons': 3.0, 'max_Mendeleev_Number': 82.0, 'max_Number_of_unfilled_s_valence_electrons': 0.0, 'min_families': 3.0, 'min_valence_s': 2.0, 'mode_Atomic_Number': 21.0, 'mode_Allred-Rockow_electronegativity': 1.19, 'mode_heat_of_vaporization_(kJ/mol)_': 314.2}] as trial 15.\n", + "[INFO 08-08 15:35:15] ax.service.ax_client: Completed trial 15 with data: {'elastic_modulus': (165, None)}.\n", + "/Users/andrewf/miniconda3/envs/ax_env_pip/lib/python3.10/site-packages/linear_operator/utils/cholesky.py:40: NumericalWarning: A not p.d., added jitter of 1.0e-08 to the diagonal\n", + " warnings.warn(\n", + "[INFO 08-08 15:35:15] ax.core.experiment: Attached custom parameterizations [{'avg_Atomic_Number': 30.0, 'avg_Allred-Rockow_electronegativity': 1.8395, 'avg_heat_of_vaporization_(kJ/mol)_': 512.675, 'dev_Pauling_Electronegativity': 0.34, 'dev_Boiling_Point_(K)': 727.625, 'range_Covalent_Radius': 0.6, 'range_outer_shell_electrons': 3.0, 'max_Mendeleev_Number': 79.0, 'max_Number_of_unfilled_s_valence_electrons': 1.0, 'min_families': 4.0, 'min_valence_s': 1.0, 'mode_Atomic_Number': 41.0, 'mode_Allred-Rockow_electronegativity': 1.41, 'mode_heat_of_vaporization_(kJ/mol)_': 682.0}] as trial 16.\n", + "[INFO 08-08 15:35:15] ax.service.ax_client: Completed trial 16 with data: {'elastic_modulus': (268, None)}.\n", + "/Users/andrewf/miniconda3/envs/ax_env_pip/lib/python3.10/site-packages/linear_operator/utils/cholesky.py:40: NumericalWarning: A not p.d., added jitter of 1.0e-08 to the diagonal\n", + " warnings.warn(\n", + "[INFO 08-08 15:35:15] ax.core.experiment: Attached custom parameterizations [{'avg_Atomic_Number': 42.0, 'avg_Allred-Rockow_electronegativity': 1.99975, 'avg_heat_of_vaporization_(kJ/mol)_': 375.23045, 'dev_Pauling_Electronegativity': 0.5575, 'dev_Boiling_Point_(K)': 2691.45, 'range_Covalent_Radius': 0.63, 'range_outer_shell_electrons': 3.0, 'max_Mendeleev_Number': 83.0, 'max_Number_of_unfilled_s_valence_electrons': 0.0, 'min_families': 4.0, 'min_valence_s': 2.0, 'mode_Atomic_Number': 73.0, 'mode_Allred-Rockow_electronegativity': 1.34, 'mode_heat_of_vaporization_(kJ/mol)_': 743.0}] as trial 17.\n", + "[INFO 08-08 15:35:15] ax.service.ax_client: Completed trial 17 with data: {'elastic_modulus': (315, None)}.\n", + "/Users/andrewf/miniconda3/envs/ax_env_pip/lib/python3.10/site-packages/linear_operator/utils/cholesky.py:40: NumericalWarning: A not p.d., added jitter of 1.0e-08 to the diagonal\n", + " warnings.warn(\n", + "[INFO 08-08 15:35:15] ax.core.experiment: Attached custom parameterizations [{'avg_Atomic_Number': 45.5, 'avg_Allred-Rockow_electronegativity': 1.7145, 'avg_heat_of_vaporization_(kJ/mol)_': 459.175, 'dev_Pauling_Electronegativity': 0.49, 'dev_Boiling_Point_(K)': 692.125, 'range_Covalent_Radius': 0.73, 'range_outer_shell_electrons': 2.0, 'max_Mendeleev_Number': 79.0, 'max_Number_of_unfilled_s_valence_electrons': 0.0, 'min_families': 4.0, 'min_valence_s': 2.0, 'mode_Atomic_Number': 72.0, 'mode_Allred-Rockow_electronegativity': 1.16, 'mode_heat_of_vaporization_(kJ/mol)_': 575.0}] as trial 18.\n", + "[INFO 08-08 15:35:15] ax.service.ax_client: Completed trial 18 with data: {'elastic_modulus': (238, None)}.\n", + "/Users/andrewf/miniconda3/envs/ax_env_pip/lib/python3.10/site-packages/linear_operator/utils/cholesky.py:40: NumericalWarning: A not p.d., added jitter of 1.0e-08 to the diagonal\n", + " warnings.warn(\n", + "[INFO 08-08 15:35:15] ax.core.experiment: Attached custom parameterizations [{'avg_Atomic_Number': 42.0, 'avg_Allred-Rockow_electronegativity': 1.85, 'avg_heat_of_vaporization_(kJ/mol)_': 597.005, 'dev_Pauling_Electronegativity': 0.19625, 'dev_Boiling_Point_(K)': 1135.25, 'range_Covalent_Radius': 0.69, 'range_outer_shell_electrons': 2.0, 'max_Mendeleev_Number': 78.0, 'max_Number_of_unfilled_s_valence_electrons': 0.0, 'min_families': 4.0, 'min_valence_s': 2.0, 'mode_Atomic_Number': 74.0, 'mode_Allred-Rockow_electronegativity': 1.47, 'mode_heat_of_vaporization_(kJ/mol)_': 824.0}] as trial 19.\n", + "[INFO 08-08 15:35:15] ax.service.ax_client: Completed trial 19 with data: {'elastic_modulus': (253, None)}.\n", + "/Users/andrewf/miniconda3/envs/ax_env_pip/lib/python3.10/site-packages/linear_operator/utils/cholesky.py:40: NumericalWarning: A not p.d., added jitter of 1.0e-08 to the diagonal\n", + " warnings.warn(\n", + "[INFO 08-08 15:35:15] ax.core.experiment: Attached custom parameterizations [{'avg_Atomic_Number': 59.0, 'avg_Allred-Rockow_electronegativity': 1.94875, 'avg_heat_of_vaporization_(kJ/mol)_': 453.7232, 'dev_Pauling_Electronegativity': 0.3625, 'dev_Boiling_Point_(K)': 2514.7, 'range_Covalent_Radius': 0.73, 'range_outer_shell_electrons': 3.0, 'max_Mendeleev_Number': 82.0, 'max_Number_of_unfilled_s_valence_electrons': 0.0, 'min_families': 4.0, 'min_valence_s': 2.0, 'mode_Atomic_Number': 74.0, 'mode_Allred-Rockow_electronegativity': 1.47, 'mode_heat_of_vaporization_(kJ/mol)_': 824.0}] as trial 20.\n", + "[INFO 08-08 15:35:15] ax.service.ax_client: Completed trial 20 with data: {'elastic_modulus': (149, None)}.\n", + "/Users/andrewf/miniconda3/envs/ax_env_pip/lib/python3.10/site-packages/linear_operator/utils/cholesky.py:40: NumericalWarning: A not p.d., added jitter of 1.0e-08 to the diagonal\n", + " warnings.warn(\n", + "[INFO 08-08 15:35:15] ax.core.experiment: Attached custom parameterizations [{'avg_Atomic_Number': 15.5, 'avg_Allred-Rockow_electronegativity': 1.71, 'avg_heat_of_vaporization_(kJ/mol)_': 342.105, 'dev_Pauling_Electronegativity': 0.4325, 'dev_Boiling_Point_(K)': 807.75, 'range_Covalent_Radius': 0.67, 'range_outer_shell_electrons': 2.0, 'max_Mendeleev_Number': 78.0, 'max_Number_of_unfilled_s_valence_electrons': 0.0, 'min_families': 3.0, 'min_valence_s': 2.0, 'mode_Atomic_Number': 21.0, 'mode_Allred-Rockow_electronegativity': 1.19, 'mode_heat_of_vaporization_(kJ/mol)_': 314.2}] as trial 21.\n", + "[INFO 08-08 15:35:15] ax.service.ax_client: Completed trial 21 with data: {'elastic_modulus': (184, None)}.\n", + "/Users/andrewf/miniconda3/envs/ax_env_pip/lib/python3.10/site-packages/linear_operator/utils/cholesky.py:40: NumericalWarning: A not p.d., added jitter of 1.0e-08 to the diagonal\n", + " warnings.warn(\n", + "[INFO 08-08 15:35:15] ax.core.experiment: Attached custom parameterizations [{'avg_Atomic_Number': 34.25, 'avg_Allred-Rockow_electronegativity': 2.055, 'avg_heat_of_vaporization_(kJ/mol)_': 217.2732, 'dev_Pauling_Electronegativity': 0.49125, 'dev_Boiling_Point_(K)': 958.925, 'range_Covalent_Radius': 0.72, 'range_outer_shell_electrons': 4.0, 'max_Mendeleev_Number': 82.0, 'max_Number_of_unfilled_s_valence_electrons': 1.0, 'min_families': 4.0, 'min_valence_s': 1.0, 'mode_Atomic_Number': 24.0, 'mode_Allred-Rockow_electronegativity': 1.65, 'mode_heat_of_vaporization_(kJ/mol)_': 344.3}] as trial 22.\n", + "[INFO 08-08 15:35:15] ax.service.ax_client: Completed trial 22 with data: {'elastic_modulus': (105, None)}.\n", + "/Users/andrewf/miniconda3/envs/ax_env_pip/lib/python3.10/site-packages/linear_operator/utils/cholesky.py:40: NumericalWarning: A not p.d., added jitter of 1.0e-08 to the diagonal\n", + " warnings.warn(\n", + "[INFO 08-08 15:35:15] ax.core.experiment: Attached custom parameterizations [{'avg_Atomic_Number': 20.5, 'avg_Allred-Rockow_electronegativity': 1.8245, 'avg_heat_of_vaporization_(kJ/mol)_': 382.175, 'dev_Pauling_Electronegativity': 0.37, 'dev_Boiling_Point_(K)': 634.625, 'range_Covalent_Radius': 0.59, 'range_outer_shell_electrons': 2.0, 'max_Mendeleev_Number': 79.0, 'max_Number_of_unfilled_s_valence_electrons': 0.0, 'min_families': 4.0, 'min_valence_s': 2.0, 'mode_Atomic_Number': 22.0, 'mode_Allred-Rockow_electronegativity': 1.38, 'mode_heat_of_vaporization_(kJ/mol)_': 421.0}] as trial 23.\n", + "[INFO 08-08 15:35:15] ax.service.ax_client: Completed trial 23 with data: {'elastic_modulus': (257, None)}.\n", + "/Users/andrewf/miniconda3/envs/ax_env_pip/lib/python3.10/site-packages/linear_operator/utils/cholesky.py:40: NumericalWarning: A not p.d., added jitter of 1.0e-08 to the diagonal\n", + " warnings.warn(\n", + "[INFO 08-08 15:35:15] ax.core.experiment: Attached custom parameterizations [{'avg_Atomic_Number': 16.25, 'avg_Allred-Rockow_electronegativity': 2.00875, 'avg_heat_of_vaporization_(kJ/mol)_': 160.2482, 'dev_Pauling_Electronegativity': 0.725, 'dev_Boiling_Point_(K)': 1353.775, 'range_Covalent_Radius': 0.69, 'range_outer_shell_electrons': 4.0, 'max_Mendeleev_Number': 88.0, 'max_Number_of_unfilled_s_valence_electrons': 0.0, 'min_families': 3.0, 'min_valence_s': 2.0, 'mode_Atomic_Number': 21.0, 'mode_Allred-Rockow_electronegativity': 1.19, 'mode_heat_of_vaporization_(kJ/mol)_': 314.2}] as trial 24.\n", + "[INFO 08-08 15:35:15] ax.service.ax_client: Completed trial 24 with data: {'elastic_modulus': (244, None)}.\n", + "/Users/andrewf/miniconda3/envs/ax_env_pip/lib/python3.10/site-packages/linear_operator/utils/cholesky.py:40: NumericalWarning: A not p.d., added jitter of 1.0e-08 to the diagonal\n", + " warnings.warn(\n", + "[INFO 08-08 15:35:15] ax.core.experiment: Attached custom parameterizations [{'avg_Atomic_Number': 22.0, 'avg_Allred-Rockow_electronegativity': 2.14425, 'avg_heat_of_vaporization_(kJ/mol)_': 181.5382, 'dev_Pauling_Electronegativity': 0.475, 'dev_Boiling_Point_(K)': 1230.7, 'range_Covalent_Radius': 0.52, 'range_outer_shell_electrons': 4.0, 'max_Mendeleev_Number': 84.0, 'max_Number_of_unfilled_s_valence_electrons': 1.0, 'min_families': 4.0, 'min_valence_s': 1.0, 'mode_Atomic_Number': 24.0, 'mode_Allred-Rockow_electronegativity': 1.65, 'mode_heat_of_vaporization_(kJ/mol)_': 344.3}] as trial 25.\n", + "[INFO 08-08 15:35:15] ax.service.ax_client: Completed trial 25 with data: {'elastic_modulus': (171, None)}.\n", + "/Users/andrewf/miniconda3/envs/ax_env_pip/lib/python3.10/site-packages/linear_operator/utils/cholesky.py:40: NumericalWarning: A not p.d., added jitter of 1.0e-08 to the diagonal\n", + " warnings.warn(\n", + "[INFO 08-08 15:35:15] ax.core.experiment: Attached custom parameterizations [{'avg_Atomic_Number': 26.5, 'avg_Allred-Rockow_electronegativity': 2.06475, 'avg_heat_of_vaporization_(kJ/mol)_': 302.73045, 'dev_Pauling_Electronegativity': 0.32625, 'dev_Boiling_Point_(K)': 2284.95, 'range_Covalent_Radius': 0.7, 'range_outer_shell_electrons': 4.0, 'max_Mendeleev_Number': 83.0, 'max_Number_of_unfilled_s_valence_electrons': 1.0, 'min_families': 4.0, 'min_valence_s': 1.0, 'mode_Atomic_Number': 42.0, 'mode_Allred-Rockow_electronegativity': 1.47, 'mode_heat_of_vaporization_(kJ/mol)_': 598.0}] as trial 26.\n", + "[INFO 08-08 15:35:15] ax.service.ax_client: Completed trial 26 with data: {'elastic_modulus': (179, None)}.\n" + ] + } + ], + "source": [ + "import numpy as np\n", + "from ax.service.ax_client import AxClient, ObjectiveProperties\n", + "\n", + "from ax.modelbridge.factory import Models\n", + "from ax.modelbridge.generation_strategy import GenerationStep, GenerationStrategy\n", + "\n", + "import pandas as pd\n", + "\n", + "obj1_name = \"elastic_modulus\" # CHANGE: update objective name\n", + "\n", + "# CHANGE: remove the branin dummy objective function, we will use tabulated data\n", + "\n", + "# CHANGE: remove dummy training data, we defined this in an earlier cell\n", + "\n", + "n_train = len(X_train)\n", + "\n", + "gs = GenerationStrategy(\n", + " steps=[\n", + " # CHANGE: remove sobol sampling step\n", + " GenerationStep(\n", + " model=Models.BOTORCH_MODULAR, # CHANGE: use modular botorch model\n", + " num_trials=-1,\n", + " max_parallelism=3,\n", + " model_kwargs={},\n", + " ),\n", + " ]\n", + ")\n", + "\n", + "ax_client = AxClient(generation_strategy=gs)\n", + "\n", + "ax_client.create_experiment(\n", + " parameters=[ # CHANGE: create flexible parameters for all generated features\n", + " {\"name\": feat, \"type\": \"range\", \"bounds\": [-1e5, 1e5]}\n", + " for feat in X_train.columns\n", + " ],\n", + " objectives={\n", + " obj1_name: ObjectiveProperties(minimize=False) # CHANGE: maximize the objective\n", + " },\n", + ")\n", + "\n", + "# Add existing data to the AxClient\n", + "for i in range(n_train):\n", + " parameterization = X_train.iloc[i].to_dict()\n", + "\n", + " ax_client.attach_trial(parameterization)\n", + " ax_client.complete_trial(trial_index=i, raw_data=y_train.iloc[i]) # CHANGE: iloc\n", + "\n", + "from ax.core.observation import ObservationFeatures # CHANGE: import ObservationFeatures\n", + "\n", + "selected_indices = [] # CHANGE: create list to store selected indices\n", + "for i in range(n_train, n_train + 19): # CHANGE: account for training data in trial num\n", + "\n", + " ax_client.fit_model() # CHANGE: fit the model to the known data\n", + " model = ax_client.generation_strategy.model # CHANGE: get model object as var\n", + "\n", + " # CHANGE: define candidates as ObservationFeatures before passing to model\n", + " obs_feat = [\n", + " ObservationFeatures(\n", + " {col: val for col, val in zip(X_candidates.columns, X_candidates.iloc[i])}\n", + " )\n", + " for i in range(len(X_candidates))\n", + " ]\n", + "\n", + " # CHANGE: evaluate the acquisition function on each candidate, and pull the best\n", + " acqf_values = np.array(\n", + " model.evaluate_acquisition_function(observation_features=obs_feat)\n", + " )\n", + " acqf_values[selected_indices] = -100 # give prev selected points a low value\n", + "\n", + " best_index = np.argmax(acqf_values) # get the index of the best candidate\n", + " selected_indices.append(best_index) # append this to the selected indices list\n", + "\n", + " results = y_candidates.iloc[best_index] # CHANGE: \"measure\" the best idx candidate\n", + "\n", + " ax_client.attach_trial(X_candidates.iloc[best_index].to_dict())\n", + " ax_client.complete_trial(trial_index=i, raw_data=results)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Show the Best Material\n", + "\n", + "After our optimization loop has completed, we can look through the data to find the best discovered material." + ] + }, + { + "cell_type": "code", + "execution_count": 26, + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[WARNING 08-06 18:39:07] ax.service.utils.report_utils: Column reason missing for all trials. Not appending column.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "Best Material: Hf2AlN\n" + ] + } + ], + "source": [ + "best_trial_index = ax_client.get_trials_data_frame()[obj1_name].idxmax()\n", + "\n", + "print(\"\\nBest Material: \", formula[best_indices[best_trial_index]])" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Plotting Optimization Performance\n", + "\n", + "We can plot the performance of our optmization loop to see how the optimization task progressed as a function of iteration count." + ] + }, + { + "cell_type": "code", + "execution_count": 41, + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[WARNING 08-08 15:37:56] ax.service.utils.report_utils: Column reason missing for all trials. Not appending column.\n" + ] + }, + { + "data": { + "image/png": "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s2dLHct8rj9ud5yZz2VjZQUAAACATeICewAAAAA2iWIFAAAAgE2iWAEAAABgkyhWAAAAANgkihUAAAAANoliBQAAAIBNolgBAAAAYJMoVgAAAADYJIoVAAAAADaJYgUAAACATaJYAQAAAGCTKFYAwIGYTKbb2lq1alXu+0VGRspkMmnfvn01kq2i33erBQsWFOdcsGBBmf08PDxkMpmqna82hIaGymQy6dy5c9aOAgA2ycXaAQAAdWfixIml9h04cECJiYnq2rWrunXrVqLtjjvuqKNk1bNy5UpFRUXJz8/P2lEAADWIYgUAHMi6detK7YuMjFRiYqJGjx5d7gqFJa+99prmzp2ru+66q2YCVoGnp6euX7+uFStWaOHChVbLAQCoeZwGBgCosmbNmqljx47y8vKyWobIyEh5eHho1apVunr1qtVyAABqHsUKAMCidevWFV8Pcvr0aU2YMEFNmzaVk5OTYmNjJZV9zcqJEyf04osvqkePHgoICJC7u7vatGmj3/3ud7p06VKN5rzzzjv19NNPKz09XW+88Ualjtm3b59MJpMiIyMttpf1uYquq8nLy9PChQvVrl07eXp6qlOnToqJiSnut2fPHg0cOFANGzaUn5+ffvvb3yolJaXcTBs3blSPHj3k5eWlJk2aaOLEibp48WKZ/T/99FOFh4eX+PedOXOmxd9z6+f5xz/+oYEDB8rX11cmk0nXrl0rNxcAWBPFCgCgXN9//7169eqlI0eOaODAgRoyZIhcXV3LPWbJkiV68803JUkPPvigRowYIcMw9Je//EU9e/as8YJl7ty58vT01OrVq3XlypUafW9LHnnkES1fvlz33nuvBgwYoLNnz2ry5MmKiYnR1q1bNWzYMOXl5WnYsGHy9vbWhg0bNHr0aBmGYfH9li1bpt/+9rfy8fHRqFGj5O3trffff199+vTRhQsXSvWfO3euwsLC9Pnnn6tDhw6KiIiQi4uL3nzzTd1///3697//bfH3fPjhhwoLC5PZbFZYWJh69eplszcfAACJa1YAABXYvHmzpk+frpUrV8rZ2blSxzz99NNatWqVmjZtWryvoKBAixYt0vz58/WHP/xB7733Xo1lDAwM1NSpU7VixQq9/vrrev3112vsvX8pKSlJDRo00JkzZxQQECBJ2rt3rwYNGqR58+bpxo0bio2NVXh4uCQpLS1Nffv21YEDB7Rv3z4NHDiw1Hu+88472rFjh0aMGCFJys3N1aRJk/TBBx9o+vTpxStZkrRlyxYtXbpU99xzjz766CO1a9dOkmQYhhYsWKBXXnlFUVFR2rx5c6nf8+6772rz5s169NFHa/qfBQBqBSsrAIByBQQEaOnSpZUuVCRp4MCBJQoVSXJyctLLL7+soKAgffLJJzUdU3PmzJGXl5f+/Oc/6/LlyzX+/rdauXJlcaEiFX7e++67Tz///LPCwsKKCxVJatiwoaZMmSJJ+vLLLy2+3yOPPFJcqEiSq6urVq1aJS8vL33yySc6f/58cdvixYslSZs2bSouVCQVn7LXrVs3bd261eIKU3h4OIUKgHqFYgUAUK7BgwdX6QL6lJQUxcTEaNasWXryyScVGRmpyMhI5ebmKiUlpcYvhm/SpImmTZumzMxMLV26tEbf+1aurq4KDQ0ttb9NmzaSpKFDh5bZ9vPPP1t8zwkTJpTa17hxYw0dOlSGYejAgQOSpMuXL+vrr7/W3XffrXvuuafUMSaTSf369VN+fr6OHz9eqj0iIqLsDwYANojTwAAA5arKbYk3bdqkKVOmKCMjo8w+6enp8vf3r060Ul544QW99dZb+stf/qIXXnhBgYGBNfr+UuEpZ5ZWmXx8fCRJQUFBZbbl5ORYfM+WLVta3F/0kMyia3yKHh555syZCq81sbSyYs1bTANAVVCsAADK5eHhcVv9k5KSiu+ytXLlSoWHhysoKEienp6SpL59++rQoUNlXmxeHQEBAZo+fbqWLl2q1157TatWrarS+xQUFJTZ5uRU/kkJFbVXR1GuwMBADRs2rNy+lgqg2x1LALA2ihUAQI3atWuXbty4odmzZysqKqpU+48//lirv79odeWvf/2r5syZY7GPm5ubJJW58nPrNSJ1ISkpScHBwRb3S4W3Z5ak5s2bS5LuuOMOiw/4BAB7wzUrAIAalZqaKunmF+tb7d+/v8zb6taUxo0b69lnn1V2drZeffVVi32aNWsmSTp9+nSptqtXryohIaFWM/7Sf//3f1vM8dlnnxVfhyIV/pt27NhRp06dspgdAOwNxQoAoEa1b99eUuFDDs1mc/H+ixcv6plnnqmTDLNmzVLDhg21Zs0a5ebmlmpv3bq17rrrLn377bf6+OOPi/ebzWZNmTJFaWlpdZKzyN/+9jf94x//KP45Ly9PM2bMkNls1kMPPVTiWpPo6GgVFBRo3LhxOnHiRKn3SklJ0bvvvlsXsQGg1nEaGACgRkVERKhLly46duyY2rVrp379+ik7O1t79+5Vt27d1LdvX8XFxdVqBn9/f0VFRWnhwoVl9pk/f76efPJJjRs3TgMGDJCPj4+OHDmihg0batSoUSWKmNo2ZcoUhYWFacCAAWrWrJni4+N19uxZ3XnnnVq9enWJvo899phOnjypV199VT169FC3bt3Utm1bGYahxMREffPNN/Lx8dFTTz1VZ/kBoLawsgIAqFFubm766quvNHXqVHl4eGjHjh367rvv9Oyzz2r37t1ydXWtkxwzZ85Uo0aNymwveuJ8p06ddPDgQR05ckQjR47UoUOH5OvrWycZi8yePVvvvfeerl+/rtjYWKWlpemJJ55QfHy8xTt4LV68WF9++aXGjRunf/3rX4qNjdXevXuVn5+vqVOn1spzbADAGkxGbdyOBQAAAACqiZUVAAAAADaJYgUAAACATaJYAQAAAGCTKFYAAAAA2CSKFQAAAAA2iWIFAAAAgE2iWAEAAABgkyhWAAAAANgkihUAAAAANoliBQAAAIBNolgBAAAAYJMoVgAAAADYJIoVAAAAADaJYgUAAACATaJYAQAAAGCTKFYAAAAA2CSKFQAAAAA26f8BkO1H9yMCB8MAAAAASUVORK5CYII=", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "objectives = ax_client.objective_names\n", + "df = ax_client.get_trials_data_frame()[objectives]\n", + "\n", + "best_to_trial = np.maximum.accumulate(df) # change if maximizing\n", + "\n", + "fig, ax = plt.subplots(figsize=(6, 4), dpi=150)\n", + "ax.scatter(df.index, df, ec=\"k\", fc=\"none\", label=\"Observed\")\n", + "ax.plot(best_to_trial, color=\"#0033FF\", lw=2, label=\"Best to Trial\")\n", + "\n", + "ax.axvline(7.5, color=\"r\", ls=\"--\", lw=1)\n", + "\n", + "ax.set_xlabel(\"Trial Number\")\n", + "ax.set_ylabel(objectives[0])\n", + "ax.legend()\n", + "plt.show()" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "ax_env_pip", + "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.10.14" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +}