From 6f2e8836a5a042596be3683136632fa3993a4037 Mon Sep 17 00:00:00 2001 From: Yuting Xu <12775874+xuyuting@users.noreply.github.com> Date: Wed, 14 Aug 2024 18:31:15 -0400 Subject: [PATCH 01/10] fix the demo ipynb files and remove outputs to reduce file sizes. Outputs could be found in gh pages --- demo/Constrained multi objective.ipynb | 51 +- ...int optimization with constant param.ipynb | 32 +- demo/Simple single objective.ipynb | 3417 +---------------- 3 files changed, 82 insertions(+), 3418 deletions(-) diff --git a/demo/Constrained multi objective.ipynb b/demo/Constrained multi objective.ipynb index c83070b..56814c2 100644 --- a/demo/Constrained multi objective.ipynb +++ b/demo/Constrained multi objective.ipynb @@ -87,6 +87,27 @@ "Z0.plot(x='Response 1', y='Response 2', kind='scatter', figsize=(4,3))" ] }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Define the Target" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "from obsidian.parameters import Target\n", + "\n", + "target = [\n", + " Target('Response 1', aim='max'),\n", + " Target('Response 2', aim='min')\n", + "]" + ] + }, { "cell_type": "markdown", "metadata": {}, @@ -109,7 +130,7 @@ "metadata": {}, "outputs": [], "source": [ - "my_campaign = Campaign(X_space)\n", + "my_campaign = Campaign(X_space, target)\n", "my_campaign.add_data(Z0)\n", "my_campaign.data" ] @@ -127,22 +148,7 @@ "metadata": {}, "outputs": [], "source": [ - "from obsidian.parameters import Target" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "target = [\n", - " Target('Response 1', aim='max'),\n", - " Target('Response 2', aim='min')\n", - "]\n", - "\n", - "my_campaign.set_target(target)\n", - "my_campaign.fit()\n" + "my_campaign.fit()" ] }, { @@ -168,10 +174,10 @@ "outputs": [], "source": [ "# # X1 + X2 >= 2\n", - "# optim_kwargs = {'m_batch':2, 'acquisition':[{'qNEHVI':{'ref_point':[-350,0]}}], 'ineq_constraints':[InConstraint_Generic(X_space, indices=[0,1], coeff=[1,1], rhs=2)]}\n", + "# optim_kwargs = {'m_batch':2, 'acquisition':[{'NEHVI':{'ref_point':[-350,0]}}], 'ineq_constraints':[InConstraint_Generic(X_space, indices=[0,1], coeff=[1,1], rhs=2)]}\n", "\n", "# X1 + X2 <= 6 aka -X1 - X2 >= -6\n", - "optim_kwargs = {'m_batch':2, 'acquisition':[{'qNEHVI':{'ref_point':[-350,0]}}], 'ineq_constraints':[InConstraint_Generic(X_space, indices=[0,1], coeff=[-1,-1], rhs=-6)]}\n", + "optim_kwargs = {'m_batch':2, 'acquisition':[{'NEHVI':{'ref_point':[-350,0]}}], 'ineq_constraints':[InConstraint_Generic(X_space, indices=[0,1], coeff=[-1,-1], rhs=-6)]}\n", "\n", "X_suggest, eval_suggest = my_campaign.optimizer.suggest(**optim_kwargs)" ] @@ -244,6 +250,13 @@ "my_campaign.data" ] }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + }, { "cell_type": "code", "execution_count": null, diff --git a/demo/Joint optimization with constant param.ipynb b/demo/Joint optimization with constant param.ipynb index b6b620e..8174785 100644 --- a/demo/Joint optimization with constant param.ipynb +++ b/demo/Joint optimization with constant param.ipynb @@ -88,6 +88,23 @@ "Z0.plot(x='Temperature', y='Yield', kind='scatter', figsize=(4,3))" ] }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Define the Target" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "from obsidian.parameters import Target\n", + "target = Target('Yield', aim='max')" + ] + }, { "cell_type": "markdown", "metadata": {}, @@ -110,7 +127,7 @@ "metadata": {}, "outputs": [], "source": [ - "my_campaign = Campaign(X_space)\n", + "my_campaign = Campaign(X_space,target)\n", "my_campaign.add_data(Z0)\n", "my_campaign.data" ] @@ -128,18 +145,7 @@ "metadata": {}, "outputs": [], "source": [ - "from obsidian.parameters import Target" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "target = Target('Yield', aim='max')\n", - "my_campaign.set_target(target)\n", - "my_campaign.fit()\n" + "my_campaign.fit()" ] }, { diff --git a/demo/Simple single objective.ipynb b/demo/Simple single objective.ipynb index dd31bfd..51f2b2c 100644 --- a/demo/Simple single objective.ipynb +++ b/demo/Simple single objective.ipynb @@ -2,17 +2,9 @@ "cells": [ { "cell_type": "code", - "execution_count": 1, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "obsidian version: 0.7.10\n" - ] - } - ], + "outputs": [], "source": [ "import obsidian\n", "print(f'obsidian version: ' + obsidian.__version__)\n", @@ -32,7 +24,7 @@ }, { "cell_type": "code", - "execution_count": 2, + "execution_count": null, "metadata": {}, "outputs": [], "source": [ @@ -42,141 +34,9 @@ }, { "cell_type": "code", - "execution_count": 3, + "execution_count": null, "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", - "
TemperatureConcentrationEnzymeVariantStir Rate
08.017.00.1405MRK001Medium
112.0143.00.1695MRK003Medium
24.0101.00.2855MRK002High
328.087.00.1115MRK002Low
4-4.0115.00.2275MRK001Low
5-8.073.00.0825MRK002Medium
620.0129.00.0535MRK001High
724.031.00.2565MRK002Medium
816.059.00.1985MRK003High
90.045.00.0245MRK003Low
\n", - "
" - ], - "text/plain": [ - " Temperature Concentration Enzyme Variant Stir Rate\n", - "0 8.0 17.0 0.1405 MRK001 Medium\n", - "1 12.0 143.0 0.1695 MRK003 Medium\n", - "2 4.0 101.0 0.2855 MRK002 High\n", - "3 28.0 87.0 0.1115 MRK002 Low\n", - "4 -4.0 115.0 0.2275 MRK001 Low\n", - "5 -8.0 73.0 0.0825 MRK002 Medium\n", - "6 20.0 129.0 0.0535 MRK001 High\n", - "7 24.0 31.0 0.2565 MRK002 Medium\n", - "8 16.0 59.0 0.1985 MRK003 High\n", - "9 0.0 45.0 0.0245 MRK003 Low" - ] - }, - "execution_count": 3, - "metadata": {}, - "output_type": "execute_result" - } - ], + "outputs": [], "source": [ "params = [\n", " Param_Continuous('Temperature', -10, 30),\n", @@ -203,127 +63,9 @@ }, { "cell_type": "code", - "execution_count": 4, + "execution_count": null, "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", - "
TemperatureConcentrationEnzymeVariantStir RateYieldIteration
Observation ID
5-8.073.00.0825MRK002Medium86.1963330
24.0101.00.2855MRK002High46.2704220
328.087.00.1115MRK002Low60.2889190
4-4.0115.00.2275MRK001Low63.0824170
112.0143.00.1695MRK003Medium44.2801310
\n", - "
" - ], - "text/plain": [ - " Temperature Concentration Enzyme Variant Stir Rate \\\n", - "Observation ID \n", - "5 -8.0 73.0 0.0825 MRK002 Medium \n", - "2 4.0 101.0 0.2855 MRK002 High \n", - "3 28.0 87.0 0.1115 MRK002 Low \n", - "4 -4.0 115.0 0.2275 MRK001 Low \n", - "1 12.0 143.0 0.1695 MRK003 Medium \n", - "\n", - " Yield Iteration \n", - "Observation ID \n", - "5 86.196333 0 \n", - "2 46.270422 0 \n", - "3 60.288919 0 \n", - "4 63.082417 0 \n", - "1 44.280131 0 " - ] - }, - "execution_count": 4, - "metadata": {}, - "output_type": "execute_result" - } - ], + "outputs": [], "source": [ "from obsidian.experiment import Simulator\n", "from obsidian.experiment.benchmark import shifted_parab\n", @@ -338,20 +80,9 @@ }, { "cell_type": "code", - "execution_count": 5, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "data": { - "image/png": "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", - "text/plain": [ - "
" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], + "outputs": [], "source": [ "from obsidian.plotting import visualize_inputs\n", "\n", @@ -367,808 +98,18 @@ }, { "cell_type": "code", - "execution_count": 6, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "GP model has been fit to data with a train-score of: 1 for response: Yield\n" - ] - } - ], + "outputs": [], "source": [ "campaign.fit()" ] }, { "cell_type": "code", - "execution_count": 7, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "data": { - "text/html": [ - " \n", - " " - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "application/vnd.plotly.v1+json": { - "config": { - "plotlyServerURL": "https://plot.ly" - }, - "data": [ - { - "error_y": { - "array": [ - 0.018810962788350594, - 0.01881091456185402, - 0.01881095275962963, - 0.018810935337775447, - 0.01881094664046401, - 0.018810935584212984, - 0.01881096416672534, - 0.018810903284204983, - 0.018810922088640325, - 0.018810992548722538 - ], - "arrayminus": [ - 0.01881095972854041, - 0.018810911502050942, - 0.01881094969981234, - 0.018810932277965264, - 0.018810943580660933, - 0.0188109325244028, - 0.01881096110691516, - 0.01881090022440901, - 0.018810919028830142, - 0.018810989488898144 - ], - "color": "gray", - "thickness": 0.5 - }, - "marker": { - "color": [ - 6.296058387458202e-13, - 5.7407106676363984e-15, - 1.3157485598457538e-13, - 3.531533078572637e-14, - 1.1309012440804044e-13, - 6.467660058121535e-14, - 1.283618563323006e-13, - 2.8661340807074577e-13, - 4.787149064302353e-13, - 2.981768401867673e-14 - ], - "colorscale": [ - [ - 0, - "#440154" - ], - [ - 0.1111111111111111, - "#482878" - ], - [ - 0.2222222222222222, - "#3e4989" - ], - [ - 0.3333333333333333, - "#31688e" - ], - [ - 0.4444444444444444, - "#26828e" - ], - [ - 0.5555555555555556, - "#1f9e89" - ], - [ - 0.6666666666666666, - "#35b779" - ], - [ - 0.7777777777777778, - "#6ece58" - ], - [ - 0.8888888888888888, - "#b5de2b" - ], - [ - 1, - "#fde725" - ] - ], - "size": 15 - }, - "mode": "markers", - "name": "Observations", - "type": "scatter", - "x": [ - 92.33980672490216, - 44.28013139056551, - 46.27042165792395, - 60.288918896712964, - 63.08241717950659, - 86.19633278740932, - 47.62503445818602, - 48.96614297388498, - 49.87657408385417, - 81.22881027324594 - ], - "y": [ - 92.33973345538415, - 44.28013474555937, - 46.270438441709, - 60.28890756699405, - 63.082395965599275, - 86.19635470851127, - 47.62505152110378, - 48.966169188540064, - 49.87660859306999, - 81.22879624681924 - ] - }, - { - "line": { - "color": "black", - "dash": "dot" - }, - "mode": "lines", - "name": "Parity", - "showlegend": false, - "type": "scatter", - "x": [ - 40.25466490051409, - 101.57378739739238 - ], - "y": [ - 40.25466490051409, - 101.57378739739238 - ] - } - ], - "layout": { - "autosize": false, - "height": 400, - "template": { - "data": { - "bar": [ - { - "error_x": { - "color": "rgb(51,51,51)" - }, - "error_y": { - "color": "rgb(51,51,51)" - }, - "marker": { - "line": { - "color": "rgb(237,237,237)", - "width": 0.5 - }, - "pattern": { - "fillmode": "overlay", - "size": 10, - "solidity": 0.2 - } - }, - "type": "bar" - } - ], - "barpolar": [ - { - "marker": { - "line": { - "color": "rgb(237,237,237)", - "width": 0.5 - }, - "pattern": { - "fillmode": "overlay", - "size": 10, - "solidity": 0.2 - } - }, - "type": "barpolar" - } - ], - "carpet": [ - { - "aaxis": { - "endlinecolor": "rgb(51,51,51)", - "gridcolor": "white", - "linecolor": "white", - "minorgridcolor": "white", - "startlinecolor": "rgb(51,51,51)" - }, - "baxis": { - "endlinecolor": "rgb(51,51,51)", - "gridcolor": "white", - "linecolor": "white", - "minorgridcolor": "white", - "startlinecolor": "rgb(51,51,51)" - }, - "type": "carpet" - } - ], - "choropleth": [ - { - "colorbar": { - "outlinewidth": 0, - "tickcolor": "rgb(237,237,237)", - "ticklen": 6, - "ticks": "inside" - }, - "type": "choropleth" - } - ], - "contour": [ - { - "colorbar": { - "outlinewidth": 0, - "tickcolor": "rgb(237,237,237)", - "ticklen": 6, - "ticks": "inside" - }, - "colorscale": [ - [ - 0, - "rgb(20,44,66)" - ], - [ - 1, - "rgb(90,179,244)" - ] - ], - "type": "contour" - } - ], - "contourcarpet": [ - { - "colorbar": { - "outlinewidth": 0, - "tickcolor": "rgb(237,237,237)", - "ticklen": 6, - "ticks": "inside" - }, - "type": "contourcarpet" - } - ], - "heatmap": [ - { - "colorbar": { - "outlinewidth": 0, - "tickcolor": "rgb(237,237,237)", - "ticklen": 6, - "ticks": "inside" - }, - "colorscale": [ - [ - 0, - "rgb(20,44,66)" - ], - [ - 1, - "rgb(90,179,244)" - ] - ], - "type": "heatmap" - } - ], - "heatmapgl": [ - { - "colorbar": { - "outlinewidth": 0, - "tickcolor": "rgb(237,237,237)", - "ticklen": 6, - "ticks": "inside" - }, - "colorscale": [ - [ - 0, - "rgb(20,44,66)" - ], - [ - 1, - "rgb(90,179,244)" - ] - ], - "type": "heatmapgl" - } - ], - "histogram": [ - { - "marker": { - "pattern": { - "fillmode": "overlay", - "size": 10, - "solidity": 0.2 - } - }, - "type": "histogram" - } - ], - "histogram2d": [ - { - "colorbar": { - "outlinewidth": 0, - "tickcolor": "rgb(237,237,237)", - "ticklen": 6, - "ticks": "inside" - }, - "colorscale": [ - [ - 0, - "rgb(20,44,66)" - ], - [ - 1, - "rgb(90,179,244)" - ] - ], - "type": "histogram2d" - } - ], - "histogram2dcontour": [ - { - "colorbar": { - "outlinewidth": 0, - "tickcolor": "rgb(237,237,237)", - "ticklen": 6, - "ticks": "inside" - }, - "colorscale": [ - [ - 0, - "rgb(20,44,66)" - ], - [ - 1, - "rgb(90,179,244)" - ] - ], - "type": "histogram2dcontour" - } - ], - "mesh3d": [ - { - "colorbar": { - "outlinewidth": 0, - "tickcolor": "rgb(237,237,237)", - "ticklen": 6, - "ticks": "inside" - }, - "type": "mesh3d" - } - ], - "parcoords": [ - { - "line": { - "colorbar": { - "outlinewidth": 0, - "tickcolor": "rgb(237,237,237)", - "ticklen": 6, - "ticks": "inside" - } - }, - "type": "parcoords" - } - ], - "pie": [ - { - "automargin": true, - "type": "pie" - } - ], - "scatter": [ - { - "fillpattern": { - "fillmode": "overlay", - "size": 10, - "solidity": 0.2 - }, - "type": "scatter" - } - ], - "scatter3d": [ - { - "line": { - "colorbar": { - "outlinewidth": 0, - "tickcolor": "rgb(237,237,237)", - "ticklen": 6, - "ticks": "inside" - } - }, - "marker": { - "colorbar": { - "outlinewidth": 0, - "tickcolor": "rgb(237,237,237)", - "ticklen": 6, - "ticks": "inside" - } - }, - "type": "scatter3d" - } - ], - "scattercarpet": [ - { - "marker": { - "colorbar": { - "outlinewidth": 0, - "tickcolor": "rgb(237,237,237)", - "ticklen": 6, - "ticks": "inside" - } - }, - "type": "scattercarpet" - } - ], - "scattergeo": [ - { - "marker": { - "colorbar": { - "outlinewidth": 0, - "tickcolor": "rgb(237,237,237)", - "ticklen": 6, - "ticks": "inside" - } - }, - "type": "scattergeo" - } - ], - "scattergl": [ - { - "marker": { - "colorbar": { - "outlinewidth": 0, - "tickcolor": "rgb(237,237,237)", - "ticklen": 6, - "ticks": "inside" - } - }, - "type": "scattergl" - } - ], - "scattermapbox": [ - { - "marker": { - "colorbar": { - "outlinewidth": 0, - "tickcolor": "rgb(237,237,237)", - "ticklen": 6, - "ticks": "inside" - } - }, - "type": "scattermapbox" - } - ], - "scatterpolar": [ - { - "marker": { - "colorbar": { - "outlinewidth": 0, - "tickcolor": "rgb(237,237,237)", - "ticklen": 6, - "ticks": "inside" - } - }, - "type": "scatterpolar" - } - ], - "scatterpolargl": [ - { - "marker": { - "colorbar": { - "outlinewidth": 0, - "tickcolor": "rgb(237,237,237)", - "ticklen": 6, - "ticks": "inside" - } - }, - "type": "scatterpolargl" - } - ], - "scatterternary": [ - { - "marker": { - "colorbar": { - "outlinewidth": 0, - "tickcolor": "rgb(237,237,237)", - "ticklen": 6, - "ticks": "inside" - } - }, - "type": "scatterternary" - } - ], - "surface": [ - { - "colorbar": { - "outlinewidth": 0, - "tickcolor": "rgb(237,237,237)", - "ticklen": 6, - "ticks": "inside" - }, - "colorscale": [ - [ - 0, - "rgb(20,44,66)" - ], - [ - 1, - "rgb(90,179,244)" - ] - ], - "type": "surface" - } - ], - "table": [ - { - "cells": { - "fill": { - "color": "rgb(237,237,237)" - }, - "line": { - "color": "white" - } - }, - "header": { - "fill": { - "color": "rgb(217,217,217)" - }, - "line": { - "color": "white" - } - }, - "type": "table" - } - ] - }, - "layout": { - "annotationdefaults": { - "arrowhead": 0, - "arrowwidth": 1 - }, - "autotypenumbers": "strict", - "coloraxis": { - "colorbar": { - "outlinewidth": 0, - "tickcolor": "rgb(237,237,237)", - "ticklen": 6, - "ticks": "inside" - } - }, - "colorscale": { - "sequential": [ - [ - 0, - "rgb(20,44,66)" - ], - [ - 1, - "rgb(90,179,244)" - ] - ], - "sequentialminus": [ - [ - 0, - "rgb(20,44,66)" - ], - [ - 1, - "rgb(90,179,244)" - ] - ] - }, - "colorway": [ - "#F8766D", - "#A3A500", - "#00BF7D", - "#00B0F6", - "#E76BF3" - ], - "font": { - "color": "rgb(51,51,51)" - }, - "geo": { - "bgcolor": "white", - "lakecolor": "white", - "landcolor": "rgb(237,237,237)", - "showlakes": true, - "showland": true, - "subunitcolor": "white" - }, - "hoverlabel": { - "align": "left" - }, - "hovermode": "closest", - "paper_bgcolor": "white", - "plot_bgcolor": "rgb(237,237,237)", - "polar": { - "angularaxis": { - "gridcolor": "white", - "linecolor": "white", - "showgrid": true, - "tickcolor": "rgb(51,51,51)", - "ticks": "outside" - }, - "bgcolor": "rgb(237,237,237)", - "radialaxis": { - "gridcolor": "white", - "linecolor": "white", - "showgrid": true, - "tickcolor": "rgb(51,51,51)", - "ticks": "outside" - } - }, - "scene": { - "xaxis": { - "backgroundcolor": "rgb(237,237,237)", - "gridcolor": "white", - "gridwidth": 2, - "linecolor": "white", - "showbackground": true, - "showgrid": true, - "tickcolor": "rgb(51,51,51)", - "ticks": "outside", - "zerolinecolor": "white" - }, - "yaxis": { - "backgroundcolor": "rgb(237,237,237)", - "gridcolor": "white", - "gridwidth": 2, - "linecolor": "white", - "showbackground": true, - "showgrid": true, - "tickcolor": "rgb(51,51,51)", - "ticks": "outside", - "zerolinecolor": "white" - }, - "zaxis": { - "backgroundcolor": "rgb(237,237,237)", - "gridcolor": "white", - "gridwidth": 2, - "linecolor": "white", - "showbackground": true, - "showgrid": true, - "tickcolor": "rgb(51,51,51)", - "ticks": "outside", - "zerolinecolor": "white" - } - }, - "shapedefaults": { - "fillcolor": "black", - "line": { - "width": 0 - }, - "opacity": 0.3 - }, - "ternary": { - "aaxis": { - "gridcolor": "white", - "linecolor": "white", - "showgrid": true, - "tickcolor": "rgb(51,51,51)", - "ticks": "outside" - }, - "baxis": { - "gridcolor": "white", - "linecolor": "white", - "showgrid": true, - "tickcolor": "rgb(51,51,51)", - "ticks": "outside" - }, - "bgcolor": "rgb(237,237,237)", - "caxis": { - "gridcolor": "white", - "linecolor": "white", - "showgrid": true, - "tickcolor": "rgb(51,51,51)", - "ticks": "outside" - } - }, - "xaxis": { - "automargin": true, - "gridcolor": "white", - "linecolor": "white", - "showgrid": true, - "tickcolor": "rgb(51,51,51)", - "ticks": "outside", - "title": { - "standoff": 15 - }, - "zerolinecolor": "white" - }, - "yaxis": { - "automargin": true, - "gridcolor": "white", - "linecolor": "white", - "showgrid": true, - "tickcolor": "rgb(51,51,51)", - "ticks": "outside", - "title": { - "standoff": 15 - }, - "zerolinecolor": "white" - } - } - }, - "title": { - "text": "Parity Plot" - }, - "width": 600, - "xaxis": { - "title": { - "text": "Actual Response (Yield)" - } - }, - "yaxis": { - "title": { - "text": "Predicted Response (Yield)" - } - } - } - }, - "text/html": [ - "
" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], + "outputs": [], "source": [ "from obsidian.plotting import parity_plot, factor_plot\n", "\n", @@ -1177,1256 +118,9 @@ }, { "cell_type": "code", - "execution_count": 8, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "data": { - "application/vnd.plotly.v1+json": { - "config": { - "plotlyServerURL": "https://plot.ly" - }, - "data": [ - { - "fill": "toself", - "line": { - "color": "#00857C" - }, - "name": "95% Pred Band", - "opacity": 0.3, - "showlegend": true, - "type": "scatter", - "x": [ - -10, - -9.595959595959597, - -9.191919191919192, - -8.787878787878789, - -8.383838383838386, - -7.979797979797982, - -7.575757575757578, - -7.171717171717175, - -6.767676767676771, - -6.363636363636367, - -5.959595959595964, - -5.55555555555556, - -5.151515151515156, - -4.747474747474753, - -4.34343434343435, - -3.9393939393939448, - -3.5353535353535417, - -3.1313131313131386, - -2.7272727272727337, - -2.3232323232323306, - -1.9191919191919276, - -1.5151515151515227, - -1.1111111111111196, - -0.7070707070707165, - -0.30303030303031164, - 0.10101010101008967, - 0.5050505050504945, - 0.9090909090908994, - 1.3131313131313007, - 1.7171717171717056, - 2.1212121212121104, - 2.5252525252525118, - 2.9292929292929166, - 3.3333333333333215, - 3.737373737373723, - 4.141414141414128, - 4.5454545454545325, - 4.949494949494934, - 5.353535353535339, - 5.757575757575744, - 6.161616161616145, - 6.56565656565655, - 6.969696969696955, - 7.373737373737356, - 7.777777777777761, - 8.181818181818166, - 8.585858585858567, - 8.989898989898972, - 9.393939393939377, - 9.797979797979778, - 10.20202020202018, - 10.606060606060588, - 11.010101010100989, - 11.41414141414139, - 11.818181818181799, - 12.2222222222222, - 12.626262626262601, - 13.03030303030301, - 13.434343434343411, - 13.838383838383812, - 14.242424242424221, - 14.646464646464622, - 15.050505050505024, - 15.454545454545432, - 15.858585858585833, - 16.262626262626235, - 16.666666666666643, - 17.070707070707044, - 17.474747474747446, - 17.878787878787854, - 18.282828282828255, - 18.686868686868657, - 19.090909090909065, - 19.494949494949466, - 19.898989898989868, - 20.303030303030276, - 20.707070707070677, - 21.11111111111108, - 21.515151515151487, - 21.91919191919189, - 22.32323232323229, - 22.727272727272698, - 23.1313131313131, - 23.5353535353535, - 23.93939393939391, - 24.34343434343431, - 24.747474747474712, - 25.15151515151512, - 25.55555555555552, - 25.959595959595923, - 26.36363636363633, - 26.767676767676733, - 27.171717171717134, - 27.575757575757542, - 27.979797979797944, - 28.383838383838345, - 28.787878787878753, - 29.191919191919155, - 29.595959595959556, - 29.999999999999957, - 29.999999999999957, - 29.595959595959556, - 29.191919191919155, - 28.787878787878753, - 28.383838383838345, - 27.979797979797944, - 27.575757575757542, - 27.171717171717134, - 26.767676767676733, - 26.36363636363633, - 25.959595959595923, - 25.55555555555552, - 25.15151515151512, - 24.747474747474712, - 24.34343434343431, - 23.93939393939391, - 23.5353535353535, - 23.1313131313131, - 22.727272727272698, - 22.32323232323229, - 21.91919191919189, - 21.515151515151487, - 21.11111111111108, - 20.707070707070677, - 20.303030303030276, - 19.898989898989868, - 19.494949494949466, - 19.090909090909065, - 18.686868686868657, - 18.282828282828255, - 17.878787878787854, - 17.474747474747446, - 17.070707070707044, - 16.666666666666643, - 16.262626262626235, - 15.858585858585833, - 15.454545454545432, - 15.050505050505024, - 14.646464646464622, - 14.242424242424221, - 13.838383838383812, - 13.434343434343411, - 13.03030303030301, - 12.626262626262601, - 12.2222222222222, - 11.818181818181799, - 11.41414141414139, - 11.010101010100989, - 10.606060606060588, - 10.20202020202018, - 9.797979797979778, - 9.393939393939377, - 8.989898989898972, - 8.585858585858567, - 8.181818181818166, - 7.777777777777761, - 7.373737373737356, - 6.969696969696955, - 6.56565656565655, - 6.161616161616145, - 5.757575757575744, - 5.353535353535339, - 4.949494949494934, - 4.5454545454545325, - 4.141414141414128, - 3.737373737373723, - 3.3333333333333215, - 2.9292929292929166, - 2.5252525252525118, - 2.1212121212121104, - 1.7171717171717056, - 1.3131313131313007, - 0.9090909090908994, - 0.5050505050504945, - 0.10101010101008967, - -0.30303030303031164, - -0.7070707070707165, - -1.1111111111111196, - -1.5151515151515227, - -1.9191919191919276, - -2.3232323232323306, - -2.7272727272727337, - -3.1313131313131386, - -3.5353535353535417, - -3.9393939393939448, - -4.34343434343435, - -4.747474747474753, - -5.151515151515156, - -5.55555555555556, - -5.959595959595964, - -6.363636363636367, - -6.767676767676771, - -7.171717171717175, - -7.575757575757578, - -7.979797979797982, - -8.383838383838386, - -8.787878787878789, - -9.191919191919192, - -9.595959595959597, - -10 - ], - "y": [ - 97.99033166985825, - 97.60527273527329, - 97.22590899996217, - 96.85252088627426, - 96.48536317696069, - 96.12465889729555, - 95.77059302467268, - 95.42330623713447, - 95.08288894321856, - 94.74937585808158, - 94.42274140447233, - 94.10289621843111, - 93.78968502248713, - 93.48288608733418, - 93.182212433715, - 92.88731483232006, - 92.5977865494512, - 92.31316967263845, - 92.03296274735447, - 91.75662937616224, - 91.48360738399349, - 91.21331814158837, - 90.94517566188213, - 90.67859513520942, - 90.41300063972427, - 90.14783184344653, - 89.8825495946724, - 89.61664037076866, - 89.34961961672147, - 89.08103405179305, - 88.81046305492193, - 88.5375192582143, - 88.26184848515032, - 87.98312916840035, - 87.70107137393781, - 87.41541554567704, - 87.12593107003427, - 86.83241474410185, - 86.53468921563406, - 86.23260144850993, - 85.92602125427969, - 85.61483991906327, - 85.2989689455365, - 84.97833892202726, - 84.65289852468771, - 84.32261365418715, - 83.98746670516817, - 83.64745596464387, - 83.30259513439604, - 82.95291297208384, - 82.5984530460644, - 82.23927359971857, - 81.8754475222744, - 81.50706242464608, - 81.13422082058841, - 80.75704041544707, - 80.37565450690822, - 79.99021250436537, - 79.60088057576684, - 79.20784243300602, - 78.81130026900257, - 78.41147586147339, - 78.00861185990922, - 77.60297327330417, - 77.19484917654903, - 76.78455465291967, - 76.37243298847166, - 75.95885813109888, - 75.54423742209553, - 75.12901460074215, - 74.71367307202631, - 74.29873941326845, - 73.88478707611229, - 73.47244021490528, - 73.06237753976559, - 72.65533605148056, - 72.25211446521328, - 71.85357607092904, - 71.46065071217848, - 71.07433549518461, - 70.69569377401999, - 70.3258519057838, - 69.96599324709793, - 69.61734888866768, - 69.28118471856143, - 68.95878458547435, - 68.65142961040503, - 68.36037406291076, - 68.08681864779318, - 67.8318824854453, - 67.59657543875689, - 67.3817726591286, - 67.18819322775443, - 67.0163845335482, - 66.86671359610031, - 66.73936598938833, - 66.634352364072, - 66.55152174366822, - 66.49057995995146, - 66.45111120356633, - 52.66702819667758, - 53.08727517868487, - 53.49685994566989, - 53.895342663834995, - 54.28239745477552, - 54.65783372470225, - 55.021614335542196, - 55.37386855662996, - 55.7148981465827, - 56.04517576524461, - 56.36533575621257, - 56.67615798821764, - 56.978545981180176, - 57.27350096686345, - 57.56209376501758, - 57.845436350724995, - 58.12465476831817, - 58.40086467716356, - 58.67515037693409, - 58.94854773008008, - 59.22203103127031, - 59.49650359626567, - 59.77279166198365, - 60.05164109556811, - 60.333716384885605, - 60.6196014055512, - 60.90980151161315, - 61.20474656336711, - 61.50479457564841, - 61.81023573639286, - 62.121296604403, - 62.43814434541261, - 62.760890906482835, - 63.08959706111415, - 63.42427628225521, - 63.76489841884802, - 64.11139316482898, - 64.46365331867811, - 64.8215378376273, - 65.18487469423137, - 65.55346354483217, - 65.9270782200038, - 66.30546904670443, - 66.68836501092451, - 67.07547576828728, - 67.46649350850672, - 67.86109467795595, - 68.25894156292522, - 68.65968373450968, - 69.06295935453059, - 69.46839634046624, - 69.87561338611467, - 70.28422083363908, - 70.69382139181934, - 71.10401069476237, - 71.51437769509513, - 71.92450488581835, - 72.33396834562562, - 72.74233760368914, - 73.14917532180486, - 73.55403679449198, - 73.95646927134183, - 74.3560111107434, - 74.75219078026996, - 75.1445257266141, - 75.53252114715758, - 75.91566870606539, - 76.29344525015831, - 76.66531159353318, - 77.03071145453706, - 77.38907064354765, - 77.73979661407756, - 78.08227850153202, - 78.41588778168062, - 78.73997968235416, - 79.05389547449555, - 79.35696575005713, - 79.6485147621572, - 79.92786585623314, - 80.19434795993308, - 80.44730302662208, - 80.68609424748011, - 80.91011476765254, - 81.11879657195713, - 81.31161915526503, - 81.48811757078764, - 81.64788946226128, - 81.79060073501073, - 81.91598960235567, - 82.02386884892496, - 82.11412626849514, - 82.18672334694244, - 82.24169235798048, - 82.27913211145747, - 82.2992026373816, - 82.3021191050683, - 82.2881452713049, - 82.25758673058377, - 82.21078420932112, - 82.14810710755556 - ] - }, - { - "line": { - "color": "#00857C" - }, - "mode": "lines", - "name": "Mean", - "type": "scatter", - "x": [ - -10, - -9.595959595959597, - -9.191919191919192, - -8.787878787878789, - -8.383838383838386, - -7.979797979797982, - -7.575757575757578, - -7.171717171717175, - -6.767676767676771, - -6.363636363636367, - -5.959595959595964, - -5.55555555555556, - -5.151515151515156, - -4.747474747474753, - -4.34343434343435, - -3.9393939393939448, - -3.5353535353535417, - -3.1313131313131386, - -2.7272727272727337, - -2.3232323232323306, - -1.9191919191919276, - -1.5151515151515227, - -1.1111111111111196, - -0.7070707070707165, - -0.30303030303031164, - 0.10101010101008967, - 0.5050505050504945, - 0.9090909090908994, - 1.3131313131313007, - 1.7171717171717056, - 2.1212121212121104, - 2.5252525252525118, - 2.9292929292929166, - 3.3333333333333215, - 3.737373737373723, - 4.141414141414128, - 4.5454545454545325, - 4.949494949494934, - 5.353535353535339, - 5.757575757575744, - 6.161616161616145, - 6.56565656565655, - 6.969696969696955, - 7.373737373737356, - 7.777777777777761, - 8.181818181818166, - 8.585858585858567, - 8.989898989898972, - 9.393939393939377, - 9.797979797979778, - 10.20202020202018, - 10.606060606060588, - 11.010101010100989, - 11.41414141414139, - 11.818181818181799, - 12.2222222222222, - 12.626262626262601, - 13.03030303030301, - 13.434343434343411, - 13.838383838383812, - 14.242424242424221, - 14.646464646464622, - 15.050505050505024, - 15.454545454545432, - 15.858585858585833, - 16.262626262626235, - 16.666666666666643, - 17.070707070707044, - 17.474747474747446, - 17.878787878787854, - 18.282828282828255, - 18.686868686868657, - 19.090909090909065, - 19.494949494949466, - 19.898989898989868, - 20.303030303030276, - 20.707070707070677, - 21.11111111111108, - 21.515151515151487, - 21.91919191919189, - 22.32323232323229, - 22.727272727272698, - 23.1313131313131, - 23.5353535353535, - 23.93939393939391, - 24.34343434343431, - 24.747474747474712, - 25.15151515151512, - 25.55555555555552, - 25.959595959595923, - 26.36363636363633, - 26.767676767676733, - 27.171717171717134, - 27.575757575757542, - 27.979797979797944, - 28.383838383838345, - 28.787878787878753, - 29.191919191919155, - 29.595959595959556, - 29.999999999999957 - ], - "y": [ - 90.06921836669864, - 89.90802747917313, - 89.74174689964158, - 89.57033213921747, - 89.3937402260298, - 89.21192987543537, - 89.02486169770847, - 88.83249844718962, - 88.6348053131274, - 88.43175024816736, - 88.22330432682674, - 88.00944212419574, - 87.79014210466802, - 87.56538701130239, - 87.3351642478458, - 87.09946624702515, - 86.85829082017541, - 86.61164148451545, - 86.35952776541193, - 86.10196547180868, - 85.83897694367437, - 85.57059127086745, - 85.29684448325327, - 85.01777971225611, - 84.73344732431514, - 84.4439050269608, - 84.14921794844307, - 83.84945869204945, - 83.5447073664305, - 83.23505159340233, - 82.9205864947981, - 82.60141465997786, - 82.27764609555271, - 81.9493981587409, - 81.61679547553427, - 81.27996984453004, - 80.93906012690154, - 80.59421212254905, - 80.24557843204605, - 79.89331830358563, - 79.53759746378668, - 79.17858793094965, - 78.81646780918729, - 78.45142106179824, - 78.08363726230358, - 77.71331132172068, - 77.34064319089858, - 76.96583753705694, - 76.58910339405841, - 76.21065378636642, - 75.83070532710028, - 75.44947779107218, - 75.06719366417634, - 74.68407767097692, - 74.30035628281972, - 73.91625720924667, - 73.53200887592654, - 73.14783989270933, - 72.76397851576556, - 72.38065210805239, - 71.99808660255357, - 71.61650597284083, - 71.23613171548584, - 70.85718234870228, - 70.47987293131004, - 70.10441460569363, - 69.73101416789504, - 69.35987366736802, - 68.9911900382582, - 68.62515476342304, - 68.26195357178736, - 67.90176616909974, - 67.54476600172919, - 67.19112005282248, - 66.8409886699542, - 66.49452542329489, - 66.15187699331784, - 65.81318308710483, - 65.47857638239503, - 65.14818249861558, - 64.82211999422208, - 64.50050038975279, - 64.18342821604504, - 63.8710010870801, - 63.56330979690406, - 63.26043844002647, - 62.96246455462513, - 62.6694592877848, - 62.3814875818847, - 62.09860838110292, - 61.82087485680072, - 61.54833465020615, - 61.281030130030445, - 61.01899866074261, - 60.76227287278611, - 60.51088091846215, - 60.264846692138775, - 60.02419000249109, - 59.78892670464867, - 59.559068810887815 - ] - } - ], - "layout": { - "autosize": false, - "height": 400, - "template": { - "data": { - "bar": [ - { - "error_x": { - "color": "rgb(51,51,51)" - }, - "error_y": { - "color": "rgb(51,51,51)" - }, - "marker": { - "line": { - "color": "rgb(237,237,237)", - "width": 0.5 - }, - "pattern": { - "fillmode": "overlay", - "size": 10, - "solidity": 0.2 - } - }, - "type": "bar" - } - ], - "barpolar": [ - { - "marker": { - "line": { - "color": "rgb(237,237,237)", - "width": 0.5 - }, - "pattern": { - "fillmode": "overlay", - "size": 10, - "solidity": 0.2 - } - }, - "type": "barpolar" - } - ], - "carpet": [ - { - "aaxis": { - "endlinecolor": "rgb(51,51,51)", - "gridcolor": "white", - "linecolor": "white", - "minorgridcolor": "white", - "startlinecolor": "rgb(51,51,51)" - }, - "baxis": { - "endlinecolor": "rgb(51,51,51)", - "gridcolor": "white", - "linecolor": "white", - "minorgridcolor": "white", - "startlinecolor": "rgb(51,51,51)" - }, - "type": "carpet" - } - ], - "choropleth": [ - { - "colorbar": { - "outlinewidth": 0, - "tickcolor": "rgb(237,237,237)", - "ticklen": 6, - "ticks": "inside" - }, - "type": "choropleth" - } - ], - "contour": [ - { - "colorbar": { - "outlinewidth": 0, - "tickcolor": "rgb(237,237,237)", - "ticklen": 6, - "ticks": "inside" - }, - "colorscale": [ - [ - 0, - "rgb(20,44,66)" - ], - [ - 1, - "rgb(90,179,244)" - ] - ], - "type": "contour" - } - ], - "contourcarpet": [ - { - "colorbar": { - "outlinewidth": 0, - "tickcolor": "rgb(237,237,237)", - "ticklen": 6, - "ticks": "inside" - }, - "type": "contourcarpet" - } - ], - "heatmap": [ - { - "colorbar": { - "outlinewidth": 0, - "tickcolor": "rgb(237,237,237)", - "ticklen": 6, - "ticks": "inside" - }, - "colorscale": [ - [ - 0, - "rgb(20,44,66)" - ], - [ - 1, - "rgb(90,179,244)" - ] - ], - "type": "heatmap" - } - ], - "heatmapgl": [ - { - "colorbar": { - "outlinewidth": 0, - "tickcolor": "rgb(237,237,237)", - "ticklen": 6, - "ticks": "inside" - }, - "colorscale": [ - [ - 0, - "rgb(20,44,66)" - ], - [ - 1, - "rgb(90,179,244)" - ] - ], - "type": "heatmapgl" - } - ], - "histogram": [ - { - "marker": { - "pattern": { - "fillmode": "overlay", - "size": 10, - "solidity": 0.2 - } - }, - "type": "histogram" - } - ], - "histogram2d": [ - { - "colorbar": { - "outlinewidth": 0, - "tickcolor": "rgb(237,237,237)", - "ticklen": 6, - "ticks": "inside" - }, - "colorscale": [ - [ - 0, - "rgb(20,44,66)" - ], - [ - 1, - "rgb(90,179,244)" - ] - ], - "type": "histogram2d" - } - ], - "histogram2dcontour": [ - { - "colorbar": { - "outlinewidth": 0, - "tickcolor": "rgb(237,237,237)", - "ticklen": 6, - "ticks": "inside" - }, - "colorscale": [ - [ - 0, - "rgb(20,44,66)" - ], - [ - 1, - "rgb(90,179,244)" - ] - ], - "type": "histogram2dcontour" - } - ], - "mesh3d": [ - { - "colorbar": { - "outlinewidth": 0, - "tickcolor": "rgb(237,237,237)", - "ticklen": 6, - "ticks": "inside" - }, - "type": "mesh3d" - } - ], - "parcoords": [ - { - "line": { - "colorbar": { - "outlinewidth": 0, - "tickcolor": "rgb(237,237,237)", - "ticklen": 6, - "ticks": "inside" - } - }, - "type": "parcoords" - } - ], - "pie": [ - { - "automargin": true, - "type": "pie" - } - ], - "scatter": [ - { - "fillpattern": { - "fillmode": "overlay", - "size": 10, - "solidity": 0.2 - }, - "type": "scatter" - } - ], - "scatter3d": [ - { - "line": { - "colorbar": { - "outlinewidth": 0, - "tickcolor": "rgb(237,237,237)", - "ticklen": 6, - "ticks": "inside" - } - }, - "marker": { - "colorbar": { - "outlinewidth": 0, - "tickcolor": "rgb(237,237,237)", - "ticklen": 6, - "ticks": "inside" - } - }, - "type": "scatter3d" - } - ], - "scattercarpet": [ - { - "marker": { - "colorbar": { - "outlinewidth": 0, - "tickcolor": "rgb(237,237,237)", - "ticklen": 6, - "ticks": "inside" - } - }, - "type": "scattercarpet" - } - ], - "scattergeo": [ - { - "marker": { - "colorbar": { - "outlinewidth": 0, - "tickcolor": "rgb(237,237,237)", - "ticklen": 6, - "ticks": "inside" - } - }, - "type": "scattergeo" - } - ], - "scattergl": [ - { - "marker": { - "colorbar": { - "outlinewidth": 0, - "tickcolor": "rgb(237,237,237)", - "ticklen": 6, - "ticks": "inside" - } - }, - "type": "scattergl" - } - ], - "scattermapbox": [ - { - "marker": { - "colorbar": { - "outlinewidth": 0, - "tickcolor": "rgb(237,237,237)", - "ticklen": 6, - "ticks": "inside" - } - }, - "type": "scattermapbox" - } - ], - "scatterpolar": [ - { - "marker": { - "colorbar": { - "outlinewidth": 0, - "tickcolor": "rgb(237,237,237)", - "ticklen": 6, - "ticks": "inside" - } - }, - "type": "scatterpolar" - } - ], - "scatterpolargl": [ - { - "marker": { - "colorbar": { - "outlinewidth": 0, - "tickcolor": "rgb(237,237,237)", - "ticklen": 6, - "ticks": "inside" - } - }, - "type": "scatterpolargl" - } - ], - "scatterternary": [ - { - "marker": { - "colorbar": { - "outlinewidth": 0, - "tickcolor": "rgb(237,237,237)", - "ticklen": 6, - "ticks": "inside" - } - }, - "type": "scatterternary" - } - ], - "surface": [ - { - "colorbar": { - "outlinewidth": 0, - "tickcolor": "rgb(237,237,237)", - "ticklen": 6, - "ticks": "inside" - }, - "colorscale": [ - [ - 0, - "rgb(20,44,66)" - ], - [ - 1, - "rgb(90,179,244)" - ] - ], - "type": "surface" - } - ], - "table": [ - { - "cells": { - "fill": { - "color": "rgb(237,237,237)" - }, - "line": { - "color": "white" - } - }, - "header": { - "fill": { - "color": "rgb(217,217,217)" - }, - "line": { - "color": "white" - } - }, - "type": "table" - } - ] - }, - "layout": { - "annotationdefaults": { - "arrowhead": 0, - "arrowwidth": 1 - }, - "autotypenumbers": "strict", - "coloraxis": { - "colorbar": { - "outlinewidth": 0, - "tickcolor": "rgb(237,237,237)", - "ticklen": 6, - "ticks": "inside" - } - }, - "colorscale": { - "sequential": [ - [ - 0, - "rgb(20,44,66)" - ], - [ - 1, - "rgb(90,179,244)" - ] - ], - "sequentialminus": [ - [ - 0, - "rgb(20,44,66)" - ], - [ - 1, - "rgb(90,179,244)" - ] - ] - }, - "colorway": [ - "#F8766D", - "#A3A500", - "#00BF7D", - "#00B0F6", - "#E76BF3" - ], - "font": { - "color": "rgb(51,51,51)" - }, - "geo": { - "bgcolor": "white", - "lakecolor": "white", - "landcolor": "rgb(237,237,237)", - "showlakes": true, - "showland": true, - "subunitcolor": "white" - }, - "hoverlabel": { - "align": "left" - }, - "hovermode": "closest", - "paper_bgcolor": "white", - "plot_bgcolor": "rgb(237,237,237)", - "polar": { - "angularaxis": { - "gridcolor": "white", - "linecolor": "white", - "showgrid": true, - "tickcolor": "rgb(51,51,51)", - "ticks": "outside" - }, - "bgcolor": "rgb(237,237,237)", - "radialaxis": { - "gridcolor": "white", - "linecolor": "white", - "showgrid": true, - "tickcolor": "rgb(51,51,51)", - "ticks": "outside" - } - }, - "scene": { - "xaxis": { - "backgroundcolor": "rgb(237,237,237)", - "gridcolor": "white", - "gridwidth": 2, - "linecolor": "white", - "showbackground": true, - "showgrid": true, - "tickcolor": "rgb(51,51,51)", - "ticks": "outside", - "zerolinecolor": "white" - }, - "yaxis": { - "backgroundcolor": "rgb(237,237,237)", - "gridcolor": "white", - "gridwidth": 2, - "linecolor": "white", - "showbackground": true, - "showgrid": true, - "tickcolor": "rgb(51,51,51)", - "ticks": "outside", - "zerolinecolor": "white" - }, - "zaxis": { - "backgroundcolor": "rgb(237,237,237)", - "gridcolor": "white", - "gridwidth": 2, - "linecolor": "white", - "showbackground": true, - "showgrid": true, - "tickcolor": "rgb(51,51,51)", - "ticks": "outside", - "zerolinecolor": "white" - } - }, - "shapedefaults": { - "fillcolor": "black", - "line": { - "width": 0 - }, - "opacity": 0.3 - }, - "ternary": { - "aaxis": { - "gridcolor": "white", - "linecolor": "white", - "showgrid": true, - "tickcolor": "rgb(51,51,51)", - "ticks": "outside" - }, - "baxis": { - "gridcolor": "white", - "linecolor": "white", - "showgrid": true, - "tickcolor": "rgb(51,51,51)", - "ticks": "outside" - }, - "bgcolor": "rgb(237,237,237)", - "caxis": { - "gridcolor": "white", - "linecolor": "white", - "showgrid": true, - "tickcolor": "rgb(51,51,51)", - "ticks": "outside" - } - }, - "xaxis": { - "automargin": true, - "gridcolor": "white", - "linecolor": "white", - "showgrid": true, - "tickcolor": "rgb(51,51,51)", - "ticks": "outside", - "title": { - "standoff": 15 - }, - "zerolinecolor": "white" - }, - "yaxis": { - "automargin": true, - "gridcolor": "white", - "linecolor": "white", - "showgrid": true, - "tickcolor": "rgb(51,51,51)", - "ticks": "outside", - "title": { - "standoff": 15 - }, - "zerolinecolor": "white" - } - } - }, - "title": { - "text": "Factor Effect Plot for Temperature" - }, - "width": 600, - "xaxis": { - "title": { - "text": "Temperature" - } - }, - "yaxis": { - "title": { - "text": "Yield" - } - } - } - }, - "text/html": [ - "
" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], + "outputs": [], "source": [ "factor_plot(campaign.optimizer, feature_id=0)" ] @@ -2440,7 +134,7 @@ }, { "cell_type": "code", - "execution_count": 9, + "execution_count": null, "metadata": {}, "outputs": [], "source": [ @@ -2449,111 +143,9 @@ }, { "cell_type": "code", - "execution_count": 10, + "execution_count": null, "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", - "
TemperatureConcentrationEnzymeVariantStir RateYield (pred)Yield lbYield ubf(Yield)aq Valueaq Value (joint)aq Method
0-10.00000010.00.131014MRK001Low104.65557597.694464111.6166872.349349-0.380345-0.292665NEI
1-10.00000010.00.135985MRK001High101.87053394.441592109.2994742.195901-0.612096-0.292665NEI
2-1.22787910.00.114474MRK002Low101.24326697.004850105.4816842.161341-0.709565-0.292665NEI
\n", - "
" - ], - "text/plain": [ - " Temperature Concentration Enzyme Variant Stir Rate Yield (pred) \\\n", - "0 -10.000000 10.0 0.131014 MRK001 Low 104.655575 \n", - "1 -10.000000 10.0 0.135985 MRK001 High 101.870533 \n", - "2 -1.227879 10.0 0.114474 MRK002 Low 101.243266 \n", - "\n", - " Yield lb Yield ub f(Yield) aq Value aq Value (joint) aq Method \n", - "0 97.694464 111.616687 2.349349 -0.380345 -0.292665 NEI \n", - "1 94.441592 109.299474 2.195901 -0.612096 -0.292665 NEI \n", - "2 97.004850 105.481684 2.161341 -0.709565 -0.292665 NEI " - ] - }, - "execution_count": 10, - "metadata": {}, - "output_type": "execute_result" - } - ], + "outputs": [], "source": [ "df_suggest = pd.concat([X_suggest, eval_suggest], axis=1)\n", "df_suggest" @@ -2568,184 +160,9 @@ }, { "cell_type": "code", - "execution_count": 11, + "execution_count": null, "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", - "
TemperatureConcentrationEnzymeVariantStir RateYieldIterationYield (pred)Yield lbYield ubf(Yield)aq Valueaq Value (joint)aq Method
Observation ID
816.00000059.00.198500MRK003High49.8765740NaNNaNNaNNaNNaNNaNNaN
90.00000045.00.024500MRK003Low81.2288100NaNNaNNaNNaNNaNNaNNaN
10-10.00000010.00.131014MRK001Low92.1968491104.65557597.694464111.6166872.349349-0.380345-0.292665NEI
11-10.00000010.00.135985MRK001High74.4994681101.87053394.441592109.2994742.195901-0.612096-0.292665NEI
12-1.22787910.00.114474MRK002Low95.0004671101.24326697.004850105.4816842.161341-0.709565-0.292665NEI
\n", - "
" - ], - "text/plain": [ - " Temperature Concentration Enzyme Variant Stir Rate \\\n", - "Observation ID \n", - "8 16.000000 59.0 0.198500 MRK003 High \n", - "9 0.000000 45.0 0.024500 MRK003 Low \n", - "10 -10.000000 10.0 0.131014 MRK001 Low \n", - "11 -10.000000 10.0 0.135985 MRK001 High \n", - "12 -1.227879 10.0 0.114474 MRK002 Low \n", - "\n", - " Yield Iteration Yield (pred) Yield lb Yield ub \\\n", - "Observation ID \n", - "8 49.876574 0 NaN NaN NaN \n", - "9 81.228810 0 NaN NaN NaN \n", - "10 92.196849 1 104.655575 97.694464 111.616687 \n", - "11 74.499468 1 101.870533 94.441592 109.299474 \n", - "12 95.000467 1 101.243266 97.004850 105.481684 \n", - "\n", - " f(Yield) aq Value aq Value (joint) aq Method \n", - "Observation ID \n", - "8 NaN NaN NaN NaN \n", - "9 NaN NaN NaN NaN \n", - "10 2.349349 -0.380345 -0.292665 NEI \n", - "11 2.195901 -0.612096 -0.292665 NEI \n", - "12 2.161341 -0.709565 -0.292665 NEI " - ] - }, - "execution_count": 11, - "metadata": {}, - "output_type": "execute_result" - } - ], + "outputs": [], "source": [ "y_iter1 = pd.DataFrame(simulator.simulate(X_suggest), columns = ['Yield'])\n", "Z_iter1 = pd.concat([X_suggest, y_iter1, eval_suggest], axis=1)\n", @@ -2762,19 +179,9 @@ }, { "cell_type": "code", - "execution_count": 12, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "GP model has been fit to data with a train-score of: 1 for response: Yield\n", - "GP model has been fit to data with a train-score of: 1 for response: Yield\n", - "GP model has been fit to data with a train-score of: 1 for response: Yield\n" - ] - } - ], + "outputs": [], "source": [ "for iter in range(3):\n", " campaign.fit()\n", @@ -2786,782 +193,20 @@ }, { "cell_type": "code", - "execution_count": 13, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "data": { - "application/vnd.plotly.v1+json": { - "config": { - "plotlyServerURL": "https://plot.ly" - }, - "data": [ - { - "hovertemplate": "Observation ID=%{x}
Yield=%{y}
aq Value=%{marker.color}", - "legendgroup": "", - "marker": { - "color": [ - null, - null, - null, - null, - null, - null, - null, - null, - null, - null, - -0.38034538065202295, - -0.6120958124027052, - -0.7095649136708557, - -2.05692078994696, - -3.1516288285054745, - -2.473037637673595, - -2.798014989204011, - -3.57020802379168, - -3.088292727987067, - -2.245755141023286, - -3.426519149943271, - -2.4302932293385533 - ], - "coloraxis": "coloraxis", - "symbol": "circle" - }, - "mode": "markers", - "name": "", - "orientation": "v", - "showlegend": false, - "type": "scatter", - "x": [ - 0, - 1, - 2, - 3, - 4, - 5, - 6, - 7, - 8, - 9, - 10, - 11, - 12, - 13, - 14, - 15, - 16, - 17, - 18, - 19, - 20, - 21 - ], - "xaxis": "x", - "y": [ - 92.33980672490216, - 44.28013139056551, - 46.27042165792395, - 60.288918896712964, - 63.08241717950659, - 86.19633278740932, - 47.62503445818602, - 48.96614297388498, - 49.87657408385417, - 81.22881027324594, - 92.19684872892208, - 74.49946768778311, - 95.0004674747163, - 99.35898338419939, - 91.60949770163496, - 91.31362421740042, - 99.99794882558741, - 92.89284062164445, - 92.23896061375875, - 100.95704001123406, - 92.7739266193329, - 99.65361433177773 - ], - "yaxis": "y" - } - ], - "layout": { - "coloraxis": { - "colorbar": { - "title": { - "text": "aq Value" - } - }, - "colorscale": [ - [ - 0, - "#0d0887" - ], - [ - 0.1111111111111111, - "#46039f" - ], - [ - 0.2222222222222222, - "#7201a8" - ], - [ - 0.3333333333333333, - "#9c179e" - ], - [ - 0.4444444444444444, - "#bd3786" - ], - [ - 0.5555555555555556, - "#d8576b" - ], - [ - 0.6666666666666666, - "#ed7953" - ], - [ - 0.7777777777777778, - "#fb9f3a" - ], - [ - 0.8888888888888888, - "#fdca26" - ], - [ - 1, - "#f0f921" - ] - ] - }, - "height": 300, - "legend": { - "tracegroupgap": 0 - }, - "margin": { - "t": 60 - }, - "template": { - "data": { - "bar": [ - { - "error_x": { - "color": "rgb(51,51,51)" - }, - "error_y": { - "color": "rgb(51,51,51)" - }, - "marker": { - "line": { - "color": "rgb(237,237,237)", - "width": 0.5 - }, - "pattern": { - "fillmode": "overlay", - "size": 10, - "solidity": 0.2 - } - }, - "type": "bar" - } - ], - "barpolar": [ - { - "marker": { - "line": { - "color": "rgb(237,237,237)", - "width": 0.5 - }, - "pattern": { - "fillmode": "overlay", - "size": 10, - "solidity": 0.2 - } - }, - "type": "barpolar" - } - ], - "carpet": [ - { - "aaxis": { - "endlinecolor": "rgb(51,51,51)", - "gridcolor": "white", - "linecolor": "white", - "minorgridcolor": "white", - "startlinecolor": "rgb(51,51,51)" - }, - "baxis": { - "endlinecolor": "rgb(51,51,51)", - "gridcolor": "white", - "linecolor": "white", - "minorgridcolor": "white", - "startlinecolor": "rgb(51,51,51)" - }, - "type": "carpet" - } - ], - "choropleth": [ - { - "colorbar": { - "outlinewidth": 0, - "tickcolor": "rgb(237,237,237)", - "ticklen": 6, - "ticks": "inside" - }, - "type": "choropleth" - } - ], - "contour": [ - { - "colorbar": { - "outlinewidth": 0, - "tickcolor": "rgb(237,237,237)", - "ticklen": 6, - "ticks": "inside" - }, - "colorscale": [ - [ - 0, - "rgb(20,44,66)" - ], - [ - 1, - "rgb(90,179,244)" - ] - ], - "type": "contour" - } - ], - "contourcarpet": [ - { - "colorbar": { - "outlinewidth": 0, - "tickcolor": "rgb(237,237,237)", - "ticklen": 6, - "ticks": "inside" - }, - "type": "contourcarpet" - } - ], - "heatmap": [ - { - "colorbar": { - "outlinewidth": 0, - "tickcolor": "rgb(237,237,237)", - "ticklen": 6, - "ticks": "inside" - }, - "colorscale": [ - [ - 0, - "rgb(20,44,66)" - ], - [ - 1, - "rgb(90,179,244)" - ] - ], - "type": "heatmap" - } - ], - "heatmapgl": [ - { - "colorbar": { - "outlinewidth": 0, - "tickcolor": "rgb(237,237,237)", - "ticklen": 6, - "ticks": "inside" - }, - "colorscale": [ - [ - 0, - "rgb(20,44,66)" - ], - [ - 1, - "rgb(90,179,244)" - ] - ], - "type": "heatmapgl" - } - ], - "histogram": [ - { - "marker": { - "pattern": { - "fillmode": "overlay", - "size": 10, - "solidity": 0.2 - } - }, - "type": "histogram" - } - ], - "histogram2d": [ - { - "colorbar": { - "outlinewidth": 0, - "tickcolor": "rgb(237,237,237)", - "ticklen": 6, - "ticks": "inside" - }, - "colorscale": [ - [ - 0, - "rgb(20,44,66)" - ], - [ - 1, - "rgb(90,179,244)" - ] - ], - "type": "histogram2d" - } - ], - "histogram2dcontour": [ - { - "colorbar": { - "outlinewidth": 0, - "tickcolor": "rgb(237,237,237)", - "ticklen": 6, - "ticks": "inside" - }, - "colorscale": [ - [ - 0, - "rgb(20,44,66)" - ], - [ - 1, - "rgb(90,179,244)" - ] - ], - "type": "histogram2dcontour" - } - ], - "mesh3d": [ - { - "colorbar": { - "outlinewidth": 0, - "tickcolor": "rgb(237,237,237)", - "ticklen": 6, - "ticks": "inside" - }, - "type": "mesh3d" - } - ], - "parcoords": [ - { - "line": { - "colorbar": { - "outlinewidth": 0, - "tickcolor": "rgb(237,237,237)", - "ticklen": 6, - "ticks": "inside" - } - }, - "type": "parcoords" - } - ], - "pie": [ - { - "automargin": true, - "type": "pie" - } - ], - "scatter": [ - { - "fillpattern": { - "fillmode": "overlay", - "size": 10, - "solidity": 0.2 - }, - "type": "scatter" - } - ], - "scatter3d": [ - { - "line": { - "colorbar": { - "outlinewidth": 0, - "tickcolor": "rgb(237,237,237)", - "ticklen": 6, - "ticks": "inside" - } - }, - "marker": { - "colorbar": { - "outlinewidth": 0, - "tickcolor": "rgb(237,237,237)", - "ticklen": 6, - "ticks": "inside" - } - }, - "type": "scatter3d" - } - ], - "scattercarpet": [ - { - "marker": { - "colorbar": { - "outlinewidth": 0, - "tickcolor": "rgb(237,237,237)", - "ticklen": 6, - "ticks": "inside" - } - }, - "type": "scattercarpet" - } - ], - "scattergeo": [ - { - "marker": { - "colorbar": { - "outlinewidth": 0, - "tickcolor": "rgb(237,237,237)", - "ticklen": 6, - "ticks": "inside" - } - }, - "type": "scattergeo" - } - ], - "scattergl": [ - { - "marker": { - "colorbar": { - "outlinewidth": 0, - "tickcolor": "rgb(237,237,237)", - "ticklen": 6, - "ticks": "inside" - } - }, - "type": "scattergl" - } - ], - "scattermapbox": [ - { - "marker": { - "colorbar": { - "outlinewidth": 0, - "tickcolor": "rgb(237,237,237)", - "ticklen": 6, - "ticks": "inside" - } - }, - "type": "scattermapbox" - } - ], - "scatterpolar": [ - { - "marker": { - "colorbar": { - "outlinewidth": 0, - "tickcolor": "rgb(237,237,237)", - "ticklen": 6, - "ticks": "inside" - } - }, - "type": "scatterpolar" - } - ], - "scatterpolargl": [ - { - "marker": { - "colorbar": { - "outlinewidth": 0, - "tickcolor": "rgb(237,237,237)", - "ticklen": 6, - "ticks": "inside" - } - }, - "type": "scatterpolargl" - } - ], - "scatterternary": [ - { - "marker": { - "colorbar": { - "outlinewidth": 0, - "tickcolor": "rgb(237,237,237)", - "ticklen": 6, - "ticks": "inside" - } - }, - "type": "scatterternary" - } - ], - "surface": [ - { - "colorbar": { - "outlinewidth": 0, - "tickcolor": "rgb(237,237,237)", - "ticklen": 6, - "ticks": "inside" - }, - "colorscale": [ - [ - 0, - "rgb(20,44,66)" - ], - [ - 1, - "rgb(90,179,244)" - ] - ], - "type": "surface" - } - ], - "table": [ - { - "cells": { - "fill": { - "color": "rgb(237,237,237)" - }, - "line": { - "color": "white" - } - }, - "header": { - "fill": { - "color": "rgb(217,217,217)" - }, - "line": { - "color": "white" - } - }, - "type": "table" - } - ] - }, - "layout": { - "annotationdefaults": { - "arrowhead": 0, - "arrowwidth": 1 - }, - "autotypenumbers": "strict", - "coloraxis": { - "colorbar": { - "outlinewidth": 0, - "tickcolor": "rgb(237,237,237)", - "ticklen": 6, - "ticks": "inside" - } - }, - "colorscale": { - "sequential": [ - [ - 0, - "rgb(20,44,66)" - ], - [ - 1, - "rgb(90,179,244)" - ] - ], - "sequentialminus": [ - [ - 0, - "rgb(20,44,66)" - ], - [ - 1, - "rgb(90,179,244)" - ] - ] - }, - "colorway": [ - "#F8766D", - "#A3A500", - "#00BF7D", - "#00B0F6", - "#E76BF3" - ], - "font": { - "color": "rgb(51,51,51)" - }, - "geo": { - "bgcolor": "white", - "lakecolor": "white", - "landcolor": "rgb(237,237,237)", - "showlakes": true, - "showland": true, - "subunitcolor": "white" - }, - "hoverlabel": { - "align": "left" - }, - "hovermode": "closest", - "paper_bgcolor": "white", - "plot_bgcolor": "rgb(237,237,237)", - "polar": { - "angularaxis": { - "gridcolor": "white", - "linecolor": "white", - "showgrid": true, - "tickcolor": "rgb(51,51,51)", - "ticks": "outside" - }, - "bgcolor": "rgb(237,237,237)", - "radialaxis": { - "gridcolor": "white", - "linecolor": "white", - "showgrid": true, - "tickcolor": "rgb(51,51,51)", - "ticks": "outside" - } - }, - "scene": { - "xaxis": { - "backgroundcolor": "rgb(237,237,237)", - "gridcolor": "white", - "gridwidth": 2, - "linecolor": "white", - "showbackground": true, - "showgrid": true, - "tickcolor": "rgb(51,51,51)", - "ticks": "outside", - "zerolinecolor": "white" - }, - "yaxis": { - "backgroundcolor": "rgb(237,237,237)", - "gridcolor": "white", - "gridwidth": 2, - "linecolor": "white", - "showbackground": true, - "showgrid": true, - "tickcolor": "rgb(51,51,51)", - "ticks": "outside", - "zerolinecolor": "white" - }, - "zaxis": { - "backgroundcolor": "rgb(237,237,237)", - "gridcolor": "white", - "gridwidth": 2, - "linecolor": "white", - "showbackground": true, - "showgrid": true, - "tickcolor": "rgb(51,51,51)", - "ticks": "outside", - "zerolinecolor": "white" - } - }, - "shapedefaults": { - "fillcolor": "black", - "line": { - "width": 0 - }, - "opacity": 0.3 - }, - "ternary": { - "aaxis": { - "gridcolor": "white", - "linecolor": "white", - "showgrid": true, - "tickcolor": "rgb(51,51,51)", - "ticks": "outside" - }, - "baxis": { - "gridcolor": "white", - "linecolor": "white", - "showgrid": true, - "tickcolor": "rgb(51,51,51)", - "ticks": "outside" - }, - "bgcolor": "rgb(237,237,237)", - "caxis": { - "gridcolor": "white", - "linecolor": "white", - "showgrid": true, - "tickcolor": "rgb(51,51,51)", - "ticks": "outside" - } - }, - "xaxis": { - "automargin": true, - "gridcolor": "white", - "linecolor": "white", - "showgrid": true, - "tickcolor": "rgb(51,51,51)", - "ticks": "outside", - "title": { - "standoff": 15 - }, - "zerolinecolor": "white" - }, - "yaxis": { - "automargin": true, - "gridcolor": "white", - "linecolor": "white", - "showgrid": true, - "tickcolor": "rgb(51,51,51)", - "ticks": "outside", - "title": { - "standoff": 15 - }, - "zerolinecolor": "white" - } - } - }, - "width": 400, - "xaxis": { - "anchor": "y", - "domain": [ - 0, - 1 - ], - "title": { - "text": "Observation ID" - } - }, - "yaxis": { - "anchor": "x", - "domain": [ - 0, - 1 - ], - "title": { - "text": "Yield" - } - } - } - }, - "text/html": [ - "
" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], + "outputs": [], "source": [ "fig = px.scatter(campaign.data, x=campaign.data.index, y='Yield', color='aq Value')\n", "fig.update_layout(height=300, width=400, template='ggplot2')" ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] } ], "metadata": { From 033b461fe3ca8e002da62ee910650e6089a95743 Mon Sep 17 00:00:00 2001 From: Kevin Stone Date: Wed, 14 Aug 2024 21:01:21 -0400 Subject: [PATCH 02/10] Improved reactivity of readme to light/dark theme --- readme.md | 22 +++++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) diff --git a/readme.md b/readme.md index d0ed0a4..d506237 100644 --- a/readme.md +++ b/readme.md @@ -3,15 +3,27 @@ obsidian ReadMe --> -
-

- obsidian logo -

+ + + + + +
+
+
-# obsidian +

obsidian

![Supports Python](https://img.shields.io/badge/Python-3.10-teal) [![License](https://img.shields.io/badge/license-GPLv3-teal.svg)](https://github.com/MSDLLCpapers/obsidian/blob/main/LICENSE) From d5401e3addc0d78e236f7853ab67f1b3bb9f3a20 Mon Sep 17 00:00:00 2001 From: Kevin Stone Date: Wed, 14 Aug 2024 21:36:02 -0400 Subject: [PATCH 03/10] Upgraded settings for parity_plot --- obsidian/plotting/plotly.py | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/obsidian/plotting/plotly.py b/obsidian/plotting/plotly.py index 8a34307..e3ab0b6 100644 --- a/obsidian/plotting/plotly.py +++ b/obsidian/plotting/plotly.py @@ -55,23 +55,36 @@ def parity_plot(optimizer: Optimizer, y_true = y_true[y_name].values RMSE = ((y_true-y_pred)/y_true)**2 + NRMSE = RMSE/(y_true.max()-y_true.min()) y_min = np.min([y_true.min(), y_pred.min()]) y_max = np.max([y_true.max(), y_pred.max()]) abs_margin = 0.1 y_abs = [y_min/(1+abs_margin), y_max*(1+abs_margin)] + error_y = y_ub - y_pred + error_y_minus = y_pred - y_lb + fig = go.Figure() fig.add_trace(go.Scatter(x=y_true, y=y_pred, - error_y={'array': y_ub - y_pred, - 'arrayminus': y_pred - y_lb, + error_y={'array': [f'{y:.3G}' for y in error_y], + 'arrayminus': [f'{y:.3G}' for y in error_y_minus], 'color': 'gray', 'thickness': 0.5}, mode='markers', name='Observations', - marker={'color': RMSE, 'colorscale': 'Viridis', 'size': 15}, + marker={'color': NRMSE, 'size': 15, + 'cmax': 0.5, 'cmin': 0, + 'colorscale': [[0, obsidian_colors.rich_blue], + [0.5, obsidian_colors.teal], + [1, obsidian_colors.lemon]], + 'colorbar': dict(title=dict(text='NRMSE', font=dict(size=10))) + }, + showlegend=False )) + fig.update_traces(hovertemplate="(%{x:.3G}, %{y:.3G}) +%{error_y.array:.3G}/-%{error_y.arrayminus:.3G}") + fig.add_trace(go.Scatter(x=y_abs, y=y_abs, mode='lines', name='Parity', @@ -81,7 +94,7 @@ def parity_plot(optimizer: Optimizer, fig.update_xaxes(title_text=f'Actual Response ({y_name})') fig.update_yaxes(title_text=f'Predicted Response ({y_name})') fig.update_layout(template='ggplot2', title='Parity Plot', - autosize=False, height=400, width=600) + autosize=False, height=400, width=500) return fig From cee5d623abb59bac44225a65d2889ac9891cef47 Mon Sep 17 00:00:00 2001 From: Kevin Stone Date: Wed, 14 Aug 2024 21:49:08 -0400 Subject: [PATCH 04/10] Fixed hoverdata for non-numeric params --- obsidian/plotting/plotly.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/obsidian/plotting/plotly.py b/obsidian/plotting/plotly.py index e3ab0b6..f8c9cb9 100644 --- a/obsidian/plotting/plotly.py +++ b/obsidian/plotting/plotly.py @@ -3,6 +3,7 @@ from obsidian.campaign import Campaign from obsidian.optimizer import Optimizer from obsidian.exceptions import UnfitError, UnsupportedError +from obsidian.parameters import Param_Continuous from .branding import obsidian_colors import plotly.graph_objects as go @@ -407,8 +408,9 @@ def optim_progress(campaign: Campaign, customdata=campaign.data[X_names], name='Data')) - template = [""+str(name)+": "+" %{customdata["+str(i)+"]:.3G}
" - for i, name in enumerate(X_names)] + template = [""+str(param.name)+": "+" %{customdata["+str(i)+"]" + + (":.3G}"if isinstance(param, Param_Continuous) else "}") + "
" + for i, param in enumerate(campaign.X_space)] fig.update_traces(hovertemplate=''.join(template) + out_names[0] + ": %{x:.3G}
" + out_names[1] + ": %{y:.3G}
") From bfe94d1d626e5263f31b71df5ed3e52a9cfe438d Mon Sep 17 00:00:00 2001 From: Yuting Xu <12775874+xuyuting@users.noreply.github.com> Date: Wed, 14 Aug 2024 23:00:07 -0400 Subject: [PATCH 05/10] enable auto adjust table width for the markdown files in docs/wiki --- docs/_static/mycss.css | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/docs/_static/mycss.css b/docs/_static/mycss.css index 182d881..cf6433b 100644 --- a/docs/_static/mycss.css +++ b/docs/_static/mycss.css @@ -7,4 +7,8 @@ .bd-page-width { max-width: 100%; /* default is 88rem */ -} \ No newline at end of file +} + +.pst-scrollable-table-container table.table { + width: auto; +} From 94b2b03b01f894535599858f29b2993a2775a050 Mon Sep 17 00:00:00 2001 From: Yuting Xu <12775874+xuyuting@users.noreply.github.com> Date: Wed, 14 Aug 2024 23:23:25 -0400 Subject: [PATCH 06/10] template of surrogate model and acquisition function user guide, to be modified --- docs/wiki/4_SurrogateModel.md | 135 ++++++++++++++++++++++++++++- docs/wiki/5_AcquisitionFunction.md | 130 ++++++++++++++++++++++++++- 2 files changed, 263 insertions(+), 2 deletions(-) diff --git a/docs/wiki/4_SurrogateModel.md b/docs/wiki/4_SurrogateModel.md index fec2840..d0f37d0 100644 --- a/docs/wiki/4_SurrogateModel.md +++ b/docs/wiki/4_SurrogateModel.md @@ -1,3 +1,136 @@ # Surrogate Model -(TBA...) \ No newline at end of file +## 1. Introduction + +The `obsidian.surrogates` submodule is a key component of the Obsidian Bayesian optimization library. It provides a collection of surrogate models used to approximate the objective function in the optimization process. These surrogate models are essential for efficient exploration of the parameter space and for making informed decisions about which points to evaluate next. + +## 2. Available Surrogate Models + +The `obsidian.surrogates` submodule offers several types of surrogate models: + +1. **Gaussian Process (GP)**: The default surrogate model, suitable for most optimization tasks. +2. **Mixed Gaussian Process (MixedGP)**: A GP model that can handle mixed continuous and categorical input spaces. +3. **Deep Kernel Learning GP (DKL)**: A GP model with a neural network feature extractor. +4. **Flat GP**: A GP model with non-informative or no prior distributions. +5. **Prior GP**: A GP model with custom prior distributions. +6. **Multi-Task GP (MTGP)**: A GP model for multi-output optimization. +7. **Deep Neural Network (DNN)**: A dropout neural network model. + +## 3. How to Use Surrogate Models + +To use a surrogate model in your optimization process, you typically don't need to interact with it directly. The Obsidian optimizer will handle the creation and management of the surrogate model. However, if you need to create a surrogate model manually, you can do so using the `SurrogateBoTorch` class: + +```python +from obsidian.surrogates import SurrogateBoTorch +from obsidian.parameters import ParamSpace, Target + +# Define your parameter space +param_space = ParamSpace([...]) # Define your parameters here + +# Create a surrogate model (default is GP) +surrogate = SurrogateBoTorch(model_type='GP') + +# Fit the model to your data +surrogate.fit(X, y) + +# Make predictions +mean, std = surrogate.predict(X_new) +``` + +## 4. Customization Options + +### 4.1 Model Selection + +You can choose different surrogate models by specifying the `model_type` parameter when creating a `SurrogateBoTorch` instance. Available options are: + +- `'GP'`: Standard Gaussian Process +- `'MixedGP'`: Mixed input Gaussian Process +- `'DKL'`: Deep Kernel Learning GP +- `'GPflat'`: Flat (non-informative prior) GP +- `'GPprior'`: Custom prior GP +- `'MTGP'`: Multi-Task GP +- `'DNN'`: Dropout Neural Network + +### 4.2 Hyperparameters + +You can pass custom hyperparameters to the surrogate model using the `hps` parameter: + +```python +surrogate = SurrogateBoTorch(model_type='GP', hps={'your_custom_param': value}) +``` + +### 4.3 Custom GP Models + +The submodule provides several custom GP implementations: + +- `PriorGP`: A GP with custom prior distributions +- `FlatGP`: A GP with non-informative or no prior distributions +- `DKLGP`: A GP with a neural network feature extractor + +### 4.4 Custom Neural Network Model + +The `DNN` class provides a customizable dropout neural network model. You can adjust parameters such as dropout probability, hidden layer width, and number of hidden layers. + +## 5. Examples + +### 5.1 Using a standard GP surrogate + +```python +from obsidian.surrogates import SurrogateBoTorch +from obsidian.parameters import ParamSpace, Target +import pandas as pd + +# Define your parameter space +param_space = ParamSpace([...]) # Define your parameters here + +# Assume X and y are your input features and target variables +X = pd.DataFrame(...) +y = pd.Series(...) + +surrogate = SurrogateBoTorch(model_type='GP') +surrogate.fit(X, y) + +# Make predictions +X_new = pd.DataFrame(...) +mean, std = surrogate.predict(X_new) +``` + +### 5.2 Using a Mixed GP for categorical and continuous variables + +```python +surrogate = SurrogateBoTorch(model_type='MixedGP') +# cat_dims should be a list of indices for categorical variables in your input space +surrogate.fit(X, y, cat_dims=[0, 2]) # Assuming columns 0 and 2 are categorical +``` + +### 5.3 Using a DNN surrogate + +```python +# The 'hps' parameter allows you to customize the DNN architecture +surrogate = SurrogateBoTorch(model_type='DNN', hps={'p_dropout': 0.1, 'h_width': 32, 'h_layers': 3}) +surrogate.fit(X, y) +``` + +## 6. Advanced Usage + +### 6.1 Saving and Loading Models + +You can save and load surrogate models using the `save_state()` and `load_state()` methods: + +```python +# Save model state +state = surrogate.save_state() + +# Load model state +loaded_surrogate = SurrogateBoTorch.load_state(state) +``` + +### 6.2 Model Evaluation + +You can evaluate the performance of a surrogate model using the `score()` method: + +```python +loss, r2_score = surrogate.score(X_test, y_test) +``` + +This concludes the user guide for the `obsidian.surrogates` submodule. For more detailed information, please refer to the source code and docstrings in the individual files. \ No newline at end of file diff --git a/docs/wiki/5_AcquisitionFunction.md b/docs/wiki/5_AcquisitionFunction.md index 9b32ee3..389b17d 100644 --- a/docs/wiki/5_AcquisitionFunction.md +++ b/docs/wiki/5_AcquisitionFunction.md @@ -1,3 +1,131 @@ # Acquisition Function -(TBA...) \ No newline at end of file +## 1. Introduction + +The `obsidian.acquisition` submodule is a crucial component of the Obsidian Bayesian optimization library. It provides acquisition functions that guide the optimization process by determining which points in the parameter space should be evaluated next. These acquisition functions balance exploration of uncertain areas and exploitation of promising regions, which is key to efficient optimization. + +## 2. Key Components + +The acquisition submodule includes several acquisition functions, both standard and custom implementations: + +### 2.1 Standard Acquisition Functions + +- Expected Improvement (EI) +- Probability of Improvement (PI) +- Upper Confidence Bound (UCB) +- Noisy Expected Improvement (NEI) +- Expected Hypervolume Improvement (EHVI) +- Noisy Expected Hypervolume Improvement (NEHVI) + +### 2.2 Custom Acquisition Functions + +- qMean: Optimizes for the maximum value of the posterior mean +- qSpaceFill: Optimizes for the maximum value of minimum distance between a point and the training data + +## 3. Understanding Acquisition Functions + +### 3.1 Expected Improvement (EI) + +EI calculates the expected amount by which we will improve upon the current best observed value. + +Mathematical formulation: +``` +EI(x) = E[max(f(x) - f(x+), 0)] +``` +where f(x+) is the current best observed value. + +Example usage: +```python +from obsidian.optimizer import BayesianOptimizer + +optimizer = BayesianOptimizer(X_space=param_space) +X_suggest, eval_suggest = optimizer.suggest(acquisition=['EI']) +``` + +### 3.2 Upper Confidence Bound (UCB) + +UCB balances exploration and exploitation by selecting points with high predicted values or high uncertainty. + +Mathematical formulation: +``` +UCB(x) = μ(x) + β * σ(x) +``` +where μ(x) is the predicted mean, σ(x) is the predicted standard deviation, and β is a parameter that controls the exploration-exploitation trade-off. + +Example usage: +```python +X_suggest, eval_suggest = optimizer.suggest(acquisition=[{'UCB': {'beta': 2.0}}]) +``` + +### 3.3 Noisy Expected Improvement (NEI) + +NEI is a variant of EI that accounts for noise in the observations, making it more suitable for real-world problems with measurement uncertainty. + +Example usage: +```python +X_suggest, eval_suggest = optimizer.suggest(acquisition=['NEI']) +``` + +## 4. Advanced Usage + +### 4.1 Multi-Objective Optimization + +For multi-objective optimization problems, you can use specialized acquisition functions: + +```python +X_suggest, eval_suggest = optimizer.suggest(acquisition=['NEHVI']) +``` + +### 4.2 Customizing Acquisition Functions + +Some acquisition functions accept parameters to customize their behavior. These can be specified in the `suggest` method: + +```python +X_suggest, eval_suggest = optimizer.suggest( + acquisition=[{'EI': {'inflate': 0.01}}] +) +``` + +### 4.3 Custom Acquisition Functions + +If you need to implement a custom acquisition function, you can extend the `MCAcquisitionFunction` class from BoTorch: + +```python +from botorch.acquisition import MCAcquisitionFunction +import torch + +class CustomAcquisition(MCAcquisitionFunction): + def forward(self, X): + posterior = self.model.posterior(X) + mean = posterior.mean + std = posterior.variance.sqrt() + return (mean + 0.1 * std).sum(dim=-1) # Example custom acquisition logic +``` + +## 5. Comparing Acquisition Functions + +Different acquisition functions have different strengths: + +- EI and PI are good for exploiting known good regions but may underexplore. +- UCB provides a tunable exploration-exploitation trade-off. +- NEI and NEHVI are robust to noisy observations. +- qMean is purely exploitative and can be useful in the final stages of optimization. +- qSpaceFill is purely explorative and can be useful for initial space exploration. + +## 6. Best Practices + +1. Choose appropriate acquisition functions based on your problem characteristics (e.g., noise level, number of objectives). +2. For noisy problems, consider using noise-aware acquisition functions like NEI or NEHVI. +3. Experiment with different acquisition functions to find the best performance for your specific problem. +4. When using UCB, carefully tune the beta parameter to balance exploration and exploitation. +5. For multi-objective problems, EHVI and NEHVI are often good choices. +6. Consider using a sequence of acquisition functions, starting with more exploratory ones and moving to more exploitative ones as the optimization progresses. + +## 7. Common Pitfalls + +1. Using EI or PI in noisy problems, which can lead to overexploitation of noisy observations. +2. Setting UCB's beta parameter too high (over-exploration) or too low (over-exploitation). +3. Using single-objective acquisition functions for multi-objective problems. +4. Not accounting for constraints when selecting acquisition functions. + +This concludes the user guide for the `obsidian.acquisition` submodule. For more detailed information, please refer to the source code and docstrings in the individual files. \ No newline at end of file From 8ac2bbc11680240e8ed94171c76cc251e5de03f1 Mon Sep 17 00:00:00 2001 From: Kevin Stone Date: Wed, 14 Aug 2024 23:27:16 -0400 Subject: [PATCH 07/10] Completed first two tutorial notebooks and HTML --- ...=> Constrained multi-output min-max.ipynb} | 139 +- demo/Simple single objective.ipynb | 59 +- .../Constrained multi-output min-max.html | 8508 +++++++++++++++++ .../tutorials/Simple single objective.html | 172 +- docs/stubs/tutorials.rst | 3 +- .../Constrained multi-output min-max.rst | 6 + 6 files changed, 8773 insertions(+), 114 deletions(-) rename demo/{Constrained multi objective.ipynb => Constrained multi-output min-max.ipynb} (58%) create mode 100644 docs/_static/tutorials/Constrained multi-output min-max.html create mode 100644 docs/stubs/tutorials/Constrained multi-output min-max.rst diff --git a/demo/Constrained multi objective.ipynb b/demo/Constrained multi-output min-max.ipynb similarity index 58% rename from demo/Constrained multi objective.ipynb rename to demo/Constrained multi-output min-max.ipynb index 56814c2..7347362 100644 --- a/demo/Constrained multi objective.ipynb +++ b/demo/Constrained multi-output min-max.ipynb @@ -7,34 +7,47 @@ "outputs": [], "source": [ "import obsidian\n", - "obsidian.__version__" + "print(f'obsidian version: ' + obsidian.__version__)\n", + "\n", + "import pandas as pd\n", + "import plotly.express as px\n", + "import plotly.io as pio\n", + "pio.renderers.default = \"plotly_mimetype+notebook\"" ] }, { - "cell_type": "code", - "execution_count": null, + "cell_type": "markdown", "metadata": {}, - "outputs": [], "source": [ - "import pandas as pd\n", - "import plotly.express as px" + "## Introduction" ] }, { - "cell_type": "code", - "execution_count": null, + "cell_type": "markdown", "metadata": {}, - "outputs": [], "source": [ - "from obsidian.parameters import ParamSpace, Param_Continuous\n", - "from obsidian.experiment import ExpDesigner" + "In this tutorial, we will see how to use _obsidian_ for multi-output optimization. To demonstrate the versatility of the approach, we will seek to maximize one response while minimizing the other.\n", + "\n", + "$$\\underset{X}{argmax} HV\\left(+f\\left(y_1\\right) -f\\left(y_2\\right)\\right)$$\n", + "\n", + "Furthermore, we will apply a linear constraint on the input variables; requiring that the $X_1 + X_2 \\leq 6 $." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "### Set up parameter space and initialize a design" + "## Set up parameter space and initialize a design" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "from obsidian import Campaign, Target, ParamSpace, BayesianOptimizer\n", + "from obsidian.parameters import Param_Continuous" ] }, { @@ -49,8 +62,12 @@ " ]\n", "\n", "X_space = ParamSpace(params)\n", - "designer = ExpDesigner(X_space, seed=0)\n", - "X0 = designer.initialize(4, 'LHS')\n", + "target = [\n", + " Target('Response 1', aim='max'),\n", + " Target('Response 2', aim='min')\n", + "]\n", + "campaign = Campaign(X_space, target, seed=0)\n", + "X0 = campaign.designer.initialize(4, 'LHS')\n", "\n", "X0" ] @@ -59,7 +76,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "### Collect results (e.g. from a simulation)" + "## Collect results (e.g. from a simulation)" ] }, { @@ -75,23 +92,15 @@ "y0 = simulator.simulate(X0)\n", "Z0 = pd.concat([X0, y0], axis=1)\n", "\n", - "Z0" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "Z0.plot(x='Response 1', y='Response 2', kind='scatter', figsize=(4,3))" + "campaign.add_data(Z0)\n", + "campaign.data" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "### Define the Target" + "### Fit an optimizer and visualize results" ] }, { @@ -100,19 +109,7 @@ "metadata": {}, "outputs": [], "source": [ - "from obsidian.parameters import Target\n", - "\n", - "target = [\n", - " Target('Response 1', aim='max'),\n", - " Target('Response 2', aim='min')\n", - "]" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Create a campaign to track optimization" + "campaign.fit()" ] }, { @@ -121,7 +118,7 @@ "metadata": {}, "outputs": [], "source": [ - "from obsidian.campaign import Campaign" + "from obsidian.plotting import surface_plot, optim_progress" ] }, { @@ -130,16 +127,14 @@ "metadata": {}, "outputs": [], "source": [ - "my_campaign = Campaign(X_space, target)\n", - "my_campaign.add_data(Z0)\n", - "my_campaign.data" + "surface_plot(campaign.optimizer)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "### Fit an optimizer" + "## Optimize new experiment suggestions" ] }, { @@ -148,23 +143,16 @@ "metadata": {}, "outputs": [], "source": [ - "my_campaign.fit()" + "from obsidian.constraints import InConstraint_Generic" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "### Make new experiment suggestions" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "from obsidian.constraints import InConstraint_Generic" + "_Note:_ It is a good idea to balance a set of acquisition functions with those that prefer design-space exploration. This helps to ensure that the optimizer is not severely misled by deficiencies in the dataset, particularly for small data. It also helps to ascertain a global optimum.\n", + "\n", + "A simple choice is __Space Filling (SF)__ although __Negative Integrated Posterior Variance (NIPV)__ is available for single-output optimizations; and there are various other acquisiiton functions whose hyperparameters can be tuned to manage the \"explore-exploit\" balance." ] }, { @@ -173,13 +161,9 @@ "metadata": {}, "outputs": [], "source": [ - "# # X1 + X2 >= 2\n", - "# optim_kwargs = {'m_batch':2, 'acquisition':[{'NEHVI':{'ref_point':[-350,0]}}], 'ineq_constraints':[InConstraint_Generic(X_space, indices=[0,1], coeff=[1,1], rhs=2)]}\n", - "\n", - "# X1 + X2 <= 6 aka -X1 - X2 >= -6\n", - "optim_kwargs = {'m_batch':2, 'acquisition':[{'NEHVI':{'ref_point':[-350,0]}}], 'ineq_constraints':[InConstraint_Generic(X_space, indices=[0,1], coeff=[-1,-1], rhs=-6)]}\n", - "\n", - "X_suggest, eval_suggest = my_campaign.optimizer.suggest(**optim_kwargs)" + "X_suggest, eval_suggest = campaign.optimizer.suggest(acquisition = [{'NEHVI':{'ref_point':[-350, -20]}}, 'SF'],\n", + " # X1 + X2 <= 6, written as -X1 - X2 >= -6\n", + " ineq_constraints = [InConstraint_Generic(X_space, indices=[0,1], coeff=[-1,-1], rhs=-6)])" ] }, { @@ -195,7 +179,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "### Collect data at new suggestions" + "## Collect data at new suggestions" ] }, { @@ -206,15 +190,15 @@ "source": [ "y_iter1 = pd.DataFrame(simulator.simulate(X_suggest))\n", "Z_iter1 = pd.concat([X_suggest, y_iter1, eval_suggest], axis=1)\n", - "my_campaign.add_data(Z_iter1)\n", - "my_campaign.data" + "campaign.add_data(Z_iter1)\n", + "campaign.data.tail()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "### Repeat as desired" + "## Repeat as desired" ] }, { @@ -224,11 +208,12 @@ "outputs": [], "source": [ "for iter in range(5):\n", - " my_campaign.fit()\n", - " X_suggest, eval_suggest = my_campaign.optimizer.suggest(**optim_kwargs)\n", + " campaign.fit()\n", + " X_suggest, eval_suggest = campaign.optimizer.suggest(acquisition = [{'NEHVI':{'ref_point':[-350, -20]}}, 'SF'],\n", + " ineq_constraints = [InConstraint_Generic(X_space, indices=[0,1], coeff=[-1,-1], rhs=-6)])\n", " y_iter = pd.DataFrame(simulator.simulate(X_suggest))\n", " Z_iter = pd.concat([X_suggest, y_iter, eval_suggest], axis=1)\n", - " my_campaign.add_data(Z_iter)" + " campaign.add_data(Z_iter)" ] }, { @@ -237,8 +222,7 @@ "metadata": {}, "outputs": [], "source": [ - "fig = px.scatter(my_campaign.data, x='Response 1', y='Response 2', color='Iteration')\n", - "fig.update_layout(height=300, width=400, template='ggplot2')" + "optim_progress(campaign)" ] }, { @@ -247,7 +231,7 @@ "metadata": {}, "outputs": [], "source": [ - "my_campaign.data" + "surface_plot(campaign.optimizer, response_id = 0)" ] }, { @@ -255,14 +239,9 @@ "execution_count": null, "metadata": {}, "outputs": [], - "source": [] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [] + "source": [ + "surface_plot(campaign.optimizer, response_id = 1)" + ] } ], "metadata": { diff --git a/demo/Simple single objective.ipynb b/demo/Simple single objective.ipynb index 51f2b2c..cef399f 100644 --- a/demo/Simple single objective.ipynb +++ b/demo/Simple single objective.ipynb @@ -49,7 +49,7 @@ "X_space = ParamSpace(params)\n", "target = Target('Yield', aim='max')\n", "campaign = Campaign(X_space, target, seed=0)\n", - "X0 = campaign.designer.initialize(10, 'LHS')\n", + "X0 = campaign.initialize(m_initial = 10, method = 'LHS')\n", "\n", "X0" ] @@ -111,8 +111,15 @@ "metadata": {}, "outputs": [], "source": [ - "from obsidian.plotting import parity_plot, factor_plot\n", - "\n", + "from obsidian.plotting import parity_plot, factor_plot, optim_progress" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ "parity_plot(campaign.optimizer)" ] }, @@ -138,7 +145,7 @@ "metadata": {}, "outputs": [], "source": [ - "X_suggest, eval_suggest = campaign.optimizer.suggest(m_batch=3)" + "X_suggest, eval_suggest = campaign.suggest(m_batch=3)" ] }, { @@ -185,7 +192,7 @@ "source": [ "for iter in range(3):\n", " campaign.fit()\n", - " X_suggest, eval_suggest = campaign.optimizer.suggest(m_batch=3)\n", + " X_suggest, eval_suggest = campaign.suggest(m_batch=3)\n", " y_iter = pd.DataFrame(simulator.simulate(X_suggest))\n", " Z_iter = pd.concat([X_suggest, y_iter, eval_suggest], axis=1)\n", " campaign.add_data(Z_iter)" @@ -197,8 +204,14 @@ "metadata": {}, "outputs": [], "source": [ - "fig = px.scatter(campaign.data, x=campaign.data.index, y='Yield', color='aq Value')\n", - "fig.update_layout(height=300, width=400, template='ggplot2')" + "optim_progress(campaign, color_feature_id = 'aq Value')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Analyze using Explainer" ] }, { @@ -206,7 +219,37 @@ "execution_count": null, "metadata": {}, "outputs": [], - "source": [] + "source": [ + "from obsidian.campaign import Explainer" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "exp = Explainer(campaign.optimizer)\n", + "exp.shap_explain(n=500)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "exp.shap_summary()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "exp.shap_pdp_ice(ind = 0, ice_color_var = 2)" + ] } ], "metadata": { diff --git a/docs/_static/tutorials/Constrained multi-output min-max.html b/docs/_static/tutorials/Constrained multi-output min-max.html new file mode 100644 index 0000000..a0f63a0 --- /dev/null +++ b/docs/_static/tutorials/Constrained multi-output min-max.html @@ -0,0 +1,8508 @@ + + + + + +Constrained multi-output min-max + + + + + + + + + + + + +
+ + + + + + + + + +
+ + diff --git a/docs/_static/tutorials/Simple single objective.html b/docs/_static/tutorials/Simple single objective.html index 4fdd762..f15cef3 100644 --- a/docs/_static/tutorials/Simple single objective.html +++ b/docs/_static/tutorials/Simple single objective.html @@ -7536,7 +7536,7 @@ @@ -7587,7 +7587,7 @@

Set up parameter space a X_space = ParamSpace(params) target = Target('Yield', aim='max') campaign = Campaign(X_space, target, seed=0) -X0 = campaign.designer.initialize(10, 'LHS') +X0 = campaign.initialize(m_initial = 10, method = 'LHS') X0

@@ -7873,7 +7873,7 @@

Collect results (e.g. from a s

@@ -7916,7 +7916,7 @@

Fit the optimizer and visualize -