Ray Tune 调参实战 FAQ 指南:超参数搜索、早停调度、资源分配与实验复现
2026/9/20 10:04:32 网站建设 项目流程
  • 人工智能
  • 分布式训练
  • 强化学习
  • 任务调度
  • 模型推理服务

【免费下载链接】ray

Ray is an AI compute engine. Ray consists of a core distributed runtime and a set of AI Libraries for accelerating ML workloads.

项目地址:https://gitcode.com/gh_mirrors/ra/ray
点击查看免费下载

Ray Tune 是 Ray 生态中面向超参数调优(Hyperparameter Tuning, HPO)的核心库。本文以 doc/source/tune/faq.rst 为主体,系统整理 Ray Tune 使用过程中最高频的疑问:如何区分超参数与模型参数、如何按问题规模选择搜索算法与调度器、如何设计搜索空间(含嵌套与条件空间)、如何控制资源、如何复现实验、如何避免性能瓶颈,以及在本地开发测试 Tune 的完整方法。读完本文,你将掌握一套可直接落地的 Ray Tune 调参方法论,并能在实际集群环境中独立排查调度与性能问题。

什么是超参数?它与模型参数有何区别?

在监督学习中,我们用带标签的数据训练模型,使模型能够正确识别新的数据。模型的一切都由一组参数定义,例如线性回归中的权重——这些是模型参数(model parameters),它们是在训练过程中被学习出来的。

与之相对,超参数(hyperparameters)定义的是模型本身的结构性细节:我们使用的是线性回归还是分类器、神经网络采用什么架构、多少层、什么类型的滤波器等。这些都是在训练之前定义的,而不是通过学习得到的。此外,学习率(learning rate)、折扣因子(discount rate)等训练过程的配置也被视为超参数。如果希望训练过程和最终模型表现良好,首先需要确定一组最优或接近最优的超参数。

确定最优超参数最直接的方法是执行一个循环:从一组合理且尽可能包容的候选值中挑选一组配置,训练模型,与前几次循环的结果比较,最后挑选表现最佳的一组。这个过程称为超参数调优或优化(HPO)。超参数在一个受限且明确的搜索空间中取值,这个搜索空间由config字典中为每个超参数定义的采样分布共同构成。Ray Tune 的搜索空间 API 详见 Search Space API 相关章节。

如何选择搜索算法与调度器?

Ray Tune 提供 多种搜索算法 和 多种调度器。选择主要取决于你的问题特征:

  • 问题规模是大还是小(训练耗时多久?资源如 GPU 成本多高?能否并行运行大量 trial?)
  • 需要调优多少个超参数
  • 超参数的合法取值范围是什么

模型能返回增量结果:优先考虑早停

如果模型逐步返回增量结果(如深度学习按 epoch 返回结果、GBDT 每添加一棵树返回结果等),使用早停(early stopping)通常能让你采样更多配置,因为表现不佳的 trial 会在跑完全程之前被提前剪枝(prune)。请注意,并非所有搜索算法都能利用被剪枝 trial 的信息。早停的前提是必须有增量结果——在使用函数式 API 时,这意味着tune.report()必须在循环中被调用多次,而不是只调用一次。

小模型:随机搜索 + ASHA

如果模型较小,通常可以并行尝试大量不同配置。随机搜索(random search)可以用来生成配置,也可以对部分取值做网格搜索(grid search)。如果问题支持早停,建议同时使用 ASHA 调度器(Async Successive Halving Algorithm,异步连续减半算法)提前终止表现差的 trial。

大模型:贝叶斯优化或 PBT

如果模型较大,可以尝试基于贝叶斯优化的搜索算法,例如 BayesOpt,在少量 trial 之后就能得到较优的配置;Ax 与之类似但对噪声数据更稳健。请注意这些算法只适合少量超参数。另一种选择是 Population Based Training(PBT),它在 trial 数量很少(例如 8 个甚至 4 个)时也能工作得很好。不过 PBT 输出的是一个超参数训练计划(schedule),而不是一组固定的超参数。

按超参数特征选择

  • 超参数数量少:贝叶斯优化方法效果好。可参考 BOHB(贝叶斯优化 + Hyperband 的结合体)或 Optuna 配合 ASHA 调度器,把贝叶斯优化的采样能力与早停的加速能力结合起来。
  • 只有连续取值:与大多数贝叶斯优化方法配合良好。离散或分类变量也能工作,但随着类别数量增加效果会变差。
  • 大量分类取值:考虑使用随机搜索,或基于 TPE 的贝叶斯优化算法,如 Optuna 或 HyperOpt。

Ray Tune 的推荐默认组合

官方 FAQ 的"go-to"方案总结如下:

问题场景推荐方案
较小问题随机搜索 + ASHA 早停
较大问题、超参数数量少BOHB
较大问题、超参数数量多、且可接受学习计划PBT

如何选择超参数的取值范围?

一个好的出发点是:查阅提出该算法的论文,以及看看其他人都在用什么值。大多数算法对其部分参数也有合理的默认值。例如 XGBoost 的参数文档建议决策树最大深度max_depth=6,这里 2 到 10 之间的任何值都可能合理(当然取决于你的问题)。

Ray Tune 官方 FAQ 给出以下经验性建议:

超参数建议取值范围/分布
学习率使用1e-51e-1之间的loguniform 分布tune.loguniform(1e-5, 1e-1)
批大小尝试2 的幂:2、4、8、16、32、64、128、256 等。数据多而问题简单时用较大的批大小,数据少而问题难时用较小的批大小
网络层大小同样尝试2 的幂。小问题(如 Cartpole)用小层尺寸,大问题用大层尺寸
强化学习折扣因子在 0.9 到 1.0 之间均匀采样。视问题而定,更严格的范围(如高于 0.97 甚至 0.99,例如 Atari)也可能合理

如何使用嵌套/条件搜索空间?

有时需要定义取值依赖于其他参数值的参数。Ray Tune 提供了多种方式。

嵌套空间(Nested spaces)

可以将超参数定义嵌套在子字典中(示例来自 doc_code/faq.py):

config = {"a": {"x": tune.uniform(0, 10)}, "b": tune.choice([1, 2, 3])}

trial 的 config 会与输入的 config 完全一致地嵌套展开。

条件空间(Conditional spaces)

自定义与条件搜索空间的详细说明见 Search Space API 文档。简而言之,可以向tune.sample_from()传入自定义函数,函数可以返回依赖其他取值的结果。在源码 python/ray/tune/search/sample.py 中,sample_from(func)接收一个可调用对象并返回Function域,该可调用对象会收到当前 trial 已采样好的config字典,因此可以实现条件采样:

config = { "a": tune.randint(5, 10), "b": tune.sample_from(lambda config: np.random.randint(0, config["a"])), }

条件网格搜索(Conditional grid search)

如果想对两个相互依赖的参数做网格搜索,直接使用tune.sample_from是行不通的,因为它不支持网格搜索。解决方案是借助辅助函数生成一组合法元组,例如:假设a在 5 到 10 之间、b在 0 到a之间:

def _iter(): for a in range(5, 10): for b in range(a): yield a, b config = { "ab": tune.grid_search(list(_iter())), }

然后你的 trainable 中可以用a, b = config["ab"]解包这两个变量并使用。

早停(如 Hyperband/ASHA)是如何工作的?

早停算法会查看中间报告的值(即每个训练 epoch 之后通过tune.report()报告的值)。经过一定步数后,它们会移除表现最差的 trial,只保留表现最好的 trial。trial 的好坏通过目标指标排序来确定,例如 accuracy 或 loss。

在 ASHA 中,你可以控制被提前终止的 trial 数量。reduction_factor=4意味着每次缩减时只保留全部 trial 的25%。通过grace_period=n可以强制 ASHA 让每个 trial 至少训练n个 epoch。

为什么所有 trial 都返回 "1" iteration?

这个情况最常出现在 Tune 的函数式 API 中。Ray Tune 在内部每次调用tune.report()时递增迭代计数器。如果只在训练结束时调用一次tune.report(),计数器就只递增了一次。如果使用类 API,计数器会在每次调用step()之后递增。

注意,多报告几次指标可能更有意义。例如,如果你的算法训练 1000 个时间步,考虑每 100 步报告一次中间性能值。这样 Hyperband/ASHA 等调度器就能尽早终止表现差的 trial。

那些额外的输出是什么?

你会发现 Ray Tune 不仅报告超参数(来自config)和指标(传给tune.report()的),还会输出一些其他信息:

Result for easy_objective_c64c9112: date: 2020-10-07_13-29-18 done: false experiment_id: 6edc31257b564bf8985afeec1df618ee experiment_tag: 7_activation=tanh,height=-53.116,steps=100,width=13.885 hostname: ubuntu iterations: 0 iterations_since_restore: 1 mean_loss: 4.688385317424468 neg_mean_loss: -4.688385317424468 node_ip: 192.168.1.115 pid: 5973 time_since_restore: 7.605552673339844e-05 time_this_iter_s: 7.605552673339844e-05 time_total_s: 7.605552673339844e-05 timestamp: 1602102558 timesteps_since_restore: 0 training_iteration: 1 trial_id: c64c9112

这些自动填充字段的完整词汇表参见 tune-autofilled-metrics 章节。

如何设置资源?

如果想为某个 trial 分配特定资源,可以使用tune.with_resources,把它包裹在 trainable 外层,并传入一个字典或 PlacementGroupFactory 对象:

tuner = tune.Tuner( tune.with_resources( train_fn, resources={"cpu": 2, "gpu": 0.5, "custom_resources": {"hdd": 80}} ), ) tuner.fit()

从源码 python/ray/tune/trainable/util.py 可以看到,with_resources会将资源请求以_resources属性注解在 trainable 上(函数式 API),或通过default_resource_request()类方法暴露(类 API),由 Tune 在调度时解析。上面的示例展示了三个要点:

  1. cpugpu选项分别设置每个 trial 可用的 CPU 与 GPU 数量。trial 不能请求超过这些数量的资源(例外见第 3 点)。
  2. 可以请求分数 GPU。值为 0.5 意味着 GPU 一半的显存可供该 trial 使用。你需要自行确保模型能放进这部分的显存中。
  3. 可以请求启动集群时提供给 Ray 的自定义资源。trial 只会被调度到能够提供你请求的全部资源的单个节点上。

一个重要的注意点:每个 Ray worker(因此每个 Ray Tune trial)只会被调度到一台机器上。这意味着如果你为一个 trial 请求 2 个 GPU,但集群由 4 台各带 1 个 GPU 的机器组成,该 trial 永远不会被调度。换句话说,你必须确保 Ray 集群中存在能够满足资源请求的机器。

使用 Placement Group 请求额外资源

在某些情况下,trainable 可能需要启动其他远程 actor,例如通过 Ray Train 进行分布式训练时。此时可以使用 placement groups 请求额外资源:

tuner = tune.Tuner( tune.with_resources( train_fn, resources=tune.PlacementGroupFactory( [ {"CPU": 2, "GPU": 0.5, "hdd": 80}, {"CPU": 1}, {"CPU": 1}, ], strategy="PACK", ), ) ) tuner.fit()

这里为远程任务额外请求了 2 个 CPU。这两个额外 actor 不必与主 trainable 在同一节点上。实际上,你可以通过strategy参数控制这一点。在这个例子中,PACK会尽量将 actor 调度到同一节点,但也允许调度到其他节点。更多 placement 策略请参阅 placement groups 文档。

基于自定义规则分配资源(lambda 函数)

还可以基于自定义规则为 trial 分配特定资源。例如根据参数空间中的某个设置来决定是否分配 GPU:

tuner = tune.Tuner( tune.with_resources( train_fn, resources=lambda config: {"GPU": 1} if config["use_gpu"] else {"GPU": 0}, ), param_space={ "use_gpu": True, }, ) tuner.fit()

with_resources接受字典、PlacementGroupFactory或可调用对象三种形式(见 util.py),lambda 形式会在每个 trial 解析资源时以该 trial 的 config 为参数被调用。

训练卡住且 Ray 报告 pending actor 或 task 无法调度?

这通常是因为 trainable 启动了 Ray actor 或 task,但没有为它们计入资源,导致死锁。也可能是 trainable 内部使用了基于 Ray 的其他库(如 Modin)"隐蔽地"造成的。解决办法是使用上文介绍的 placement groups 为 trial 请求额外资源。

例如,如果 trainable 使用 Modin dataframe,对其的操作会生成 Ray task。通过为 trial 额外分配一个 CPU bundle,这些 task 就能正常运行而不至于资源匮乏:

def train_fn(config): # some Modin operations here # import modin.pandas as pd tune.report({"metric": metric}) tuner = tune.Tuner( tune.with_resources( train_fn, resources=tune.PlacementGroupFactory( [ {"CPU": 1}, # this bundle will be used by the trainable itself {"CPU": 1}, # this bundle will be used by Modin ], strategy="PACK", ), ) ) tuner.fit()

如何向 trainable 传递额外参数?

Ray Tune 期望你的 trainable 函数最多只接受两个参数:configcheckpoint_dir。但有时你想传入常量参数,比如运行的 epoch 数或训练用的数据集。Ray Tune 提供了包装函数 tune.with_parameters():

from ray import tune import numpy as np def train_func(config, num_epochs=5, data=None): for i in range(num_epochs): for sample in data: # ... train on sample pass # Some huge dataset data = np.random.random(size=100000000) tuner = tune.Tuner(tune.with_parameters(train_func, num_epochs=5, data=data)) tuner.fit()

这个函数的工作方式类似于functools.partial,但它会把参数**直接存放到 Ray 对象存储(object store)**中。这意味着即使传入数据集这样的大对象,Ray 也能保证它们在集群各机器上被高效存储与检索。从源码看,with_parameters通过内部_ParameterRegistry将每个 kwargs 对象put到对象存储,并在函数 trainable 每次被调用时按 key 取回注入(util.py)。

tune.with_parameters()也适用于类 trainable:对于类 API,参数会作为 kwargs 传给Trainable.setup()方法。

如何复现实验?

复现实验意味着重复运行时得到完全一致的结果。要做到这一点,每次运行实验的条件必须完全相同。在 ML 训练与调优中,这主要涉及训练和调优生命周期中各处用于采样的随机数生成器(RNG)

随机数生成器用于产生随机性,例如为你定义的参数采样超参数值。计算中没有真正的随机,而是存在能生成看似随机、满足随机分布所有性质的复杂算法。这些算法可以**播种(seeded)**一个初始状态,此后生成的随机数序列就总是相同的。

各环节的播种方法

训练与调优过程中多处存在随机性,需要在所有这些地方引入种子:

  • 搜索算法(Search algorithm):搜索算法需要播种,以便每次运行生成相同的超参数配置。某些搜索算法可以在构造函数中显式指定随机种子(寻找构造器中的seed参数);对于其他算法,尝试使用下面的代码块。
  • 调度器(Schedulers):像 PBT 这样的调度器依赖重新采样部分参数,这需要随机性。使用下面的代码块设置初始种子。
  • 训练函数(Training function):除了初始化配置,训练函数本身也必须使用种子,例如数据切分。你应该在训练函数开头设置种子。
# This should suffice to initialize the RNGs for most Python-based libraries import random import numpy as np random.seed(1234) np.random.seed(5678)

PyTorch 和 TensorFlow 使用各自的 RNG,也需要初始化:

import torch torch.manual_seed(0) import tensorflow as tf tf.random.set_seed(0)

因此你应当同时播种 Ray Tune 的调度器、搜索算法和训练代码。调度器与搜索算法应该始终使用同一个种子。训练代码也是如此,但通常让不同训练运行之间的种子互不相同更有益。

可复现实验的完整蓝图

import random import numpy as np from ray import tune def trainable(config): # config["seed"] is set deterministically, but differs between training runs random.seed(config["seed"]) np.random.seed(config["seed"]) # torch.manual_seed(config["seed"]) # ... training code config = { "seed": tune.randint(0, 10000), # ... } if __name__ == "__main__": # Set seed for the search algorithms/schedulers random.seed(1234) np.random.seed(1234) # Don't forget to check if the search alg has a `seed` parameter tuner = tune.Tuner(trainable, param_space=config) tuner.fit()

一个最小的可复现示例(来自 doc_code/faq.py):

import numpy as np from ray import tune def train_func(config): # Set seed for trainable random result. # If you remove this line, you will get different results # each time you run the trial, even if the configuration # is the same. np.random.seed(config["seed"]) random_result = np.random.uniform(0, 100, size=1).item() tune.report({"result": random_result}) # Set seed for Ray Tune's random search. # If you remove this line, you will get different configurations # each time you run the script. np.random.seed(1234) tuner = tune.Tuner( train_func, tune_config=tune.TuneConfig( num_samples=10, search_alg=tune.search.BasicVariantGenerator(), ), param_space={"seed": tune.randint(0, 1000)}, ) tuner.fit()

请注意,并非总能控制所有非确定性来源。例如使用 ASHA 或 PBT 时,某些 trial 可能比其他 trial 更早结束,从而影响调度器行为;哪个 trial 先结束又可能取决于系统负载、网络通信等我们无法用随机种子控制的环境因素。这对贝叶斯优化等搜索算法同样成立,因为它们会在采样新配置时参考先前结果。可以通过使用 PBT 和 Hyperband 的同步模式来缓解:这些模式下,调度器会等待所有 trial 完成一个 epoch 后再决定提升哪些 trial。

官方建议:在依赖复现结果进行大规模实验之前,先在较小的玩具问题上尝试复现。

如何避免性能瓶颈?

有时你会遇到类似这样的消息:

The `experiment_checkpoint` operation took 2.43 seconds to complete, which may be a performance bottleneck

最常见的是experiment_checkpoint操作抛出此警告,但也可能是别的操作,比如process_trial_result。这些操作通常应在 500ms 内完成;当它持续更长时间时,可能意味着存在问题或低效之处。要消除这条消息,需要理解它从何而来。主要原因如下:

trial config 非常大

例如试图通过config参数传入数据集或其他大对象。这种情况下,数据集在实验检查点(experiment checkpointing)期间被反复序列化并写入磁盘,耗时很长。

解决方案:使用 tune.with_parameters 通过对象存储向函数 trainable 传递大对象。对于类 trainable,可以手动通过ray.put()ray.get()完成。如果需要传递类定义,考虑传递一个指示符(如字符串)而让 trainable 自行选择类。一般来说,config 字典应该只包含数字、字符串等原始类型

trial result 非常大

例如在类 trainable 的step()返回值或函数 trainable 的tune.report()中返回对象、数据或其他大对象。效果同上:结果被反复序列化并写入磁盘,耗时很长。

解决方案:改用检查点(checkpoint),把数据写入 trainable 的当前工作目录。根据使用的是类 API 还是函数 API,有多种实现方式。

在集群上训练大量 trial,或保存了巨大的检查点

解决方案:使用 cloud checkpointing 将日志和检查点保存到指定的storage_path。这是处理该问题的首选方式:所有节点都能访问云存储,同步工作会自动完成;同时结果也是安全的,即使你在可抢占实例上工作也不会丢失数据。

报告结果过于频繁

每个结果都会被搜索算法、trial 调度器和回调(包括 logger 与 trial syncer)处理。如果每个 trial 报告的结果数量很大(例如每秒多个结果),会非常耗时。

解决方案:减少报告频率。在类 trainable 中,step()也许应该处理更大块的数据;在函数 trainable 中,可以只在训练循环的每 n 次迭代报告一次。平衡好真正需要用于调度与搜索决策的结果数量。如果需要更细粒度的指标做日志或追踪,考虑使用独立的日志机制,而不是 Ray Tune 自带的结果进度日志。

如何配置搜索空间?

可以通过传给Tuner(param_space=...)的字典指定网格搜索或采样分布:

parameters = { "qux": tune.sample_from(lambda spec: 2 + 2), "bar": tune.grid_search([True, False]), "foo": tune.grid_search([1, 2, 3]), "baz": "asd", # a constant value } tuner = tune.Tuner(train_fn, param_space=parameters) tuner.fit()

默认情况下,每个随机变量和网格搜索点各采样一次。要多次随机采样,可在实验配置中添加num_samples: N。如果提供了grid_search参数,网格会重复num_samples次。例如下面这个配置会产生总共 90 个 trial(3×3 的网格被num_samples=10重复 10 次):

# num_samples=10 repeats the 3x3 grid search 10 times, for a total of 90 trials tuner = tune.Tuner( train_fn, run_config=tune.RunConfig(name="my_trainable"), param_space={ "alpha": tune.uniform(100, 200), "beta": tune.sample_from(lambda config: config["alpha"] * np.random.normal()), "nn_layers": [ tune.grid_search([16, 64, 256]), tune.grid_search([16, 64, 256]), ], }, tune_config=tune.TuneConfig(num_samples=10), )

注意,搜索空间在不同的搜索算法之间可能不互通。例如,对很多搜索算法而言,你无法使用grid_searchsample_from参数。详细说明参见 Search Space API 文档页。

如何在训练函数中访问相对文件路径?

假设你在~/code目录下用my_script.py启动一个 Tune 实验。默认情况下,Tune 会把每个 worker 的工作目录切换到其对应的 trial 目录(例如~/ray_results/exp_name/trial_0000x)。这保证了每个 worker 进程有独立的工作目录,避免保存 trial 专属输出时的冲突。

可以通过设置环境变量RAY_CHDIR_TO_TRIAL_DIR=0来配置:这明确告诉 Tune把工作目录切换到 trial 目录,从而可以访问相对原始工作目录的路径。一个注意事项是:工作目录此时在 worker 之间是共享的,因此应该使用 tune.get_context().get_trial_dir() API 获取保存 trial 专属输出的路径:

def train_func(config): # Read from relative paths print(open("./read.txt").read()) # The working directory shouldn't have changed from the original # NOTE: The `TUNE_ORIG_WORKING_DIR` environment variable is deprecated. assert os.getcwd() == os.environ["TUNE_ORIG_WORKING_DIR"] # Write to the Tune trial directory, not the shared working dir tune_trial_dir = Path(ray.tune.get_context().get_trial_dir()) with open(tune_trial_dir / "write.txt", "w") as f: f.write("trial saved artifact") os.environ["RAY_CHDIR_TO_TRIAL_DIR"] = "0" tuner = tune.Tuner(train_func) tuner.fit()

警告TUNE_ORIG_WORKING_DIR环境变量是访问相对原始工作目录路径的旧方案,已被弃用,应改用上述RAY_CHDIR_TO_TRIAL_DIR环境变量。

如何在同一个集群上同时运行多个 Ray Tune 任务(多租户)?

在同一个集群上同时运行多个 Ray Tune 任务并不被官方支持。我们不会测试这一工作流,建议每个调优任务使用独立的集群。原因如下:

  1. 多个 Ray Tune 任务同时运行时,它们会竞争资源。一个任务可能同时运行其全部 trial,而另一个任务要等很长时间才能获得运行第一个 trial 的资源。
  2. 如果在你的基础设施上很容易启动一个新的 Ray 集群,运行一个大集群通常并不比运行多个小集群更省钱。例如,运行一个 32 实例的集群与运行 4 个各 8 实例的集群成本几乎相同。
  3. 并发任务更难调试。如果任务 A 的某个 trial 写满了磁盘,同一节点上任务 B 的 trial 也会受影响。实践中,出问题时很难仅凭日志推断出这些情况。

此前,Ray Tune 的一些内部实现假设同一时刻只运行一个任务。一个症状是任务 A 的 trial 使用了任务 B 中指定的参数,导致意外结果。

如何基于已完成实验继续训练(迭代式实验)?

假设有一个已完成的 Tune 实验,配置如下:

def trainable(config): for epoch in range(1, config["num_epochs"]): # Do some training... with tempfile.TemporaryDirectory() as tempdir: torch.save( {"model_state_dict": {"x": 1}}, os.path.join(tempdir, "model.pt") ) tune.report( {"score": random.random()}, checkpoint=Checkpoint.from_directory(tempdir), ) tuner = tune.Tuner( trainable, param_space={"num_epochs": 10, "hyperparam": tune.grid_search([1, 2, 3])}, tune_config=tune.TuneConfig(metric="score", mode="max"), ) result_grid = tuner.fit() best_result = result_grid.get_best_result() best_checkpoint = best_result.checkpoint

现在你想从上一个实验生成的检查点(例如最佳的那个)继续训练,并在新的搜索空间上再搜索 10 个 epoch。

容错恢复文档 说明,Tuner.restore() 的用途是恢复一个中断的未完成实验,且必须使用初始训练时提供的完全相同的配置。因此Tuner.restore并不适合我们想要的行为。这种"迭代式实验"应该通过新建 Tune 实验来完成,而不是反复恢复同一个实验并修改实验规格。

下面是一个基于旧实验创建新实验的示例:

def trainable(config): # Add logic to handle the initial checkpoint. checkpoint: Checkpoint = config["start_from_checkpoint"] with checkpoint.as_directory() as checkpoint_dir: model_state_dict = torch.load(os.path.join(checkpoint_dir, "model.pt")) # Initialize a model from the checkpoint... # model = ... # model.load_state_dict(model_state_dict) for epoch in range(1, config["num_epochs"]): # Do some more training... ... tune.report({"score": random.random()}) new_tuner = tune.Tuner( trainable, param_space={ "num_epochs": 10, "hyperparam": tune.grid_search([4, 5, 6]), "start_from_checkpoint": best_checkpoint, }, tune_config=tune.TuneConfig(metric="score", mode="max"), ) result_grid = new_tuner.fit()

核心思路是:把上一个实验的最佳检查点作为best_checkpoint取出,作为新实验参数空间中的一个值传入(本例中为start_from_checkpoint),然后在新搜索空间上重新调优。

如何将 Tune 结果上传到云存储 / 在 Kubernetes、Docker 中使用 Tune?

云存储上传:参见 cloud checkpointing 文档。请确保 worker 节点对云存储有写入权限,否则会出现类似Error message (1): fatal error: Unable to locate credentials的错误。对于 AWS 环境,需要为 worker 节点配置 IamInstanceProfile。

Kubernetes 与 Docker:在这两种环境中使用 Tune,都应配置共享存储,参见 存储选项用户指南。

如何在本地开发和测试 Tune?

首先,按照 python-develop 指南 在不编译 Ray 的情况下搭建 Tune 开发环境。Ray 就绪后,运行以下命令安装 Tune 开发所需的全部包:

pip install -r ray/python/ray/tune/requirements-dev.txt

然后运行全部 Tune 测试:

pytest ray/python/ray/tune/tests/

如果要提交 Pull Request,建议先在本机运行单元测试以加速评审流程。虽然我们有钩子会对每个 PR 自动运行单元测试,但通常先在本地跑一遍更快,可以避免明显的错误。

如何开始为 Tune 贡献代码?

我们使用 GitHub 跟踪 issue、功能请求和 bug。可以从标记为 "good first issue" 和 "help wanted" 的 issue 入手,并寻找标题中带 "[tune]" 的 issue。

注意:如果提交与 Tune 相关的 issue 或 PR,请务必在标题中包含 "[tune]" 并为该 issue/PR 添加tune标签。

总结

Ray Tune FAQ 覆盖了从概念(超参数 vs 模型参数)、策略(搜索算法 + 调度器组合)、搜索空间设计(嵌套/条件/网格)、资源管理(with_resources与 Placement Group)、性能优化(避免 checkpoint 瓶颈)到工程实践(可复现性、迭代式实验、本地开发测试)的完整链路。结合 FAQ 示例代码 与核心实现(trainable/util.py、search/sample.py、execution/placement_groups.py),你可以快速定位实际调参任务中的常见问题,并把本文中的方案直接应用到自己的 Ray Tune 工作流中。

  • 人工智能
  • 分布式训练
  • 强化学习
  • 任务调度
  • 模型推理服务

【免费下载链接】ray

Ray is an AI compute engine. Ray consists of a core distributed runtime and a set of AI Libraries for accelerating ML workloads.

项目地址:https://gitcode.com/gh_mirrors/ra/ray
点击查看免费下载

相关推荐

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询