Ray----Tune(3):Tune试验(trial)调度
本篇介绍Tune中trial调度算法。主要介绍了Population Based Training (PBT)、Asynchronous HyperBand、 HyperBand及实现、Median Stopping Rule四种试验调度。
默认情况下,Tune使用FIFOSchscheduler类按顺序安排试验。不过,您还可以指定一个自定义调度算法,该算法可以提前停止试验或干扰参数。
tune.run( ... , scheduler=AsyncHyperBandScheduler())
Tune包括早期停止算法的分布式实现,例如中值停止规则,HyperBand和HyperBand的异步版本。这些算法具有很高的资源效率,在很多情况下都优于贝叶斯优化方法。目前,所有调度程序都接受一个reward_attr
,该值假定为最大化。
目前可用的试验调度程序:
- Population Based Training (PBT)
- Asynchronous HyperBand
- HyperBand--------HyperBand Implementation Details
- Median Stopping Rule
下面介绍这四种调度算法。
1.Population Based Training (PBT)
Population Based Training (PBT)的分布式实现。这可以通过设置tune.run
的scheduler
参数来启动,例如:
pbt_scheduler = PopulationBasedTraining(
time_attr='time_total_s',
reward_attr='mean_accuracy',
perturbation_interval=600.0,
hyperparam_mutations={
"lr": [1e-3, 5e-4, 1e-4, 5e-5, 1e-5],
"alpha": lambda: random.uniform(0.0, 1.0),
...
})
tune.run( ... , scheduler=pbt_scheduler)
当启用PBT调度程序时,每个试验变量都被视为总体中的一个成员。性能最好的trial是周期性的检查点测试(这要求您的Trainable 支持检查点测试)。对高性能的检查点的试验进行克隆是低性能的,会扰乱希望的好变量的配置信息。
可以通过运行toy PBT 例子了解PBT的工作。当在PBT模型下进行训练时,单个试验可能会在其生命周期中看到许多不同的超参数,并将其记录在result.json
文件。单个实验过程中优化LR调度的PBT生成了下图:
class ray.tune.schedulers.PopulationBasedTraining(time_attr='time_total_s',
reward_attr='episode_reward_mean', perturbation_interval=60.0,
hyperparam_mutations={}, resample_probability=0.25, custom_explore_fn=None)
PopulationBasedTraining源码,PBT论文
PBT并行地训练一组模型(或代理)。性能较差的模型会周期性地克隆性能最好的模型的状态,并对它们的超参数进行随机突变,希望能够超过当前性能最好的模型。
与其他超参数搜索算法不同,PBT在训练过程中会改变超参数。这支持非常快的超参数发现,并自动发现良好的退火调度。
此Tune PBT实现将所有添加的试验视为PBT总体的一部分。如果试验的数量超过了集群的能力,将对试验进行时间复用,以平衡整个实验的训练进展。
参数:
time_attr (str) –训练结果用的比较时间。注意,您可以传递一些非时间的东西,比如training_iteration
作为进度的度量,惟一的要求是属性应该单调地增加。
reward_attr (str) – 训练结果目标值属性。与time_attr一样,这可以引用任何客观值。停止过程将使用
此属性。
perturbation_interval (float) – 模型将考虑在这个 time_attr时间间隔内的扰动。注意,扰动会导致检查
点开销,因此不应该将此设置为太频繁。
hyperparam_mutations (dict) –Hyperparams变异。格式如下:对于每个键,可以提供列表或函数。列表
指定一组允许的分类值。函数指定连续参数的分布。您必须指定至少一个hyperparam_variables或
custom_explore_fn。
resample_probability (float) – 当应用hyperparam_mutation时,从原始分布重新采样的概率。如果不
进行重采样,则连续的值会受到1.2或0.8倍的扰动,离散的值则会变为相邻值。
custom_explore_fn (func) –您还可以指定一个定制的探测函数。在应用了hyperparam_variables的内
置扰动之后,这个函数被调用为f(config),并且应该返回根据需要更新的配置。您必须指定至少一个
hyperparam_variables或custom_explore_fn。
Example
>>> pbt = PopulationBasedTraining(
>>> time_attr="training_iteration",
>>> reward_attr="episode_reward_mean",
>>> perturbation_interval=10, # every 10 `time_attr` units
>>> # (training_iterations in this case) 每一个time_attr 进行10次
>>> hyperparam_mutations={
>>> # Perturb factor1 by scaling it by 0.8 or 1.2. Resampling
>>> # resets it to a value sampled from the lambda function.
>>> "factor_1": lambda: random.uniform(0.0, 20.0),
>>> # Perturb factor2 by changing it to an adjacent value, e.g.
>>> # 10 -> 1 or 10 -> 100. Resampling will choose at random.
>>> "factor_2": [1, 10, 100, 1000, 10000],
>>> })
>>> run_experiments({...}, scheduler=pbt)
Asynchronous(异步) HyperBand
通过设置tune.run
的scheduler
参数,可以使用HyperBand 调度器的异步版本。
async_hb_scheduler = AsyncHyperBandScheduler(
time_attr='training_iteration',
reward_attr='episode_reward_mean',
max_t=100,
grace_period=10,
reduction_factor=3,
brackets=3)
tune.run( ... , scheduler=async_hb_scheduler)
与原始版本的HyperBand相比,该实现提供了更好的并行性,并避免了消除过程中的掉队问题。在async_hyperband_example.py中可以找到一个这样的例子。我们建议在标准HyperBand 调度程序上使用此功能。
class ray.tune.schedulers.AsyncHyperBandScheduler(time_attr='training_iteration',
reward_attr='episode_reward_mean', max_t=100, grace_period=10,
reduction_factor=3, brackets=3)
AsyncHyperBandScheduler类源码,Asynchronous HyperBand论文
这应该提供与 HyperBand类似的理论性能,但是避免了 HyperBand所面临的问题(消除过程中的掉队问题)。一个实现细节是,当使用多个方括号时,试验分配到方括号是随机进行的,具有超过软最大值的概率。
参数:
time_attr (str) – 用于比较时间的训练结果。注意,您可以传递一些非时间的东西,比如
training_iteration作为进度的度量,惟一的要求是属性应该单调地增加。
reward_attr (str) – 训练结果目标值属性。与time_attr一样,这可以引用任何客观值。停止过程将使用
此属性。
max_t (float) – 每次训练的最大时间单位。max_t时间单位(由time_attr决定)通过后,将停止试验。
grace_period (float) – 只有停止试验,至少在这个老的时间。这些单元与time_attr所命名的属性相同。
reduction_factor (float) –用于设定减半率和用量。这只是一个无单位标量。
brackets (int) –括号数量。 每个括号具有不同的减半率,由减少系数指定。
HyperBand
请注意,HyperBand调度程序要求您的trainable支持检查点,这在Tune用户指南中进行了描述。检查点使调度程序能够将许多并发测试多路复用到一个有限大小的集群上。
Tune还实现了HyperBand的标准版本。你可以这样使用:
tune.run( ... , scheduler=HyperBandScheduler())
一个例子可以在hyperband_example.py中找到。一个这样的hyperband运行过程如下所示。
== Status ==
Using HyperBand: num_stopped=0 total_brackets=5
Round #0:
Bracket(n=5, r=100, completed=80%): {'PAUSED': 4, 'PENDING': 1}
Bracket(n=8, r=33, completed=23%): {'PAUSED': 4, 'PENDING': 4}
Bracket(n=15, r=11, completed=4%): {'RUNNING': 2, 'PAUSED': 2, 'PENDING': 11}
Bracket(n=34, r=3, completed=0%): {'RUNNING': 2, 'PENDING': 32}
Bracket(n=81, r=1, completed=0%): {'PENDING': 38}
Resources used: 4/4 CPUs, 0/0 GPUs
Result logdir: ~/ray_results/hyperband_test
PAUSED trials:
- my_class_0_height=99,width=43: PAUSED [pid=11664], 0 s, 100 ts, 97.1 rew
- my_class_11_height=85,width=81: PAUSED [pid=11771], 0 s, 33 ts, 32.8 rew
- my_class_12_height=0,width=52: PAUSED [pid=11785], 0 s, 33 ts, 0 rew
- my_class_19_height=44,width=88: PAUSED [pid=11811], 0 s, 11 ts, 5.47 rew
- my_class_27_height=96,width=84: PAUSED [pid=11840], 0 s, 11 ts, 12.5 rew
... 5 more not shown
PENDING trials:
- my_class_10_height=12,width=25: PENDING
- my_class_13_height=90,width=45: PENDING
- my_class_14_height=69,width=45: PENDING
- my_class_15_height=41,width=11: PENDING
- my_class_16_height=57,width=69: PENDING
... 81 more not shown
RUNNING trials:
- my_class_23_height=75,width=51: RUNNING [pid=11843], 0 s, 1 ts, 1.47 rew
- my_class_26_height=16,width=48: RUNNING
- my_class_31_height=40,width=10: RUNNING
- my_class_53_height=28,width=96: RUNNING
class ray.tune.schedulers.HyperBandScheduler(time_attr='training_iteration', reward_attr='episode_reward_mean', max_t=81)
HyperBandScheduler类的源码,HyperBand论文
HyperBandScheduler早期停止使用超带优化算法的试验。它将试验分为不同大小的括号,并定期在每个括号内提前停止性能较差的试验。
要使用这个带Tune的HyperBand实现,您所需要做的就是指定一个试验可以运行max_t的最大时间长度、时间单位time_attr和报告的目标值reward_attr的名称。我们根据给定的值自动确定其他超带参数的合理值。
例如,要根据episode_mean_reward attr将试验限制为10分钟并提前停止,请构造:HyperBand('time_total_s', 'episode_reward_mean', max_t=600)
请注意,Tune的停止标准将与HyperBand的早期停止机制一起应用。
参数:
time_attr (str) – 训练结果用于比较时间。注意,您可以传递一些非时间的东西,比如
training_iteration作为进度的度量,惟一的要求是属性应该单调地增加。
reward_attr (str) – 训练结果目标值属性。与time_attr一样,这可以引用任何客观值。停止过程将使
用此属性。
max_t (int) –每次试验的最大时间单位。max_t时间单位(由time_attr决定)通过后,将停止试验。调度
程序将在此时间通过后终止试验。注意,这与原始HyperBand论文中提到的max_t的语义不同。
HyperBand实现细节
实现细节可能会稍微偏离理论,但重点是提高可用性。注:R、s_max、eta为论文给出的HyperBand参数。详情查看本论文了解上下文。
-
s_max
(表示number of brackets - 1
)和eta
(表示下采样率)都是固定的。在许多实际设置中,R
可以设置得相当大,比如R >= 200
,R
表示某个资源单元和通常训练迭代的次数。为了简单起见,假设eta = 3
。在R = 200
和R = 1000
之间改变R
,就会产生一个巨大的范围,需要大量的试验来填充所有的括号。
另一方面,在R = 300处保持R不变,并且改变eta也会导致HyperBand构型,这不是很直观:
该实现采用与论文给出的示例相同的配置,并公开max_t
,max_t
不是论文中的参数。 - 后文中计算
n_0
的例子实际上与论文给出的算法略有不同。在这个实现中,我们根据论文实现n_0
(如下例中为n):
3.还有一些具体的实现细节,比如如何将试验放在括号中,这些在本文中没有涉及。该实现将试验按照较小的括号放在括号内——这意味着试验数量越少,早期停止的次数就越少。
Median Stopping Rule(中值停止规则)
中值停止规则实现了一个简单的策略,即如果一个试验的性能在相同时间点低于其他试验的中值,则停止该试验。你可以设置scheduler
参数如下:
tune.run( ... , scheduler=MedianStoppingRule())
class ray.tune.schedulers.MedianStoppingRule(time_attr='time_total_s', reward_attr='episode_reward_mean', grace_period=60.0, min_samples_required=3, hard_stop=True, verbose=True)
MedianStoppingRule类源代码,Median Stopping Rule论文
参数:
time_attr (str) –训练结果用于比较时间。注意,您可以传递一些非时间的东西,比如
training_iteration作为进度的度量,惟一的要求是属性应该单调地增加。
reward_attr (str) –训练结果目标值属性。与time_attr一样,这可以引用任何应该随时间增长的客
观值。
grace_period (float) – 只有停止试验,至少在这个老的时间。这些单元与time_attr所命名的属性
相同。
min_samples_required (int) –计算中值的最小样本。
hard_stop (bool) – 如果错误,暂停试验而不是停止试验。当所有其他试验完成时,暂停的试验将重新开始并允许运行FIFO。
verbose (bool) – 如果为真,将在每次试验报告时输出中值和最佳结果。默认值为True。
此篇主要参考Ray官网,如有错误,请阅读者提出指正,谢谢!
原英文链接:https://ray.readthedocs.io/en/latest/tune-schedulers.html
Ray----Tune(4):Tune 的搜索(Search)算法:https://blog.****.net/weixin_43255962/article/details/89307928