使用 Tune 搜索空间#
Tune 有一个用于指定搜索空间的本地接口。你可以通过 Tuner(param_space=...)
来指定搜索空间。
因此,你可以使用 tune.grid_search
原语来进行网格搜索:
tuner = tune.Tuner(
trainable,
param_space={"bar": tune.grid_search([True, False])})
results = tuner.fit()
或者你可以使用随机采样原语来指定分布 (调整搜索空间 API):
tuner = tune.Tuner(
trainable,
param_space={
"param1": tune.choice([True, False]),
"bar": tune.uniform(0, 10),
"alpha": tune.sample_from(lambda _: np.random.uniform(100) ** 2),
"const": "hello" # It is also ok to specify constant values.
})
results = tuner.fit()
小心
如果你使用一个搜索算法,你可能无法通过这个接口指定lambda或网格搜索,因为某些搜索算法可能不兼容。
要多次采样/运行多次试验,请指定 tune.RunConfig(num_samples=N
。如果提供了 grid_search
作为参数,则 相同 的网格将被重复 N
次。
# 13 different configs.
tuner = tune.Tuner(trainable, tune_config=tune.TuneConfig(num_samples=13), param_space={
"x": tune.choice([0, 1, 2]),
}
)
tuner.fit()
# 13 different configs.
tuner = tune.Tuner(trainable, tune_config=tune.TuneConfig(num_samples=13), param_space={
"x": tune.choice([0, 1, 2]),
"y": tune.randn([0, 1, 2]),
}
)
tuner.fit()
# 4 different configs.
tuner = tune.Tuner(trainable, tune_config=tune.TuneConfig(num_samples=1), param_space={"x": tune.grid_search([1, 2, 3, 4])})
tuner.fit()
# 3 different configs.
tuner = tune.Tuner(trainable, tune_config=tune.TuneConfig(num_samples=1), param_space={"x": grid_search([1, 2, 3])})
tuner.fit()
# 6 different configs.
tuner = tune.Tuner(trainable, tune_config=tune.TuneConfig(num_samples=2), param_space={"x": tune.grid_search([1, 2, 3])})
tuner.fit()
# 9 different configs.
tuner = tune.Tuner(trainable, tune_config=tune.TuneConfig(num_samples=1), param_space={
"x": tune.grid_search([1, 2, 3]),
"y": tune.grid_search([a, b, c])}
)
tuner.fit()
# 18 different configs.
tuner = tune.Tuner(trainable, tune_config=tune.TuneConfig(num_samples=2), param_space={
"x": tune.grid_search([1, 2, 3]),
"y": tune.grid_search([a, b, c])}
)
tuner.fit()
# 45 different configs.
tuner = tune.Tuner(trainable, tune_config=tune.TuneConfig(num_samples=5), param_space={
"x": tune.grid_search([1, 2, 3]),
"y": tune.grid_search([a, b, c])}
)
tuner.fit()
请注意,网格搜索和随机搜索原语是可互操作的。每个都可以独立使用,也可以相互结合使用。
# 6 different configs.
tuner = tune.Tuner(trainable, tune_config=tune.TuneConfig(num_samples=2), param_space={
"x": tune.sample_from(...),
"y": tune.grid_search([a, b, c])
}
)
tuner.fit()
在下面的例子中,num_samples=10
重复了3x3的网格搜索10次,总共进行了90次试验,每次试验都有随机采样的 alpha
和 beta
值。
tuner = tune.Tuner(
my_trainable,
run_config=RunConfig(name="my_trainable"),
# num_samples will repeat the entire config 10 times.
tune_config=tune.TuneConfig(num_samples=10),
param_space={
# ``sample_from`` creates a generator to call the lambda once per trial.
"alpha": tune.sample_from(lambda spec: np.random.uniform(100)),
# ``sample_from`` also supports "conditional search spaces"
"beta": tune.sample_from(lambda spec: spec.config.alpha * np.random.normal()),
"nn_layers": [
# tune.grid_search will make it so that all values are evaluated.
tune.grid_search([16, 64, 256]),
tune.grid_search([16, 64, 256]),
],
},
)
tuner.fit()
小技巧
避免在搜索空间中传递大型对象作为值,因为这会导致性能开销。使用 tune.with_parameters
来传递大型对象,或者从磁盘(确保所有节点都能访问文件)或云存储中加载它们。更多信息请参见 我如何避免瓶颈?。
请注意,当使用 Ray Train 与 Ray Tune 时,某些配置对象也可以作为搜索空间的一部分包含在内,从而允许您调整训练器的工作者数量等参数。
如何在 Tune 中使用自定义和条件搜索空间?#
你经常会遇到尴尬的搜索空间(即,当一个超参数依赖于另一个时)。使用 tune.sample_from(func)
来提供一个 自定义 的可调用函数用于生成搜索空间。
参数 func
应该接收一个 spec
对象,该对象有一个 config
命名空间,您可以从中访问其他超参数。这对于条件分布非常有用:
tuner = tune.Tuner(
...,
param_space={
# A random function
"alpha": tune.sample_from(lambda _: np.random.uniform(100)),
# Use the `spec.config` namespace to access other hyperparameters
"beta": tune.sample_from(lambda spec: spec.config.alpha * np.random.normal())
}
)
tuner.fit()
以下是一个示例,展示了在两个嵌套参数上进行网格搜索,并结合从两个lambda函数中随机采样,生成9个不同的试验。注意,beta
的值取决于 alpha
的值,这在lambda函数中通过引用 spec.config.alpha
来表示。这使您能够指定条件参数分布。
tuner = tune.Tuner(
my_trainable,
run_config=RunConfig(name="my_trainable"),
param_space={
"alpha": tune.sample_from(lambda spec: np.random.uniform(100)),
"beta": tune.sample_from(lambda spec: spec.config.alpha * np.random.normal()),
"nn_layers": [
tune.grid_search([16, 64, 256]),
tune.grid_search([16, 64, 256]),
],
}
)
备注
并非所有 SearchAlgorithm 都支持此格式,只有部分 SearchAlgorithm,如 HyperOpt 和 Optuna,才完全处理条件搜索空间。
为了使用带有 HyperOpt 的条件搜索空间,需要一个 Hyperopt 搜索空间 。Optuna 通过其 define-by-run 接口支持条件搜索空间(使用Optuna运行Tune实验)。