tuner.py
ultralytics\utils\tuner.py
目录
[2.def run_ray_tune(model, space: dict = None, grace_period: int = 10, gpu_per_trial: int = None, max_samples: int = 10, **train_args):](#2.def run_ray_tune(model, space: dict = None, grace_period: int = 10, gpu_per_trial: int = None, max_samples: int = 10, **train_args):)
1.所需的库和模块
python
# Ultralytics YOLO 🚀, AGPL-3.0 license
import subprocess
from ultralytics.cfg import TASK2DATA, TASK2METRIC, get_save_dir
from ultralytics.utils import DEFAULT_CFG, DEFAULT_CFG_DICT, LOGGER, NUM_THREADS, checks
2.def run_ray_tune(model, space: dict = None, grace_period: int = 10, gpu_per_trial: int = None, max_samples: int = 10, **train_args):
python
# 这段代码定义了一个名为 run_ray_tune 的函数,它用于使用 Ray Tune 库对 YOLOv8 模型进行超参数调优。
# 参数解释。
# 1.model :要调优的 YOLOv8 模型。
# 2.space :自定义的超参数搜索空间,默认为 None。
# 3.grace_period : ASHAScheduler 的宽限期,即在终止表现不佳的试验之前至少运行的最小 epoch 数,默认为 10。
# 4.gpu_per_trial :每个试验分配的 GPU 数量,默认为 None。
# 5.max_samples : Ray Tune 进行的样本数量,默认为 10。
# 6.**train_args :传递给模型训练方法的其他参数。
def run_ray_tune(
model, space: dict = None, grace_period: int = 10, gpu_per_trial: int = None, max_samples: int = 10, **train_args
):
# 使用 Ray Tune 运行超参数调整。
"""
Runs hyperparameter tuning using Ray Tune.
Args:
model (YOLO): Model to run the tuner on.
space (dict, optional): The hyperparameter search space. Defaults to None.
grace_period (int, optional): The grace period in epochs of the ASHA scheduler. Defaults to 10.
gpu_per_trial (int, optional): The number of GPUs to allocate per trial. Defaults to None.
max_samples (int, optional): The maximum number of trials to run. Defaults to 10.
train_args (dict, optional): Additional arguments to pass to the `train()` method. Defaults to {}.
Returns:
(dict): A dictionary containing the results of the hyperparameter search.
Example:
```python
from ultralytics import YOLO
# Load a YOLOv8n model
model = YOLO("yolov8n.pt")
# Start tuning hyperparameters for YOLOv8n training on the COCO8 dataset
result_grid = model.tune(data="coco8.yaml", use_ray=True)
```
"""
# 记录日志信息。使用日志记录器 LOGGER 记录一条信息,提示用户可以在哪里学习关于 Ray Tune 的更多信息。
LOGGER.info("💡 Learn about RayTune at https://docs.ultralytics.com/integrations/ray-tune") # 💡 了解 RayTune,请访问 https://docs.ultralytics.com/integrations/ray-tune。
# 初始化 train_args 。
# 检查 train_args 是否为 None ,如果是,则初始化为一个空字典。 train_args 用于存储传递给模型训练方法的额外参数。
if train_args is None:
train_args = {}
# 尝试安装 Ray Tune 。
try:
# subprocess.run(args, *, stdin=None, input=None, stdout=None, stderr=None, capture_output=False,
# check=False, timeout=None, device=None, text=None, encoding=None, errors=None,
# shell=False, cwd=None, env=None, universal_newlines=False, bufsize=-1,
# start_new_session=False, restore_signals=True, preexec_fn=None,
# pass_fds=(), warn=False)
# subprocess.run() 是 Python 标准库 subprocess 模块中的一个函数,用于执行外部命令和程序。这个函数在 Python 3.5 中被引入,作为替代旧的 subprocess.call() 、 subprocess.check_call() 和 subprocess.check_output() 函数的一个更现代的接口。
# 参数说明 :
# args :命令及其参数。可以是字符串列表或单个字符串。如果 shell=True ,则 args 应该是单个字符串。
# stdin :指定 stdin 的文件描述符或文件对象。
# input :如果提供,写入到 stdin 。
# stdout 和 stderr :指定 stdout 和 stderr 的文件描述符或文件对象。
# capture_output :如果为 True ,则捕获 stdout 和 stderr 。
# check :如果为 True ,则在命令返回非零退出状态时引发 CalledProcessError 异常。
# timeout :等待命令完成的秒数。超时则引发 TimeoutExpired 异常。
# device 、 text 、 encoding 、 errors :控制输出和错误输出的编码。
# shell :如果为 True ,则通过 shell 执行 args 。
# cwd :子进程的当前工作目录。
# env :子进程的环境变量。
# universal_newlines :如果为 True ,则将输出和错误解释为文本。
# bufsize :缓冲区大小。
# start_new_session :如果为 True ,则在子进程中启动一个新的会话。
# restore_signals :如果为 True ,则在子进程中恢复信号。
# preexec_fn :在子进程中执行的函数。
# pass_fds :需要传递给子进程的文件描述符列表。
# warn :(已弃用)是否发出警告。
# 返回值 :
# 返回一个 CompletedProcess 实例,它包含执行命令后的信息,如 args 、 returncode 、 stdout 、 stderr 等。
# 尝试使用 subprocess 运行 pip install ray[tune] 命令来安装 Ray Tune 库。 split() 用于将字符串分割成列表,以符合 subprocess.run() 的参数要求。 check=True 会在命令执行失败时抛出异常。
subprocess.run("pip install ray[tune]".split(), check=True) # do not add single quotes here
# 导入 Ray Tune 相关模块。
# 导入 Ray 库。
import ray
# 导入 Ray Tune 模块。
from ray import tune
# 导入 RunConfig 类,用于配置 Ray 运行环境。
from ray.air import RunConfig
# 导入 WandbLoggerCallback 类,用于集成 Weights & Biases(W&B)日志记录。
from ray.air.integrations.wandb import WandbLoggerCallback
# 导入 ASHAScheduler 类,用于超参数调整的调度。
from ray.tune.schedulers import ASHAScheduler
# 处理导入错误。
# 如果导入过程中出现 ImportError ,则抛出 ModuleNotFoundError 异常,并提示用户安装 Ray Tune。
except ImportError:
raise ModuleNotFoundError('Ray Tune required but not found. To install run: pip install "ray[tune]"') # 需要 Ray Tune,但未找到。要安装,请运行:pip install "ray[tune]。
# 尝试导入 W&B 并验证版本。
# 尝试导入 W&B 库。
try:
import wandb
# 验证导入的 W&B 库是否有版本信息。
assert hasattr(wandb, "__version__")
# 如果导入失败或没有版本信息,则将 wandb 设置为 False ,表示 W&B 库不可用。
except (ImportError, AssertionError):
wandb = False
# 这段代码确保了 Ray Tune 环境的正确设置,包括安装、导入必要的库,并检查 W&B 库的可用性。如果用户没有安装 Ray Tune 或 W&B,代码会提供相应的错误信息和安装指导。
# 这段代码包含两个主要部分 :
# 一个函数调用 checks.check_version 用于检查 Ray 框架的版本。
# 以及一个字典 default_space 定义了一组默认的超参数搜索空间,这些超参数通常用于机器学习模型的训练过程中,特别是在使用 Ray Tune 进行超参数优化时。
# 检查 Ray 版本。
# def check_version(current: str = "0.0.0", required: str = "0.0.0", name: str = "version", hard: bool = False, verbose: bool = False, msg: str = "",) -> bool:
# -> 用于检查当前安装的软件包版本是否满足特定的要求。返回结果。函数返回 result ,表示当前版本是否满足要求。
# -> return result
checks.check_version(ray.__version__, ">=2.0.0", "ray")
# 默认超参数搜索空间。
# 这个字典 default_space 定义了一系列超参数的搜索范围,这些超参数通常用于深度学习模型的训练中。每个键值对定义了一个超参数的名称和它的搜索范围。 tune.uniform(a, b) 表示该超参数的值将在区间 [a, b] 内均匀分布。
default_space = {
# tune.uniform(lower, upper)
# tune.uniform() 是 Ray Tune 库中的一个函数,用于定义超参数搜索空间时指定一个均匀分布的范围。当你希望超参数在某个连续的区间内均匀地被采样时,可以使用这个函数。
# 参数说明 :
# lower :均匀分布的下限。
# upper :均匀分布的上限。
# 返回值 :
# 返回一个在 [lower, upper] 区间内均匀分布的浮点数。
# 用法示例 :
# 在超参数调优中,如果你想要学习率 lr 在 0.0001 到 0.1 之间均匀地被采样,可以这样定义搜索空间:
# search_space = {"lr": tune.uniform(1e-4, 1e-1)} # 等价于 tune.uniform(0.0001, 0.1)
# 在这个例子中, tune.uniform(1e-4, 1e-1) 表示 lr 将在这个范围内均匀地被采样。Ray Tune 将会在这个区间内随机选择值,作为学习率的候选值,进行模型的训练和评估。
# tune.uniform 是定义连续超参数搜索空间的常用方法之一,它使得超参数优化过程更加灵活和高效。通过调整 lower 和 upper 参数,你可以控制超参数的搜索范围,从而对模型进行更精细的调优。
# 'optimizer': tune.choice(['SGD', 'Adam', 'AdamW', 'NAdam', 'RAdam', 'RMSProp']),
# 学习率 ( lr0 , lrf )。
"lr0": tune.uniform(1e-5, 1e-1),
"lrf": tune.uniform(0.01, 1.0), # final OneCycleLR learning rate (lr0 * lrf) 最终 OneCycleLR 学习率 (lr0 * lrf)。
# 动量 ( momentum )。
"momentum": tune.uniform(0.6, 0.98), # SGD momentum/Adam beta1 SGD 动量/Adam beta1。
# 权重衰减 ( weight_decay )。
"weight_decay": tune.uniform(0.0, 0.001), # optimizer weight decay 5e-4 优化器权重衰减 5e-4。
# 预热周期 ( warmup_epochs ) 和动量 ( warmup_momentum )。
"warmup_epochs": tune.uniform(0.0, 5.0), # warmup epochs (fractions ok) 预热时期 (分数 ok)。
"warmup_momentum": tune.uniform(0.0, 0.95), # warmup initial momentum 预热初始动量。
# 损失增益 ( box , cls )。
"box": tune.uniform(0.02, 0.2), # box loss gain 边界框损失增益
"cls": tune.uniform(0.2, 4.0), # cls loss gain (scale with pixels) cls 损失增益(按像素缩放)。
# 图像增强参数( HSV 色调 、 饱和度 、 值 , 旋转 、 平移 、 缩放 、 剪切 、 透视 )。
"hsv_h": tune.uniform(0.0, 0.1), # image HSV-Hue augmentation (fraction) 图像 HSV-色调增强(分数)。
"hsv_s": tune.uniform(0.0, 0.9), # image HSV-Saturation augmentation (fraction) 图像 HSV-饱和度增强(分数)。
"hsv_v": tune.uniform(0.0, 0.9), # image HSV-Value augmentation (fraction) 图像 HSV-值增强(分数)。
"degrees": tune.uniform(0.0, 45.0), # image rotation (+/- deg) 图像旋转(+/- 度)。
"translate": tune.uniform(0.0, 0.9), # image translation (+/- fraction) 图像平移(+/- 分数)。
"scale": tune.uniform(0.0, 0.9), # image scale (+/- gain) 图像比例 (+/- 增益)。
"shear": tune.uniform(0.0, 10.0), # image shear (+/- deg) 图像剪切 (+/- 度)。
"perspective": tune.uniform(0.0, 0.001), # image perspective (+/- fraction), range 0-0.001 图像透视 (+/- 分数),范围 0-0.001。
# 概率( 上下翻转 、 左右翻转 、 BGR 通道交换 、 混合 、 复制粘贴 )。
"flipud": tune.uniform(0.0, 1.0), # image flip up-down (probability) 图像上下翻转 (概率)。
"fliplr": tune.uniform(0.0, 1.0), # image flip left-right (probability) 图像左右翻转 (概率)。
"bgr": tune.uniform(0.0, 1.0), # image channel BGR (probability) 图像通道 BGR (概率)。
"mosaic": tune.uniform(0.0, 1.0), # image mixup (probability) 图像混合 (概率)。
"mixup": tune.uniform(0.0, 1.0), # image mixup (probability) 图像mixup(概率)。
"copy_paste": tune.uniform(0.0, 1.0), # segment copy-paste (probability) 片段复制粘贴(概率)。
}
# 这些超参数的调整对于优化模型性能至关重要,尤其是在使用 Ray Tune 进行自动化超参数优化时。通过定义这些默认值,用户可以快速开始调优过程,也可以根据需要自定义这些值以适应特定的训练需求。
# Put the model in ray store
# 这段代码是 run_ray_tune 函数的一部分,它涉及将模型放入 Ray 的对象存储中,并定义了一个用于训练的内部函数 _tune 。
# 保存模型到 Ray 对象存储。
# 获取模型的任务类型。
task = model.task
# ray.put(value, *, owner=None)
# ray.put() 是 Ray 框架中的一个核心函数,用于将 Python 对象存储到 Ray 的分布式对象存储(Object Store)中,并异步返回一个唯一的对象引用(ObjectID)。
# 参数说明 :
# value :要存储的 Python 对象。
# owner :(实验性参数)拥有该对象的 actor。这允许创建与创建进程的生命周期解耦的对象。拥有者 actor 必须在对象创建者退出前接收到对象的引用,否则引用仍然会丢失。
# 返回值 :
# 返回一个对象引用(ObjectID),该 ID 可用于在 Ray 集群中的任何节点上访问该对象。
# 用法示例:
# import ray
# # 初始化 Ray
# ray.init()
# # 将一个 Python 对象存储到 Ray 的对象存储中
# object_id = ray.put("hello world")
# # 在 Ray 的其他部分,可以通过 object_id 访问该对象
# result = ray.get(object_id)
# print(result) # 输出: hello world
# 在这个示例中,字符串 "hello world" 被存储到 Ray 的对象存储中,并且返回了一个对象引用 object_id 。随后,可以通过 ray.get(object_id) 获取存储的对象。
# 注意事项 :
# ray.put() 返回的对象引用(ObjectID)是不可变的,并且只要存在对该 ID 的引用,存储的对象就不会被驱逐。
# ray.put() 通常用于将大型对象或需要在多个任务或 actor 之间共享的对象存储到对象存储中,以减少数据复制和传输的开销。
# 使用 ray.put() 可以有效地减少函数参数的写入对象存储的次数,通过传递对象 ID 而不是直接传递对象,可以提高性能和容错性。
# 使用 ray.put 将模型对象序列化并存储在 Ray 的分布式对象存储中。这使得模型可以在 Ray Tune 的分布式环境中被访问和使用。
model_in_store = ray.put(model)
# 定义 _tune 函数。
# 定义了一个名为 _tune 的内部函数,它将被 Ray Tune 调用以训练模型。函数接受一个参数。
# 1.config :这是一个包含超参数的字典。
def _tune(config):
# 使用指定的超参数和其他参数训练 YOLO 模型。
"""
Trains the YOLO model with the specified hyperparameters and additional arguments.
Args:
config (dict): A dictionary of hyperparameters to use for training.
Returns:
None
"""
# ray.get(*ids, timeout=None, num_returns=None, ignore_errors=False)
# ray.get() 是 Ray 框架中的一个核心函数,用于从 Ray 的分布式对象存储中检索之前通过 ray.put() 存储的对象。这个函数可以同步或异步地获取一个或多个对象的值。
# 参数说明 :
# ids :一个或多个 ObjectID 实例,这些是之前通过 ray.put() 存储对象时返回的引用。
# timeout :(可选)等待获取对象的超时时间(以秒为单位)。如果设置为 None ,则无限期等待。
# num_returns :(可选)指定返回值的数量。默认情况下,返回所有请求的值。
# ignore_errors :(可选)如果设置为 True ,则 Ray 将忽略在执行过程中遇到的任何错误,并返回一个包含正常结果和错误的列表。
# 返回值 :
# 如果请求单个对象,返回该对象的值。
# 如果请求多个对象,返回一个列表,其中包含所有请求对象的值,顺序与请求时的顺序相同。
# 注意事项 :
# ray.get() 可以用于同步地等待任务完成并获取结果,这对于调试和获取单个任务的结果非常有用。
# 在分布式环境中, ray.get() 可以跨多个节点工作,允许从不同的计算节点检索结果。
# 使用 ray.get() 获取多个对象时,如果任何一个对象的获取失败,整个 ray.get() 调用将抛出异常,除非 ignore_errors 被设置为 True ,在这种情况下,它将返回一个包含正常结果和错误的列表。
# 从 Ray 存储中获取模型。从 Ray 对象存储中获取模型对象,以便进行训练。
model_to_train = ray.get(model_in_store) # get the model from ray store for tuning
# 重置模型回调。重置模型的回调函数,这通常在开始新的训练周期前执行,以确保不会保留旧的训练状态。
model_to_train.reset_callbacks()
# 更新配置参数。将额外的训练参数 train_args 与超参数 config 合并,确保训练时使用了所有必要的参数。
config.update(train_args)
# 训练模型。使用更新后的配置参数训练模型,并获取训练结果。
results = model_to_train.train(**config)
# 返回训练结果。返回训练结果的字典,这个字典包含了训练过程中的关键指标和结果,可以被 Ray Tune 用于分析和优化。
return results.results_dict
# 这段代码展示了如何在 Ray Tune 中使用分布式超参数调优。通过将模型放入 Ray 的对象存储,可以确保模型在多个训练过程中被高效地共享和使用。
# _tune 函数定义了如何使用给定的超参数配置来训练模型,并返回训练结果,这是 Ray Tune 进行超参数优化的核心部分。
# Get search space
# 这段代码是一个条件语句,用于检查是否提供了自定义的超参数搜索空间 space 。如果没有提供,它将使用一个默认的搜索空间 default_space ,并记录一条警告日志。
# 条件检查。这个条件检查 space 变量是否为 None 、空或假值。如果 space 未被提供或者值为 None ,条件将为真。
if not space:
# 设置默认搜索空间。 如果 space 为假,将 space 设置为 default_space 。这意味着如果用户没有提供一个自定义的搜索空间,将使用预定义的默认搜索空间进行超参数调优。
space = default_space
# 记录警告日志。使用日志记录器 LOGGER 记录一条警告信息,告知用户因为没有提供搜索空间,所以将使用默认的搜索空间。这有助于用户了解当前调优过程中使用的搜索空间状态。
LOGGER.warning("WARNING ⚠️ search space not provided, using default search space.") # 警告⚠️未提供搜索空间,使用默认搜索空间。
# 这段代码确保了即使用户没有指定自己的搜索空间,超参数调优过程仍然可以继续进行,使用一组预定义的默认值。同时,通过日志记录,用户可以清楚地知道调优过程使用的是默认设置,而不是他们可能预期的自定义设置。这对于确保调优过程的透明度和可重复性非常重要。
# Get dataset
# 这段代码负责从训练参数中获取数据集配置,并将其设置到超参数搜索空间中。
# 获取数据集配置。这行代码尝试从 train_args 字典中获取名为 "data" 的值。如果 "data" 键不存在,则使用 TASK2DATA 字典中与当前任务 task 相关联的默认数据集配置。 TASK2DATA 是一个预定义的字典,它将不同的任务映射到它们对应的默认数据集配置。
data = train_args.get("data", TASK2DATA[task])
# 设置数据集到搜索空间。将获取到的数据集配置 data 设置到 space 字典中,这样在超参数搜索过程中就会使用这个数据集。
space["data"] = data
# 检查并记录数据集配置。这个条件检查 train_args 字典中是否包含了 "data" 键。
if "data" not in train_args:
# 如果 "data" 键不存在,使用日志记录器 LOGGER 记录一条警告信息,告知用户没有提供数据集配置,因此使用了默认的数据集 data 。这条警告帮助用户了解当前使用的配置,并提示他们如果需要自定义数据集配置,应在 train_args 中明确提供。
LOGGER.warning(f'WARNING ⚠️ data not provided, using default "data={data}".') # 警告⚠️未提供数据,使用默认的"data={data}"。
# 这段代码确保了即使用户没有在训练参数中指定数据集配置,超参数搜索过程也能使用一个默认的数据集继续进行。同时,通过日志记录,用户可以清楚地知道当前使用的是默认数据集配置,而不是他们可能预期的自定义配置。这对于确保超参数搜索过程的透明度和可重复性非常重要。
# 这段代码定义了使用 Ray Tune 进行超参数调优所需的关键组件,包括资源分配、调度器、回调函数和调优器本身。
# Define the trainable function with allocated resources 使用分配的资源定义可训练函数。
# tune.with_resources(trainable, resources)
# tune.with_resources() 是 Ray Tune 库中的一个函数,它用于为具体的可训练对象(trainable)指定资源需求。这个包装器允许你为特定的可训练对象声明资源要求,并且会覆盖已有的资源请求。
# 参数说明 :
# trainable :要包装的可训练对象,可以是函数或类。
# resources :资源字典、放置组工厂(PlacementGroupFactory),或者是接受配置字典并返回放置组工厂的可调用对象。
# 返回值 :
# 返回一个包装后的可训练对象,其中包含了指定的资源请求。
# 注意事项 :
# tune.with_resources 主要用于函数类型的可训练对象,当你使用 Tuner() API 时。
# 类类型的可训练对象通常只需要实现 default_resource_request() 方法来声明资源需求。
# 使用 tune.with_resources 时需要谨慎,因为它会覆盖已有的资源请求。
# 这个函数的主要用例是为函数类型的可训练对象请求资源,特别是在使用 Tuner() API 时。通过这种方式,可以确保在分布式环境中,每个训练试验都能获得所需的计算资源。
# 定义带资源的可训练函数。
# tune.with_resources :这个函数用于指定训练函数 _tune 所需的资源。
# _tune :这是之前定义的用于训练模型并返回结果的函数。
# {"cpu": NUM_THREADS, "gpu": gpu_per_trial or 0} :这是一个字典,指定了每个训练试验所需的 CPU 和 GPU 资源。 NUM_THREADS 是所需的 CPU 线程数, gpu_per_trial 是每个试验所需的 GPU 数量,如果没有提供,则默认为 0。
trainable_with_resources = tune.with_resources(_tune, {"cpu": NUM_THREADS, "gpu": gpu_per_trial or 0})
# Define the ASHA scheduler for hyperparameter search 定义用于超参数搜索的 ASHA 调度程序。
# 定义 ASHA 调度器。
# ASHAScheduler(time_attr='training_iteration', metric='metric', mode='max', max_t=100, grace_period=1, reduction_factor=4, brackets=1)
# ASHAScheduler 是 Ray Tune 中的一个调度器,它实现了异步连续减半(Async Successive Halving)算法。这种算法可以提前终止性能较差的试验,节省计算资源,并将资源分配给表现较好的试验。
# 参数说明 :
# time_attr :(默认为 'training_iteration')用于比较时间的属性,可以是任何单调递增的属性,例如训练轮次。
# metric :要优化的指标名称,即在训练结果字典中用于衡量优化目标的值。
# mode :(默认为 'max')优化模式,可以是 'min' 或 'max',表示是最小化还是最大化指标。
# max_t :(默认为 100)试验可以运行的最大时间单位,单位由 time_attr 决定。
# grace_period :(默认为 1)在至少这个时间之后才考虑停止试验,单位与 time_attr 相同。
# reduction_factor :(默认为 4)用于设置减半率和数量的无量纲标量。
# brackets :(默认为 1)分组的数量,每个分组有不同的减半率,由 reduction_factor 指定。
# ASHAScheduler 与其他调度器相比,提供了更好的并行性,并且在淘汰过程中避免了落后问题。因此,Ray Tune 推荐使用 ASHAScheduler 而不是标准的 HyperBandScheduler 。
# ASHAScheduler :这是 Ray Tune 中用于超参数搜索的调度器,它结合了早停和缩放的特性。
# time_attr :表示调优过程中的时间单位,通常是 "epoch"。
# metric :要优化的指标,从 TASK2METRIC 字典中根据任务 task 获取。
# mode :优化模式,"max" 表示最大化指标。
# max_t :最大训练时间或 epoch 数。
# grace_period :宽限期,即在终止表现不佳的试验之前至少运行的最小 epoch 数。
# reduction_factor :缩放因子,用于确定在每个周期后保留多少表现最好的试验。
asha_scheduler = ASHAScheduler(
time_attr="epoch",
metric=TASK2METRIC[task],
mode="max",
max_t=train_args.get("epochs") or DEFAULT_CFG_DICT["epochs"] or 100,
grace_period=grace_period,
reduction_factor=3,
)
# Define the callbacks for the hyperparameter search 定义超参数搜索的回调。
# 定义回调函数。
# WandbLoggerCallback :如果 wandb (Weights & Biases)库可用,则定义一个回调函数,用于将调优过程的日志记录到 W&B 平台。
# project :W&B 项目名称。
tuner_callbacks = [WandbLoggerCallback(project="YOLOv8-tune")] if wandb else []
# Create the Ray Tune hyperparameter search tuner 创建 Ray Tune 超参数搜索调谐器。
# 创建 Ray Tune 调优器。
# 获取保存调优结果的目录。
# def get_save_dir(args, name=None): -> 获取或创建一个用于保存特定数据(如模型权重、日志等)的目录路径。返回保存目录的路径。返回一个 Path 对象,表示保存目录的路径。 -> return Path(save_dir)
tune_dir = get_save_dir(DEFAULT_CFG, name="tune").resolve() # must be absolute dir
# 确保保存目录存在。
tune_dir.mkdir(parents=True, exist_ok=True)
# tune.Tuner(trainable, param_space=None, tune_config=None, run_config=None, **tuner_kwargs)
# tune.Tuner() 是 Ray Tune 中用于启动和执行超参数调优作业的主要类。
# 参数说明 :
# trainable :这是要调优的可训练对象,可以是字符串、可调用函数、 Trainable 类型、 BaseTrainer 实例,或者是 None。这个参数定义了要优化的目标函数或模型。
# param_space :这是超参数搜索空间,可以是字典、搜索算法对象或者是 None。这个参数定义了超参数调优的范围和分布。
# tune_config :这是调优算法特定的配置,类型为 TuneConfig 。这个参数定义了调优过程中的算法配置,如试验次数、调度器等。
# run_config :这是针对个别试验的运行时配置,类型为 RunConfig 。这个参数定义了每个试验的运行配置,如资源需求、存储路径等。
# 返回值 :
# 返回一个 Tuner 对象,该对象可以用于执行超参数调优作业,并获取调优结果。
# tune.Tuner() 是 Ray Tune 中最核心的接口之一,它提供了一个简洁而强大的方法来执行超参数调优。通过配置 param_space 和 tune_config ,用户可以灵活地定义搜索空间和调优策略,以优化机器学习模型的性能。
# Tuner 对象是 Ray Tune 中用于启动和管理超参数调优作业的核心组件。以下是 Tuner 对象的主要方法 :
# __init__ :构造函数,用于配置和构造一个调优作业。
# 参数包括 trainable (可训练对象), param_space (超参数搜索空间), tune_config (调优算法特定的配置), run_config (针对个别试验的运行时配置)等。
# fit :执行超参数调优作业,并返回结果。
# 这个方法会根据配置的搜索空间、调度器和其他设置来运行调优过程,并返回一个包含调优结果的 ResultGrid 对象。
# get_results :获取超参数调优作业的结果。
# 这个方法返回一个 ResultGrid 对象,其中包含了所有试验的结果,可以用于后续分析。
# restore :恢复之前失败的调优作业。
# 通过提供之前调优作业的实验路径和可训练对象,可以恢复调优作业,继续之前的工作。
# can_restore :检查给定目录是否包含可恢复的 Ray Tune 实验。
# 这个方法用于确定是否可以通过 restore 方法恢复调优作业。
# 这些方法是 Tuner 对象的主要接口,提供了启动、管理和恢复超参数调优作业的能力。通过这些方法,用户可以灵活地执行调优作业,并根据需要获取和分析调优结果。
# tune.TuneConfig( metric=None, mode=None, search_alg=None, scheduler=None, num_samples=1, max_concurrent_trials=None, time_budget_s=None,
# reuse_actors=False, trial_name_creator=None, trial_dirname_creator=None, chdir_to_trial_dir=False,)
# tune.TuneConfig() 是 Ray Tune 中的一个配置类,用于设置调优作业的特定参数。
# 参数说明 :
# metric :要优化的指标名称,该指标应该通过 tune.report() 报告。如果设置,将被传递给搜索算法和调度器。
# mode :优化模式,必须是 min 或 max 之一。确定优化目标是最小化还是最大化指标。如果设置,将被传递给搜索算法和调度器。
# search_alg :用于优化的搜索算法。默认为随机搜索。
# scheduler :用于执行试验的调度器。可以选择 FIFO、MedianStopping、AsyncHyperBand、HyperBand 和 PopulationBasedTraining 等。更多选项可以参考 ray.tune.schedulers 。
# num_samples :从超参数空间中采样的次数。默认为 1。如果提供了 grid_search ,则网格将重复 num_samples 次。如果设置为 -1,则在满足停止条件之前(虚拟地)无限生成样本。
# max_concurrent_trials :同时运行的最大试验数。必须是非负数。如果为 None 或 0,则不限制并发试验数。
# time_budget_s :全局时间预算,单位为秒,超过此时间后将停止调优作业。
# reuse_actors :是否重用 actor 。默认为 False。
# trial_name_creator :创建试验名称的回调函数。
# trial_dirname_creator :创建试验目录名称的回调函数。
# chdir_to_trial_dir :(已弃用)是否在试验运行前切换到试验目录。
# tune.TuneConfig() 提供了丰富的配置选项,允许用户根据具体需求定制调优作业的行为。通过合理配置这些参数,可以更有效地进行超参数优化。
# RunConfig(name=None, local_dir=None, stop=None, checkpoint_config=None, storage_path=None, fail_fast=False, keep_checkpoints_num=None,
# synchronous_stop=False, verbose=False, experiment_name=None, trial_name_creator=None, trial_dirname_creator=None, chdir_to_trial_dir=False, callbacks=None,)
# 参数说明 :
# name :实验的名称,默认与 trainable 同名,用于保存结果时生成相应的文件夹。
# local_dir :存储地址,默认为 ~/ray_results ,搜索结果的存储地址。
# stop :终止条件,可以是一个字典,指定基于性能指标停止训练的条件,如 {"loss": 0.1, "training_iteration": 100} 。
# checkpoint_config :检查点配置,用于设置检查点的保存策略。
# storage_path :实验结果的存储路径,必须是绝对路径。
# fail_fast :是否快速失败,如果设置为 True ,则在出现异常时立即停止所有试验。
# keep_checkpoints_num :保留检查点的数量。
# synchronous_stop :是否同步停止,如果设置为 True ,则在停止条件满足时同步停止所有试验。
# verbose :是否为详细模式,如果设置为 True ,则输出更多的调试信息。
# experiment_name :实验的名称,用于组织和查找实验结果。
# trial_name_creator :创建试验名称的回调函数。
# trial_dirname_creator :创建试验目录名称的回调函数。
# chdir_to_trial_dir :是否在试验运行前切换到试验目录。
# callbacks :回调函数列表,用于在试验的生命周期中执行自定义逻辑。
# RunConfig 提供了丰富的配置选项,允许用户根据具体需求定制每个试验的运行参数,包括存储路径、终止条件和检查点策略等。通过合理配置这些参数,可以更有效地管理和分析超参数调优过程。
# tune.Tuner :创建一个 Ray Tune 调优器对象。
# trainable_with_resources :要调优的函数。
# param_space :超参数搜索空间。
# tune_config :调优配置,包括调度器和样本数量。
# run_config :运行配置,包括回调函数和存储路径。
tuner = tune.Tuner(
trainable_with_resources,
param_space=space,
tune_config=tune.TuneConfig(scheduler=asha_scheduler, num_samples=max_samples),
run_config=RunConfig(callbacks=tuner_callbacks, storage_path=tune_dir),
)
# 这段代码完整地设置了 Ray Tune 调优环境,包括资源分配、调度器、回调函数和调优器本身,使得可以开始执行超参数调优过程。
# 这段代码是使用 Ray Tune 进行超参数调优流程中的最后几个步骤,包括运行调优、获取结果和关闭 Ray。
# Run the hyperparameter search
# 运行超参数搜索。调用 Ray Tune 的 Tuner 对象的 fit 方法来启动超参数搜索过程。这个方法会根据之前配置的搜索空间、调度器和其他设置来运行调优过程。
tuner.fit()
# Get the results of the hyperparameter search
# 获取超参数搜索结果。
# 在调优过程完成后,调用 Tuner 对象的 get_results() 方法来获取所有试验的结果。这些结果包含了每个试验的配置和性能指标,可以用于分析和确定最佳超参数组合。
results = tuner.get_results()
# Shut down Ray to clean up workers
# ray.shutdown(terminate_workers=True)
# ray.shutdown() 是 Ray 框架中的一个函数,用于关闭 Ray 的会话并清理资源。这个函数通常在完成所有 Ray 相关的任务后调用,以确保释放所有分配的资源,包括 CPU、GPU 和内存资源。
# 参数说明 :
# terminate_workers :(可选)一个布尔值,指示是否终止 Ray 工作节点上的进程。默认值为 True ,表示终止所有工作节点上的进程。
# 返回值 :无返回值。
# 注意事项 :
# 调用 ray.shutdown() 后,当前 Python 进程中的 Ray 客户端将不再能够提交新的任务或访问 Ray 集群的资源。
# 如果你的应用程序或脚本中有多个 Ray 会话,确保在每个会话完成后都调用 ray.shutdown() 。
# 在某些情况下,如果你不希望立即终止工作节点上的进程,可以设置 terminate_workers=False ,但这可能会阻止资源被完全释放。
# 在使用 Jupyter notebook 或其他交互式环境时,通常不需要显式调用 ray.shutdown() ,因为 Ray 会话会在内核重启时自动关闭。
# ray.shutdown() 是确保 Ray 资源被正确管理和释放的重要函数,特别是在长时间运行的应用或在资源受限的环境中。
# 关闭 Ray 清理工作节点。在获取结果后,调用 ray.shutdown() 方法来关闭 Ray 服务并清理所有工作节点。这个步骤很重要,因为它会释放由 Ray 管理的资源,包括 CPU 和 GPU,确保这些资源可以被其他任务或应用程序使用。
ray.shutdown()
# 返回结果。函数返回超参数搜索的结果,这样调用者可以进一步分析这些结果,或者使用最佳超参数组合来训练最终模型。
return results
# 这段代码确保了 Ray Tune 调优过程的完整性,从启动调优到获取结果再到资源清理。通过返回结果,用户可以继续进行后续分析或应用最佳超参数。
# 这个函数提供了一个完整的流程,从安装依赖、定义搜索空间、训练模型到分析结果,使得使用 Ray Tune 对 YOLOv8 模型进行超参数调优变得简单和高效。通过自定义搜索空间和训练参数,用户可以针对自己的需求和计算资源进行调优。