使用 Tune 搜索空间#

Tune 提供了用于指定搜索空间的本机接口。您可以通过 Tuner(param_space=...) 指定搜索空间。

因此,您可以使用 tune.grid_search 原语进行网格搜索

tuner = tune.Tuner(
    trainable,
    param_space={"bar": tune.grid_search([True, False])})
results = tuner.fit()

或者使用随机采样原语之一来指定分布(Tune 搜索空间 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()

注意

如果您使用 SearchAlgorithm,您可能无法通过此接口指定 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 个试验,每个试验都包含随机采样的 alphabeta 值。

 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 传入大型对象,或从磁盘(确保所有节点都能访问文件)或云存储在您的 trainable 内部加载它们。有关更多信息,请参阅如何避免瓶颈?

请注意,当将 Ray Train 与 Ray Tune 一起使用时,某些 config 对象也可以包含在搜索空间中,从而允许您调优诸如训练器的 worker 数量之类的参数。

如何在 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,如 HyperOptOptuna,才能处理条件搜索空间。

为了将条件搜索空间与 HyperOpt 一起使用,Hyperopt 搜索空间 是必要的。Optuna 通过其 define-by-run 接口支持条件搜索空间(使用 Optuna 运行 Tune 实验)。