- 人工智能
- 分布式训练
- 强化学习
- 任务调度
- 模型推理服务
【免费下载链接】ray
Ray is an AI compute engine. Ray consists of a core distributed runtime and a set of AI Libraries for accelerating ML workloads.
导读
trainer.fit()是 Ray Train 训练流程的终点,它返回的ray.train.Result对象封装了一次训练运行的全部可交付成果:最后报告的指标、全部指标的历史 DataFrame、训练函数(worker 0)的返回值、可加载模型的检查点、持久化存储位置以及训练过程中的错误信息。本文以 results.rst 为主线,结合仓库中Result的源码实现(python/ray/train/v2/api/result.py 与 python/ray/air/result.py)以及配套示例代码 doc_code/key_concepts.py,系统讲解如何正确消费这些结果,并将其用于模型加载、离线批推理(Ray Data)、在线服务(Ray Serve)和训练后分析等下游任务。
一、Result 对象概览:trainer.fit() 返回了什么
在 Ray Train 中,无论你使用TorchTrainer、LightGBMTrainer、XGBoostTrainer还是通用的DataParallelTrainer,trainer.fit()的返回值都是一个ray.train.Result对象。它集中承载了一次训练运行需要对外暴露的所有信息:
- 最后报告的检查点(checkpoint)及其附带的指标——用于加载模型;
- 错误信息(error)——如果训练过程中发生了异常;
- 训练函数的返回值(return_value)——仅来自 rank 0(worker 0)训练函数的返回数据;
- 全部指标历史(metrics_dataframe)与最佳检查点列表(best_checkpoints);
- 结果在持久化存储上的位置(path)与文件系统(filesystem)。
从源码结构看,Result在 v2 API 中被定义为 dataclass(见 python/ray/train/v2/api/result.py),它继承自 Ray AIR 的基类ray.air.result.Result(python/ray/air/result.py),基类标注为@PublicAPI(stability="stable"),说明这是一套稳定的公共接口。
下面是一个贯穿全文的最小训练示例(来源于 doc_code/key_concepts.py):训练函数循环 3 次,每次都通过ray.train.report()上报指标并附带一个检查点目录,最后返回一个汇总 dict:
import tempfile from pathlib import Path import ray.train from ray.train.v2.api.data_parallel_trainer import DataParallelTrainer def train_fn(config): for i in range(3): with tempfile.TemporaryDirectory() as temp_checkpoint_dir: Path(temp_checkpoint_dir).joinpath("model.pt").touch() ray.train.report( {"loss": i}, checkpoint=ray.train.Checkpoint.from_directory(temp_checkpoint_dir), ) return {"total loss": 3} trainer = DataParallelTrainer( train_fn, scaling_config=ray.train.ScalingConfig(num_workers=2) )运行result = trainer.fit()之后,result即为本文要深入剖析的Result对象。
二、查看指标(Metrics)
训练过程中通过ray.train.report(metrics, checkpoint=...)上报的指标,会在训练结束后从Result对象中取回。常见指标包括训练/验证损失(loss)、预测准确率(accuracy)等。
2.1 最近一次报告的指标:Result.metrics
Result.metrics返回附着在最后报告的检查点上的那组指标,是一个普通 dict:
result = trainer.fit() print("Observed metrics:", result.metrics) # Observed metrics: {'loss': 2}在train_fn的循环中最后一次report的是{"loss": 2},因此result.metrics就是{"loss": 2}。需要说明的是,result.metrics与训练函数中传给ray.train.report()的指标一一对应,完整的指标上报机制可参见 monitoring-logging.rst(metrics 监控与日志指南)。
注意(重要弃用说明):原文档明确提示,ray.train.report(metrics, checkpoint=None)这种"游离指标"(free-floating metrics)的持久化已被弃用。这意味着只上报指标、不附带检查点的指标,将无法从Result对象中取回。只有附着在检查点上的指标才会被持久化,具体细节参见train-metric-only-reporting-deprecation(位于 monitoring-logging.rst)。从 python/ray/train/v2/api/result.py 的实现可以看出,metrics与checkpoint均取自checkpoint_manager.latest_checkpoint_result,即"与最后检查点绑定的一组结果"。
2.2 全部指标历史:Result.metrics_dataframe
如果需要查看整个训练过程中所有指标的变化趋势,使用Result.metrics_dataframe。它返回一个 pandas DataFrame,每一行对应一个检查点(即每次携带 checkpoint 的report调用):
df = result.metrics_dataframe print("Minimum loss", min(df["loss"])) # Minimum loss 0在 python/ray/train/v2/api/result.py 中,该 DataFrame 由best_checkpoint_results的指标列表直接构造:
if best_checkpoints: metrics_dataframe = pd.DataFrame([m for _, m in best_checkpoints])这意味着 DataFrame 的行与检查点一一对应,非常适合绘制训练曲线或做训练后分析(例如找出 loss 最低的轮次)。注意 DataFrame 的列使用展平后的指标键(flattened keys),与Result.metrics的未展平 dict 在格式上可能略有差异(见 python/ray/air/result.py 的属性注释)。
2.3 训练函数返回值:Result.return_value
如果训练函数(在 worker 0 上执行的那个)带有return语句,返回值会保存在Result.return_value中:
print("Returned data", result.return_value) # Returned data {'total loss': 3}从 python/ray/train/v2/api/result.py 的文档字符串可知:return_value是 rank 0 worker 上用户定义训练函数的返回值;如果函数没有返回值,或训练未成功完成,则为None;返回值必须是可序列化的(serializable),因为它需要跨进程传输。这为"训练结束后把汇总统计、最佳超参或验证结论直接带回主进程"提供了便捷通道。
三、获取检查点(Checkpoints)
检查点包含恢复训练状态所需的全部信息,通常包括训练好的模型权重。Result对象提供两条取检查点的路径:取最后一个,或取历史上所有保留的检查点。
3.1 最后一个检查点:Result.checkpoint
Result.checkpoint返回训练过程中最后保存的检查点(ray.train.Checkpoint对象)。最常见的用法是拿到检查点后加载模型:
print("Last checkpoint:", result.checkpoint) with result.checkpoint.as_directory() as tmpdir: # Load model from directory # 例如:torch.load(os.path.join(tmpdir, "model.pt")) ...Checkpoint.as_directory()会把检查点内容物化为本地目录(如果检查点本就在远端存储上,会自动下载到临时目录),with块退出时自动清理。
3.2 其他检查点:Result.best_checkpoints
有些场景下你需要访问更早的检查点。典型的例子是:随着训练继续,loss 因过拟合反而上升,此时你可能想取回 loss 最低的那个检查点。
Result.best_checkpoints返回一个(checkpoint, metrics)元组列表,列出本次运行中所有被保留的检查点及其指标。默认情况下(不额外配置)所有检查点都会保留:
# Print available checkpoints for checkpoint, metrics in result.best_checkpoints: print("Loss", metrics["loss"], "checkpoint", checkpoint) # Get checkpoint with minimal loss best_checkpoint = min( result.best_checkpoints, key=lambda checkpoint: checkpoint[1]["loss"] )[0] with best_checkpoint.as_directory() as tmpdir: # Load model from directory ...需要指出的是,best_checkpoints保留哪些检查点由ray.train.CheckpointConfig决定。例如下面的配置只保留最近 2 个检查点,或按指标mean_accuracy取最高的 2 个:
from ray.train import RunConfig, CheckpointConfig # Example 1: Only keep the 2 *most recent* checkpoints and delete the others. run_config = RunConfig(checkpoint_config=CheckpointConfig(num_to_keep=2)) # Example 2: Only keep the 2 *best* checkpoints and delete the others. run_config = RunConfig( checkpoint_config=CheckpointConfig( num_to_keep=2, # *Best* checkpoints are determined by these params: checkpoint_score_attribute="mean_accuracy", checkpoint_score_order="max", ), # This will store checkpoints on S3. storage_path="s3://remote-bucket/location", )基类还提供了一个便捷方法Result.get_best_checkpoint(metric, mode)(python/ray/air/result.py),直接按指标名与"min"/"max"模式挑出最优检查点:mode只接受"max"/"min";没有对应指标的检查点会被过滤;若指标名非法,会抛出RuntimeError并列出可用指标。不过要注意,Result.from_path恢复出的best_checkpoints只按检查点序号排序,因为离线恢复时无法得知按哪个指标排序(见 python/ray/air/result.py 中的 TODO 注释)。
3.3 检查点的下游用途
检查点最常见的下游消费场景有两个:
- 基于 Ray Data 的离线批推理:把检查点加载为模型后,用
predict_batch等接口对数据集批量打分,相关文档见 doc/source/data/; - 基于 Ray Serve 的在线模型服务:把检查点加载为模型后部署为 HTTP 服务,相关文档见 doc/source/serve/。
完整的检查点保存/恢复机制请参见 checkpoints.rst。
四、访问存储位置(Storage Location)
训练结果会被写入持久化存储,如果你需要在集群销毁后、或另起一个 Python 进程里重新获取结果,可以通过Result.path与Result.from_path完成。
4.1 结果路径与文件系统:Result.path / Result.filesystem
Result.path指向本次训练运行的输出目录,它对应你在ray.train.RunConfig(storage_path=...)中配置的存储路径下的一个(嵌套)子目录,通常形如TrainerName_date-string/TrainerName_id_00000_0_...。Result.filesystem返回一个pyarrow.fs.FileSystem实例,用于访问该路径——当结果存放在云存储(如 S3)上时尤其有用:
import pyarrow result_path: str = result.path result_filesystem: pyarrow.fs.FileSystem = result.filesystem print(f"Results location (fs, path) = ({result_filesystem}, {result_path})") # 例如:Results location (fs, path) = (s3://..., bucket/location)一个值得注意的细节:当结果位于 S3 时,path的值是去掉s3://前缀后的形式(如bucket/location),需要通过filesystem配合访问(见 python/ray/air/result.py 的属性说明)。filesystem属性在未显式指定时默认回退为pyarrow.fs.LocalFileSystem()(python/ray/air/result.py)。
storage_path的配置方式如下(详见 persistent-storage.rst 中的train-log-dir一节):
import os from ray.train import RunConfig run_config = RunConfig( # Name of the training run (directory name). name="my_train_run", # The experiment results will be saved to: storage_path/name storage_path=os.path.expanduser("~/ray_results"), # storage_path="s3://my_bucket/tune_results", )Ray Train 支持本地路径,也支持 S3(s3://)、GCS(gs://)等云对象存储 URI;多节点训练要求所有 worker 都能写入同一个持久化存储位置。需要说明的是:只有附着在检查点上的指标会被持久化(游离指标已弃用),因此Result.from_path恢复出的指标均来自检查点记录。
4.2 从磁盘恢复结果:Result.from_path
你可以在任意时刻用Result.from_path从之前保存的路径重建一个Result对象,而无需重新训练:
from ray.train import Result restored_result = Result.from_path(result_path) print("Restored loss", restored_result.metrics["loss"]) # Restored loss 2from_path的签名(v2 实现见 python/ray/train/v2/api/result.py):
Result.from_path( path: Union[str, os.PathLike], storage_filesystem: Optional[pyarrow.fs.FileSystem] = None, ) -> "Result"其内部逻辑分两步校验与恢复:
- 校验实验目录存在,并据此构造一个只读(
read_only=True)的StorageContext; - 校验 checkpoint manager 快照文件(
CHECKPOINT_MANAGER_SNAPSHOT_FILENAME,即 v2 的checkpoint_manager_snapshot.json一类文件)存在,否则抛出RuntimeError,提示"该目录不是 Ray Train 运行产生的输出目录"。
恢复出的Result包含检查点与指标;注意 v2 实现中错误信息不会被加载(源码注释为 "the error is not loaded",见 python/ray/train/v2/api/result.py)。而在 AIR 基类(v1 语义)的 from_path 中,恢复逻辑为:优先从result.json读取指标(每行一个 JSON,用pd.json_normalize展平),缺失时回退到progress.csv;再扫描checkpoint_*目录重建检查点列表;若存在错误 pickle 文件(error.pkl),则反序列化并填充Result.error。
五、捕获训练错误(Catching Errors)
如果训练过程中发生异常,Result.error会被设置并保存抛出的异常。原文档给出的典型捕获模式如下:
def error_train_fn(config): raise RuntimeError("Simulated training error") trainer = DataParallelTrainer( error_train_fn, scaling_config=ray.train.ScalingConfig(num_workers=1) ) try: result = trainer.fit() except ray.train.TrainingFailedError as e: if isinstance(e, ray.train.WorkerGroupError): print(e.worker_failures)在 v2 实现中,Result.error的类型是ray.train.v2.api.exceptions.TrainingFailedError,它包装了原始的异常(见 python/ray/train/v2/api/result.py)。TrainingFailedError有两个典型子类:WorkerGroupError表示训练函数本身在 worker 上抛错,可通过e.worker_failures查看每个 worker 的具体失败;ActorCreationError则表示 worker actor 未能成功启动。这为"区分基础设施故障与业务代码 bug"提供了清晰的异常分层。
需要说明的是,fit()默认会在训练失败时直接抛出异常(fail fast);Result.error字段主要用于那些训练"以错误状态结束"但仍返回了Result对象的场景,例如设置了容错重试后的最终失败结果,或通过Tuner/容错回调处理后的运行。
六、在持久化存储上查找结果
所有训练结果(包括上报的指标和检查点)都会保存到你在RunConfig(storage_path=...)中配置的持久化存储上。这意味着:
- 即使 Ray 集群已经终止,结果依然存在;
- 你可以事后用
Result.from_path在任何环境(甚至本地笔记本)中恢复它们; - 最佳检查点、超参配置等都能从存储位置直接取用。
持久化存储的完整配置指南(本地路径、S3/GCS/Azure Blob、共享文件系统、fsspec、S3 兼容后端等)参见 persistent-storage.rst。配置storage_path之后,每次trainer.fit()都会在该路径下生成一个以"Trainer 名 + 时间戳 + run id"命名的子目录,即Result.path指向的位置,该目录下存放着检查点目录、指标文件与 checkpoint manager 快照,是Result.from_path恢复的数据来源。
七、Result 对象属性速查表
| 属性 / 方法 | 类型 | 含义 |
|---|---|---|
Result.metrics | Optional[Dict] | 最后报告检查点附带的指标(最近一次report的指标) |
Result.metrics_dataframe | Optional[pd.DataFrame] | 所有检查点附带指标的 DataFrame,一行对应一个检查点 |
Result.return_value | Optional[Any] | rank 0 训练函数的返回值(需可序列化,失败或无返回时为None) |
Result.checkpoint | Optional[Checkpoint] | 最后保存的检查点,配合as_directory()加载模型 |
Result.best_checkpoints | Optional[List[Tuple[Checkpoint, Dict]]] | 被保留的检查点及其指标列表(数量由CheckpointConfig决定) |
Result.get_best_checkpoint(metric, mode) | Optional[Checkpoint] | 按指标与"min"/"max"模式挑出最优检查点 |
Result.path | str | 结果目录在持久化存储上的路径(云存储时可能不带 scheme 前缀) |
Result.filesystem | pyarrow.fs.FileSystem | 访问结果路径所用的文件系统(默认本地文件系统) |
Result.error | Optional[Exception] | 训练错误(v2 中为TrainingFailedError包装) |
Result.from_path(path, storage_filesystem=None) | Result | 从已保存的运行目录恢复Result对象 |
其中metrics、checkpoint、error、path四个字段是 dataclass 的必填字段,best_checkpoints、metrics_dataframe、return_value等为可选字段(默认None,见 python/ray/train/v2/api/result.py)。另外,Result.config属性在 v2 中已标记为废弃——它只与 Ray Tune 的搜索空间相关,对独立训练的Result不再有意义(python/ray/train/v2/api/result.py)。
八、最佳实践小结
- 指标一律附着检查点上报:由于游离指标持久化已弃用,请始终使用
ray.train.report(metrics, checkpoint=...)的形式,否则训练结束后将无法从Result中取回这些指标。 - 用
metrics_dataframe做趋势分析:一行一检查点的结构便于绘制 loss/accuracy 曲线,或用min(df["loss"])定位最优轮次。 - 取最优检查点用
best_checkpoints或get_best_checkpoint:过拟合场景下最后检查点未必最优,按验证指标挑选更可靠;需要控制存储成本时用CheckpointConfig(num_to_keep=...)限制保留数量。 - 结果落盘到持久化存储:为
RunConfig配置storage_path(本地目录或 S3/GCS 等),让Result.path指向可长期保留的位置,之后用Result.from_path随时恢复,支撑"训练与推理解耦"的工作流。 - 区分错误类型:捕获
ray.train.TrainingFailedError并用WorkerGroupError/ActorCreationError子类判断失败来源,再决定是排查训练代码还是集群资源问题。
上述所有行为均有仓库源码与示例可验证:完整可运行的示例见 doc_code/key_concepts.py,v2 的Result数据类与from_path实现见 python/ray/train/v2/api/result.py,跨版本稳定的基类实现与get_best_checkpoint见 python/ray/air/result.py,ray.train.report的语义(rank 0 指标跟踪、多 worker 检查点合并、迭代计数等)见 python/ray/train/_internal/session.py。
- 人工智能
- 分布式训练
- 强化学习
- 任务调度
- 模型推理服务
【免费下载链接】ray
Ray is an AI compute engine. Ray consists of a core distributed runtime and a set of AI Libraries for accelerating ML workloads.
相关推荐
CAI 结果对象完全指南:解析 `RunResult`、`RunResultStreaming` 与 `Runner.run` 的全部返回值
CAI 结果对象完全指南:解析 RunResult 、 RunResultStreaming 与 Runner.run 的全部返回值 Runner.run 系列
人工智能AI Agent网络安全渗透测试工具调用AI 评测Apache Airflow DAG Result 实战指南:标记结果任务并用 Wait API 同步取回返回值
Apache Airflow DAG Result 实战指南:标记结果任务并用 Wait API 同步取回返回值 导读 Apache Airflow 3.3 引
后端任务调度工作流自动化数据编排批处理数据工程流程编排android-sunflower中的ViewModel与导航返回值:返回结果
android sunflower中的ViewModel与导航返回值:返回结果 在Android应用开发中,ViewModel与导航返回值的结合使用是实现页面间
移动开发示例工程
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考