From 35eea9ba6547db18d1fe8eded438ce88b68a5cbe Mon Sep 17 00:00:00 2001 From: Sarah Krebs Date: Fri, 8 Sep 2023 16:33:18 +0200 Subject: [PATCH 01/26] Draft for symbolic explanations plugin --- deepcave/config.py | 2 + deepcave/plugins/hyperparameter/pdp.py | 2 +- .../hyperparameter/symbolic_explanations.py | 323 ++++++++++++++++++ deepcave/utils/symbolic_regression.py | 102 ++++++ requirements.txt | 3 + 5 files changed, 431 insertions(+), 1 deletion(-) create mode 100644 deepcave/plugins/hyperparameter/symbolic_explanations.py create mode 100644 deepcave/utils/symbolic_regression.py diff --git a/deepcave/config.py b/deepcave/config.py index c568bbf5..674a338a 100644 --- a/deepcave/config.py +++ b/deepcave/config.py @@ -49,6 +49,7 @@ def PLUGINS(self) -> Dict[str, List["Plugin"]]: from deepcave.plugins.budget.budget_correlation import BudgetCorrelation from deepcave.plugins.hyperparameter.importances import Importances from deepcave.plugins.hyperparameter.pdp import PartialDependencies + from deepcave.plugins.hyperparameter.symbolic_explanations import SymbolicExplanations from deepcave.plugins.objective.configuration_cube import ConfigurationCube from deepcave.plugins.objective.cost_over_time import CostOverTime from deepcave.plugins.objective.parallel_coordinates import ParallelCoordinates @@ -75,6 +76,7 @@ def PLUGINS(self) -> Dict[str, List["Plugin"]]: "Hyperparameter Analysis": [ Importances(), PartialDependencies(), + SymbolicExplanations(), ], } return plugins diff --git a/deepcave/plugins/hyperparameter/pdp.py b/deepcave/plugins/hyperparameter/pdp.py index 4db4d92e..104ed619 100644 --- a/deepcave/plugins/hyperparameter/pdp.py +++ b/deepcave/plugins/hyperparameter/pdp.py @@ -20,7 +20,7 @@ class PartialDependencies(StaticPlugin): id = "pdp" name = "Partial Dependencies" - icon = "far fa-grip-lines" + icon = "fas fa-grip-lines" help = "docs/plugins/partial_dependencies.rst" activate_run_selection = True diff --git a/deepcave/plugins/hyperparameter/symbolic_explanations.py b/deepcave/plugins/hyperparameter/symbolic_explanations.py new file mode 100644 index 00000000..7097f52c --- /dev/null +++ b/deepcave/plugins/hyperparameter/symbolic_explanations.py @@ -0,0 +1,323 @@ +import dash_bootstrap_components as dbc +import numpy as np +import plotly.graph_objs as go +from dash import dcc, html +from pyPDP.algorithms.pdp import PDP +from gplearn.genetic import SymbolicRegressor + +from deepcave import config +from deepcave.evaluators.epm.random_forest_surrogate import RandomForestSurrogate +from deepcave.plugins.static import StaticPlugin +from deepcave.runs import Status +from deepcave.utils.layout import get_checklist_options, get_select_options, help_button +from deepcave.utils.styled_plotty import get_color, get_hyperparameter_ticks, save_image +from deepcave.utils.symbolic_regression import get_function_set, convert_symb + +GRID_POINTS_PER_AXIS = 20 +SAMPLES_PER_HP = 10 +MAX_SAMPLES = 10000 +MAX_SHOWN_SAMPLES = 100 +PARSIMONY_COEFFICIENT = 0.0001 + + +class SymbolicExplanations(StaticPlugin): + id = "symbolic_explanations" + name = "Symbolic Explanations" + icon = "fas fa-subscript" + help = "docs/plugins/partial_dependencies.rst" # TODO + activate_run_selection = True + + @staticmethod + def get_input_layout(register): + return [ + dbc.Row( + [ + dbc.Col( + [ + dbc.Label("Objective"), + dbc.Select( + id=register("objective_id", ["value", "options"], type=int), + placeholder="Select objective ...", + ), + ], + md=6, + ), + dbc.Col( + [ + dbc.Label("Budget"), + help_button( + "Combined budget means that the trial on the highest" + " evaluated budget is used.\n\n" + "Note: Selecting combined budget might be misleading if" + " a time objective is used. Often, higher budget take " + " longer to evaluate, which might negatively influence " + " the results." + ), + dbc.Select( + id=register("budget_id", ["value", "options"], type=int), + placeholder="Select budget ...", + ), + ], + md=6, + ), + ], + className="mb-3", + ), + dbc.Row( + [ + dbc.Col( + [ + dbc.Label("Hyperparameter #1"), + dbc.Select( + id=register("hyperparameter_name_1", ["value", "options"]), + placeholder="Select hyperparameter ...", + ), + ], + md=6, + ), + dbc.Col( + [ + dbc.Label("Hyperparameter #2"), + dbc.Select( + id=register("hyperparameter_name_2", ["value", "options"]), + placeholder="Select hyperparameter ...", + ), + ], + md=6, + ), + ], + ), + ] + + @staticmethod + def get_filter_layout(register): + return [ + dbc.Row( + [ + dbc.Col( + [ + html.Div( + [ + dbc.Label("Show confidence"), + help_button("Displays the confidence bands."), + dbc.Select( + id=register("show_confidence", ["value", "options"]) + ), + ] + ) + ], + md=6, + ), + dbc.Col( + [ + html.Div( + [ + dbc.Label("Show ICE curves"), + help_button( + "Displays the ICE curves from which the PDP curve is " + "derivied." + ), + dbc.Select(id=register("show_ice", ["value", "options"])), + ] + ) + ], + md=6, + ), + ], + ), + ] + + def load_inputs(self): + return { + #"show_confidence": {"options": get_select_options(binary=True), "value": "true"}, + #"show_ice": {"options": get_select_options(binary=True), "value": "true"}, + } + + def load_dependency_inputs(self, run, previous_inputs, inputs): + objective_names = run.get_objective_names() + objective_ids = run.get_objective_ids() + objective_options = get_select_options(objective_names, objective_ids) + + budgets = run.get_budgets(human=True) + budget_ids = run.get_budget_ids() + budget_options = get_checklist_options(budgets, budget_ids) + + hp_names = run.configspace.get_hyperparameter_names() + + # Get selected values + objective_value = inputs["objective_id"]["value"] + budget_value = inputs["budget_id"]["value"] + hp1_value = inputs["hyperparameter_name_1"]["value"] + + if objective_value is None: + objective_value = objective_ids[0] + budget_value = budget_ids[-1] + hp1_value = hp_names[0] + + return { + "objective_id": {"options": objective_options, "value": objective_value}, + "budget_id": {"options": budget_options, "value": budget_value}, + "hyperparameter_name_1": { + "options": get_checklist_options(hp_names), + "value": hp1_value, + }, + "hyperparameter_name_2": { + "options": get_checklist_options([None] + hp_names), + }, + } + + @staticmethod + def process(run, inputs): + # Surrogate + hp_names = run.configspace.get_hyperparameter_names() + objective = run.get_objective(inputs["objective_id"]) + budget = run.get_budget(inputs["budget_id"]) + hp1 = inputs["hyperparameter_name_1"] + hp2 = inputs["hyperparameter_name_2"] + + if objective is None: + raise RuntimeError("Objective not found.") + + # Encode data + df = run.get_encoded_data( + objective, + budget, + specific=True, + statuses=Status.SUCCESS, + ) + + X = df[hp_names].to_numpy() + Y = df[objective.name].to_numpy() + + # Let's initialize the surrogate + surrogate_model = RandomForestSurrogate(run.configspace, seed=0) + surrogate_model.fit(X, Y) + + # Prepare the hyperparameters + selected_hyperparameters = [hp1] + if hp2 is not None and hp2 != "": + selected_hyperparameters += [hp2] + + num_samples = SAMPLES_PER_HP * len(X) + # We limit the samples to max 10k + if num_samples > MAX_SAMPLES: + num_samples = MAX_SAMPLES + + # And finally call PDP + pdp = PDP.from_random_points( + surrogate_model, + selected_hyperparameter=selected_hyperparameters, + seed=0, + num_grid_points_per_axis=GRID_POINTS_PER_AXIS, + num_samples=num_samples, + ) + + x = pdp.x_pdp.tolist() + y = pdp.y_pdp.tolist() + + symb_params = dict( + population_size=5000, + generations=20, + function_set=get_function_set(), + metric="rmse", + parsimony_coefficient=PARSIMONY_COEFFICIENT, + verbose=1, + ) + + # run SR on samples + symb_model = SymbolicRegressor(**symb_params, random_state=0) + symb_model.fit(x, y) + try: + conv_expr = convert_symb(symb_model, n_dim=len(X), n_decimals=3) + except: + conv_expr = "" + + y_symbolic = symb_model.predict(x).tolist() + + return { + "x": x, + "y": y_symbolic, + "expr": str(conv_expr) + } + + @staticmethod + def get_output_layout(register): + return dcc.Graph(register("graph", "figure"), style={"height": config.FIGURE_HEIGHT}) + + @staticmethod + def load_outputs(run, inputs, outputs): + # Parse inputs + hp1_name = inputs["hyperparameter_name_1"] + hp1_idx = run.configspace.get_idx_by_hyperparameter_name(hp1_name) + hp1 = run.configspace.get_hyperparameter(hp1_name) + + hp2_name = inputs["hyperparameter_name_2"] + hp2_idx = None + hp2 = None + if hp2_name is not None and hp2_name != "": + hp2_idx = run.configspace.get_idx_by_hyperparameter_name(hp2_name) + hp2 = run.configspace.get_hyperparameter(hp2_name) + + objective = run.get_objective(inputs["objective_id"]) + objective_name = objective.name + + # Parse outputs + x = np.asarray(outputs["x"]) + y = np.asarray(outputs["y"]) + expr = outputs["expr"] + + traces = [] + if hp2_idx is None: # 1D + traces += [ + go.Scatter( + x=x[:, hp1_idx], + y=y, + line=dict(color=get_color(0, 1)), + hoverinfo="skip", + showlegend=False, + ) + ] + + tickvals, ticktext = get_hyperparameter_ticks(hp1) + layout = go.Layout( + { + "xaxis": { + "tickvals": tickvals, + "ticktext": ticktext, + "title": hp1_name, + }, + "yaxis": { + "title": objective_name, + }, + } + ) + else: + z = y + traces += [ + go.Contour( + z=z, + x=x[:, hp1_idx], + y=x[:, hp2_idx], + colorbar=dict( + title=objective_name, + ), + hoverinfo="skip", + ) + ] + + x_tickvals, x_ticktext = get_hyperparameter_ticks(hp1) + y_tickvals, y_ticktext = get_hyperparameter_ticks(hp2) + + layout = go.Layout( + dict( + xaxis=dict(tickvals=x_tickvals, ticktext=x_ticktext, title=hp1_name), + yaxis=dict(tickvals=y_tickvals, ticktext=y_ticktext, title=hp2_name), + margin=config.FIGURE_MARGIN, + title=expr + ) + ) + + figure = go.Figure(data=traces, layout=layout) + save_image(figure, "pdp.pdf") + + return figure diff --git a/deepcave/utils/symbolic_regression.py b/deepcave/utils/symbolic_regression.py new file mode 100644 index 00000000..6f999cb2 --- /dev/null +++ b/deepcave/utils/symbolic_regression.py @@ -0,0 +1,102 @@ +import sympy +import numpy as np +from gplearn import functions +from gplearn.functions import make_function + + +# Create a safe exp function which does not cause problems +def exp(x): + with np.errstate(all="ignore"): + max_value = np.full(shape=x.shape, fill_value=100000) + return np.minimum(np.exp(x), max_value) + + +def get_function_set(): + exp_func = make_function(function=exp, arity=1, name="exp") + + function_set = [ + "add", + "sub", + "mul", + "div", + "sqrt", + "log", + "sin", + "cos", + "abs", + exp_func + ] + + return function_set + +def convert_symb(symb, n_dim: int = None, n_decimals: int = None) -> sympy.core.expr: + """ + Convert a fitted symbolic regression to a simplified and potentially rounded mathematical expression. + Warning: eval is used in this function, thus it should not be used on unsanitized input (see + https://docs.sympy.org/latest/modules/core.html?highlight=eval#module-sympy.core.sympify). + + Parameters + ---------- + symb: Fitted symbolic regressor to find a simplified expression for. + n_dim: Number of input dimensions. If input has only a single dimension, X0 in expression is exchanged by x. + n_decimals: If set, round floats in the expression to this number of decimals. + + Returns + ------- + symb_conv: Converted mathematical expression. + """ + + # sqrt is protected function in gplearn, always returning sqrt(abs(x)) + sqrt_pos = [] + prev_sqrt_inserts = 0 + for i, f in enumerate(symb._program.program): + if isinstance(f, functions._Function) and f.name == "sqrt": + sqrt_pos.append(i) + for i in sqrt_pos: + symb._program.program.insert(i + prev_sqrt_inserts + 1, functions.abs1) + prev_sqrt_inserts += 1 + + # log is protected function in gplearn, always returning sqrt(abs(x)) + log_pos = [] + prev_log_inserts = 0 + for i, f in enumerate(symb._program.program): + if isinstance(f, functions._Function) and f.name == "log": + log_pos.append(i) + for i in log_pos: + symb._program.program.insert(i + prev_log_inserts + 1, functions.abs1) + prev_log_inserts += 1 + + symb_str = str(symb._program) + + + converter = { + "sub": lambda x, y: x - y, + "div": lambda x, y: x / y, + "mul": lambda x, y: x * y, + "add": lambda x, y: x + y, + "neg": lambda x: -x, + "pow": lambda x, y: x**y + } + + if symb._program.length_ > 300: + print( + f"Expression of length {symb._program._length} too long to convert, return raw string." + ) + return symb_str + + symb_conv = sympy.sympify(symb_str.replace("[", "").replace("]", ""), locals=converter) + if n_dim == 1: + x, X0 = sympy.symbols("x X0") + symb_conv = symb_conv.subs(X0, x) + if n_dim == 2: + X0, X1 = sympy.symbols("X0 X1", real=True) + symb_conv = symb_conv.subs(X0, X1) + symb_simpl = sympy.simplify(symb_conv) + + if n_decimals: + # Make sure also floats deeper in the expression tree are rounded + for a in sympy.preorder_traversal(symb_simpl): + if isinstance(a, sympy.core.numbers.Float): + symb_simpl = symb_simpl.subs(a, round(a, n_decimals)) + + return symb_simpl \ No newline at end of file diff --git a/requirements.txt b/requirements.txt index 177ef401..c22904f0 100644 --- a/requirements.txt +++ b/requirements.txt @@ -5,6 +5,9 @@ jsonlines>=3.0.0 pandas>=1.3.4 numpy>=1.22.2 matplotlib>=3.5.1 +seaborn>=0.12.2 +gplearn>=0.4.2 +sympy>=1.12 pyyaml # AutoML packages From aded2570a19c7dd14eb60137e93bb5b42a36f611 Mon Sep 17 00:00:00 2001 From: Sarah Krebs Date: Fri, 8 Sep 2023 16:35:11 +0200 Subject: [PATCH 02/26] Format --- deepcave/config.py | 4 +++- .../hyperparameter/symbolic_explanations.py | 18 +++++++--------- deepcave/utils/symbolic_regression.py | 21 +++++-------------- 3 files changed, 15 insertions(+), 28 deletions(-) diff --git a/deepcave/config.py b/deepcave/config.py index 674a338a..4aefb8b8 100644 --- a/deepcave/config.py +++ b/deepcave/config.py @@ -49,7 +49,9 @@ def PLUGINS(self) -> Dict[str, List["Plugin"]]: from deepcave.plugins.budget.budget_correlation import BudgetCorrelation from deepcave.plugins.hyperparameter.importances import Importances from deepcave.plugins.hyperparameter.pdp import PartialDependencies - from deepcave.plugins.hyperparameter.symbolic_explanations import SymbolicExplanations + from deepcave.plugins.hyperparameter.symbolic_explanations import ( + SymbolicExplanations, + ) from deepcave.plugins.objective.configuration_cube import ConfigurationCube from deepcave.plugins.objective.cost_over_time import CostOverTime from deepcave.plugins.objective.parallel_coordinates import ParallelCoordinates diff --git a/deepcave/plugins/hyperparameter/symbolic_explanations.py b/deepcave/plugins/hyperparameter/symbolic_explanations.py index 7097f52c..9f094ed9 100644 --- a/deepcave/plugins/hyperparameter/symbolic_explanations.py +++ b/deepcave/plugins/hyperparameter/symbolic_explanations.py @@ -2,8 +2,8 @@ import numpy as np import plotly.graph_objs as go from dash import dcc, html -from pyPDP.algorithms.pdp import PDP from gplearn.genetic import SymbolicRegressor +from pyPDP.algorithms.pdp import PDP from deepcave import config from deepcave.evaluators.epm.random_forest_surrogate import RandomForestSurrogate @@ -11,7 +11,7 @@ from deepcave.runs import Status from deepcave.utils.layout import get_checklist_options, get_select_options, help_button from deepcave.utils.styled_plotty import get_color, get_hyperparameter_ticks, save_image -from deepcave.utils.symbolic_regression import get_function_set, convert_symb +from deepcave.utils.symbolic_regression import convert_symb, get_function_set GRID_POINTS_PER_AXIS = 20 SAMPLES_PER_HP = 10 @@ -24,7 +24,7 @@ class SymbolicExplanations(StaticPlugin): id = "symbolic_explanations" name = "Symbolic Explanations" icon = "fas fa-subscript" - help = "docs/plugins/partial_dependencies.rst" # TODO + help = "docs/plugins/partial_dependencies.rst" # TODO activate_run_selection = True @staticmethod @@ -129,8 +129,8 @@ def get_filter_layout(register): def load_inputs(self): return { - #"show_confidence": {"options": get_select_options(binary=True), "value": "true"}, - #"show_ice": {"options": get_select_options(binary=True), "value": "true"}, + # "show_confidence": {"options": get_select_options(binary=True), "value": "true"}, + # "show_ice": {"options": get_select_options(binary=True), "value": "true"}, } def load_dependency_inputs(self, run, previous_inputs, inputs): @@ -234,11 +234,7 @@ def process(run, inputs): y_symbolic = symb_model.predict(x).tolist() - return { - "x": x, - "y": y_symbolic, - "expr": str(conv_expr) - } + return {"x": x, "y": y_symbolic, "expr": str(conv_expr)} @staticmethod def get_output_layout(register): @@ -313,7 +309,7 @@ def load_outputs(run, inputs, outputs): xaxis=dict(tickvals=x_tickvals, ticktext=x_ticktext, title=hp1_name), yaxis=dict(tickvals=y_tickvals, ticktext=y_ticktext, title=hp2_name), margin=config.FIGURE_MARGIN, - title=expr + title=expr, ) ) diff --git a/deepcave/utils/symbolic_regression.py b/deepcave/utils/symbolic_regression.py index 6f999cb2..c726914f 100644 --- a/deepcave/utils/symbolic_regression.py +++ b/deepcave/utils/symbolic_regression.py @@ -1,5 +1,5 @@ -import sympy import numpy as np +import sympy from gplearn import functions from gplearn.functions import make_function @@ -14,21 +14,11 @@ def exp(x): def get_function_set(): exp_func = make_function(function=exp, arity=1, name="exp") - function_set = [ - "add", - "sub", - "mul", - "div", - "sqrt", - "log", - "sin", - "cos", - "abs", - exp_func - ] + function_set = ["add", "sub", "mul", "div", "sqrt", "log", "sin", "cos", "abs", exp_func] return function_set + def convert_symb(symb, n_dim: int = None, n_decimals: int = None) -> sympy.core.expr: """ Convert a fitted symbolic regression to a simplified and potentially rounded mathematical expression. @@ -68,14 +58,13 @@ def convert_symb(symb, n_dim: int = None, n_decimals: int = None) -> sympy.core. symb_str = str(symb._program) - converter = { "sub": lambda x, y: x - y, "div": lambda x, y: x / y, "mul": lambda x, y: x * y, "add": lambda x, y: x + y, "neg": lambda x: -x, - "pow": lambda x, y: x**y + "pow": lambda x, y: x**y, } if symb._program.length_ > 300: @@ -99,4 +88,4 @@ def convert_symb(symb, n_dim: int = None, n_decimals: int = None) -> sympy.core. if isinstance(a, sympy.core.numbers.Float): symb_simpl = symb_simpl.subs(a, round(a, n_decimals)) - return symb_simpl \ No newline at end of file + return symb_simpl From 252ea68532b7fec3364784496a681ec5c28ddc32 Mon Sep 17 00:00:00 2001 From: Sarah Krebs Date: Wed, 27 Sep 2023 12:59:38 +0200 Subject: [PATCH 03/26] Filter out categorical HPs for symbolic explanations --- deepcave/plugins/hyperparameter/symbolic_explanations.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/deepcave/plugins/hyperparameter/symbolic_explanations.py b/deepcave/plugins/hyperparameter/symbolic_explanations.py index 9f094ed9..12e964f0 100644 --- a/deepcave/plugins/hyperparameter/symbolic_explanations.py +++ b/deepcave/plugins/hyperparameter/symbolic_explanations.py @@ -1,6 +1,7 @@ import dash_bootstrap_components as dbc import numpy as np import plotly.graph_objs as go +from ConfigSpace.hyperparameters import CategoricalHyperparameter from dash import dcc, html from gplearn.genetic import SymbolicRegressor from pyPDP.algorithms.pdp import PDP @@ -142,7 +143,12 @@ def load_dependency_inputs(self, run, previous_inputs, inputs): budget_ids = run.get_budget_ids() budget_options = get_checklist_options(budgets, budget_ids) - hp_names = run.configspace.get_hyperparameter_names() + hp_dict = run.configspace.get_hyperparameters_dict() + hp_names_numerical = [] + for k, v in hp_dict.items(): + if not isinstance(v, CategoricalHyperparameter): + hp_names_numerical.append(k) + hp_names = hp_names_numerical # Get selected values objective_value = inputs["objective_id"]["value"] From a510db8989ab74fd6314e6ec44498f3bfe05f251 Mon Sep 17 00:00:00 2001 From: Sarah Krebs Date: Wed, 27 Sep 2023 17:22:39 +0200 Subject: [PATCH 04/26] Handling sympy timeouts --- .../hyperparameter/symbolic_explanations.py | 44 +++++++++++++++---- deepcave/utils/symbolic_regression.py | 6 +++ 2 files changed, 41 insertions(+), 9 deletions(-) diff --git a/deepcave/plugins/hyperparameter/symbolic_explanations.py b/deepcave/plugins/hyperparameter/symbolic_explanations.py index 12e964f0..65251ba4 100644 --- a/deepcave/plugins/hyperparameter/symbolic_explanations.py +++ b/deepcave/plugins/hyperparameter/symbolic_explanations.py @@ -1,3 +1,5 @@ +import signal + import dash_bootstrap_components as dbc import numpy as np import plotly.graph_objs as go @@ -18,7 +20,6 @@ SAMPLES_PER_HP = 10 MAX_SAMPLES = 10000 MAX_SHOWN_SAMPLES = 100 -PARSIMONY_COEFFICIENT = 0.0001 class SymbolicExplanations(StaticPlugin): @@ -88,6 +89,18 @@ def get_input_layout(register): ), ], ), + dbc.Row( + [ + dbc.Col( + [ + dbc.Label("Parsimony Hyperparameter"), + help_button("Controls the complexity of the resulting formulas."), + dbc.Input(id=register("parsimony", type=float), type="float"), + ], + md=6, + ), + ], + ), ] @staticmethod @@ -130,7 +143,7 @@ def get_filter_layout(register): def load_inputs(self): return { - # "show_confidence": {"options": get_select_options(binary=True), "value": "true"}, + "parsimony": {"value": "0.0001"}, # "show_ice": {"options": get_select_options(binary=True), "value": "true"}, } @@ -154,6 +167,7 @@ def load_dependency_inputs(self, run, previous_inputs, inputs): objective_value = inputs["objective_id"]["value"] budget_value = inputs["budget_id"]["value"] hp1_value = inputs["hyperparameter_name_1"]["value"] + parsimony = inputs["parsimony"]["value"] if objective_value is None: objective_value = objective_ids[0] @@ -170,6 +184,7 @@ def load_dependency_inputs(self, run, previous_inputs, inputs): "hyperparameter_name_2": { "options": get_checklist_options([None] + hp_names), }, + "parsimony": {"value": inputs["parsimony"]["value"]}, } @staticmethod @@ -180,6 +195,7 @@ def process(run, inputs): budget = run.get_budget(inputs["budget_id"]) hp1 = inputs["hyperparameter_name_1"] hp2 = inputs["hyperparameter_name_2"] + parsimony = inputs["parsimony"] if objective is None: raise RuntimeError("Objective not found.") @@ -226,21 +242,31 @@ def process(run, inputs): generations=20, function_set=get_function_set(), metric="rmse", - parsimony_coefficient=PARSIMONY_COEFFICIENT, + parsimony_coefficient=parsimony, verbose=1, ) # run SR on samples symb_model = SymbolicRegressor(**symb_params, random_state=0) symb_model.fit(x, y) - try: - conv_expr = convert_symb(symb_model, n_dim=len(X), n_decimals=3) - except: - conv_expr = "" - y_symbolic = symb_model.predict(x).tolist() + def handler(signo, frame): + raise RuntimeError + + signal.signal(signal.SIGALRM, handler) + signal.alarm(6) # seconds + while True: + try: + conv_expr = convert_symb(symb_model, n_dim=len(X), n_decimals=3) + except: + conv_expr = ( + "The conversion of the expression failed. Please try another seed or increase " + "the parsimony hyperparameter to obtain a symbolic explanation." + ) + + y_symbolic = symb_model.predict(x).tolist() - return {"x": x, "y": y_symbolic, "expr": str(conv_expr)} + return {"x": x, "y": y_symbolic, "expr": str(conv_expr)} @staticmethod def get_output_layout(register): diff --git a/deepcave/utils/symbolic_regression.py b/deepcave/utils/symbolic_regression.py index c726914f..df89f0bc 100644 --- a/deepcave/utils/symbolic_regression.py +++ b/deepcave/utils/symbolic_regression.py @@ -3,6 +3,10 @@ from gplearn import functions from gplearn.functions import make_function +from deepcave.utils.logs import get_logger + +logger = get_logger(__name__) + # Create a safe exp function which does not cause problems def exp(x): @@ -80,6 +84,8 @@ def convert_symb(symb, n_dim: int = None, n_decimals: int = None) -> sympy.core. if n_dim == 2: X0, X1 = sympy.symbols("X0 X1", real=True) symb_conv = symb_conv.subs(X0, X1) + + logger.debug("Start to simplify the expression with Sympy.") symb_simpl = sympy.simplify(symb_conv) if n_decimals: From 60580c525a1b56eeece7cf07f67a7821574f4410 Mon Sep 17 00:00:00 2001 From: Sarah Krebs Date: Fri, 22 Dec 2023 13:32:17 +0100 Subject: [PATCH 05/26] Improvements for symbolic explanations plugin --- .../hyperparameter/symbolic_explanations.py | 199 ++++++++++++------ deepcave/utils/symbolic_regression.py | 23 +- 2 files changed, 149 insertions(+), 73 deletions(-) diff --git a/deepcave/plugins/hyperparameter/symbolic_explanations.py b/deepcave/plugins/hyperparameter/symbolic_explanations.py index 65251ba4..581ae5ba 100644 --- a/deepcave/plugins/hyperparameter/symbolic_explanations.py +++ b/deepcave/plugins/hyperparameter/symbolic_explanations.py @@ -16,7 +16,7 @@ from deepcave.utils.styled_plotty import get_color, get_hyperparameter_ticks, save_image from deepcave.utils.symbolic_regression import convert_symb, get_function_set -GRID_POINTS_PER_AXIS = 20 +SR_TRAIN_POINTS_PER_AXIS = 20 SAMPLES_PER_HP = 10 MAX_SAMPLES = 10000 MAX_SHOWN_SAMPLES = 100 @@ -88,63 +88,111 @@ def get_input_layout(register): md=6, ), ], + className="mb-3", ), dbc.Row( [ dbc.Col( [ - dbc.Label("Parsimony Hyperparameter"), - help_button("Controls the complexity of the resulting formulas."), - dbc.Input(id=register("parsimony", type=float), type="float"), + html.Div( + [ + dbc.Label("Parsimony coefficient"), + help_button( + "Penalizes the complexity of the resulting formulas." + ), + dcc.Slider( + id=register("parsimony", "value", type=int), + marks=dict([i, str(10**i)] for i in range(-8, 1)), + min=-8, + max=0, + step=1, + updatemode="drag", + ), + ], + ) ], - md=6, - ), + ) ], + className="mb-3", ), - ] - - @staticmethod - def get_filter_layout(register): - return [ - dbc.Row( + html.Details( [ - dbc.Col( + html.Summary("Additional options for symbolic regression configuration"), + dbc.Row( [ - html.Div( + dbc.Col( [ - dbc.Label("Show confidence"), - help_button("Displays the confidence bands."), - dbc.Select( - id=register("show_confidence", ["value", "options"]) + dbc.Label("Generations"), + help_button("The number of generations to evolve."), + dbc.Input( + id=register("generations", type=int), + type="number", + min=5, + step=5, ), - ] - ) + ], + md=6, + ), + dbc.Col( + [ + dbc.Label("Population Size"), + help_button( + "The number of formulas competing in each generation." + ), + dbc.Input( + id=register("population_size", type=int), + type="number", + min=1000, + step=1000, + ), + ], + md=6, + ), ], - md=6, + className="mb-3", + style={"marginTop": "0.8em"}, ), - dbc.Col( + dbc.Row( [ - html.Div( + dbc.Col( [ - dbc.Label("Show ICE curves"), + dbc.Label("Random seed"), help_button( - "Displays the ICE curves from which the PDP curve is " - "derivied." + "The random seed to be used in the symbolic regression." ), - dbc.Select(id=register("show_ice", ["value", "options"])), - ] - ) + dbc.Input( + id=register("random_seed", type=int), type="number", min=0 + ), + ], + md=6, + ), + dbc.Col( + [ + dbc.Label("Metric"), + help_button( + "The metric to evaluate the fitness of the formulas." + ), + dbc.Select(id=register("metric", ["value", "options"])), + ], + md=6, + ), ], - md=6, + className="mb-3", ), - ], + ] ), ] def load_inputs(self): return { - "parsimony": {"value": "0.0001"}, - # "show_ice": {"options": get_select_options(binary=True), "value": "true"}, + "parsimony": {"value": "-4"}, + "generations": {"value": "10"}, + "population_size": {"value": "5000"}, + "random_seed": {"value": "0"}, + "metric": { + "options": get_select_options(values=["rmse", "mse", "mean absolute error"]), + "value": "rmse", + }, } def load_dependency_inputs(self, run, previous_inputs, inputs): @@ -167,7 +215,6 @@ def load_dependency_inputs(self, run, previous_inputs, inputs): objective_value = inputs["objective_id"]["value"] budget_value = inputs["budget_id"]["value"] hp1_value = inputs["hyperparameter_name_1"]["value"] - parsimony = inputs["parsimony"]["value"] if objective_value is None: objective_value = objective_ids[0] @@ -184,7 +231,6 @@ def load_dependency_inputs(self, run, previous_inputs, inputs): "hyperparameter_name_2": { "options": get_checklist_options([None] + hp_names), }, - "parsimony": {"value": inputs["parsimony"]["value"]}, } @staticmethod @@ -195,7 +241,11 @@ def process(run, inputs): budget = run.get_budget(inputs["budget_id"]) hp1 = inputs["hyperparameter_name_1"] hp2 = inputs["hyperparameter_name_2"] - parsimony = inputs["parsimony"] + parsimony = 10 ** inputs["parsimony"] + generations = inputs["generations"] + population_size = inputs["population_size"] + random_seed = inputs["random_seed"] + metric = inputs["metric"] if objective is None: raise RuntimeError("Objective not found.") @@ -217,37 +267,56 @@ def process(run, inputs): # Prepare the hyperparameters selected_hyperparameters = [hp1] + idx1 = run.configspace.get_idx_by_hyperparameter_name(hp1) + idxs = [idx1] if hp2 is not None and hp2 != "": selected_hyperparameters += [hp2] + idx2 = run.configspace.get_idx_by_hyperparameter_name(hp2) + idxs += [idx2] + + if len(selected_hyperparameters) < len(hp_names): + num_samples = SAMPLES_PER_HP * len(X) + # We limit the samples to max 10k + if num_samples > MAX_SAMPLES: + num_samples = MAX_SAMPLES + + # And finally call PDP + pdp = PDP.from_random_points( + surrogate_model, + selected_hyperparameter=selected_hyperparameters, + seed=0, + num_grid_points_per_axis=SR_TRAIN_POINTS_PER_AXIS, + num_samples=num_samples, + ) - num_samples = SAMPLES_PER_HP * len(X) - # We limit the samples to max 10k - if num_samples > MAX_SAMPLES: - num_samples = MAX_SAMPLES - - # And finally call PDP - pdp = PDP.from_random_points( - surrogate_model, - selected_hyperparameter=selected_hyperparameters, - seed=0, - num_grid_points_per_axis=GRID_POINTS_PER_AXIS, - num_samples=num_samples, - ) + x = pdp.x_pdp[:, idxs].tolist() + y = pdp.y_pdp.tolist() - x = pdp.x_pdp.tolist() - y = pdp.y_pdp.tolist() + else: + cs = surrogate_model.config_space + random_samples = np.asarray( + [ + config.get_array() + for config in cs.sample_configuration( + SR_TRAIN_POINTS_PER_AXIS ** len(selected_hyperparameters) + ) + ] + ) + x = random_samples.tolist() + y = surrogate_model.predict(random_samples)[0] symb_params = dict( - population_size=5000, - generations=20, + population_size=population_size, + generations=generations, function_set=get_function_set(), - metric="rmse", + metric=metric, parsimony_coefficient=parsimony, + random_state=random_seed, verbose=1, ) # run SR on samples - symb_model = SymbolicRegressor(**symb_params, random_state=0) + symb_model = SymbolicRegressor(**symb_params) symb_model.fit(x, y) def handler(signo, frame): @@ -257,7 +326,9 @@ def handler(signo, frame): signal.alarm(6) # seconds while True: try: - conv_expr = convert_symb(symb_model, n_dim=len(X), n_decimals=3) + conv_expr = convert_symb( + symb_model, n_decimals=3, hp_names=selected_hyperparameters + ) except: conv_expr = ( "The conversion of the expression failed. Please try another seed or increase " @@ -276,14 +347,11 @@ def get_output_layout(register): def load_outputs(run, inputs, outputs): # Parse inputs hp1_name = inputs["hyperparameter_name_1"] - hp1_idx = run.configspace.get_idx_by_hyperparameter_name(hp1_name) hp1 = run.configspace.get_hyperparameter(hp1_name) hp2_name = inputs["hyperparameter_name_2"] - hp2_idx = None hp2 = None if hp2_name is not None and hp2_name != "": - hp2_idx = run.configspace.get_idx_by_hyperparameter_name(hp2_name) hp2 = run.configspace.get_hyperparameter(hp2_name) objective = run.get_objective(inputs["objective_id"]) @@ -295,10 +363,10 @@ def load_outputs(run, inputs, outputs): expr = outputs["expr"] traces = [] - if hp2_idx is None: # 1D + if hp2 is None: # 1D traces += [ go.Scatter( - x=x[:, hp1_idx], + x=x[:, 0], y=y, line=dict(color=get_color(0, 1)), hoverinfo="skip", @@ -317,6 +385,7 @@ def load_outputs(run, inputs, outputs): "yaxis": { "title": objective_name, }, + "title": f"{objective.name} = {expr}", } ) else: @@ -324,8 +393,8 @@ def load_outputs(run, inputs, outputs): traces += [ go.Contour( z=z, - x=x[:, hp1_idx], - y=x[:, hp2_idx], + x=x[:, 0], + y=x[:, 1], colorbar=dict( title=objective_name, ), @@ -341,11 +410,11 @@ def load_outputs(run, inputs, outputs): xaxis=dict(tickvals=x_tickvals, ticktext=x_ticktext, title=hp1_name), yaxis=dict(tickvals=y_tickvals, ticktext=y_ticktext, title=hp2_name), margin=config.FIGURE_MARGIN, - title=expr, + title=f"{objective.name} = {expr}", ) ) figure = go.Figure(data=traces, layout=layout) - save_image(figure, "pdp.pdf") + save_image(figure, "symbolic_explanation.pdf") return figure diff --git a/deepcave/utils/symbolic_regression.py b/deepcave/utils/symbolic_regression.py index df89f0bc..04be91c0 100644 --- a/deepcave/utils/symbolic_regression.py +++ b/deepcave/utils/symbolic_regression.py @@ -23,7 +23,7 @@ def get_function_set(): return function_set -def convert_symb(symb, n_dim: int = None, n_decimals: int = None) -> sympy.core.expr: +def convert_symb(symb, n_decimals: int = None, hp_names: list = None) -> sympy.core.expr: """ Convert a fitted symbolic regression to a simplified and potentially rounded mathematical expression. Warning: eval is used in this function, thus it should not be used on unsanitized input (see @@ -32,8 +32,8 @@ def convert_symb(symb, n_dim: int = None, n_decimals: int = None) -> sympy.core. Parameters ---------- symb: Fitted symbolic regressor to find a simplified expression for. - n_dim: Number of input dimensions. If input has only a single dimension, X0 in expression is exchanged by x. n_decimals: If set, round floats in the expression to this number of decimals. + hp_names: If set, replace X0 and X1 in the expression by the names given. Returns ------- @@ -78,12 +78,19 @@ def convert_symb(symb, n_dim: int = None, n_decimals: int = None) -> sympy.core. return symb_str symb_conv = sympy.sympify(symb_str.replace("[", "").replace("]", ""), locals=converter) - if n_dim == 1: - x, X0 = sympy.symbols("x X0") - symb_conv = symb_conv.subs(X0, x) - if n_dim == 2: - X0, X1 = sympy.symbols("X0 X1", real=True) - symb_conv = symb_conv.subs(X0, X1) + if hp_names is not None: + if len(hp_names) == 1: + X0, hp0 = sympy.symbols(f"X0 {hp_names[0]}") + symb_conv = symb_conv.subs(X0, hp0) + elif len(hp_names) == 2: + X0, hp0, X1, hp1 = sympy.symbols(f"X0 {hp_names[0]} X1 {hp_names[1]}") + symb_conv = symb_conv.subs(X0, hp0) + symb_conv = symb_conv.subs(X1, hp1) + else: + raise ValueError( + f"Numer of hyperparameters to be explained by symbolic explanations must not " + f"be larger than 2" + ) logger.debug("Start to simplify the expression with Sympy.") symb_simpl = sympy.simplify(symb_conv) From 4f2636eb2c5309e863701347a2f8245fab41bf4b Mon Sep 17 00:00:00 2001 From: Sarah Krebs Date: Fri, 22 Dec 2023 16:59:20 +0100 Subject: [PATCH 06/26] Add exit button and delete jobs on exit --- configs/local.py | 1 + configs/server.py | 1 + deepcave/cli.py | 9 +++++--- deepcave/config.py | 1 + deepcave/layouts/header.py | 44 ++++++++++++++++++++++++++++++++++++-- deepcave/server.py | 2 +- 6 files changed, 52 insertions(+), 6 deletions(-) diff --git a/configs/local.py b/configs/local.py index 9540c64d..b16e9f83 100644 --- a/configs/local.py +++ b/configs/local.py @@ -3,4 +3,5 @@ class Config(C): DEBUG = True + DEV_TOOLS = False REFRESH_RATE: int = 2000 diff --git a/configs/server.py b/configs/server.py index c7365928..09390c0c 100644 --- a/configs/server.py +++ b/configs/server.py @@ -3,6 +3,7 @@ class Config(C): DEBUG = False + DEV_TOOLS = False REDIS_PORT = 6379 REDIS_ADDRESS = "redis://localhost" diff --git a/deepcave/cli.py b/deepcave/cli.py index a16784a3..acb1fff8 100644 --- a/deepcave/cli.py +++ b/deepcave/cli.py @@ -1,5 +1,4 @@ -from typing import Any, List - +import os import multiprocessing import subprocess from pathlib import Path @@ -49,4 +48,8 @@ def execute(_) -> None: def main() -> None: - app.run(execute) + try: + app.run(execute) + except KeyboardInterrupt: + print('KeyboardInterrupt') + os._exit(130) diff --git a/deepcave/config.py b/deepcave/config.py index 4aefb8b8..5e3de163 100644 --- a/deepcave/config.py +++ b/deepcave/config.py @@ -7,6 +7,7 @@ class Config: # General config TITLE: str = "DeepCAVE" DEBUG: bool = True + DEV_TOOLS: bool = False # How often to refresh background activities (such as update the sidebar or process button for # static plugins). Value in milliseconds. REFRESH_RATE: int = 500 diff --git a/deepcave/layouts/header.py b/deepcave/layouts/header.py index ca11aa03..3aa3ed9a 100644 --- a/deepcave/layouts/header.py +++ b/deepcave/layouts/header.py @@ -9,7 +9,11 @@ class HeaderLayout(Layout): def register_callbacks(self) -> None: super().register_callbacks() + self._callback_update_matplotlib_mode() + self._callback_exit_deepcave() + self._callback_exit_deepcave2() + def _callback_update_matplotlib_mode(self) -> None: outputs = [ Output("matplotlib-mode-toggle", "color"), Output("matplotlib-mode-badge", "children"), @@ -21,7 +25,7 @@ def register_callbacks(self) -> None: ] @app.callback(outputs, inputs) - def update_matplotlib_mode(n_clicks, pathname): + def callback(n_clicks, pathname): update = None mode = c.get("matplotlib-mode") if mode is None: @@ -37,6 +41,35 @@ def update_matplotlib_mode(n_clicks, pathname): else: return "secondary", "off", update + def _callback_exit_deepcave(self) -> None: + inputs = [Input("exit-deepcave", "n_clicks")] + outputs = [ + Output("exit-deepcave", "color"), + Output("exit-deepcave", "children"), + Output("exit-deepcave", "disabled"), + ] + + @app.callback(inputs, outputs) + def callback(n_clicks): + if n_clicks is not None: + from deepcave import queue + queue.delete_jobs() + return "danger", "Terminated DeepCAVE", True + else: + return "primary", "Exit", False + + def _callback_exit_deepcave2(self) -> None: + inputs = [Input("exit-deepcave", "n_clicks")] + outputs = [] + + @app.callback(inputs, outputs) + def callback(n_clicks): + if n_clicks is not None: + import os + import time + time.sleep(1) + os._exit(130) + def __call__(self) -> html.Header: return html.Header( className="navbar navbar-dark sticky-top bg-dark flex-md-nowrap p-0 shadow", @@ -59,5 +92,12 @@ def __call__(self) -> html.Header: className="me-2", id="matplotlib-mode-toggle", ), - ], + dbc.Button( + "Exit", + color="secondary", + className="me-2", + id="exit-deepcave", + disabled=False + ), + ], ) diff --git a/deepcave/server.py b/deepcave/server.py index de786638..b59d3fbd 100644 --- a/deepcave/server.py +++ b/deepcave/server.py @@ -4,4 +4,4 @@ if __name__ == "__main__": print("\n-------------STARTING SERVER-------------") app.layout = MainLayout(config.PLUGINS)() - app.run_server(debug=config.DEBUG, port=config.DASH_PORT, host=config.DASH_ADDRESS) + app.run_server(debug=config.DEBUG, dev_tools_ui=config.DEV_TOOLS, port=config.DASH_PORT, host=config.DASH_ADDRESS) From 803cfc359d0b168ab1333ebb7660e1695b39066c Mon Sep 17 00:00:00 2001 From: Sarah Krebs Date: Wed, 3 Jan 2024 11:10:57 +0100 Subject: [PATCH 07/26] Update author email --- deepcave/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/deepcave/__init__.py b/deepcave/__init__.py index 75139590..8d53bae7 100644 --- a/deepcave/__init__.py +++ b/deepcave/__init__.py @@ -9,7 +9,7 @@ name = "DeepCAVE" package_name = "deepcave" author = "R. Sass and E. Bergman and A. Biedenkapp and F. Hutter and M. Lindauer" -author_email = "sass@tnt.uni-hannover.de" +author_email = "s.segel@ai.uni-hannover.de" description = "An interactive framework to visualize and analyze your AutoML process in real-time." url = "automl.org" project_urls = { From cd5b1c5d32812bdb2db7d191d1a5ef99f7efa2d1 Mon Sep 17 00:00:00 2001 From: Sarah Krebs Date: Wed, 3 Jan 2024 14:48:50 +0100 Subject: [PATCH 08/26] Add symb expl docs and handle long formulas --- .../hyperparameter/symbolic_explanations.py | 23 ++++++++++++------ deepcave/utils/symbolic_regression.py | 16 ++++++++---- docs/images/plugins/symbolic_explanations.png | Bin 0 -> 240390 bytes docs/plugins/index.rst | 3 ++- docs/plugins/symbolic_explanations.rst | 14 +++++++++++ 5 files changed, 42 insertions(+), 14 deletions(-) create mode 100644 docs/images/plugins/symbolic_explanations.png create mode 100644 docs/plugins/symbolic_explanations.rst diff --git a/deepcave/plugins/hyperparameter/symbolic_explanations.py b/deepcave/plugins/hyperparameter/symbolic_explanations.py index 581ae5ba..07d4221f 100644 --- a/deepcave/plugins/hyperparameter/symbolic_explanations.py +++ b/deepcave/plugins/hyperparameter/symbolic_explanations.py @@ -26,7 +26,7 @@ class SymbolicExplanations(StaticPlugin): id = "symbolic_explanations" name = "Symbolic Explanations" icon = "fas fa-subscript" - help = "docs/plugins/partial_dependencies.rst" # TODO + help = "docs/plugins/symbolic_explanations.rst" activate_run_selection = True @staticmethod @@ -326,18 +326,25 @@ def handler(signo, frame): signal.alarm(6) # seconds while True: try: - conv_expr = convert_symb( - symb_model, n_decimals=3, hp_names=selected_hyperparameters + conv_expr = ( + f"{objective.name} = " + f"{convert_symb(symb_model, n_decimals=3, hp_names=selected_hyperparameters)}" ) except: conv_expr = ( - "The conversion of the expression failed. Please try another seed or increase " - "the parsimony hyperparameter to obtain a symbolic explanation." + "Conversion of the expression failed. Please try another seed or increase " + "the parsimony hyperparameter." + ) + + if len(conv_expr) > 115: + conv_expr = ( + "Expression is too long to display. Please try another seed or increase " + "the parsimony hyperparameter." ) y_symbolic = symb_model.predict(x).tolist() - return {"x": x, "y": y_symbolic, "expr": str(conv_expr)} + return {"x": x, "y": y_symbolic, "expr": conv_expr} @staticmethod def get_output_layout(register): @@ -385,7 +392,7 @@ def load_outputs(run, inputs, outputs): "yaxis": { "title": objective_name, }, - "title": f"{objective.name} = {expr}", + "title": expr, } ) else: @@ -410,7 +417,7 @@ def load_outputs(run, inputs, outputs): xaxis=dict(tickvals=x_tickvals, ticktext=x_ticktext, title=hp1_name), yaxis=dict(tickvals=y_tickvals, ticktext=y_ticktext, title=hp2_name), margin=config.FIGURE_MARGIN, - title=f"{objective.name} = {expr}", + title=expr, ) ) diff --git a/deepcave/utils/symbolic_regression.py b/deepcave/utils/symbolic_regression.py index 04be91c0..a8b3c41b 100644 --- a/deepcave/utils/symbolic_regression.py +++ b/deepcave/utils/symbolic_regression.py @@ -71,13 +71,14 @@ def convert_symb(symb, n_decimals: int = None, hp_names: list = None) -> sympy.c "pow": lambda x, y: x**y, } + # Abort conversion for very long programs, as they take too much time or do not finish at all. if symb._program.length_ > 300: - print( - f"Expression of length {symb._program._length} too long to convert, return raw string." - ) return symb_str + # Convert formula string to SymPy object symb_conv = sympy.sympify(symb_str.replace("[", "").replace("]", ""), locals=converter) + + # Replace variable names in formula by hyperparameter names if hp_names is not None: if len(hp_names) == 1: X0, hp0 = sympy.symbols(f"X0 {hp_names[0]}") @@ -92,9 +93,14 @@ def convert_symb(symb, n_decimals: int = None, hp_names: list = None) -> sympy.c f"be larger than 2" ) - logger.debug("Start to simplify the expression with Sympy.") - symb_simpl = sympy.simplify(symb_conv) + # Simplify the formula + try: + # Simplification can fail in some cases. If so, use the unsimplified version. + symb_simpl = sympy.simplify(symb_conv) + except: + symb_simpl = symb_conv + # Round floats to n_decimals if n_decimals: # Make sure also floats deeper in the expression tree are rounded for a in sympy.preorder_traversal(symb_simpl): diff --git a/docs/images/plugins/symbolic_explanations.png b/docs/images/plugins/symbolic_explanations.png new file mode 100644 index 0000000000000000000000000000000000000000..109aaf1df5cc0c5639f08150748bb1cb21b4234e GIT binary patch literal 240390 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

g0~bDjPWy!vf5@6A>V3Mb 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

jPlHoCD0w`9fy@$ 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 wGKT+p$geH(>i Date: Wed, 3 Jan 2024 15:23:38 +0100 Subject: [PATCH 09/26] Edit exit callbacks --- deepcave/layouts/header.py | 26 ++++++++++++-------------- 1 file changed, 12 insertions(+), 14 deletions(-) diff --git a/deepcave/layouts/header.py b/deepcave/layouts/header.py index 3aa3ed9a..41ac88b7 100644 --- a/deepcave/layouts/header.py +++ b/deepcave/layouts/header.py @@ -1,8 +1,11 @@ +import os +import time + import dash_bootstrap_components as dbc from dash import dcc, html from dash.dependencies import Input, Output -from deepcave import app, c +from deepcave import app, c, queue from deepcave.layouts import Layout @@ -10,8 +13,8 @@ class HeaderLayout(Layout): def register_callbacks(self) -> None: super().register_callbacks() self._callback_update_matplotlib_mode() - self._callback_exit_deepcave() - self._callback_exit_deepcave2() + self._callback_delete_jobs() + self._callback_terminate_deepcave() def _callback_update_matplotlib_mode(self) -> None: outputs = [ @@ -41,7 +44,7 @@ def callback(n_clicks, pathname): else: return "secondary", "off", update - def _callback_exit_deepcave(self) -> None: + def _callback_delete_jobs(self) -> None: inputs = [Input("exit-deepcave", "n_clicks")] outputs = [ Output("exit-deepcave", "color"), @@ -51,22 +54,21 @@ def _callback_exit_deepcave(self) -> None: @app.callback(inputs, outputs) def callback(n_clicks): + # When clicking the Exit button, we first want to delete existing jobs and update the button if n_clicks is not None: - from deepcave import queue queue.delete_jobs() return "danger", "Terminated DeepCAVE", True else: return "primary", "Exit", False - def _callback_exit_deepcave2(self) -> None: + def _callback_terminate_deepcave(self) -> None: inputs = [Input("exit-deepcave", "n_clicks")] outputs = [] @app.callback(inputs, outputs) def callback(n_clicks): + # Then we want to terminate DeepCAVE if n_clicks is not None: - import os - import time time.sleep(1) os._exit(130) @@ -93,11 +95,7 @@ def __call__(self) -> html.Header: id="matplotlib-mode-toggle", ), dbc.Button( - "Exit", - color="secondary", - className="me-2", - id="exit-deepcave", - disabled=False + "Exit", color="secondary", className="me-2", id="exit-deepcave", disabled=False ), - ], + ], ) From d56b82fb9df01a04e3c4b2d453a7f8e843c87ae7 Mon Sep 17 00:00:00 2001 From: Sarah Krebs Date: Wed, 3 Jan 2024 15:58:06 +0100 Subject: [PATCH 10/26] Disable debug mode --- configs/local.py | 1 - configs/server.py | 1 - deepcave/config.py | 3 +-- deepcave/server.py | 2 +- 4 files changed, 2 insertions(+), 5 deletions(-) diff --git a/configs/local.py b/configs/local.py index b16e9f83..9540c64d 100644 --- a/configs/local.py +++ b/configs/local.py @@ -3,5 +3,4 @@ class Config(C): DEBUG = True - DEV_TOOLS = False REFRESH_RATE: int = 2000 diff --git a/configs/server.py b/configs/server.py index 09390c0c..c7365928 100644 --- a/configs/server.py +++ b/configs/server.py @@ -3,7 +3,6 @@ class Config(C): DEBUG = False - DEV_TOOLS = False REDIS_PORT = 6379 REDIS_ADDRESS = "redis://localhost" diff --git a/deepcave/config.py b/deepcave/config.py index 5e3de163..0cc24f68 100644 --- a/deepcave/config.py +++ b/deepcave/config.py @@ -6,8 +6,7 @@ class Config: # General config TITLE: str = "DeepCAVE" - DEBUG: bool = True - DEV_TOOLS: bool = False + DEBUG: bool = False # How often to refresh background activities (such as update the sidebar or process button for # static plugins). Value in milliseconds. REFRESH_RATE: int = 500 diff --git a/deepcave/server.py b/deepcave/server.py index b59d3fbd..de786638 100644 --- a/deepcave/server.py +++ b/deepcave/server.py @@ -4,4 +4,4 @@ if __name__ == "__main__": print("\n-------------STARTING SERVER-------------") app.layout = MainLayout(config.PLUGINS)() - app.run_server(debug=config.DEBUG, dev_tools_ui=config.DEV_TOOLS, port=config.DASH_PORT, host=config.DASH_ADDRESS) + app.run_server(debug=config.DEBUG, port=config.DASH_PORT, host=config.DASH_ADDRESS) From 1e75d3cbc8e04895bf6e0bb063f3b5680adb9a7b Mon Sep 17 00:00:00 2001 From: Sarah Krebs Date: Wed, 3 Jan 2024 16:22:05 +0100 Subject: [PATCH 11/26] Update changelog --- CHANGELOG.md | 9 ++++++++- deepcave/cli.py | 3 +-- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b3ef73be..ca1d45dd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,7 +1,14 @@ -# Version 1.1.4 +# Version 1.2 + +## Plugins +- Add symbolic explanations plugin. ## Enhancements - Fix lower bounds of dependency versions. +- Update author email. +- Add exit button which first deletes running jobs and then terminates DeepCave. +- Nicer handling of Keyboard Interrupt. +- Disable debug mode. ## Bug-Fixes - Don't convert BOHB runs with status 'running' (consistent with SMAC). diff --git a/deepcave/cli.py b/deepcave/cli.py index acb1fff8..9231872e 100644 --- a/deepcave/cli.py +++ b/deepcave/cli.py @@ -51,5 +51,4 @@ def main() -> None: try: app.run(execute) except KeyboardInterrupt: - print('KeyboardInterrupt') - os._exit(130) + exit("KeyboardInterrupt.") From 87b02bdd63bb83d94aa1aba8c9ce2c76b7a8e3d0 Mon Sep 17 00:00:00 2001 From: Sarah Krebs Date: Wed, 3 Jan 2024 16:30:16 +0100 Subject: [PATCH 12/26] Remove signal runtime alarm from symbolic conversion --- .../hyperparameter/symbolic_explanations.py | 40 ++++++++----------- 1 file changed, 17 insertions(+), 23 deletions(-) diff --git a/deepcave/plugins/hyperparameter/symbolic_explanations.py b/deepcave/plugins/hyperparameter/symbolic_explanations.py index 07d4221f..77ecc81b 100644 --- a/deepcave/plugins/hyperparameter/symbolic_explanations.py +++ b/deepcave/plugins/hyperparameter/symbolic_explanations.py @@ -319,32 +319,26 @@ def process(run, inputs): symb_model = SymbolicRegressor(**symb_params) symb_model.fit(x, y) - def handler(signo, frame): - raise RuntimeError - - signal.signal(signal.SIGALRM, handler) - signal.alarm(6) # seconds - while True: - try: - conv_expr = ( - f"{objective.name} = " - f"{convert_symb(symb_model, n_decimals=3, hp_names=selected_hyperparameters)}" - ) - except: - conv_expr = ( - "Conversion of the expression failed. Please try another seed or increase " - "the parsimony hyperparameter." - ) + try: + conv_expr = ( + f"{objective.name} = " + f"{convert_symb(symb_model, n_decimals=3, hp_names=selected_hyperparameters)}" + ) + except: + conv_expr = ( + "Conversion of the expression failed. Please try another seed or increase " + "the parsimony hyperparameter." + ) - if len(conv_expr) > 115: - conv_expr = ( - "Expression is too long to display. Please try another seed or increase " - "the parsimony hyperparameter." - ) + if len(conv_expr) > 115: + conv_expr = ( + "Expression is too long to display. Please try another seed or increase " + "the parsimony hyperparameter." + ) - y_symbolic = symb_model.predict(x).tolist() + y_symbolic = symb_model.predict(x).tolist() - return {"x": x, "y": y_symbolic, "expr": conv_expr} + return {"x": x, "y": y_symbolic, "expr": conv_expr} @staticmethod def get_output_layout(register): From 205f6723ce745996a22ec18c02c7aead1dc8df35 Mon Sep 17 00:00:00 2001 From: Sarah Krebs Date: Wed, 3 Jan 2024 16:34:50 +0100 Subject: [PATCH 13/26] Update version number --- Makefile | 6 +++--- deepcave/__init__.py | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Makefile b/Makefile index 258de3a9..84b857e9 100644 --- a/Makefile +++ b/Makefile @@ -2,7 +2,7 @@ # are usually completed in github actions. SHELL := /bin/bash -VERSION := 1.1.3 +VERSION := 1.2 NAME := DeepCAVE PACKAGE_NAME := deepcave @@ -42,7 +42,7 @@ MYPY ?= mypy PRECOMMIT ?= pre-commit FLAKE8 ?= flake8 -install: +install: $(PIP) install -e . install-dev: @@ -115,7 +115,7 @@ build: # This is done to prevent accidental publishing but provide the same conveniences publish: clean build read -p "Did you update the version number in Makefile and deepcave/__init__.py?" - + $(PIP) install twine $(PYTHON) -m twine upload --repository testpypi ${DIST}/* @echo diff --git a/deepcave/__init__.py b/deepcave/__init__.py index 8d53bae7..84c9914c 100644 --- a/deepcave/__init__.py +++ b/deepcave/__init__.py @@ -17,7 +17,7 @@ "Source Code": "https://github.com/automl/deepcave", } copyright = f"Copyright {datetime.date.today().strftime('%Y')}, {author}" -version = "1.1.3" +version = "1.2" _exec_file = sys.argv[0] _exec_files = ["server.py", "worker.py", "sphinx-build"] From 95473b6b56c0e1ecc0fc957a3b856ac00f3c4d5d Mon Sep 17 00:00:00 2001 From: Sarah Krebs Date: Thu, 4 Jan 2024 15:55:44 +0100 Subject: [PATCH 14/26] Update changelog --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ca1d45dd..31b6ba26 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,7 +1,7 @@ # Version 1.2 ## Plugins -- Add symbolic explanations plugin. +- Add symbolic explanations plugin (#46). ## Enhancements - Fix lower bounds of dependency versions. From d8bb6a7a8fd0b32bcda72ebbc712be3cab5d1112 Mon Sep 17 00:00:00 2001 From: Sarah Krebs Date: Fri, 5 Jan 2024 16:48:20 +0100 Subject: [PATCH 15/26] Reset inputs for symb expl when changing runs --- deepcave/plugins/hyperparameter/symbolic_explanations.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/deepcave/plugins/hyperparameter/symbolic_explanations.py b/deepcave/plugins/hyperparameter/symbolic_explanations.py index 77ecc81b..f8d1b670 100644 --- a/deepcave/plugins/hyperparameter/symbolic_explanations.py +++ b/deepcave/plugins/hyperparameter/symbolic_explanations.py @@ -215,10 +215,13 @@ def load_dependency_inputs(self, run, previous_inputs, inputs): objective_value = inputs["objective_id"]["value"] budget_value = inputs["budget_id"]["value"] hp1_value = inputs["hyperparameter_name_1"]["value"] + hp2_value = inputs["hyperparameter_name_2"]["value"] if objective_value is None: objective_value = objective_ids[0] + if budget_value is None: budget_value = budget_ids[-1] + if hp1_value is None: hp1_value = hp_names[0] return { @@ -230,6 +233,7 @@ def load_dependency_inputs(self, run, previous_inputs, inputs): }, "hyperparameter_name_2": { "options": get_checklist_options([None] + hp_names), + "value": hp2_value, }, } From 77e224635fa6f0773adf6c9af91c73c5abda80d5 Mon Sep 17 00:00:00 2001 From: Sarah Krebs Date: Fri, 5 Jan 2024 17:09:21 +0100 Subject: [PATCH 16/26] Edit symb expl input settings --- deepcave/plugins/hyperparameter/symbolic_explanations.py | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/deepcave/plugins/hyperparameter/symbolic_explanations.py b/deepcave/plugins/hyperparameter/symbolic_explanations.py index f8d1b670..07353b5b 100644 --- a/deepcave/plugins/hyperparameter/symbolic_explanations.py +++ b/deepcave/plugins/hyperparameter/symbolic_explanations.py @@ -127,8 +127,7 @@ def get_input_layout(register): dbc.Input( id=register("generations", type=int), type="number", - min=5, - step=5, + min=1, ), ], md=6, @@ -142,8 +141,7 @@ def get_input_layout(register): dbc.Input( id=register("population_size", type=int), type="number", - min=1000, - step=1000, + min=1, ), ], md=6, From 77779340652ad7f4696a4c648ad44be330b2231e Mon Sep 17 00:00:00 2001 From: Sarah Krebs Date: Mon, 15 Jan 2024 15:30:41 +0100 Subject: [PATCH 17/26] Fix varying configspace index order in PDP and symbolic explanations --- CHANGELOG.md | 1 + deepcave/plugins/hyperparameter/pdp.py | 4 ++++ deepcave/plugins/hyperparameter/symbolic_explanations.py | 4 ++++ 3 files changed, 9 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 31b6ba26..4d249b31 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,7 @@ ## Bug-Fixes - Don't convert BOHB runs with status 'running' (consistent with SMAC). +- Fix varying configspace index order in PDP and symbolic explanations. # Version 1.1.3 diff --git a/deepcave/plugins/hyperparameter/pdp.py b/deepcave/plugins/hyperparameter/pdp.py index 104ed619..4157eda9 100644 --- a/deepcave/plugins/hyperparameter/pdp.py +++ b/deepcave/plugins/hyperparameter/pdp.py @@ -190,6 +190,10 @@ def process(run, inputs): surrogate_model = RandomForestSurrogate(run.configspace, seed=0) surrogate_model.fit(X, Y) + # This is necessary as the run configspace can differ from the surrogate, which would be problematic as the + # surrogate configspace is used in the PDP and the run configspace for plotting in load_outputs() + surrogate_model.config_space = run.configspace + # Prepare the hyperparameters selected_hyperparameters = [hp1] if hp2 is not None and hp2 != "": diff --git a/deepcave/plugins/hyperparameter/symbolic_explanations.py b/deepcave/plugins/hyperparameter/symbolic_explanations.py index 07353b5b..c8957c5c 100644 --- a/deepcave/plugins/hyperparameter/symbolic_explanations.py +++ b/deepcave/plugins/hyperparameter/symbolic_explanations.py @@ -267,6 +267,10 @@ def process(run, inputs): surrogate_model = RandomForestSurrogate(run.configspace, seed=0) surrogate_model.fit(X, Y) + # This is necessary as the run configspace can differ from the surrogate, which would be problematic as the + # surrogate configspace is used in the PDP and the run configspace for plotting in load_outputs() + surrogate_model.config_space = run.configspace + # Prepare the hyperparameters selected_hyperparameters = [hp1] idx1 = run.configspace.get_idx_by_hyperparameter_name(hp1) From b3723aa420cb448074aa2700ed9c42d47caee61e Mon Sep 17 00:00:00 2001 From: Sarah Krebs Date: Tue, 16 Jan 2024 13:26:46 +0100 Subject: [PATCH 18/26] Allow longer expression --- deepcave/plugins/hyperparameter/symbolic_explanations.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/deepcave/plugins/hyperparameter/symbolic_explanations.py b/deepcave/plugins/hyperparameter/symbolic_explanations.py index c8957c5c..d65aca65 100644 --- a/deepcave/plugins/hyperparameter/symbolic_explanations.py +++ b/deepcave/plugins/hyperparameter/symbolic_explanations.py @@ -336,7 +336,7 @@ def process(run, inputs): "the parsimony hyperparameter." ) - if len(conv_expr) > 115: + if len(conv_expr) > 150: conv_expr = ( "Expression is too long to display. Please try another seed or increase " "the parsimony hyperparameter." From 933a1377c8020d2fb0181d02a1fa6d06afc9a13d Mon Sep 17 00:00:00 2001 From: Sarah Krebs Date: Tue, 23 Jan 2024 10:39:51 +0100 Subject: [PATCH 19/26] Add pdp plot to symbolic explanation output --- deepcave/plugins/hyperparameter/pdp.py | 16 +++- .../hyperparameter/symbolic_explanations.py | 78 +++++++++++++------ 2 files changed, 68 insertions(+), 26 deletions(-) diff --git a/deepcave/plugins/hyperparameter/pdp.py b/deepcave/plugins/hyperparameter/pdp.py index 4157eda9..005be747 100644 --- a/deepcave/plugins/hyperparameter/pdp.py +++ b/deepcave/plugins/hyperparameter/pdp.py @@ -237,7 +237,7 @@ def get_output_layout(register): return dcc.Graph(register("graph", "figure"), style={"height": config.FIGURE_HEIGHT}) @staticmethod - def load_outputs(run, inputs, outputs): + def get_pdp_figure(run, inputs, outputs, show_confidence, show_ice, title=None): # Parse inputs hp1_name = inputs["hyperparameter_name_1"] hp1_idx = run.configspace.get_idx_by_hyperparameter_name(hp1_name) @@ -250,9 +250,6 @@ def load_outputs(run, inputs, outputs): hp2_idx = run.configspace.get_idx_by_hyperparameter_name(hp2_name) hp2 = run.configspace.get_hyperparameter(hp2_name) - show_confidence = inputs["show_confidence"] - show_ice = inputs["show_ice"] - objective = run.get_objective(inputs["objective_id"]) objective_name = objective.name @@ -323,6 +320,7 @@ def load_outputs(run, inputs, outputs): "yaxis": { "title": objective_name, }, + "title": title } ) else: @@ -349,6 +347,7 @@ def load_outputs(run, inputs, outputs): xaxis=dict(tickvals=x_tickvals, ticktext=x_ticktext, title=hp1_name), yaxis=dict(tickvals=y_tickvals, ticktext=y_ticktext, title=hp2_name), margin=config.FIGURE_MARGIN, + title=title ) ) @@ -356,3 +355,12 @@ def load_outputs(run, inputs, outputs): save_image(figure, "pdp.pdf") return figure + + @staticmethod + def load_outputs(run, inputs, outputs): + show_confidence = inputs["show_confidence"] + show_ice = inputs["show_ice"] + + figure = PartialDependencies.get_pdp_figure(run, inputs, outputs, show_confidence, show_ice) + + return figure diff --git a/deepcave/plugins/hyperparameter/symbolic_explanations.py b/deepcave/plugins/hyperparameter/symbolic_explanations.py index d65aca65..c829d7e7 100644 --- a/deepcave/plugins/hyperparameter/symbolic_explanations.py +++ b/deepcave/plugins/hyperparameter/symbolic_explanations.py @@ -1,5 +1,3 @@ -import signal - import dash_bootstrap_components as dbc import numpy as np import plotly.graph_objs as go @@ -11,6 +9,7 @@ from deepcave import config from deepcave.evaluators.epm.random_forest_surrogate import RandomForestSurrogate from deepcave.plugins.static import StaticPlugin +from deepcave.plugins.hyperparameter.pdp import PartialDependencies from deepcave.runs import Status from deepcave.utils.layout import get_checklist_options, get_select_options, help_button from deepcave.utils.styled_plotty import get_color, get_hyperparameter_ticks, save_image @@ -295,9 +294,21 @@ def process(run, inputs): num_samples=num_samples, ) - x = pdp.x_pdp[:, idxs].tolist() + x = pdp.x_pdp y = pdp.y_pdp.tolist() + # Save PDP information for PDP plot as comparison + y_pdp = y + pdp_variances = pdp.y_variances.tolist() + + # We have to cut the ICE curves because it's too much data + x_ice = pdp._ice.x_ice.tolist() + y_ice = pdp._ice.y_ice.tolist() + + if len(x_ice) > MAX_SHOWN_SAMPLES: + x_ice = x_ice[:MAX_SHOWN_SAMPLES] + y_ice = y_ice[:MAX_SHOWN_SAMPLES] + else: cs = surrogate_model.config_space random_samples = np.asarray( @@ -308,8 +319,9 @@ def process(run, inputs): ) ] ) - x = random_samples.tolist() + x = random_samples y = surrogate_model.predict(random_samples)[0] + x_ice, y_ice, pdp_variances, y_pdp = [], [], [], [] symb_params = dict( population_size=population_size, @@ -323,7 +335,7 @@ def process(run, inputs): # run SR on samples symb_model = SymbolicRegressor(**symb_params) - symb_model.fit(x, y) + symb_model.fit(x[:, idxs], y) try: conv_expr = ( @@ -342,23 +354,35 @@ def process(run, inputs): "the parsimony hyperparameter." ) - y_symbolic = symb_model.predict(x).tolist() + y_symbolic = symb_model.predict(x[:, idxs]).tolist() - return {"x": x, "y": y_symbolic, "expr": conv_expr} + return { + "x": x.tolist(), + "y": y_pdp, + "y_symbolic": y_symbolic, + "expr": conv_expr, + "variances": pdp_variances, + "x_ice": x_ice, + "y_ice": y_ice, + } @staticmethod def get_output_layout(register): - return dcc.Graph(register("graph", "figure"), style={"height": config.FIGURE_HEIGHT}) + return [dcc.Graph(register("symb_graph", "figure"), style={"height": config.FIGURE_HEIGHT}), + dcc.Graph(register("pdp_graph", "figure"), style={"height": config.FIGURE_HEIGHT})] @staticmethod def load_outputs(run, inputs, outputs): # Parse inputs hp1_name = inputs["hyperparameter_name_1"] + hp1_idx = run.configspace.get_idx_by_hyperparameter_name(hp1_name) hp1 = run.configspace.get_hyperparameter(hp1_name) hp2_name = inputs["hyperparameter_name_2"] + hp2_idx = None hp2 = None if hp2_name is not None and hp2_name != "": + hp2_idx = run.configspace.get_idx_by_hyperparameter_name(hp2_name) hp2 = run.configspace.get_hyperparameter(hp2_name) objective = run.get_objective(inputs["objective_id"]) @@ -366,15 +390,15 @@ def load_outputs(run, inputs, outputs): # Parse outputs x = np.asarray(outputs["x"]) - y = np.asarray(outputs["y"]) + y_symbolic = np.asarray(outputs["y_symbolic"]) expr = outputs["expr"] - traces = [] + traces1 = [] if hp2 is None: # 1D - traces += [ + traces1 += [ go.Scatter( - x=x[:, 0], - y=y, + x=x[:, hp1_idx], + y=y_symbolic, line=dict(color=get_color(0, 1)), hoverinfo="skip", showlegend=False, @@ -382,7 +406,7 @@ def load_outputs(run, inputs, outputs): ] tickvals, ticktext = get_hyperparameter_ticks(hp1) - layout = go.Layout( + layout1 = go.Layout( { "xaxis": { "tickvals": tickvals, @@ -396,12 +420,12 @@ def load_outputs(run, inputs, outputs): } ) else: - z = y - traces += [ + z = y_symbolic + traces1 += [ go.Contour( z=z, - x=x[:, 0], - y=x[:, 1], + x=x[:, hp1_idx], + y=x[:, hp2_idx], colorbar=dict( title=objective_name, ), @@ -412,7 +436,7 @@ def load_outputs(run, inputs, outputs): x_tickvals, x_ticktext = get_hyperparameter_ticks(hp1) y_tickvals, y_ticktext = get_hyperparameter_ticks(hp2) - layout = go.Layout( + layout1 = go.Layout( dict( xaxis=dict(tickvals=x_tickvals, ticktext=x_ticktext, title=hp1_name), yaxis=dict(tickvals=y_tickvals, ticktext=y_ticktext, title=hp2_name), @@ -421,7 +445,17 @@ def load_outputs(run, inputs, outputs): ) ) - figure = go.Figure(data=traces, layout=layout) - save_image(figure, "symbolic_explanation.pdf") + figure1 = go.Figure(data=traces1, layout=layout1) + save_image(figure1, "symbolic_explanation.pdf") - return figure + if len(outputs["y_ice"]) > 0: + figure2 = PartialDependencies.get_pdp_figure(run, inputs, outputs, + show_confidence=False, + show_ice=True, + title="Partial Dependency Plot leveraged for training of " + "Symbolic Explanation:" + ) + + return [figure1, figure2] + else: + return [figure1, []] From b62462e37be430813ea5285215baef7bc31e76d1 Mon Sep 17 00:00:00 2001 From: Sarah Krebs Date: Wed, 24 Jan 2024 11:37:08 +0100 Subject: [PATCH 20/26] Add pdp plot to symbolic explanation output and add paper to docs --- .../hyperparameter/symbolic_explanations.py | 98 ++++++++++--------- docs/plugins/symbolic_explanations.rst | 3 + 2 files changed, 55 insertions(+), 46 deletions(-) diff --git a/deepcave/plugins/hyperparameter/symbolic_explanations.py b/deepcave/plugins/hyperparameter/symbolic_explanations.py index c829d7e7..b9a9ec57 100644 --- a/deepcave/plugins/hyperparameter/symbolic_explanations.py +++ b/deepcave/plugins/hyperparameter/symbolic_explanations.py @@ -279,37 +279,39 @@ def process(run, inputs): idx2 = run.configspace.get_idx_by_hyperparameter_name(hp2) idxs += [idx2] - if len(selected_hyperparameters) < len(hp_names): - num_samples = SAMPLES_PER_HP * len(X) - # We limit the samples to max 10k - if num_samples > MAX_SAMPLES: - num_samples = MAX_SAMPLES - - # And finally call PDP - pdp = PDP.from_random_points( - surrogate_model, - selected_hyperparameter=selected_hyperparameters, - seed=0, - num_grid_points_per_axis=SR_TRAIN_POINTS_PER_AXIS, - num_samples=num_samples, - ) - - x = pdp.x_pdp - y = pdp.y_pdp.tolist() + num_samples = SAMPLES_PER_HP * len(X) + # We limit the samples to max 10k + if num_samples > MAX_SAMPLES: + num_samples = MAX_SAMPLES + + # And finally call PDP + pdp = PDP.from_random_points( + surrogate_model, + selected_hyperparameter=selected_hyperparameters, + seed=0, + num_grid_points_per_axis=SR_TRAIN_POINTS_PER_AXIS, + num_samples=num_samples, + ) - # Save PDP information for PDP plot as comparison - y_pdp = y - pdp_variances = pdp.y_variances.tolist() + x_pdp = pdp.x_pdp + y_pdp = pdp.y_pdp.tolist() + pdp_variances = pdp.y_variances.tolist() - # We have to cut the ICE curves because it's too much data - x_ice = pdp._ice.x_ice.tolist() - y_ice = pdp._ice.y_ice.tolist() + x_ice = pdp._ice.x_ice.tolist() + y_ice = pdp._ice.y_ice.tolist() - if len(x_ice) > MAX_SHOWN_SAMPLES: - x_ice = x_ice[:MAX_SHOWN_SAMPLES] - y_ice = y_ice[:MAX_SHOWN_SAMPLES] + # We have to cut the ICE curves because it's too much data + if len(x_ice) > MAX_SHOWN_SAMPLES: + x_ice = x_ice[:MAX_SHOWN_SAMPLES] + y_ice = y_ice[:MAX_SHOWN_SAMPLES] + if len(selected_hyperparameters) < len(hp_names): + # If number of hyperparameters to explain is smaller than number of hyperparameters optimizes, + # use PDP to train the symbolic explanation + x_symbolic = x_pdp + y_train = y_pdp else: + # Else, use random samples evaluated with the surrogate model to train the symbolic explanation cs = surrogate_model.config_space random_samples = np.asarray( [ @@ -319,9 +321,8 @@ def process(run, inputs): ) ] ) - x = random_samples - y = surrogate_model.predict(random_samples)[0] - x_ice, y_ice, pdp_variances, y_pdp = [], [], [], [] + x_symbolic = random_samples + y_train = surrogate_model.predict(random_samples)[0] symb_params = dict( population_size=population_size, @@ -335,7 +336,7 @@ def process(run, inputs): # run SR on samples symb_model = SymbolicRegressor(**symb_params) - symb_model.fit(x[:, idxs], y) + symb_model.fit(x_symbolic[:, idxs], y_train) try: conv_expr = ( @@ -354,10 +355,11 @@ def process(run, inputs): "the parsimony hyperparameter." ) - y_symbolic = symb_model.predict(x[:, idxs]).tolist() + y_symbolic = symb_model.predict(x_symbolic[:, idxs]).tolist() return { - "x": x.tolist(), + "x": x_pdp.tolist(), + "x_symbolic": x_symbolic.tolist(), "y": y_pdp, "y_symbolic": y_symbolic, "expr": conv_expr, @@ -377,6 +379,7 @@ def load_outputs(run, inputs, outputs): hp1_name = inputs["hyperparameter_name_1"] hp1_idx = run.configspace.get_idx_by_hyperparameter_name(hp1_name) hp1 = run.configspace.get_hyperparameter(hp1_name) + selected_hyperparameters = [hp1] hp2_name = inputs["hyperparameter_name_2"] hp2_idx = None @@ -384,12 +387,14 @@ def load_outputs(run, inputs, outputs): if hp2_name is not None and hp2_name != "": hp2_idx = run.configspace.get_idx_by_hyperparameter_name(hp2_name) hp2 = run.configspace.get_hyperparameter(hp2_name) + selected_hyperparameters += [hp2] + hp_names = run.configspace.get_hyperparameter_names() objective = run.get_objective(inputs["objective_id"]) objective_name = objective.name # Parse outputs - x = np.asarray(outputs["x"]) + x_symbolic = np.asarray(outputs["x_symbolic"]) y_symbolic = np.asarray(outputs["y_symbolic"]) expr = outputs["expr"] @@ -397,7 +402,7 @@ def load_outputs(run, inputs, outputs): if hp2 is None: # 1D traces1 += [ go.Scatter( - x=x[:, hp1_idx], + x=x_symbolic[:, hp1_idx], y=y_symbolic, line=dict(color=get_color(0, 1)), hoverinfo="skip", @@ -424,8 +429,8 @@ def load_outputs(run, inputs, outputs): traces1 += [ go.Contour( z=z, - x=x[:, hp1_idx], - y=x[:, hp2_idx], + x=x_symbolic[:, hp1_idx], + y=x_symbolic[:, hp2_idx], colorbar=dict( title=objective_name, ), @@ -448,14 +453,15 @@ def load_outputs(run, inputs, outputs): figure1 = go.Figure(data=traces1, layout=layout1) save_image(figure1, "symbolic_explanation.pdf") - if len(outputs["y_ice"]) > 0: - figure2 = PartialDependencies.get_pdp_figure(run, inputs, outputs, - show_confidence=False, - show_ice=True, - title="Partial Dependency Plot leveraged for training of " - "Symbolic Explanation:" - ) - - return [figure1, figure2] + if len(selected_hyperparameters) < len(hp_names): + pdp_title = "Partial Dependency leveraged for training of Symbolic Explanation:" else: - return [figure1, []] + pdp_title = "Partial Dependency for comparison:" + + figure2 = PartialDependencies.get_pdp_figure(run, inputs, outputs, + show_confidence=False, + show_ice=False, + title=pdp_title + ) + + return [figure1, figure2] diff --git a/docs/plugins/symbolic_explanations.rst b/docs/plugins/symbolic_explanations.rst index 0be1c438..563dab3a 100644 --- a/docs/plugins/symbolic_explanations.rst +++ b/docs/plugins/symbolic_explanations.rst @@ -12,3 +12,6 @@ performance, the Symbolic Explanations plugin additionally allows to obtain an e these effects. .. image:: ../images/plugins/symbolic_explanations.png + +To learn more about Symbolic Explanations, please see the paper +`Symbolic Explanations for Hyperparameter Optimization `_. From 42529942396595a32c43da03d915886cff6464c0 Mon Sep 17 00:00:00 2001 From: Sarah Krebs Date: Wed, 24 Jan 2024 12:03:58 +0100 Subject: [PATCH 21/26] Solve merge conflict --- CHANGELOG.md | 6 ++- deepcave/plugins/__init__.py | 40 +++++++++++-------- deepcave/plugins/budget/budget_correlation.py | 7 ++-- .../plugins/hyperparameter/importances.py | 7 ++-- deepcave/plugins/hyperparameter/pdp.py | 10 +++-- .../hyperparameter/symbolic_explanations.py | 8 ++-- .../plugins/objective/configuration_cube.py | 7 ++-- deepcave/plugins/objective/cost_over_time.py | 6 +-- .../plugins/objective/parallel_coordinates.py | 7 ++-- deepcave/plugins/objective/pareto_front.py | 6 +-- deepcave/plugins/static.py | 4 +- deepcave/plugins/summary/configurations.py | 8 ++-- deepcave/plugins/summary/footprint.py | 8 ++-- deepcave/plugins/summary/overview.py | 10 ++--- deepcave/utils/logging.yml | 1 + deepcave/utils/styled_plotty.py | 6 +-- examples/api/importances.py | 38 ++++++++++++++++++ examples/api/parallel_coordinates.py | 11 +++-- examples/api/pdp.py | 37 +++++++++++++++++ requirements.txt | 1 + 20 files changed, 162 insertions(+), 66 deletions(-) create mode 100644 examples/api/importances.py create mode 100644 examples/api/pdp.py diff --git a/CHANGELOG.md b/CHANGELOG.md index 4d249b31..ad952bc0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,10 +1,11 @@ -# Version 1.2 +# Version 1.1.4 ## Plugins - Add symbolic explanations plugin (#46). ## Enhancements - Fix lower bounds of dependency versions. +- Do not disable existing loggers. - Update author email. - Add exit button which first deletes running jobs and then terminates DeepCave. - Nicer handling of Keyboard Interrupt. @@ -12,6 +13,9 @@ ## Bug-Fixes - Don't convert BOHB runs with status 'running' (consistent with SMAC). +- Fix api examples (#68). +- Reset inputs to fix error when subsequently selecting runs with different configspaces, objectives or budgets (#106). +- Fix errors due to changing inputs before runselection (#64). - Fix varying configspace index order in PDP and symbolic explanations. # Version 1.1.3 diff --git a/deepcave/plugins/__init__.py b/deepcave/plugins/__init__.py index 85026af8..a2ac0edc 100644 --- a/deepcave/plugins/__init__.py +++ b/deepcave/plugins/__init__.py @@ -93,9 +93,9 @@ def get_base_url(cls) -> str: str Url for the plugin as string. """ - from deepcave import config + from deepcave.config import Config - return f"http://{config.DASH_ADDRESS}:{config.DASH_PORT}/plugins/{cls.id}" + return f"http://{Config.DASH_ADDRESS}:{Config.DASH_PORT}/plugins/{cls.id}" @staticmethod def check_run_compatibility(run: AbstractRun) -> bool: @@ -360,22 +360,28 @@ def plugin_input_update(pathname: str, *inputs_list: str) -> List[str]: # because `run` would be removed. # Also: We want to keep the current run name. update_dict(_inputs, self.load_inputs()) + # Reset inputs + if "objective_id" in _inputs.keys(): + update_dict(_inputs, {"objective_id": {"value": None}}) + if "budget_id" in _inputs.keys(): + update_dict(_inputs, {"budget_id": {"value": None}}) + if "hyperparameter_name_1" in _inputs.keys(): + update_dict(_inputs, {"hyperparameter_name_1": {"value": None}}) + if "hyperparameter_name_2" in _inputs.keys(): + update_dict(_inputs, {"hyperparameter_name_2": {"value": None}}) + + if _run_id: + selected_run = run_handler.get_run(_run_id) + + if selected_run is not None: + # How to update only parameters which have a dependency? + user_dependencies_inputs = self.load_dependency_inputs( + selected_run, _previous_inputs, _inputs + ) - # TODO: Reset only inputs which are not available in another run. - # E.g. if options from budget in run_2 and run_3 are the same - # take the budget from run_2 if changed to run_3. Otherwise, - # reset budgets. - - selected_run = run_handler.get_run(_run_id) - - # How to update only parameters which have a dependency? - user_dependencies_inputs = self.load_dependency_inputs( - selected_run, _previous_inputs, _inputs - ) - - # Update dict - # dict.update() remove keys, so we use our own method to do so - update_dict(inputs, user_dependencies_inputs) # inplace operation + # Update dict + # dict.update() remove keys, so we use our own method to do so + update_dict(inputs, user_dependencies_inputs) # inplace operation # Let's cast the inputs inputs = self._cast_inputs(inputs) diff --git a/deepcave/plugins/budget/budget_correlation.py b/deepcave/plugins/budget/budget_correlation.py index 33c2b01e..6688fbb4 100644 --- a/deepcave/plugins/budget/budget_correlation.py +++ b/deepcave/plugins/budget/budget_correlation.py @@ -7,7 +7,8 @@ from dash import dcc, html from scipy import stats -from deepcave import config, notification +from deepcave import notification +from deepcave.config import Config from deepcave.plugins.dynamic import DynamicPlugin from deepcave.runs import Status from deepcave.utils.layout import create_table, get_select_options @@ -114,7 +115,7 @@ def get_output_layout(register): [ dbc.Tab( dcc.Graph( - id=register("graph", "figure"), style={"height": config.FIGURE_HEIGHT} + id=register("graph", "figure"), style={"height": Config.FIGURE_HEIGHT} ), label="Graph", ), @@ -171,7 +172,7 @@ def load_outputs(run, _, outputs): layout = go.Layout( xaxis=dict(title="Budget"), yaxis=dict(title="Correlation"), - margin=config.FIGURE_MARGIN, + margin=Config.FIGURE_MARGIN, legend=dict(title="Budgets"), ) diff --git a/deepcave/plugins/hyperparameter/importances.py b/deepcave/plugins/hyperparameter/importances.py index 261c9a9e..5b197b50 100644 --- a/deepcave/plugins/hyperparameter/importances.py +++ b/deepcave/plugins/hyperparameter/importances.py @@ -4,7 +4,7 @@ from dash import dcc, html from dash.exceptions import PreventUpdate -from deepcave import config +from deepcave.config import Config from deepcave.evaluators.fanova import fANOVA as GlobalEvaluator from deepcave.evaluators.lpi import LPI as LocalEvaluator from deepcave.plugins.static import StaticPlugin @@ -137,7 +137,6 @@ def load_dependency_inputs(self, run, _, inputs): # Pre-set values if objective_value is None: objective_value = objective_ids[0] - n_hps = len(hp_names) if n_hps == 0: n_hps = len(hp_names) @@ -201,7 +200,7 @@ def process(run, inputs): @staticmethod def get_output_layout(register): - return dcc.Graph(register("graph", "figure"), style={"height": config.FIGURE_HEIGHT}) + return dcc.Graph(register("graph", "figure"), style={"height": Config.FIGURE_HEIGHT}) @staticmethod def load_outputs(run, inputs, outputs): @@ -273,7 +272,7 @@ def load_outputs(run, inputs, outputs): barmode="group", yaxis_title="Importance", legend={"title": "Budget"}, - margin=config.FIGURE_MARGIN, + margin=Config.FIGURE_MARGIN, xaxis=dict(tickangle=-45), ) save_image(figure, "importances.pdf") diff --git a/deepcave/plugins/hyperparameter/pdp.py b/deepcave/plugins/hyperparameter/pdp.py index 005be747..78b8468a 100644 --- a/deepcave/plugins/hyperparameter/pdp.py +++ b/deepcave/plugins/hyperparameter/pdp.py @@ -4,7 +4,7 @@ from dash import dcc, html from pyPDP.algorithms.pdp import PDP -from deepcave import config +from deepcave.config import Config from deepcave.evaluators.epm.random_forest_surrogate import RandomForestSurrogate from deepcave.plugins.static import StaticPlugin from deepcave.runs import Status @@ -145,10 +145,13 @@ def load_dependency_inputs(self, run, previous_inputs, inputs): objective_value = inputs["objective_id"]["value"] budget_value = inputs["budget_id"]["value"] hp1_value = inputs["hyperparameter_name_1"]["value"] + hp2_value = inputs["hyperparameter_name_2"]["value"] if objective_value is None: objective_value = objective_ids[0] + if budget_value is None: budget_value = budget_ids[-1] + if hp1_value is None: hp1_value = hp_names[0] return { @@ -160,6 +163,7 @@ def load_dependency_inputs(self, run, previous_inputs, inputs): }, "hyperparameter_name_2": { "options": get_checklist_options([None] + hp_names), + "value": hp2_value, }, } @@ -234,7 +238,7 @@ def process(run, inputs): @staticmethod def get_output_layout(register): - return dcc.Graph(register("graph", "figure"), style={"height": config.FIGURE_HEIGHT}) + return dcc.Graph(register("graph", "figure"), style={"height": Config.FIGURE_HEIGHT}) @staticmethod def get_pdp_figure(run, inputs, outputs, show_confidence, show_ice, title=None): @@ -346,7 +350,7 @@ def get_pdp_figure(run, inputs, outputs, show_confidence, show_ice, title=None): dict( xaxis=dict(tickvals=x_tickvals, ticktext=x_ticktext, title=hp1_name), yaxis=dict(tickvals=y_tickvals, ticktext=y_ticktext, title=hp2_name), - margin=config.FIGURE_MARGIN, + margin=Config.FIGURE_MARGIN, title=title ) ) diff --git a/deepcave/plugins/hyperparameter/symbolic_explanations.py b/deepcave/plugins/hyperparameter/symbolic_explanations.py index b9a9ec57..a391c26c 100644 --- a/deepcave/plugins/hyperparameter/symbolic_explanations.py +++ b/deepcave/plugins/hyperparameter/symbolic_explanations.py @@ -6,7 +6,7 @@ from gplearn.genetic import SymbolicRegressor from pyPDP.algorithms.pdp import PDP -from deepcave import config +from deepcave.config import Config from deepcave.evaluators.epm.random_forest_surrogate import RandomForestSurrogate from deepcave.plugins.static import StaticPlugin from deepcave.plugins.hyperparameter.pdp import PartialDependencies @@ -370,8 +370,8 @@ def process(run, inputs): @staticmethod def get_output_layout(register): - return [dcc.Graph(register("symb_graph", "figure"), style={"height": config.FIGURE_HEIGHT}), - dcc.Graph(register("pdp_graph", "figure"), style={"height": config.FIGURE_HEIGHT})] + return [dcc.Graph(register("symb_graph", "figure"), style={"height": Config.FIGURE_HEIGHT}), + dcc.Graph(register("pdp_graph", "figure"), style={"height": Config.FIGURE_HEIGHT})] @staticmethod def load_outputs(run, inputs, outputs): @@ -445,7 +445,7 @@ def load_outputs(run, inputs, outputs): dict( xaxis=dict(tickvals=x_tickvals, ticktext=x_ticktext, title=hp1_name), yaxis=dict(tickvals=y_tickvals, ticktext=y_ticktext, title=hp2_name), - margin=config.FIGURE_MARGIN, + margin=Config.FIGURE_MARGIN, title=expr, ) ) diff --git a/deepcave/plugins/objective/configuration_cube.py b/deepcave/plugins/objective/configuration_cube.py index adb13919..00cbf3dc 100644 --- a/deepcave/plugins/objective/configuration_cube.py +++ b/deepcave/plugins/objective/configuration_cube.py @@ -7,7 +7,7 @@ from dash import dcc, html from dash.exceptions import PreventUpdate -from deepcave import config +from deepcave.config import Config from deepcave.plugins.dynamic import DynamicPlugin from deepcave.runs import Status from deepcave.utils.compression import deserialize, serialize @@ -126,6 +126,7 @@ def load_dependency_inputs(self, run, _, inputs): # Pre-set values if objective_value is None: objective_value = objective_ids[0] + if budget_value is None: budget_value = budget_ids[-1] else: budget_value = inputs["budget_id"]["value"] @@ -177,7 +178,7 @@ def process(run, inputs): @staticmethod def get_output_layout(register): - return (dcc.Graph(register("graph", "figure"), style={"height": config.FIGURE_HEIGHT}),) + return (dcc.Graph(register("graph", "figure"), style={"height": Config.FIGURE_HEIGHT}),) @staticmethod def load_outputs(run, inputs, outputs): @@ -277,7 +278,7 @@ def load_outputs(run, inputs, outputs): layout = go.Layout(**layout_kwargs) figure = go.Figure(data=trace, layout=layout) - figure.update_layout(dict(margin=config.FIGURE_MARGIN)) + figure.update_layout(dict(margin=Config.FIGURE_MARGIN)) save_image(figure, "configuration_cube.pdf") return figure diff --git a/deepcave/plugins/objective/cost_over_time.py b/deepcave/plugins/objective/cost_over_time.py index a4fbd30d..02293a56 100644 --- a/deepcave/plugins/objective/cost_over_time.py +++ b/deepcave/plugins/objective/cost_over_time.py @@ -6,7 +6,7 @@ from dash import dcc, html from dash.exceptions import PreventUpdate -from deepcave import config +from deepcave.config import Config from deepcave.plugins.dynamic import DynamicPlugin from deepcave.runs import AbstractRun, check_equality from deepcave.utils.layout import get_select_options, help_button @@ -150,7 +150,7 @@ def process(run, inputs): @staticmethod def get_output_layout(register): - return dcc.Graph(register("graph", "figure"), style={"height": config.FIGURE_HEIGHT}) + return dcc.Graph(register("graph", "figure"), style={"height": Config.FIGURE_HEIGHT}) @staticmethod def load_outputs(runs, inputs, outputs): @@ -245,7 +245,7 @@ def load_outputs(runs, inputs, outputs): layout = go.Layout( xaxis=dict(title=xaxis_label, type=type), yaxis=dict(title=objective.name), - margin=config.FIGURE_MARGIN, + margin=Config.FIGURE_MARGIN, ) figure = go.Figure(data=traces, layout=layout) diff --git a/deepcave/plugins/objective/parallel_coordinates.py b/deepcave/plugins/objective/parallel_coordinates.py index 7c3eaf96..7afeaeab 100644 --- a/deepcave/plugins/objective/parallel_coordinates.py +++ b/deepcave/plugins/objective/parallel_coordinates.py @@ -7,7 +7,7 @@ from dash import dcc, html from dash.exceptions import PreventUpdate -from deepcave import config +from deepcave.config import Config from deepcave.constants import VALUE_RANGE from deepcave.evaluators.fanova import fANOVA from deepcave.plugins.static import StaticPlugin @@ -88,7 +88,7 @@ def get_filter_layout(register): dbc.Label("Limit Hyperparameters"), help_button( "Shows either the n most important hyperparameters (if show " - "importance hyperparameters is true) or the first n selected " + "important hyperparameters is true) or the first n selected " "hyperparameters." ), dbc.Input(id=register("n_hps", "value"), type="number"), @@ -164,7 +164,6 @@ def load_dependency_inputs(self, run, _, inputs): objective_value = objective_ids[0] budget_value = budget_ids[-1] hp_value = hp_names - n_hps = len(hp_names) if n_hps == 0: n_hps = len(hp_names) @@ -206,7 +205,7 @@ def process(run, inputs): @staticmethod def get_output_layout(register): - return dcc.Graph(register("graph", "figure"), style={"height": config.FIGURE_HEIGHT}) + return dcc.Graph(register("graph", "figure"), style={"height": Config.FIGURE_HEIGHT}) @staticmethod def load_outputs(run, inputs, outputs): diff --git a/deepcave/plugins/objective/pareto_front.py b/deepcave/plugins/objective/pareto_front.py index 17e55a39..db527cca 100644 --- a/deepcave/plugins/objective/pareto_front.py +++ b/deepcave/plugins/objective/pareto_front.py @@ -5,7 +5,7 @@ import plotly.graph_objs as go from dash import dcc, html -from deepcave import config +from deepcave.config import Config from deepcave.plugins.dynamic import DynamicPlugin from deepcave.runs import Status, check_equality from deepcave.utils.layout import get_select_options, help_button @@ -206,7 +206,7 @@ def process(run, inputs): @staticmethod def get_output_layout(register): - return dcc.Graph(register("graph", "figure"), style={"height": config.FIGURE_HEIGHT}) + return dcc.Graph(register("graph", "figure"), style={"height": Config.FIGURE_HEIGHT}) @staticmethod def load_outputs(runs, inputs, outputs): @@ -291,7 +291,7 @@ def load_outputs(runs, inputs, outputs): layout = go.Layout( xaxis=dict(title=objective_1.name), yaxis=dict(title=objective_2.name), - margin=config.FIGURE_MARGIN, + margin=Config.FIGURE_MARGIN, ) else: layout = None diff --git a/deepcave/plugins/static.py b/deepcave/plugins/static.py index 27c4bd5d..bf2c503b 100644 --- a/deepcave/plugins/static.py +++ b/deepcave/plugins/static.py @@ -295,12 +295,12 @@ def _get_job_id(self, run_name: str, inputs_key: str) -> str: @interactive def __call__(self) -> List[Component]: # type: ignore - from deepcave import config + from deepcave.config import Config self._setup() components = [ - dcc.Interval(id=self.get_internal_id("update-interval"), interval=config.REFRESH_RATE), + dcc.Interval(id=self.get_internal_id("update-interval"), interval=Config.REFRESH_RATE), dcc.Store(id=self.get_internal_id("update-interval-output"), data=0), ] components += super().__call__(True) diff --git a/deepcave/plugins/summary/configurations.py b/deepcave/plugins/summary/configurations.py index 29e3ea4f..bc8e9389 100644 --- a/deepcave/plugins/summary/configurations.py +++ b/deepcave/plugins/summary/configurations.py @@ -5,7 +5,7 @@ import plotly.graph_objs as go from dash import dcc, html -from deepcave import config +from deepcave.config import Config from deepcave.constants import VALUE_RANGE from deepcave.plugins.dynamic import DynamicPlugin from deepcave.runs import AbstractRun, Status @@ -178,7 +178,7 @@ def get_output_layout(register): dbc.Tab( dcc.Graph( id=register("performance_graph", "figure"), - style={"height": config.FIGURE_HEIGHT}, + style={"height": Config.FIGURE_HEIGHT}, ), label="Graph", ), @@ -192,7 +192,7 @@ def get_output_layout(register): dbc.Tab( dcc.Graph( id=register("configspace_graph", "figure"), - style={"height": config.FIGURE_HEIGHT}, + style={"height": Config.FIGURE_HEIGHT}, ), label="Graph", ), @@ -231,7 +231,7 @@ def _get_objective_figure(_, outputs, run): objective_data.append(trace) layout_kwargs = { - "margin": config.FIGURE_MARGIN, + "margin": Config.FIGURE_MARGIN, "xaxis": {"title": "Budget", "domain": [0.05 * len(run.get_objectives()), 1]}, } diff --git a/deepcave/plugins/summary/footprint.py b/deepcave/plugins/summary/footprint.py index 1d14af63..abcb8bfb 100644 --- a/deepcave/plugins/summary/footprint.py +++ b/deepcave/plugins/summary/footprint.py @@ -2,7 +2,7 @@ import plotly.graph_objs as go from dash import dcc, html -from deepcave import config +from deepcave.config import Config from deepcave.evaluators.footprint import Footprint as Evaluator from deepcave.plugins.static import StaticPlugin from deepcave.utils.layout import get_select_options, help_button @@ -173,13 +173,13 @@ def get_output_layout(register): [ dbc.Tab( dcc.Graph( - id=register("performance", "figure"), style={"height": config.FIGURE_HEIGHT} + id=register("performance", "figure"), style={"height": Config.FIGURE_HEIGHT} ), label="Performance", ), dbc.Tab( dcc.Graph( - id=register("area", "figure"), style={"height": config.FIGURE_HEIGHT} + id=register("area", "figure"), style={"height": Config.FIGURE_HEIGHT} ), label="Coverage", ), @@ -264,7 +264,7 @@ def load_outputs(run, inputs, outputs): layout = go.Layout( xaxis=dict(title=None, tickvals=[]), yaxis=dict(title=None, tickvals=[]), - margin=config.FIGURE_MARGIN, + margin=Config.FIGURE_MARGIN, ) performance = go.Figure(data=[performance_data] + traces, layout=layout) diff --git a/deepcave/plugins/summary/overview.py b/deepcave/plugins/summary/overview.py index d78f5978..61ee452b 100644 --- a/deepcave/plugins/summary/overview.py +++ b/deepcave/plugins/summary/overview.py @@ -12,7 +12,7 @@ ) from dash import dcc, html -from deepcave import config +from deepcave.config import Config from deepcave.plugins.dynamic import DynamicPlugin from deepcave.plugins.summary.configurations import Configurations from deepcave.runs.group import Group @@ -51,14 +51,14 @@ def get_output_layout(register): dbc.Tab( dcc.Graph( id=register("status_statistics", "figure"), - style={"height": config.FIGURE_HEIGHT}, + style={"height": Config.FIGURE_HEIGHT}, ), label="Barplot", ), dbc.Tab( dcc.Graph( id=register("config_statistics", "figure"), - style={"height": config.FIGURE_HEIGHT}, + style={"height": Config.FIGURE_HEIGHT}, ), label="Heatmap", ), @@ -328,7 +328,7 @@ def load_outputs(run, *_): barmode="group", xaxis=dict(title="Status"), yaxis=dict(title="Number of configurations"), - margin=config.FIGURE_MARGIN, + margin=Config.FIGURE_MARGIN, ) stats_figure = go.Figure(data=stats_data, layout=stats_layout) save_image(stats_figure, "status_bar.pdf") @@ -337,7 +337,7 @@ def load_outputs(run, *_): legend={"title": "Status"}, xaxis=dict(title="Budget"), yaxis=dict(title="Configuration ID"), - margin=config.FIGURE_MARGIN, + margin=Config.FIGURE_MARGIN, ) config_figure = go.Figure( data=get_discrete_heatmap( diff --git a/deepcave/utils/logging.yml b/deepcave/utils/logging.yml index 809d21d7..68d54734 100644 --- a/deepcave/utils/logging.yml +++ b/deepcave/utils/logging.yml @@ -24,3 +24,4 @@ loggers: root: level: DEBUG handlers: [console] +disable_existing_loggers: false diff --git a/deepcave/utils/styled_plotty.py b/deepcave/utils/styled_plotty.py index 725ebad4..0f06ca03 100644 --- a/deepcave/utils/styled_plotty.py +++ b/deepcave/utils/styled_plotty.py @@ -34,15 +34,15 @@ def save_image(figure: go.Figure, name: str) -> None: name : str Name of the image with extension. Will be automatically saved to the cache. """ - from deepcave import config + from deepcave.config import Config - if not config.SAVE_IMAGES: + if not Config.SAVE_IMAGES: return ratio = 16 / 9 width = 500 height = int(width / ratio) - path = config.CACHE_DIR / "figures" / name + path = Config.CACHE_DIR / "figures" / name figure.write_image(path, width=width, height=height) logger.info(f"Saved figure {name} to {path}.") diff --git a/examples/api/importances.py b/examples/api/importances.py new file mode 100644 index 00000000..981f5d87 --- /dev/null +++ b/examples/api/importances.py @@ -0,0 +1,38 @@ +""" +Importances +^^^^^^^^^^^^^^^^^^^^ + +This example shows how to use the plugin Importances. +Note that other plugins use the same interfaces and can be used in the same fashion. +""" + +from deepcave.plugins.hyperparameter.importances import Importances +from deepcave.runs.converters.deepcave import DeepCAVERun +from pathlib import Path + + +if __name__ == "__main__": + # Instantiate the run + run = DeepCAVERun.from_path(Path("logs/DeepCAVE/minimal/run_2")) + + objective_id = run.get_objective_ids()[0] + budget_ids = run.get_budget_ids() + + # Instantiate the plugin + plugin = Importances() + inputs = plugin.generate_inputs( + hyperparameter_names=run.configspace.get_hyperparameter_names(), + objective_id=objective_id, + budget_ids=budget_ids, + method="global", + n_hps=3, + n_trees=10 + ) + # Note: Filter variables are not considered. + outputs = plugin.generate_outputs(run, inputs) + + # Finally, you can load the figure. Here, the filter variables play a role. + # Alternatively: Use the matplotlib output (`load_mpl_outputs`) if available. + figure = plugin.load_outputs(run, inputs, outputs) # plotly.go figure + figure.write_image("examples/api/importances.png", scale=2.) + # figure.show() \ No newline at end of file diff --git a/examples/api/parallel_coordinates.py b/examples/api/parallel_coordinates.py index b57f6215..6df3f406 100644 --- a/examples/api/parallel_coordinates.py +++ b/examples/api/parallel_coordinates.py @@ -2,17 +2,18 @@ Parallel Coordinates ^^^^^^^^^^^^^^^^^^^^ -This example shows how to use the plugin parallel coordinates. +This example shows how to use the plugin Parallel Coordinates. Note that other plugins use the same interfaces and can be used in the same fashion. """ from deepcave.plugins.objective.parallel_coordinates import ParallelCoordinates from deepcave.runs.converters.deepcave import DeepCAVERun +from pathlib import Path if __name__ == "__main__": # Instantiate the run - run = DeepCAVERun.from_path("examples/record/logs/DeepCAVE/mlp/run_2") + run = DeepCAVERun.from_path(Path("logs/DeepCAVE/minimal/run_2")) objective_id = run.get_objective_ids()[0] budget_id = run.get_budget_ids()[-1] @@ -22,6 +23,10 @@ hyperparameter_names=run.configspace.get_hyperparameter_names(), objective_id=objective_id, budget_id=budget_id, + show_important_only=True, + show_unsuccessful=False, + hide_hps=False, + n_hps=3, ) # Note: Filter variables are not considered. outputs = plugin.generate_outputs(run, inputs) @@ -29,5 +34,5 @@ # Finally, you can load the figure. Here, the filter variables play a role. # Alternatively: Use the matplotlib output (`load_mpl_outputs`) if available. figure = plugin.load_outputs(run, inputs, outputs) # plotly.go figure + figure.write_image("examples/api/parallel_coordinates.png", scale=2.) # figure.show() - # figure.write_image("examples/api/test.png") diff --git a/examples/api/pdp.py b/examples/api/pdp.py new file mode 100644 index 00000000..83479592 --- /dev/null +++ b/examples/api/pdp.py @@ -0,0 +1,37 @@ +""" +Partial Dependencies +^^^^^^^^^^^^^^^^^^^^ + +This example shows how to use the plugin Partial Dependencies. +Note that other plugins use the same interfaces and can be used in the same fashion. +""" + +from deepcave.plugins.hyperparameter.pdp import PartialDependencies +from deepcave.runs.converters.deepcave import DeepCAVERun +from pathlib import Path + + +if __name__ == "__main__": + # Instantiate the run + run = DeepCAVERun.from_path(Path("logs/DeepCAVE/minimal/run_2")) + objective_id = run.get_objective_ids()[0] + budget_id = run.get_budget_ids()[-1] + + # Instantiate the plugin + plugin = PartialDependencies() + inputs = plugin.generate_inputs( + hyperparameter_name_1="alpha", + hyperparameter_name_2="beta", + objective_id=objective_id, + budget_id=budget_id, + show_confidence=False, + show_ice=True, + ) + # Note: Filter variables are not considered. + outputs = plugin.generate_outputs(run, inputs) + + # Finally, you can load the figure. Here, the filter variables play a role. + # Alternatively: Use the matplotlib output (`load_mpl_outputs`) if available. + figure = plugin.load_outputs(run, inputs, outputs) # plotly.go figure + figure.write_image("examples/api/pdp.png") + #figure.show() diff --git a/requirements.txt b/requirements.txt index 38a9e9b2..4f560dbe 100644 --- a/requirements.txt +++ b/requirements.txt @@ -9,6 +9,7 @@ seaborn>=0.13.0 pyyaml>=6.0.1 gplearn>=0.4.2 sympy>=1.12 +kaleido>=0.2.1 # AutoML packages ConfigSpace==0.6.1 From e7b2e9cbe103391e0b3a0181f4869f99e341e671 Mon Sep 17 00:00:00 2001 From: Sarah Krebs Date: Wed, 24 Jan 2024 12:06:51 +0100 Subject: [PATCH 22/26] Disable existing loggers again to suppress redis logs --- CHANGELOG.md | 1 - deepcave/utils/logging.yml | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ad952bc0..cca1f911 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,7 +5,6 @@ ## Enhancements - Fix lower bounds of dependency versions. -- Do not disable existing loggers. - Update author email. - Add exit button which first deletes running jobs and then terminates DeepCave. - Nicer handling of Keyboard Interrupt. diff --git a/deepcave/utils/logging.yml b/deepcave/utils/logging.yml index 68d54734..aea65373 100644 --- a/deepcave/utils/logging.yml +++ b/deepcave/utils/logging.yml @@ -24,4 +24,4 @@ loggers: root: level: DEBUG handlers: [console] -disable_existing_loggers: false +disable_existing_loggers: true From 208ebfa0ee8af6ea089d215bf6ed5b8c663db855 Mon Sep 17 00:00:00 2001 From: Sarah Krebs Date: Fri, 9 Feb 2024 10:23:11 +0100 Subject: [PATCH 23/26] Revert incomplete fix of configspace index order in pdp and symb. expl. --- CHANGELOG.md | 1 - deepcave/plugins/hyperparameter/pdp.py | 4 ---- deepcave/plugins/hyperparameter/symbolic_explanations.py | 4 ---- 3 files changed, 9 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index cca1f911..f39cc5d5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,7 +15,6 @@ - Fix api examples (#68). - Reset inputs to fix error when subsequently selecting runs with different configspaces, objectives or budgets (#106). - Fix errors due to changing inputs before runselection (#64). -- Fix varying configspace index order in PDP and symbolic explanations. # Version 1.1.3 diff --git a/deepcave/plugins/hyperparameter/pdp.py b/deepcave/plugins/hyperparameter/pdp.py index 8c9f1965..5783903f 100644 --- a/deepcave/plugins/hyperparameter/pdp.py +++ b/deepcave/plugins/hyperparameter/pdp.py @@ -191,10 +191,6 @@ def process(run, inputs): surrogate_model = RandomForestSurrogate(run.configspace, seed=0) surrogate_model.fit(X, Y) - # This is necessary as the run configspace can differ from the surrogate, which would be problematic as the - # surrogate configspace is used in the PDP and the run configspace for plotting in load_outputs() - surrogate_model.config_space = run.configspace - # Prepare the hyperparameters selected_hyperparameters = [hp1] if hp2 is not None and hp2 != "": diff --git a/deepcave/plugins/hyperparameter/symbolic_explanations.py b/deepcave/plugins/hyperparameter/symbolic_explanations.py index a391c26c..afbe229b 100644 --- a/deepcave/plugins/hyperparameter/symbolic_explanations.py +++ b/deepcave/plugins/hyperparameter/symbolic_explanations.py @@ -266,10 +266,6 @@ def process(run, inputs): surrogate_model = RandomForestSurrogate(run.configspace, seed=0) surrogate_model.fit(X, Y) - # This is necessary as the run configspace can differ from the surrogate, which would be problematic as the - # surrogate configspace is used in the PDP and the run configspace for plotting in load_outputs() - surrogate_model.config_space = run.configspace - # Prepare the hyperparameters selected_hyperparameters = [hp1] idx1 = run.configspace.get_idx_by_hyperparameter_name(hp1) From da987e8187ec4e7dbfdf2c1694a6e7ef08de94d8 Mon Sep 17 00:00:00 2001 From: Sarah Krebs Date: Fri, 16 Feb 2024 10:47:58 +0100 Subject: [PATCH 24/26] Fixes from review --- CHANGELOG.md | 2 +- deepcave/cli.py | 1 - deepcave/evaluators/epm/random_forest.py | 2 +- deepcave/evaluators/fanova.py | 2 +- .../hyperparameter/symbolic_explanations.py | 192 ++++++++++++++++-- deepcave/utils/logging.yml | 6 +- deepcave/utils/symbolic_regression.py | 63 +++++- docs/plugins/configurations.rst | 4 +- docs/plugins/parallel_coordinates.rst | 2 +- docs/plugins/partial_dependencies.rst | 6 +- docs/plugins/symbolic_explanations.rst | 19 +- 11 files changed, 246 insertions(+), 53 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f1e522b8..e83e6a1b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,4 @@ -# Version 1.1.4 +# Version 1.2 ## Plugins - Add symbolic explanations plugin (#46). diff --git a/deepcave/cli.py b/deepcave/cli.py index 9231872e..c5c0e347 100644 --- a/deepcave/cli.py +++ b/deepcave/cli.py @@ -1,4 +1,3 @@ -import os import multiprocessing import subprocess from pathlib import Path diff --git a/deepcave/evaluators/epm/random_forest.py b/deepcave/evaluators/epm/random_forest.py index 64d69ad3..fc4d1e61 100644 --- a/deepcave/evaluators/epm/random_forest.py +++ b/deepcave/evaluators/epm/random_forest.py @@ -180,7 +180,7 @@ def _impute_inactive(self, X: np.ndarray) -> np.ndarray: def _check_dimensions(self, X: np.ndarray, Y: Optional[np.ndarray] = None) -> None: """ - Checks if the dimensions of X and Y are correct wrt features. + Checks if the dimensions of X and Y are correct with respect to features. Parameters ---------- diff --git a/deepcave/evaluators/fanova.py b/deepcave/evaluators/fanova.py index 8507ae2a..f6873610 100644 --- a/deepcave/evaluators/fanova.py +++ b/deepcave/evaluators/fanova.py @@ -33,7 +33,7 @@ def calculate( seed: int = 0, ) -> None: """ - Get the data wrt budget and trains the forest on the encoded data. + Get the data with respect to budget and trains the forest on the encoded data. Note ---- diff --git a/deepcave/plugins/hyperparameter/symbolic_explanations.py b/deepcave/plugins/hyperparameter/symbolic_explanations.py index afbe229b..746ce528 100644 --- a/deepcave/plugins/hyperparameter/symbolic_explanations.py +++ b/deepcave/plugins/hyperparameter/symbolic_explanations.py @@ -1,3 +1,24 @@ +# noqa: D400 +""" +# SymbolicExplanations + +This module provides utilities for generating Symbolic Explanations. + +Provided utilities include getting input and output layout, +processing the data and loading the outputs. + +## Classes + - SymbolicExplanations: Leverage Symbolic Explanations to obtain a formula an plot it. + +## Constants + GRID_POINTS_PER_AXIS : int + SAMPLES_PER_HP : int + MAX_SAMPLES : int + MAX_SHOWN_SAMPLES : int +""" + +from typing import Any, Callable, Dict, List, Union + import dash_bootstrap_components as dbc import numpy as np import plotly.graph_objs as go @@ -8,8 +29,8 @@ from deepcave.config import Config from deepcave.evaluators.epm.random_forest_surrogate import RandomForestSurrogate -from deepcave.plugins.static import StaticPlugin from deepcave.plugins.hyperparameter.pdp import PartialDependencies +from deepcave.plugins.static import StaticPlugin from deepcave.runs import Status from deepcave.utils.layout import get_checklist_options, get_select_options, help_button from deepcave.utils.styled_plotty import get_color, get_hyperparameter_ticks, save_image @@ -22,6 +43,13 @@ class SymbolicExplanations(StaticPlugin): + """ + Generate Symbolic Explanations. + + Provided utilities include getting input and output layout, + processing the data and loading the outputs. + """ + id = "symbolic_explanations" name = "Symbolic Explanations" icon = "fas fa-subscript" @@ -29,7 +57,21 @@ class SymbolicExplanations(StaticPlugin): activate_run_selection = True @staticmethod - def get_input_layout(register): + def get_input_layout(register: Callable) -> List[Union[dbc.Row, html.Details]]: + """ + Get the layout for the input block. + + Parameters + ---------- + register : Callable + Method to register (user) variables. + The register_input function is located in the Plugin superclass. + + Returns + ------- + List[Union[dbc.Row, html.Details] + The layout for the input block. + """ return [ dbc.Row( [ @@ -97,7 +139,9 @@ def get_input_layout(register): [ dbc.Label("Parsimony coefficient"), help_button( - "Penalizes the complexity of the resulting formulas." + "Penalizes the complexity of the resulting formulas. The " + "higher the value, the higher the penalty on the " + "complexity will be, resulting in simpler formulas." ), dcc.Slider( id=register("parsimony", "value", type=int), @@ -180,7 +224,19 @@ def get_input_layout(register): ), ] - def load_inputs(self): + def load_inputs(self) -> Dict[str, Dict[str, Any]]: + """ + Load the content for the defined inputs in 'get_input_layout' and 'get_filter_layout'. + + This method is necessary to pre-load contents for the inputs. + If the plugin is called for the first time, or there are no results in the cache, + the plugin gets its content from this method. + + Returns + ------- + Dict[str, Dict[str, Any]] + Content to be filled. + """ return { "parsimony": {"value": "-4"}, "generations": {"value": "10"}, @@ -192,7 +248,30 @@ def load_inputs(self): }, } - def load_dependency_inputs(self, run, previous_inputs, inputs): + def load_dependency_inputs(self, run, previous_inputs, inputs) -> Dict[str, Any]: # type: ignore # noqa: E501 + """ + Work like 'load_inputs' but called after inputs have changed. + + Note + ---- + Only the changes have to be returned. The returned dictionary + will be merged with the inputs. + + Parameters + ---------- + run + The selected run. + inputs + Current content of the inputs. + previous_inputs + Previous content of the inputs. + Not used in this specific function. + + Returns + ------- + Dict[str, Any] + Dictionary with the changes. + """ objective_names = run.get_objective_names() objective_ids = run.get_objective_ids() objective_options = get_select_options(objective_names, objective_ids) @@ -235,8 +314,37 @@ def load_dependency_inputs(self, run, previous_inputs, inputs): } @staticmethod - def process(run, inputs): - # Surrogate + def process(run, inputs) -> Dict[str, Any]: # type: ignore + """ + Return raw data based on a run and the input data. + + Warning + ------- + The returned data must be JSON serializable. + + Note + ---- + The passed inputs are cleaned and therefore differ + compared to 'load_inputs' or 'load_dependency_inputs'. + Please see '_clean_inputs' for more information. + + Parameters + ---------- + run + The run to process. + inputs + The input data. + + Returns + ------- + Dict[str, Any] + A serialized dictionary. + + Raises + ------ + RuntimeError + If the objective is None. + """ hp_names = run.configspace.get_hyperparameter_names() objective = run.get_objective(inputs["objective_id"]) budget = run.get_budget(inputs["budget_id"]) @@ -276,7 +384,7 @@ def process(run, inputs): idxs += [idx2] num_samples = SAMPLES_PER_HP * len(X) - # We limit the samples to max 10k + # The samples are limited to max 10k if num_samples > MAX_SAMPLES: num_samples = MAX_SAMPLES @@ -296,18 +404,19 @@ def process(run, inputs): x_ice = pdp._ice.x_ice.tolist() y_ice = pdp._ice.y_ice.tolist() - # We have to cut the ICE curves because it's too much data + # The ICE curves have to be cut because it's too much data if len(x_ice) > MAX_SHOWN_SAMPLES: x_ice = x_ice[:MAX_SHOWN_SAMPLES] y_ice = y_ice[:MAX_SHOWN_SAMPLES] if len(selected_hyperparameters) < len(hp_names): - # If number of hyperparameters to explain is smaller than number of hyperparameters optimizes, - # use PDP to train the symbolic explanation + # If number of hyperparameters to explain is smaller than number of hyperparameters + # optimizes, use PDP to train the symbolic explanation x_symbolic = x_pdp y_train = y_pdp else: - # Else, use random samples evaluated with the surrogate model to train the symbolic explanation + # Else, use random samples evaluated with the surrogate model to train the symbolic + # explanation cs = surrogate_model.config_space random_samples = np.asarray( [ @@ -365,13 +474,54 @@ def process(run, inputs): } @staticmethod - def get_output_layout(register): - return [dcc.Graph(register("symb_graph", "figure"), style={"height": Config.FIGURE_HEIGHT}), - dcc.Graph(register("pdp_graph", "figure"), style={"height": Config.FIGURE_HEIGHT})] + def get_output_layout(register: Callable) -> List[dcc.Graph]: + """ + Get the layout for the output block. + + Parameters + ---------- + register : Callable + Method to register outputs. + The register_input function is located in the Plugin superclass. + + Returns + ------- + List[dcc.Graph] + Layout for the output block. + """ + return [ + dcc.Graph(register("symb_graph", "figure"), style={"height": Config.FIGURE_HEIGHT}), + dcc.Graph(register("pdp_graph", "figure"), style={"height": Config.FIGURE_HEIGHT}), + ] @staticmethod - def load_outputs(run, inputs, outputs): - # Parse inputs + def load_outputs(run, inputs, outputs) -> List[go.Figure]: # type: ignore + """ + Read the raw data and prepare it for the layout. + + Note + ---- + The passed inputs are cleaned and therefore differ + compared to 'load_inputs' or 'load_dependency_inputs'. + Please see '_clean_inputs' for more information. + + Parameters + ---------- + run + The selected run. + inputs + Input and filter values from the user. + outputs + Raw output from the run. + + Returns + ------- + List[go.Figure] + The figure of the Symbolic Explanation and the Partial Dependency Plot (PDP) leveraged + for training in the case that the number of hyperparameters to be explained is smaller + than the number of hyperparameters that was optimized, else, a Partial Dependency Plot + (PDP) for comparison. + """ hp1_name = inputs["hyperparameter_name_1"] hp1_idx = run.configspace.get_idx_by_hyperparameter_name(hp1_name) hp1 = run.configspace.get_hyperparameter(hp1_name) @@ -454,10 +604,8 @@ def load_outputs(run, inputs, outputs): else: pdp_title = "Partial Dependency for comparison:" - figure2 = PartialDependencies.get_pdp_figure(run, inputs, outputs, - show_confidence=False, - show_ice=False, - title=pdp_title - ) + figure2 = PartialDependencies.get_pdp_figure( + run, inputs, outputs, show_confidence=False, show_ice=False, title=pdp_title + ) return [figure1, figure2] diff --git a/deepcave/utils/logging.yml b/deepcave/utils/logging.yml index aea65373..338c05a2 100644 --- a/deepcave/utils/logging.yml +++ b/deepcave/utils/logging.yml @@ -5,12 +5,12 @@ formatters: handlers: console: class: logging.StreamHandler - level: DEBUG + level: INFO formatter: simple stream: ext://sys.stdout loggers: src.plugins: - level: DEBUG + level: INFO handlers: [ console ] propagate: no matplotlib: @@ -22,6 +22,6 @@ loggers: handlers: [ console ] propagate: no root: - level: DEBUG + level: INFO handlers: [console] disable_existing_loggers: true diff --git a/deepcave/utils/symbolic_regression.py b/deepcave/utils/symbolic_regression.py index a8b3c41b..33781f60 100644 --- a/deepcave/utils/symbolic_regression.py +++ b/deepcave/utils/symbolic_regression.py @@ -1,21 +1,51 @@ +# noqa: D400 +""" +# Symbolic Regression + +This module provides utilities for running symbolic regression with gplearn. +""" + +from typing import List, Union + import numpy as np import sympy from gplearn import functions -from gplearn.functions import make_function +from gplearn.functions import _Function, make_function +from gplearn.genetic import SymbolicRegressor from deepcave.utils.logs import get_logger logger = get_logger(__name__) -# Create a safe exp function which does not cause problems def exp(x): + """ + Get a safe exp function with a maximum value of 100000 to avoid overflow. + + Parameters + ---------- + x : float + The value to calculate the exponential of. + + Returns + ------- + float + The safe exponential of x. + """ with np.errstate(all="ignore"): max_value = np.full(shape=x.shape, fill_value=100000) return np.minimum(np.exp(x), max_value) -def get_function_set(): +def get_function_set() -> List[Union[str, _Function]]: + """ + Get a function set for symbolic regression with gplearn. + + Returns + ------- + List[Union[str, _Function]] + List of functions to use in symbolic regression. + """ exp_func = make_function(function=exp, arity=1, name="exp") function_set = ["add", "sub", "mul", "div", "sqrt", "log", "sin", "cos", "abs", exp_func] @@ -23,23 +53,30 @@ def get_function_set(): return function_set -def convert_symb(symb, n_decimals: int = None, hp_names: list = None) -> sympy.core.expr: +def convert_symb( + symb: SymbolicRegressor, n_decimals: int = None, hp_names: list = None +) -> sympy.core.expr: """ - Convert a fitted symbolic regression to a simplified and potentially rounded mathematical expression. + Convert a fitted symbolic regression to a simplified and potentially rounded mathematical + expression. + Warning: eval is used in this function, thus it should not be used on unsanitized input (see https://docs.sympy.org/latest/modules/core.html?highlight=eval#module-sympy.core.sympify). Parameters ---------- - symb: Fitted symbolic regressor to find a simplified expression for. - n_decimals: If set, round floats in the expression to this number of decimals. - hp_names: If set, replace X0 and X1 in the expression by the names given. + symb: SymbolicRegressor + Fitted symbolic regressor to find a simplified expression for. + n_decimals: Optional[int] + If set, round floats in the expression to this number of decimals. + hp_names: Optional[List[str]] + If set, replace X0 and X1 in the expression by the names given. Returns ------- - symb_conv: Converted mathematical expression. + SymbolicRegressor + Converted mathematical expression. """ - # sqrt is protected function in gplearn, always returning sqrt(abs(x)) sqrt_pos = [] prev_sqrt_inserts = 0 @@ -97,7 +134,11 @@ def convert_symb(symb, n_decimals: int = None, hp_names: list = None) -> sympy.c try: # Simplification can fail in some cases. If so, use the unsimplified version. symb_simpl = sympy.simplify(symb_conv) - except: + except Exception as e: + logger.debug( + f"Simplification of symbolic regression failed, use unsimplified expression " + f"instead: {e}" + ) symb_simpl = symb_conv # Round floats to n_decimals diff --git a/docs/plugins/configurations.rst b/docs/plugins/configurations.rst index 2f532f31..9d4d5a90 100644 --- a/docs/plugins/configurations.rst +++ b/docs/plugins/configurations.rst @@ -13,7 +13,7 @@ Since configurations are used throughout the application, you might find links a plugin. This plugin is capable of answering following questions: * Where is the configuration coming from? -* How are the objective values wrt the budgets? +* How are the objective values with respect to the budgets? * How is the status of a trial associated with the selected configuration? * Which values have been used for a certain configuration? * How can I access the configuration in python? @@ -43,7 +43,7 @@ graph view gives you a nice overview, the table displays the concrete values. Code ---- Often a configuration is selected for deployment, which makes it crucial to access it somehow. -The code block provides you the code to access the configuration code-wise. +The code block provides you the code to access the configuration code-wise. .. image:: ../images/plugins/configurations.png diff --git a/docs/plugins/parallel_coordinates.rst b/docs/plugins/parallel_coordinates.rst index 9abdd43b..da01db1b 100644 --- a/docs/plugins/parallel_coordinates.rst +++ b/docs/plugins/parallel_coordinates.rst @@ -1,7 +1,7 @@ Parallel Coordinates ==================== -With parallel coordinates, you can see configurations plotted as a line through their hyperparamter +With parallel coordinates, you can see configurations plotted as a line through their hyperparameter values and to which final score they reach. You can use this to identify trends in hyperparamter value ranges that achieve certain scores. For example, you may find that high performing configurations may all share the same value for a diff --git a/docs/plugins/partial_dependencies.rst b/docs/plugins/partial_dependencies.rst index 3371e6e8..1d91bd5b 100644 --- a/docs/plugins/partial_dependencies.rst +++ b/docs/plugins/partial_dependencies.rst @@ -3,12 +3,12 @@ Partial Dependencies This plugin is capable of answering following questions: -* How does the objective change wrt one or two hyperparameters? For example, does the accuracy - increase if the learning rate decreases? +* How does the objective change with respect to one or two hyperparameters? For example, does the + accuracy increase if the learning rate decreases? * Do multiple trials show similar behavior? -.. warning:: +.. warning:: This page is under construction. diff --git a/docs/plugins/symbolic_explanations.rst b/docs/plugins/symbolic_explanations.rst index 563dab3a..5e9f8478 100644 --- a/docs/plugins/symbolic_explanations.rst +++ b/docs/plugins/symbolic_explanations.rst @@ -1,17 +1,22 @@ Symbolic Explanations ==================== -This plugin is capable of answering similar questions as the Partial Dependencies plugin, i.e.: +Symbolic Explanations allow to obtain explicit formulas quantifying the relation between +hyperparameter values and model performance by applying symbolic regression to meta-data collected +during hyperparameter optimization. -* How does the objective change wrt one or two hyperparameters? For example, does the accuracy - increase if the learning rate decreases? +The plugin is capable of answering similar questions as the Partial Dependencies plugin, i.e.: + +* How does the objective change with respect to one or two hyperparameters? For example, does the + accuracy increase if the learning rate decreases? * Do multiple trials show similar behavior? -While the Partial Dependencies plugin provides a plot describing the effects of hyperparameters on the model -performance, the Symbolic Explanations plugin additionally allows to obtain an explicit formula capturing -these effects. +While the Partial Dependencies plugin provides a plot describing the effects of hyperparameters on +the model performance, the Symbolic Explanations plugin additionally allows to obtain an explicit +formula capturing these effects. .. image:: ../images/plugins/symbolic_explanations.png To learn more about Symbolic Explanations, please see the paper -`Symbolic Explanations for Hyperparameter Optimization `_. +`Symbolic Explanations for Hyperparameter Optimization +`_. From bc8bfd40e0c745f29d3241fe1e3f71651793ed5e Mon Sep 17 00:00:00 2001 From: Sarah Krebs Date: Fri, 16 Feb 2024 11:00:21 +0100 Subject: [PATCH 25/26] Fixes from review --- tests/test_utils/test_cache.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test_utils/test_cache.py b/tests/test_utils/test_cache.py index 2751504b..3d7c3939 100644 --- a/tests/test_utils/test_cache.py +++ b/tests/test_utils/test_cache.py @@ -303,7 +303,7 @@ def test_logging_config(self): self.assertFalse(mpl_logger.propagate) plugin_logger = get_logger("src.plugins") - self.assertEqual(logging.DEBUG, plugin_logger.level) + self.assertEqual(logging.INFO, plugin_logger.level) self.assertFalse(plugin_logger.propagate) From d4101f632dec4f5642e36bfe191129b21e08fddb Mon Sep 17 00:00:00 2001 From: Sarah Krebs Date: Fri, 16 Feb 2024 11:50:00 +0100 Subject: [PATCH 26/26] Fixes from review --- deepcave/plugins/hyperparameter/symbolic_explanations.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/deepcave/plugins/hyperparameter/symbolic_explanations.py b/deepcave/plugins/hyperparameter/symbolic_explanations.py index 746ce528..d9ba94f9 100644 --- a/deepcave/plugins/hyperparameter/symbolic_explanations.py +++ b/deepcave/plugins/hyperparameter/symbolic_explanations.py @@ -8,7 +8,7 @@ processing the data and loading the outputs. ## Classes - - SymbolicExplanations: Leverage Symbolic Explanations to obtain a formula an plot it. + - SymbolicExplanations: Leverage Symbolic Explanations to obtain a formula and plot it. ## Constants GRID_POINTS_PER_AXIS : int @@ -226,7 +226,7 @@ def get_input_layout(register: Callable) -> List[Union[dbc.Row, html.Details]]: def load_inputs(self) -> Dict[str, Dict[str, Any]]: """ - Load the content for the defined inputs in 'get_input_layout' and 'get_filter_layout'. + Load the content for the defined inputs in 'get_input_layout'. This method is necessary to pre-load contents for the inputs. If the plugin is called for the first time, or there are no results in the cache,