如何为 Ray Tune 实验定义停止标准#
在运行 Tune 实验时,事先确定理想的训练时长可能具有挑战性。Tune 中的停止标准可以根据特定条件终止训练,这非常有用。
例如,可能希望在以下情况下设置实验停止:
设置一个实验,使其在
N
个周期后结束,或者当报告的评估分数超过特定阈值时结束,以先发生者为准。在
T
秒后停止实验。当试验遇到运行时错误时终止。
通过利用 Tune 的早期停止调度器,尽早停止表现不佳的试验。
本用户指南将演示如何在 Tune 实验中实现这些类型的停止标准。
对于所有的代码示例,我们使用以下训练函数进行演示:
from ray import train
def my_trainable(config):
i = 1
while True:
# Do some training...
time.sleep(1)
# Report some metrics for demonstration...
train.report({"mean_accuracy": min(i / 10, 1.0)})
i += 1
手动停止一个 Tune 实验#
如果你向运行 Tuner.fit()
的进程发送 SIGINT
信号(这通常是在终端中按下 Ctrl+C
时发生的情况),Ray Tune 会优雅地关闭训练并保存最终的实验状态。
备注
强制终止一个 Tune 实验,例如通过多次 Ctrl+C
命令,将不会给 Tune 最后一次机会来快照实验状态。如果你在未来恢复实验,这可能导致以陈旧状态恢复。
Ray Tune 也接受 SIGUSR1
信号以优雅地中断训练。当在远程 Ray 任务中运行 Ray Tune 时,应使用此信号,因为 Ray 默认会过滤掉 SIGINT
和 SIGTERM
信号。
停止使用基于指标的标准#
除了手动停止外,Tune 还提供了几种以编程方式停止实验的方法。最简单的方法是使用基于指标的标准。这些是一组固定的阈值,用于确定实验何时应停止。
你可以使用字典、函数或自定义的 Stopper
来实现停止条件。
如果传递的是一个字典,键可以是 Function API 中 session.report
返回结果或 Class API 中 step()
的任何字段。
备注
这包括 自动填充的指标 ,例如 training_iteration
。
在下面的例子中,每个试验将在完成 10
次迭代或达到 0.8
或更高的平均准确率时停止。
这些指标被假定为 递增 ,因此一旦报告的指标超过了字典中指定的阈值,试验将停止。
from ray import train, tune
tuner = tune.Tuner(
my_trainable,
run_config=train.RunConfig(stop={"training_iteration": 10, "mean_accuracy": 0.8}),
)
result_grid = tuner.fit()
为了更灵活,你可以传入一个函数。如果传入一个函数,它必须接受 (trial_id: str, result: dict)
作为参数并返回一个布尔值(如果试验应该停止则返回 True
,否则返回 False
)。
在下面的例子中,每个试验将在完成 10
次迭代或达到 0.8
或更高的平均准确率时停止。
from ray import train, tune
def stop_fn(trial_id: str, result: dict) -> bool:
return result["mean_accuracy"] >= 0.8 or result["training_iteration"] >= 10
tuner = tune.Tuner(my_trainable, run_config=train.RunConfig(stop=stop_fn))
result_grid = tuner.fit()
最后,您可以实现 Stopper
接口,以根据自定义停止条件停止单个试验甚至整个实验。例如,以下示例在任何单个试验达到条件后停止所有试验,并阻止新的试验开始:
from ray import train, tune
from ray.tune import Stopper
class CustomStopper(Stopper):
def __init__(self):
self.should_stop = False
def __call__(self, trial_id: str, result: dict) -> bool:
if not self.should_stop and result["mean_accuracy"] >= 0.8:
self.should_stop = True
return self.should_stop
def stop_all(self) -> bool:
"""Returns whether to stop trials and prevent new ones from starting."""
return self.should_stop
stopper = CustomStopper()
tuner = tune.Tuner(
my_trainable,
run_config=train.RunConfig(stop=stopper),
tune_config=tune.TuneConfig(num_samples=2),
)
result_grid = tuner.fit()
在示例中,一旦任何试验达到 mean_accuracy
为 0.8 或更高,所有试验将停止。
备注
当从 stop_all
返回 True
时,当前正在运行的试验不会立即停止。它们将在完成当前的训练迭代后停止(在 session.report
或 step
之后)。
Ray Tune 自带一组开箱即用的停止类。请参阅 停止器 文档。
在一定时间后停止试验#
有两种基于时间的停止Tune实验的选择:在指定超时后单独停止试验,或在一定时间后停止整个实验。
使用超时单独停止试验#
如上所述,您可以使用字典停止标准,使用 Tune 自动填充的 time_total_s
指标。
from ray import train, tune
tuner = tune.Tuner(
my_trainable,
# Stop a trial after it's run for more than 5 seconds.
run_config=train.RunConfig(stop={"time_total_s": 5}),
)
result_grid = tuner.fit()
备注
如果你使用 Function Trainable API,你需要通过 train.report
包含一些中间报告。每次报告都会自动记录试验的 time_total_s
,这允许 Tune 基于时间作为指标来停止。
如果训练循环在某处挂起,Tune 将无法拦截训练并为您停止试验。在这种情况下,您可以在训练循环中显式实现超时逻辑。
使用超时停止实验#
使用 TuneConfig(time_budget_s)
配置来告诉 Tune 在 time_budget_s
秒后停止实验。
from ray import tune
# Stop the entire experiment after ANY trial has run for more than 5 seconds.
tuner = tune.Tuner(my_trainable, tune_config=tune.TuneConfig(time_budget_s=5.0))
result_grid = tuner.fit()
备注
如果你使用 Function Trainable API,你需要通过 train.report
包含一些中间报告,原因与上述相同。
在试验失败时停止#
除了根据试验的表现停止试验外,如果任何试验遇到运行时错误,您还可以停止整个实验。为此,您可以使用 ray.train.FailureConfig
类。
通过此配置,如果任何试验遇到错误,整个实验将立即停止。
from ray import train, tune
import time
def my_failing_trainable(config):
if config["should_fail"]:
raise RuntimeError("Failing (on purpose)!")
# Do some training...
time.sleep(10)
train.report({"mean_accuracy": 0.9})
tuner = tune.Tuner(
my_failing_trainable,
param_space={"should_fail": tune.grid_search([True, False])},
run_config=train.RunConfig(failure_config=train.FailureConfig(fail_fast=True)),
)
result_grid = tuner.fit()
当你在调试一个包含许多试验的Tune实验时,这非常有用。
使用 Tune 调度器的早期停止#
另一种停止 Tune 实验的方法是使用提前停止调度器。这些调度器监控试验的性能,并在试验没有取得足够进展时提前停止它们。
AsyncHyperBandScheduler
和 HyperBandForBOHB
是 Tune 内置的早期停止调度器的例子。请参阅 Tune 调度器 API 参考 以获取完整列表,以及更多实际示例。
在下面的例子中,我们同时使用了一个字典停止标准和一个早停标准:
from ray import train, tune
from ray.tune.schedulers import AsyncHyperBandScheduler
scheduler = AsyncHyperBandScheduler(time_attr="training_iteration")
tuner = tune.Tuner(
my_trainable,
run_config=train.RunConfig(stop={"training_iteration": 10}),
tune_config=tune.TuneConfig(
scheduler=scheduler, num_samples=2, metric="mean_accuracy", mode="max"
),
)
result_grid = tuner.fit()
摘要#
在本用户指南中,我们学习了如何使用指标、试验错误和早期停止调度器来停止 Tune 实验。
更多信息请参阅以下资源:
对于一个手动中断的实验,或者在试验仍在运行时集群意外死亡的情况,可以恢复实验。请参阅 如何在 Ray Tune 中启用容错。