最佳实践

本页包含一些关于如何使用 HpBandSter 的(希望有益的)提示。它混合了如何实现你的 Worker、选择预算以及如何使用正确的参数运行优化器等方面的内容。

实现你的 Worker

a. 将 ConfigSpace 附加到 Worker

由于这两者通常紧密相连,因此将搜索空间的定义包含在 Worker 中是很有意义的。我们通常会添加一个名为 get_configspace 的静态方法,用于返回相应的 ConfigSpace 对象。这样可以确保你在所有使用此 Worker 的脚本中都使用相同的搜索空间。

b. 在本地使用少量预算运行你的 Worker

这听起来可能很傻,但我们认为有时强调显而易见的事情是值得的。在实现 Worker 时,你只需在脚本末尾添加以下几行,即可使其可运行,并使用随机配置执行 Worker 的计算函数。

if __name__ == "__main__":
	worker = KerasWorker(run_id='0')
	cs = worker.get_configspace()
	
	config = cs.sample_configuration().get_dictionary()
	print(config)
	res = worker.compute(config=config, budget=1, working_directory='.')
	print(res)

只需将 Worker 类名更改为你的类名,并选择一个少量预算。这将使你能够快速尝试随机配置,尽早发现简单错误。

c. 在本地运行短时运行并带有调试输出

大多数情况下,当 HpBandSter 似乎停滞不前时,是由于 Worker、其返回值或设置中的小错误造成的。为了排除前两种情况,修改 示例 1,使用你的 Worker 并使用少量预算运行一次迭代。通过将日志级别设置为 DEBUG,你将看到 Worker 端抛出的每一个异常,否则这些异常可能会丢失。

一旦这部分工作正常,你可以从其他示例开始,在合适的设置下运行 HpBandSter。这些示例可以作为起点,但绝不是设置事物的唯一方式。它们旨在减轻由于 HpBandSter 的灵活性而需要的一些样板代码负担。

选择和配置优化器

实现 Worker 后,是时候考虑实际的优化运行了。有几件事需要考虑:

a. 我应该使用多少次迭代?

简短的答案是:尽你所能承受的。

但现实比这要微妙一些。这取决于你使用的优化器、你拥有的 Worker 数量以及你愿意花费的资源。

对于依赖随机采样的优化器,Worker 数量和迭代次数之间没有相互作用,但对于基于模型的优化器,有一些事情需要记住。首先,你拥有的 Worker 越多,并发运行就越多。这意味着最初(没有模型时)会抽取更多的随机配置。因此,如果 Worker 池中 Worker 更多,模型的构建可能会更晚,这可能会对优化产生负面影响,尤其是迭代次数很少时。其次,Worker 越多,在新结果出现之前对模型的查询就越多。这可能导致过程比顺序运行时在局部最优解中停留更长时间。

b. 如何选择预算?

这是一个很难笼统回答的问题,完全取决于具体问题。当我们通常将 BOHB 应用于新问题时,我们采取以下步骤:

  1. 如果必要/可能,我们简化配置空间,使其最多为 10 维,以使问题更容易。
  2. 我们对我们认为 合理 的预算进行短时优化运行。max_budget 不必是我们最终实际目标达到的预算,但应该足够大,以便我们确信它能代表完整问题。
  3. 我们分析运行结果,特别是查看不同预算之间的秩相关性。如果从一个预算到下一个更大预算之间的相关性非常小(小于 0.2 或左右),我们预计 Hyperband 或 BOHB 的性能不会很好。在这种情况下,我们会增加最小预算,或者降低 eta 参数,这将缩小预算之间的步长。
  4. 我们重复步骤 2 和 3,直到我们发现优化进展令人满意。

理想情况下,优化器会在运行时调整预算,但目前实现的优化器中没有一个做到这一点。我们正在开发自动执行此过程并将其纳入优化运行本身的扩展。

c. 我什么时候应该更改优化器的参数?

希望永远不需要,但这可能不是真的。我们知道有些情况下,我们必须调整 BOHB 的默认参数才能获得最佳性能。这一切都有些依赖于具体问题,所以没有通用的建议,但有一些经验法则:

如果 BOHB 一段时间没有找到更好的解,但你知道/期望更好的性能是可能的,你可以尝试通过以下方式使其更多地探索:
  1. 减少 num_samples
  2. 增加 top_n_percent
  3. 增加 min_bandwidth 和/或 bandwidth_factor