Skip to content

Commit b06d19b

Browse files
authored
Merge pull request #226 from automl/218-ensure-complete-display-with-high-dimensional-hyperparameter-configuration-spaces
218 ensure complete display with high dimensional hyperparameter configuration spaces
2 parents e122de0 + 006490f commit b06d19b

File tree

403 files changed

+15344
-55
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

403 files changed

+15344
-55
lines changed

CHANGELOG.md

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,28 @@
1+
# Version 1.3.9
2+
3+
## Parallel Coordinates
4+
- Set the margin of the graph so it gets dynamically computed depending on the length of the labels.
5+
6+
# Version 1.3.6
7+
8+
## New SMAC version compatibility
9+
- The smac3v2 converter can now also handle the output of the new smac version
10+
11+
# Version 1.3.5
12+
13+
## Converter
14+
- Added a new converter to handle RayTune runs
15+
- Added example RayTune runs to logs
16+
17+
# Version 1.3.5
18+
19+
## Access Specifier
20+
- Changed access specifier from '_fit' to 'fit' in the RF surrogate
21+
22+
## Ablation tests
23+
- Added Polynomial "model" class for testing ablation path behavior
24+
- Added extra test case using the polynomial to validate ablation output correctness
25+
126
# Version 1.3.4
227

328
## Bug-Fixes

Makefile

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,9 @@ install-optuna:
6161
install-bohb:
6262
$(PIP) install -e ".[bohb]"
6363

64+
install-raytune:
65+
$(PIP) install -e ".[raytune]"
66+
6467
check-black:
6568
$(BLACK) ${SOURCE_DIR} --check || :
6669
$(BLACK) ${EXAMPLES_DIR} --check || :

README.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,11 +25,12 @@ conda install -c anaconda swig
2525
pip install DeepCAVE
2626
```
2727

28-
To load runs created with Optuna or the BOHB optimizer, you need to install the
28+
To load runs created with Optuna, the BOHB optimizer or RayTune, you need to install the
2929
respective packages by running:
3030
```bash
3131
pip install deepcave[optuna]
3232
pip install deepcave[bohb]
33+
pip install deepcave[raytune]
3334
```
3435

3536
To try the examples for recording your results in DeepCAVE format, run this after installing:

deepcave/config.py

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -156,7 +156,17 @@ def CONVERTERS(self) -> List[Type["Run"]]:
156156
from deepcave.runs.converters.dataframe import DataFrameRun
157157
from deepcave.runs.converters.deepcave import DeepCAVERun
158158
from deepcave.runs.converters.optuna import OptunaRun
159+
from deepcave.runs.converters.raytune import RayTuneRun
159160
from deepcave.runs.converters.smac3v1 import SMAC3v1Run
160161
from deepcave.runs.converters.smac3v2 import SMAC3v2Run
161162

162-
return [AMLTKRun, BOHBRun, DeepCAVERun, OptunaRun, SMAC3v1Run, SMAC3v2Run, DataFrameRun]
163+
return [
164+
AMLTKRun,
165+
BOHBRun,
166+
DeepCAVERun,
167+
OptunaRun,
168+
RayTuneRun,
169+
SMAC3v1Run,
170+
SMAC3v2Run,
171+
DataFrameRun,
172+
]

deepcave/custom_queue.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,7 @@ def get_workers(self) -> List[Worker]:
103103
List[Worker]
104104
A list of the queued workers.
105105
"""
106-
return Worker.all(queue=self._queue)
106+
return Worker.all(queue=self._queue) # type: ignore
107107

108108
def is_processed(self, job_id: str) -> bool:
109109
"""

deepcave/evaluators/ablation.py

Lines changed: 19 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -75,25 +75,24 @@ def calculate(
7575
self,
7676
objectives: Optional[Union[Objective, List[Objective]]], # noqa
7777
budget: Optional[Union[int, float]] = None, # noqa
78-
n_trees: int = 50, # noqa
79-
seed: int = 0, # noqa
78+
model: Any = None,
8079
) -> None:
8180
"""
8281
Calculate the ablation path performances and improvements.
8382
83+
To use standard Random Forest surrogate do not pass a model.
84+
The option to pass another model is just for testing purposes.
85+
8486
Parameters
8587
----------
8688
objectives : Optional[Union[Objective, List[Objective]]]
8789
The objective(s) to be considered.
8890
budget : Optional[Union[int, float]]
8991
The budget to be considered. If None, all budgets of the run are considered.
9092
Default is None.
91-
n_trees : int
92-
The number of trees for the surrogate model.
93-
Default is 50.
94-
seed : int
95-
The seed for the surrogate model.
96-
Default is 0.
93+
model :
94+
The surrogate model to use for the prediction of the perfromances.
95+
By default None.
9796
"""
9897
if isinstance(objectives, list) and len(objectives) > 1:
9998
raise ValueError("Only one objective is supported for ablation paths.")
@@ -103,25 +102,30 @@ def calculate(
103102
performances: OrderedDict = OrderedDict()
104103
improvements: OrderedDict = OrderedDict()
105104

105+
self._model = model
106+
106107
df = self.run.get_encoded_data(objective, budget, specific=True)
107108

108109
# Obtain all configurations with theirs costs
109110
df = df.dropna(subset=[objective.name])
110111
X = df[list(self.run.configspace.keys())].to_numpy()
111112
Y = df[objective.name].to_numpy()
112113

113-
# A Random Forest Regressor is used as surrogate model
114-
self._model = RandomForestSurrogate(self.cs, seed=seed, n_trees=n_trees)
115-
self._model._fit(X, Y)
116-
117114
# Get the incumbent configuration
118115
incumbent_config, _ = self.run.get_incumbent(budget=budget, objectives=objective)
119116
incumbent_encode = self.run.encode_config(incumbent_config)
120117

121118
# Get the default configuration
119+
122120
self.default_config = self.cs.get_default_configuration()
123121
default_encode = self.run.encode_config(self.default_config)
124122

123+
# The default model is a RF Surrogate, but it cant be passed as parameter directly
124+
# because it needs access to its config space
125+
if self._model is None:
126+
self._model = RandomForestSurrogate(self.cs, seed=0, n_trees=50)
127+
128+
self._model.fit(X, Y)
125129
# Obtain the predicted cost of the default and incumbent configuration
126130
def_cost, def_std = self._model.predict(np.array([default_encode]))
127131
def_cost, def_std = def_cost[0], def_std[0]
@@ -166,6 +170,7 @@ def calculate(
166170
performances[max_hp] = (max_hp_cost, max_hp_std)
167171
impr_std = np.sqrt(def_std**2 + max_hp_std**2)
168172
improvements[max_hp] = ((def_cost - max_hp_cost), impr_std)
173+
169174
# New 'default' cost and std
170175
def_cost = max_hp_cost
171176
def_std = max_hp_std
@@ -248,7 +253,6 @@ def _ablation(
248253
if hp in incumbent_config.keys() and hp in self.default_config.keys():
249254
config_copy = copy.copy(self.default_config)
250255
config_copy[hp] = incumbent_config[hp]
251-
252256
new_cost, _ = self._model.predict(np.array([self.run.encode_config(config_copy)]))
253257
if objective.optimize == "upper":
254258
new_cost = -new_cost
@@ -262,6 +266,7 @@ def _ablation(
262266
else:
263267
continue
264268
hp_count = len(list(self.cs.keys()))
269+
265270
if max_hp != "":
266271
# For the maximum impact hyperparameter, switch the default with the incumbent value
267272
self.default_config[max_hp] = incumbent_config[max_hp]
@@ -270,6 +275,7 @@ def _ablation(
270275
)
271276
if objective.optimize == "upper":
272277
max_hp_cost = -max_hp_cost
278+
273279
return True, max_hp, max_hp_cost[0], max_hp_std[0]
274280
else:
275281
self.logger.info(

deepcave/evaluators/epm/random_forest_surrogate.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,3 +78,16 @@ def _fit(self, X: np.ndarray, y: np.ndarray) -> None:
7878
Corresponding target values.
7979
"""
8080
self._model.train(X, y)
81+
82+
def fit(self, X: np.ndarray, y: np.ndarray) -> None:
83+
"""
84+
Train the surrogate model.
85+
86+
Parameters
87+
----------
88+
X : np.ndarray
89+
Input data points.
90+
y : np.ndarray
91+
Corresponding target values.
92+
"""
93+
self._fit(X, y)

deepcave/evaluators/mo_ablation.py

Lines changed: 7 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -122,8 +122,7 @@ def calculate(
122122
self,
123123
objectives: Optional[Union[Objective, List[Objective]]], # noqa
124124
budget: Optional[Union[int, float]] = None, # noqa
125-
n_trees: int = 50, # noqa
126-
seed: int = 0, # noqa
125+
model: Any = None,
127126
) -> None:
128127
"""
129128
Calculate the MO ablation path performances and improvements.
@@ -135,12 +134,9 @@ def calculate(
135134
budget : Optional[Union[int, float]]
136135
The budget to be considered. If None, all budgets of the run are considered.
137136
Default is None.
138-
n_trees : int
139-
The number of trees for the surrogate model.
140-
Default is 50.
141-
seed : int
142-
The seed for the surrogate model.
143-
Default is 0.
137+
model : Any
138+
For mo ablation this parameter does not do anything, except fit the head.
139+
By default None.
144140
"""
145141
assert isinstance(objectives, list)
146142
for objective in objectives:
@@ -166,8 +162,9 @@ def calculate(
166162

167163
# train one model per objective
168164
Y = df[normed].to_numpy()
169-
model = RandomForestSurrogate(self.cs, seed=seed, n_trees=n_trees)
170-
model._fit(X, Y)
165+
if model is None:
166+
model = RandomForestSurrogate(self.cs, seed=0, n_trees=50)
167+
model.fit(X, Y)
171168
self.models.append(model)
172169

173170
weightings = get_weightings(objectives_normed, df)

deepcave/plugins/__init__.py

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -306,7 +306,6 @@ def plugin_input_update(pathname: str, *inputs_list: str) -> List[Optional[str]]
306306
if passed_inputs is not None:
307307
# First get normal inputs
308308
inputs = self.load_inputs()
309-
310309
# Overwrite/set the passed inputs
311310
update_dict(inputs, passed_inputs)
312311

@@ -1096,7 +1095,6 @@ def load_run_inputs(
10961095
run_path = run.path
10971096
if run_path is not None:
10981097
run_name = run_path.parent.name + "/" + run.name
1099-
11001098
values.append(run.id)
11011099
labels.append(run_name)
11021100
disabled.append(False)

deepcave/plugins/budget/budget_correlation.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -198,6 +198,7 @@ def process(run: AbstractRun, inputs: Dict[str, int]) -> Dict[str, Any]:
198198
objective_id
199199
]
200200
]
201+
201202
c2 += [
202203
run.get_avg_costs(config_id, budget2, statuses=[Status.SUCCESS])[0][
203204
objective_id

0 commit comments

Comments
 (0)