Skip to content

Commit 6e59103

Browse files
Copilotthinkall
andauthored
Add hierarchical search space documentation (#1496)
* Initial plan * Add hierarchical search space documentation to Tune-User-Defined-Function.md Co-authored-by: thinkall <3197038+thinkall@users.noreply.github.com> * Add clarifying comments to hierarchical search space examples Co-authored-by: thinkall <3197038+thinkall@users.noreply.github.com> * Fix formatting issues with pre-commit Co-authored-by: thinkall <3197038+thinkall@users.noreply.github.com> --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: thinkall <3197038+thinkall@users.noreply.github.com> Co-authored-by: Li Jiang <bnujli@gmail.com>
1 parent d9e7403 commit 6e59103

1 file changed

Lines changed: 156 additions & 0 deletions

File tree

website/docs/Use-Cases/Tune-User-Defined-Function.md

Lines changed: 156 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -181,6 +181,162 @@ config = {
181181

182182
<!-- Please refer to [ray.tune](https://docs.ray.io/en/latest/tune/api_docs/search_space.html#overview) for a more comprehensive introduction about possible choices of the domain. -->
183183

184+
#### Hierarchical search space
185+
186+
A hierarchical (or conditional) search space allows you to define hyperparameters that depend on the value of other hyperparameters. This is useful when different choices for a categorical hyperparameter require different sets of hyperparameters.
187+
188+
For example, if you're tuning a machine learning pipeline where different models require different hyperparameters, or when the choice of an optimizer determines which optimizer-specific hyperparameters are relevant.
189+
190+
**Syntax**: To create a hierarchical search space, use `tune.choice()` with a list where some elements are dictionaries containing nested hyperparameter definitions.
191+
192+
**Example 1: Model selection with model-specific hyperparameters**
193+
194+
In this example, we have two model types (linear and tree-based), each with their own specific hyperparameters:
195+
196+
```python
197+
from flaml import tune
198+
199+
search_space = {
200+
"model": tune.choice(
201+
[
202+
{
203+
"model_type": "linear",
204+
"learning_rate": tune.loguniform(1e-4, 1e-1),
205+
"regularization": tune.uniform(0, 1),
206+
},
207+
{
208+
"model_type": "tree",
209+
"n_estimators": tune.randint(10, 100),
210+
"max_depth": tune.randint(3, 10),
211+
},
212+
]
213+
),
214+
# Common hyperparameters for all models
215+
"batch_size": tune.choice([32, 64, 128]),
216+
}
217+
218+
219+
def evaluate_config(config):
220+
model_config = config["model"]
221+
if model_config["model_type"] == "linear":
222+
# Use learning_rate and regularization
223+
# train_linear_model() is a placeholder for your actual training code
224+
score = train_linear_model(
225+
lr=model_config["learning_rate"],
226+
reg=model_config["regularization"],
227+
batch_size=config["batch_size"],
228+
)
229+
else: # tree
230+
# Use n_estimators and max_depth
231+
# train_tree_model() is a placeholder for your actual training code
232+
score = train_tree_model(
233+
n_est=model_config["n_estimators"],
234+
depth=model_config["max_depth"],
235+
batch_size=config["batch_size"],
236+
)
237+
return {"score": score}
238+
239+
240+
# Run tuning
241+
analysis = tune.run(
242+
evaluate_config,
243+
config=search_space,
244+
metric="score",
245+
mode="min",
246+
num_samples=20,
247+
)
248+
```
249+
250+
**Example 2: Mixed choices with constants and nested spaces**
251+
252+
You can also mix constant values with nested hyperparameter spaces in `tune.choice()`:
253+
254+
```python
255+
search_space = {
256+
"optimizer": tune.choice(
257+
[
258+
"sgd", # constant value
259+
{
260+
"optimizer_type": "adam",
261+
"beta1": tune.uniform(0.8, 0.99),
262+
"beta2": tune.uniform(0.9, 0.999),
263+
},
264+
{
265+
"optimizer_type": "rmsprop",
266+
"decay": tune.loguniform(1e-3, 1e-1),
267+
"momentum": tune.uniform(0, 0.99),
268+
},
269+
]
270+
),
271+
"learning_rate": tune.loguniform(1e-5, 1e-1),
272+
}
273+
274+
275+
def evaluate_config(config):
276+
optimizer_config = config["optimizer"]
277+
if optimizer_config == "sgd":
278+
optimizer = create_sgd_optimizer(lr=config["learning_rate"])
279+
elif optimizer_config["optimizer_type"] == "adam":
280+
optimizer = create_adam_optimizer(
281+
lr=config["learning_rate"],
282+
beta1=optimizer_config["beta1"],
283+
beta2=optimizer_config["beta2"],
284+
)
285+
else: # rmsprop
286+
optimizer = create_rmsprop_optimizer(
287+
lr=config["learning_rate"],
288+
decay=optimizer_config["decay"],
289+
momentum=optimizer_config["momentum"],
290+
)
291+
# train_model() is a placeholder for your actual training code
292+
return train_model(optimizer)
293+
```
294+
295+
**Example 3: Nested hierarchical spaces**
296+
297+
You can also nest dictionaries within the search space for organizing related hyperparameters:
298+
299+
```python
300+
search_space = {
301+
"preprocessing": {
302+
"normalize": tune.choice([True, False]),
303+
"feature_selection": tune.choice(["none", "pca", "lda"]),
304+
},
305+
"model": tune.choice(
306+
[
307+
{
308+
"type": "neural_net",
309+
"layers": tune.randint(1, 5),
310+
"units_per_layer": tune.randint(32, 256),
311+
},
312+
{
313+
"type": "ensemble",
314+
"n_models": tune.randint(3, 10),
315+
},
316+
]
317+
),
318+
}
319+
320+
321+
def evaluate_config(config):
322+
# Access nested hyperparameters
323+
normalize = config["preprocessing"]["normalize"]
324+
feature_selection = config["preprocessing"]["feature_selection"]
325+
model_config = config["model"]
326+
327+
# Use the hyperparameters accordingly
328+
# train_with_config() is a placeholder for your actual training code
329+
score = train_with_config(normalize, feature_selection, model_config)
330+
return {"score": score}
331+
```
332+
333+
**Notes:**
334+
335+
- When a configuration is sampled, only the selected branch of the hierarchical space will be active.
336+
- The evaluation function should check which choice was selected and use the corresponding nested hyperparameters.
337+
- Hierarchical search spaces work with all FLAML search algorithms (CFO, BlendSearch).
338+
- You can specify `low_cost_partial_config` for hierarchical spaces as well by providing the path to the nested parameters.
339+
184340
#### Cost-related hyperparameters
185341

186342
Cost-related hyperparameters are a subset of the hyperparameters which directly affect the computation cost incurred in the evaluation of any hyperparameter configuration. For example, the number of estimators (`n_estimators`) and the maximum number of leaves (`max_leaves`) are known to affect the training cost of tree-based learners. So they are cost-related hyperparameters for tree-based learners.

0 commit comments

Comments
 (0)