Tune:一个分布式模型选择与训练研究平台

本篇主要是对Tune: A Research Platform for Distributed Model Selectionand Training,论文的翻译。介绍了ray中并行的tune超参数搜索框架集成的超参数优化算法和和调度算法的运行原理,只需要修改很少自己的代码就可以使用性能强大的超参数搜索算法,并能实现在不修改代码(或极少代码)的同步到集群上。

摘要: 现代机器学习算法对计算的要求越来越高,需要专门的硬件和分布式计算来在合理的时间范围内实现更高的性能。为了提高超参数模型对参数的选择效率,已经提出了许多超参数搜索算法,但它们对分布式计算环境的适应性往往是临时的。我们提出了一个统一的模型选择和训练框架Tune,它在训练脚本和搜索算法之间提供了一个统一的接口。结果表明,该接口能够满足大范围超参数搜索算法的要求,可以直接将搜索扩展到较大的集群上,并简化了算法的实现。在Tune演示了几种最先进的超参数搜索算法的实现。Tune可以在http://ray.readthedocs.io/en/latest/tune.html中找到。

1.介绍

机器学习过程的复杂性导致了成本的昂贵。特别是模型选择阶段,包括模型训练和超参数调优,会占用机器学习实践者的大部分时间,消耗大量的计算资源。例如,一名研究人员打算训练ResNet-101,这是一个包含数百万参数的卷积神经网络模型。在一个GPU上训练这个模型可能需要大约24小时,而按顺序执行模型选择将需要数周时间来完成。自然,人们倾向于在一个分布式集群上训练模型 ,并利用许多机器并行地执行模型选择。
为此,研究团队开发了许多加速模型选择的技术,包括顺序 、并行和两者同时。然而,每一种技术通常都是单独实现的,与特定的框架相关联,是闭源的,或者在没有大量计算资源的情况下甚至无法重现。此外,这些技术常常需要在软件基础设施上投入大量资金来执行实验。
Tune:一个分布式模型选择与训练研究平台_第1张图片
图1:Tune提供了窄腰接口,训练脚本可以通过几行代码更改来实现。修改一旦完成,就可以使用tune进行实验管理、结果可视化和试验调度策略的选择。这个狭窄的接口还拥有AutoML研究权力能够轻松地替换不同的搜索算法进行比较,或者发布新算法的分布式实现,而无需担心分布式框架。
本篇文章主要介绍一下两个部分:

  • 介绍了用于分布式模型选择的开源框架Tune。
  • 展示Tune的api如何轻松地复制和集成各种最先进的超参数搜索算法。

2.相关工作

有多种用于模型选择的开源系统。HyperOpt, Spearmint, and HPOLib 是分布式模型选择工具,管理模型的搜索和评估,实现随机搜索和 tree of parzen estimators(TPE)等搜索技术(TPE有需要有数学基础才可以读懂,有兴趣的可以去研究一下)。但是,这两个框架都与搜索算法结构紧密耦合,需要跨集群手工管理计算资源。此外,诸如Spearmint、HyperOpt和TuPAQ (MLBase)等系统)将完整的试验执行视为一个原子单元,不允许对试验执行进行中间控制。这限制了集群资源的有效使用,也没有提供支持 HyperBand等算法所需的表达能力。
谷歌Vizier 是Google的内部服务,提供模型选择功能。与Tune类似,Vizier提供试验的并行评估,托管许多最先进的优化算法,提供性能分析的功能。然而,它首先最重要的是一个服务,并且与闭源基础设施相关联(不开源)。
Mistique 也是一个处理模型选择的系统。然而,Mistique关注的不是选择过程的执行,而是模型调试,强调迭代过程和内存占用最小化。
最后,Auto-SKLearn和Auto-WEKA是自动选择模型的系统,将元学习和集成到一个系统中。这些系统的重点是执行层,而不是算法层。这意味着,原则上可以在调优的基础上实现Auto-WEKA和Auto-SKLearn,提供这些AutoML组件的分布式执行。此外,Auto-KLearn 和Auto-WEKA都分别与Scikit-Learn和WEKA绑定,作为唯一受支持的机器学习框架。

3.API通用性的要求

我们将试验称为具有固定初始超参数配置的单个训练运行。一个实验(类似于Vizier中的一个研究)是由Tune使用它的一个试验调度算法(实现模型选择)监督的试验集合(注意:试验是实验中并行运行的一个trial)。
一个模型搜索和训练平台混合了顺序和并行计算。在搜索过程中,多个试验是并行评估的。超参数搜索算法按顺序检查试验结果,并做出决策进而提高并行的计算效率。为了支持广泛的训练工作量和选择算法,模型搜索框架需要满足以下要求:

  • 处理不规则试验计算的能力:试验通常在长度和资源使用上有所不同。
  • 能够处理任意用户代码和第三方库的资源需求。这包括并行性和硬件资源(如gpu)的使用。
  • 能够根据中间试验结果做出搜索/调度决策。例如,遗传算法通常在训练过程中克隆或变异模型参数。执行早期停止的算法也使用中间结果来做出停止决策。

为了获得良好的用户体验,还需要具备以下功能:

  • 监测和可视化试验进展和结果。
  • 简单的集成和规范的实验执行。

为了满足这些需求,我们提出了面向用户和调度api(第4节)的tune,并能在Ray分布式计算框架上实现。Ray框架提供了底层的分布式执行和资源管理。其灵活的任务和参与者抽象允许Tune调度不规则的计算,并根据中间结果做出决策。

4.Tune API

Tune提供了两个开发接口:一个用户API,用于寻求训练模型的用户;一个调度API,用于对改进模型搜索过程本身感兴趣的研究人员。由于这种划分,Tune的用户API可以选择许多搜索算法。相应地,调度 API使研究人员能够轻松地针对不同范围的工作负载,并提供一种机制使用户可以使用他们的算法。

4.1 用户API

模型训练脚本通常被实现为一个模型改进步骤的循环,结果定期记录到控制台(例如,每个训练历元)。为了支持全范围的模型搜索算法,Tune需要访问中间训练结果、快速获取训练状态的能力,以及在训练过程中更改超参数的能力。通过协作控制模型,只需对现有用户代码进行最小的修改,就可以满足这些需求。
Tune:一个分布式模型选择与训练研究平台_第2张图片
图2:Tune提供了基于功能的协作控制API和基于类的允许直接控制试验(trial)执行API。用户可以采用任何一种方法,通过tune的试验(trial)调度程序来启用对模型训练的控制。

考虑一个典型的模型训练脚本,如图2(a)所示。函数中传递了一个tune句柄。为了与tune集成,从tune.params映射中提取模型和优化器超参数,在tune.should_checkpoint()返回正值时创建检查点,并将保存的检查点文件传递给tune.record_checkpoint()。中间结果通过tune_report()报告。这些协作调用使tune调度算法能够监视每个试验的训练进度(通过报告的度量),保存和克隆有希望的参数(通过检查点保存和恢复),并在运行时更改超参数(通过使用更改的超参数映射恢复检查点)。关键的是,这些调用只需要对现有用户代码进行很小的更改。
如果用户扩展了可训练的模型类,Tune也可以直接控制试验执行(图2(b))。 这里,训练步骤,检查点和恢复是作为类方法实现的,Tune调度程序调用这些方法来逐步训练模型。 与协同控制相比,这种执行方式具有一些可调试性优势。 在内部,Tune通过协作接口插入适配器,为试用调度程序提供直接控制的外观。

4.2 调度API

考虑到创建试验并控制其执行的能力,下一个问题是应该如何安排试验。Tune的试验调度程序在一组可以运行的试验上运行,在给定可用集群资源的情况下对试验执行进行优先级排序。此外,它们还可以添加到要执行的试验列表中(例如,根据HyperOpt的建议suggestions)。
最简单的试验调度程序按顺序执行试验,直到满足停止条件为止。当集群中有足够的资源时,将并行启动试验。然而,这并不是所有的试验调度程序都能做到的。他们可以:

  1. 根据中间结果,早期停止性能不佳的试验。
  2. 调整学习速率等超参数的退化。
  3. 克隆有希望的试验的参数,并启动探索附近超参数空间的其他试验。
  4. 查询一个共享的试验结果数据库,选择有希望的超参数。
  5. 优先考虑大量试验之间的资源分配,并且可以在给定可用资源的情况下同时运行。

试用调度器的主要接口如下:

class TrialScheduler:
	def on_result(self, trial, result): ...
	def choose_trial_to_run(self): ...

接口是基于事件的。当Tune有可用资源时,它调用scheduler.choice_ try_to_run()来获得要在集群上启动的试验(trial)。当试验结果可用时,将调用scheduler.on_result()回调函数,调度器返回一个标志,指示是否更新超参数配置信息去继续、检查点、停止或重启试验。该接口足以提供广泛的超参数调优算法,包括中值停止规则(Median Stopping Rule)、贝叶斯优化方法( Bayesian Optimization approaches)、HyperBand和基于种群的训练( Population-based Training)。
我们注意到,Tune将活动试验的元数据保存在内存中,并依赖检查点来进行容错。这极大地简化了试验调度程序的设计,并且在实践中没有限制。如果需要,试用调度程序实现可以自由地利用外部存储。

4.3 组合起来

要启动一个实验,用户必须指定他们的模型训练函数或类(图1和图2(b))、一组初始试验和一个试验调度程序。下面是一个最小的例子:

def my_func(): ...
tune.run_experiments(my_func, {
	"lr": tune.grid_search([0.01, 0.001, 0.0001]),
	"activation": tune.grid_search(["relu", "tanh"]),
}, scheduler=HyperBand)

在这里,我们使用Tune的内置DSL在两个超参数上指定一个小型的3*2网格搜索。这些将作为调度程序的初始试验(trial)输入集。Tune的参数DSL提供了与HyperOpt类似的特性。或者,用户可以使用他们选择的机制生成初始试验(trial)配置列表。一旦启动了一个实验,就会在控制台中定期报告试验的进展,还可以通过诸如TensorBoard之类的集成来查看。

4.3.1 比例计算(Scaling computation)

Tune中的每个测试运行在它自己的Python进程中,并且可以通过Ray分配给定数量的CPU和GPU资源。单个试验本身也可以利用分布式计算,通过使用Ray api启动更多的子进程。这些子进程可以使用Ray来相互协调,例如,执行SGD,或者使用由诸如torch.distributed和Nvidia NCCL之类的库提供的集体通信原语。

Algorithm(算法) 代码行数
FIFO (trivial scheduler) 默认 10
Asynchronous HyperBand 78
HyperBand 215
Median Stopping Rule 68
HyperOpt 137
Population-Based Training 169

表1:Tune中实现(或集成)的模型选择算法。HyperBand实现了两个版本的HyperBand:原始格式和异步变化,在分布式设置中更容易实现。

4.3.2 数据输入

由于Tune中的每个试验(trial)都作为一个Ray任务或参与者(actor)运行,所以它们可以使用Ray api来处理数据的摄取。例如,可以使用ray.put(obj)将权重广播给所有工作人员(worker)到Ray对象存储中,并在试验(trial)初始化期间通过ray.get(obj_id)检索权重。
注:此处的权重可以理解为对象。ray.put(obj)–把obi这个对象告知所有的woker,存储到对象存储中,且返回一个对象ID(即obj_id).ray.get(obj_id)–通过obj_id在对象存储中检索,若检索成功返回对象值。

5 实现

我们在表1中列出了当前tune实现的算法。行数包括用于记录和调试功能的行。我们使用Ray框架实现了tune,如前所述,tune框架提供了用于运行测试的actor抽象。与流行的分布式框架(如Spark 或MPI)相比,Ray提供了更灵活的编程模型。这种灵活性使Tune的试验调度程序能够集中控制由超参数优化算法创建的许多类型的有状态分布式计算。

Ray框架也特别适合于执行嵌套计算(即,超参数优化),因为它具有两级分布式调度程序。 在Ray中,任务调度决策通常会尽可能的在本地计算机上进行,仅在本地资源耗尽时才会溢出到群集上的其他计算机。 这可以避免在自己利用并行计算的试验执行时可能出现任何中心瓶颈。

6 总结与展望

本篇中,探讨了超参数调优的一般框架的设计。提出了调优API和系统,它支持可扩展的分布式超参数搜索算法,同时也便于终端用户模型开发人员将其集成到模型设计过程中。我们正在积极开发新的功能,不仅在调优过程中提供帮助,而且在分析和调试中间结果方面也提供帮助。

此篇主要参考Ray官网中的Tune: A Research Platform for Distributed Model Selection and Training论文,如有错误,请阅读者提出指正,谢谢!
原英文论文链接:https://arxiv.org/abs/1807.05118

你可能感兴趣的:(学习,ray,ray,tune)