Skip to content

Commit

Permalink
Merge pull request #11 from MindFoundry/upgrade-to-1.3.11
Browse files Browse the repository at this point in the history
Upgrade to 1.3.11
  • Loading branch information
csymeonides-mf authored Apr 30, 2020
2 parents 20dc4ea + 22ab7d7 commit 5caea71
Show file tree
Hide file tree
Showing 23 changed files with 1,937 additions and 17 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
__pycache__/
.idea/
.ipynb_checkpoints
optaas-tutorials.iml
2 changes: 1 addition & 1 deletion notebooks/R/01. Quick Start.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
"source": [
"# OPTaaS Quick Start\n",
"\n",
"### <span style=\"color:red\">Note:</span> To run this notebook, you need an API Key. You can get one <a href=\"mailto:charles.brecque@mindfoundry.ai\">here</a>."
"### <span style=\"color:red\">Note:</span> To run this notebook, you need an API Key. You can get one <a href=\"mailto:info@mindfoundry.ai\">here</a>."
]
},
{
Expand Down
2 changes: 1 addition & 1 deletion notebooks/R/02. Multi Objective.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
"source": [
"# OPTaaS Multi-Objective\n",
"\n",
"### <span style=\"color:red\">Note:</span> To run this notebook, you need an API Key. You can get one <a href=\"mailto:charles.brecque@mindfoundry.ai\">here</a>.\n",
"### <span style=\"color:red\">Note:</span> To run this notebook, you need an API Key. You can get one <a href=\"mailto:info@mindfoundry.ai\">here</a>.\n",
"\n",
"OPTaaS can optimize multiple objectives within a single Task. Your scoring function should return a named list of scores for each objective."
]
Expand Down
2 changes: 1 addition & 1 deletion notebooks/R/03. Constraints.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
"source": [
"# OPTaaS Constraints\n",
"\n",
"### <span style=\"color:red\">Note:</span> To run this notebook, you need an API Key. You can get one <a href=\"mailto:charles.brecque@mindfoundry.ai\">here</a>.\n",
"### <span style=\"color:red\">Note:</span> To run this notebook, you need an API Key. You can get one <a href=\"mailto:info@mindfoundry.ai\">here</a>.\n",
"\n",
"Constraints allow you to specify relationships between the parameters you want to optimize, or just constrain the values that a parameter can take. \n",
"\n",
Expand Down
2 changes: 1 addition & 1 deletion notebooks/R/04. Batching.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
"source": [
"# OPTaaS Batching\n",
"\n",
"### <span style=\"color:red\">Note:</span> To run this notebook, you need an API Key. You can get one <a href=\"mailto:charles.brecque@mindfoundry.ai\">here</a>.\n",
"### <span style=\"color:red\">Note:</span> To run this notebook, you need an API Key. You can get one <a href=\"mailto:info@mindfoundry.ai\">here</a>.\n",
"\n",
"OPTaaS can facilitate parallel computation, where you generate a batch of configurations, pass them to a number of workers to calculate the results, and then store the results to get the next batch of configurations."
]
Expand Down
2 changes: 1 addition & 1 deletion notebooks/R/05. Surrogate Prediction.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
"source": [
"# OPTaaS Surrogate Prediction\n",
"\n",
"### <span style=\"color:red\">Note:</span> To run this notebook, you need an API Key. You can get one <a href=\"mailto:charles.brecque@mindfoundry.ai\">here</a>.\n",
"### <span style=\"color:red\">Note:</span> To run this notebook, you need an API Key. You can get one <a href=\"mailto:info@mindfoundry.ai\">here</a>.\n",
"\n",
"The surrogate model is what the optimizer *thinks* the scoring function looks like. It is part of the mechanism used to choose optimal configurations.\n",
"\n",
Expand Down
2 changes: 1 addition & 1 deletion notebooks/R/06. Warm Start.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
"source": [
"# OPTaaS Warm Start\n",
"\n",
"### <span style=\"color:red\">Note:</span> To run this notebook, you need an API Key. You can get one <a href=\"mailto:charles.brecque@mindfoundry.ai\">here</a>.\n",
"### <span style=\"color:red\">Note:</span> To run this notebook, you need an API Key. You can get one <a href=\"mailto:info@mindfoundry.ai\">here</a>.\n",
"\n",
"You can \"warm-start\" an OPTaaS Task by providing some results that you've already calculated. This should help you get to the optimum faster."
]
Expand Down
2 changes: 1 addition & 1 deletion notebooks/R/07. Cyclical Parameters.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
"source": [
"# OPTaaS Cyclical Parameters\n",
"\n",
"### <span style=\"color:red\">Note:</span> To run this notebook, you need an API Key. You can get one <a href=\"mailto:charles.brecque@mindfoundry.ai\">here</a>.\n",
"### <span style=\"color:red\">Note:</span> To run this notebook, you need an API Key. You can get one <a href=\"mailto:info@mindfoundry.ai\">here</a>.\n",
"\n",
"A new flag on `FloatParameter` now allows you to specify that the parameter is **cyclical** (aka *circular* or *periodic*). OPTaaS will select values from a period starting from the `minimum` (inclusive) and ending at the `maximum` (exclusive). Values near the minimum and maximum will be considered to be close, as if they were on a circle.\n",
"\n",
Expand Down
2 changes: 1 addition & 1 deletion notebooks/python/01. Quick Start.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
"source": [
"# OPTaaS Quick Start\n",
"\n",
"### <span style=\"color:red\">Note:</span> To run this notebook, you need an API Key. You can get one <a href=\"mailto:charles.brecque@mindfoundry.ai\">here</a>.\n",
"### <span style=\"color:red\">Note:</span> To run this notebook, you need an API Key. You can get one <a href=\"mailto:info@mindfoundry.ai\">here</a>.\n",
"\n",
"More tutorials are [available here](./)"
]
Expand Down
2 changes: 1 addition & 1 deletion notebooks/python/02. Advanced Options.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
"source": [
"# OPTaaS - Advanced Options\n",
"\n",
"### <span style=\"color:red\">Note:</span> To run this notebook, you need an API Key. You can get one <a href=\"mailto:charles.brecque@mindfoundry.ai\">here</a>."
"### <span style=\"color:red\">Note:</span> To run this notebook, you need an API Key. You can get one <a href=\"mailto:info@mindfoundry.ai\">here</a>."
]
},
{
Expand Down
2 changes: 1 addition & 1 deletion notebooks/python/03. Constraints.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
"source": [
"# OPTaaS Constraints\n",
"\n",
"### <span style=\"color:red\">Note:</span> To run this notebook, you need an API Key. You can get one <a href=\"mailto:charles.brecque@mindfoundry.ai\">here</a>.\n",
"### <span style=\"color:red\">Note:</span> To run this notebook, you need an API Key. You can get one <a href=\"mailto:info@mindfoundry.ai\">here</a>.\n",
"\n",
"Constraints allow you to specify relationships between the parameters you want to optimize, or just constrain the values that a parameter can take. \n",
"\n",
Expand Down
2 changes: 1 addition & 1 deletion notebooks/python/04. Batching.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
"source": [
"# OPTaaS Batching\n",
"\n",
"### <span style=\"color:red\">Note:</span> To run this notebook, you need an API Key. You can get one <a href=\"mailto:charles.brecque@mindfoundry.ai\">here</a>.\n",
"### <span style=\"color:red\">Note:</span> To run this notebook, you need an API Key. You can get one <a href=\"mailto:info@mindfoundry.ai\">here</a>.\n",
"\n",
"OPTaaS can facilitate parallel computation, where you generate a batch of configurations, pass them to a number of workers to calculate the results, and then store the results to get the next batch of configurations."
]
Expand Down
2 changes: 1 addition & 1 deletion notebooks/python/05. Multi Objective.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
"source": [
"# OPTaaS Multi-Objective\n",
"\n",
"### <span style=\"color:red\">Note:</span> To run this notebook, you need an API Key. You can get one <a href=\"mailto:charles.brecque@mindfoundry.ai\">here</a>.\n",
"### <span style=\"color:red\">Note:</span> To run this notebook, you need an API Key. You can get one <a href=\"mailto:info@mindfoundry.ai\">here</a>.\n",
"\n",
"OPTaaS can optimize multiple objectives within a single Task. Your scoring function should return a dictionary of scores for each objective. You can also optionally return a dictionary of variances for each objective (i.e. return a tuple of dictionaries)."
]
Expand Down
2 changes: 1 addition & 1 deletion notebooks/python/06. Scikit-learn Pipelines.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
"source": [
"# OPTaaS Scikit-learn Pipelines\n",
"\n",
"### <span style=\"color:red\">Note:</span> To run this notebook, you need an API Key. You can get one <a href=\"mailto:charles.brecque@mindfoundry.ai\">here</a>.\n",
"### <span style=\"color:red\">Note:</span> To run this notebook, you need an API Key. You can get one <a href=\"mailto:info@mindfoundry.ai\">here</a>.\n",
"\n",
"Using the OPTaaS Python Client, you can optimize any scikit-learn pipeline. For each step or estimator in the pipeline, OPTaaS just needs to know what parameters to optimize and what constraints will apply to them.\n",
"\n",
Expand Down
2 changes: 1 addition & 1 deletion notebooks/python/07. Custom Scikit-learn Estimators.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
"source": [
"# OPTaaS Scikit-learn Custom Optimizable Estimators\n",
"\n",
"### <span style=\"color:red\">Note:</span> To run this notebook, you need an API Key. You can get one <a href=\"mailto:charles.brecque@mindfoundry.ai\">here</a>.\n",
"### <span style=\"color:red\">Note:</span> To run this notebook, you need an API Key. You can get one <a href=\"mailto:info@mindfoundry.ai\">here</a>.\n",
"\n",
"Using the OPTaaS Python Client, you can optimize any scikit-learn pipeline. For each step or estimator in the pipeline, OPTaaS just needs to know what parameters to optimize and what constraints will apply to them.\n",
"\n",
Expand Down
2 changes: 1 addition & 1 deletion notebooks/python/08. Subset Parameters.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
"source": [
"# OPTaaS SubsetParameter\n",
"\n",
"### <span style=\"color:red\">Note:</span> To run this notebook, you need an API Key. You can get one <a href=\"mailto:charles.brecque@mindfoundry.ai\">here</a>.\n",
"### <span style=\"color:red\">Note:</span> To run this notebook, you need an API Key. You can get one <a href=\"mailto:info@mindfoundry.ai\">here</a>.\n",
"\n",
"A new feature in the latest version of OPTaaS is the `SubsetParameter`. It's similar to the existing `CategoricalParameter`, but instead of choosing one value from a set of allowed values, we can choose a subset (zero or more values).\n",
"\n",
Expand Down
2 changes: 1 addition & 1 deletion notebooks/python/13. Cyclical Parameters.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
"source": [
"# OPTaaS Cyclical Parameters\n",
"\n",
"### <span style=\"color:red\">Note:</span> To run this notebook, you need an API Key. You can get one <a href=\"mailto:charles.brecque@mindfoundry.ai\">here</a>.\n",
"### <span style=\"color:red\">Note:</span> To run this notebook, you need an API Key. You can get one <a href=\"mailto:info@mindfoundry.ai\">here</a>.\n",
"\n",
"A new flag on `FloatParameter` now allows you to specify that the parameter is **cyclical** (aka *circular* or *periodic*). OPTaaS will select values from a period starting from the `minimum` (inclusive) and ending at the `maximum` (exclusive). Values near the minimum and maximum will be considered to be close, as if they were on a circle.\n",
"\n",
Expand Down
1,327 changes: 1,327 additions & 0 deletions notebooks/python/14. Prior Means.ipynb

Large diffs are not rendered by default.

Empty file.
230 changes: 230 additions & 0 deletions notebooks/python/utils/demo.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,230 @@
import math
import os
import random
from typing import List, Dict, Callable, Any, Union

import numpy as np
import pandas as pd
from IPython.display import display, clear_output

from mindfoundry.optaas.client.task import Configuration
from mindfoundry.optaas.client.utils import get_choice_value, get_choice_name
from utils.plotters import PlotlyChartPlotter, MatPlotLibPlotter

DEFAULT_DISPLAY_FREQUENCY = 1


class Demo:
def __init__(self, configuration_keys: List[str],
use_plotly: bool = False, getters: Dict[str, Union[str, Callable]] = None,
minimise: bool = None, use_3d_plot: bool = False, display_frequency: int = None, plot_table: bool = True,
plot_best_scores_on_left: bool = True, display_table_best_first: bool = True, clear_output: bool = True):
self.use_plotly = use_plotly
self.plot_table = plot_table
chart_plotter_type = PlotlyChartPlotter if use_plotly else MatPlotLibPlotter
self.chart_plotter = chart_plotter_type(minimise=minimise, use_3d_plot=use_3d_plot,
plot_best_scores_on_left=plot_best_scores_on_left)
self.chart_plotter.use_3d_plot = use_3d_plot
self.chart_plotter.minimise = minimise

self.display_table_best_first = display_table_best_first

self.current_iteration = 0
self.display_frequency = DEFAULT_DISPLAY_FREQUENCY if display_frequency is None else display_frequency

self.better_of = min if minimise else max
self.best_score = math.inf if minimise else -math.inf
self.best_scores = []

self.configuration_keys = configuration_keys
self.getters = getters or {}

self.df = pd.DataFrame({key: [] for key in configuration_keys + ['Score', 'Configuration Type']})
self.all_scores = {type: {} for type in self.chart_plotter.plot_types_and_colours}

self.clear_output = clear_output

def display(self, configuration: Configuration, score: float, counter: int):
self.update_data(configuration, score)
if counter % self.display_frequency == 0:
self.update_display()

def update_data(self, configuration: Configuration, score: float):
self.log_configuration(configuration)
self.log_score(configuration, score)

def log_configuration(self, configuration: Configuration):
data_values = {key: self.get_value(configuration.values, key) for key in self.configuration_keys}
data_values['Score'] = None
data_values['Configuration Type'] = configuration.type
self.all_scores[configuration.type][self.current_iteration] = data_values
self.df.loc[self.current_iteration] = data_values

def log_score(self, configuration: Configuration, score: float):
self.all_scores[configuration.type][self.current_iteration]['Score'] = score
self.df.at[self.current_iteration, 'Score'] = score

if self.display_table_best_first:
self.df = self.df.sort_values(by=['Score'], ascending=self.chart_plotter.minimise)

self.best_score = self.better_of(self.best_score, score)
self.best_scores.append(self.best_score)

self.current_iteration += 1

def get_value(self, config: Dict, key: str) -> Any:
value = config.get(key)
getter = self.getters.get(key)
if getter == 'choice_name':
value = get_choice_name(value)
elif getter == 'choice_value':
value = get_choice_value(value)
elif getter == 'is_present':
value = (value is not None)
elif getter is None:
if isinstance(value, Dict):
value = list(value.values())
if len(value) == 1:
value = value[0]
else:
value = getter(config)
return value

def update_display(self):
if self.clear_output:
clear_output(wait=True)

self.chart_plotter.start_update()

self.add_overall_plots()

for type, colour in self.chart_plotter.plot_types_and_colours.items():
iterations = self.all_scores[type].keys()
if iterations:
dicts = self.all_scores[type].values()
values = {key: [d[key] for d in dicts] for key in (self.configuration_keys + ['Score'])}
self.add_per_configuration_type_plots(type.capitalize(), colour, iterations, values)

self.chart_plotter.update_display()
self.display_table()

def display_table(self):
if self.plot_table:
display(self.df)

def add_overall_plots(self):
iterations = list(range(self.current_iteration))
self.chart_plotter.plot_best_scores(iterations, self.best_scores)

def add_per_configuration_type_plots(self, configuration_type: str, colour: str, iterations: List[int],
values: Dict):
self.chart_plotter.plot_scores_by_type(configuration_type, colour, list(iterations),
values['Score'])


class DemoWith3dPlot(Demo):
def __init__(self, minimum: float, maximum: float, score_function,
use_plotly: bool = None, minimise: bool = None, display_frequency: int = None,
use_3d_log_scale: bool = None, detail: int = 100):
super().__init__(configuration_keys=['x', 'y'], use_plotly=use_plotly, minimise=minimise, use_3d_plot=True,
display_frequency=display_frequency)
self.minimum = minimum
self.maximum = maximum
self.score_function = score_function

self.detail = detail
x_space = np.linspace(minimum, maximum, num=detail)
y_space = np.linspace(minimum, maximum, num=detail)
self.X, self.Y = np.meshgrid(x_space, y_space)

if use_3d_log_scale is None:
use_3d_log_scale = self.chart_plotter.minimise
self.use_3d_log_scale = use_3d_log_scale

if use_3d_log_scale:
self.Z = np.log(score_function(self.X, self.Y) + 1)
else:
self.Z = np.vectorize(score_function)(self.X, self.Y)

def add_overall_plots(self):
super().add_overall_plots()
self.chart_plotter.plot_3d_surface(self.X, self.Y, self.Z)

def add_per_configuration_type_plots(self, configuration_type: str, colour: str, iterations: List[int],
values: Dict):
super().add_per_configuration_type_plots(configuration_type, colour, iterations, values)

scores = values['Score']
if self.use_3d_log_scale:
scores = np.log([score + 1 for score in scores])
self.chart_plotter.plot_3d_scores_by_type(configuration_type, colour, values['x'], values['y'], scores)

def display_random_search(self):
RandomSearchDemo(self).display_all()

def display_grid_search(self):
GridSearchDemo(self).display_all()


class ComparisonWith3dDemo(DemoWith3dPlot):
def __init__(self, parent: DemoWith3dPlot, comparison_type: str):
super().__init__(minimum=parent.minimum, maximum=parent.maximum, score_function=parent.score_function,
use_plotly=parent.use_plotly, minimise=parent.chart_plotter.minimise, detail=parent.detail,
use_3d_log_scale=parent.use_3d_log_scale, display_frequency=parent.display_frequency)
self.best_score = parent.best_score
self.number_of_iterations = len(parent.best_scores)
self.comparison_type = comparison_type

def display_all(self):
for i in range(self.number_of_iterations):
x, y = self.get_parameter_values(i)
score = self.score_function(x, y)
configuration = make_configuration(x, y, self.comparison_type)
self.update_data(configuration, score)
self.update_display()

def get_parameter_values(self, counter: int):
raise NotImplementedError()


class RandomSearchDemo(ComparisonWith3dDemo):
def __init__(self, parent: DemoWith3dPlot):
super().__init__(parent, 'random')
random.seed(101)

def display_all(self):
super().display_all()

def get_parameter_values(self, counter: int):
x = random.uniform(self.minimum, self.maximum)
y = random.uniform(self.minimum, self.maximum)
return x, y


class GridSearchDemo(ComparisonWith3dDemo):
def __init__(self, parent: DemoWith3dPlot):
super().__init__(parent, 'grid')
self.grid_size = (self.number_of_iterations // 4) * 3
self.x_grid = np.linspace(self.minimum, self.maximum, num=self.grid_size)
self.y_grid = np.linspace(self.maximum, self.minimum, num=self.grid_size)

def get_parameter_values(self, counter: int):
x = self.x_grid[counter % self.grid_size]
y = self.y_grid[counter // self.grid_size]
return x, y


def make_configuration(x: float, y: float, type: str) -> Configuration:
return Configuration({
'type': type,
'values': {
'x': x,
'y': y
},
'id': random.randint(111, 999),
'_links': {
'results': {
'href': ''
}
}
})
Loading

0 comments on commit 5caea71

Please sign in to comment.