chore: import upstream snapshot with attribution
This commit is contained in:
@@ -0,0 +1,162 @@
|
||||
import logging
|
||||
import os
|
||||
from dataclasses import dataclass
|
||||
from typing import Any, Dict, List, Optional, Tuple, Union
|
||||
|
||||
import pandas as pd
|
||||
import pyarrow
|
||||
|
||||
import ray
|
||||
from ray.air.result import Result as ResultV1
|
||||
from ray.train import Checkpoint, CheckpointConfig
|
||||
from ray.train.v2._internal.constants import CHECKPOINT_MANAGER_SNAPSHOT_FILENAME
|
||||
from ray.train.v2._internal.execution.checkpoint.checkpoint_manager import (
|
||||
CheckpointManager,
|
||||
)
|
||||
from ray.train.v2._internal.execution.storage import (
|
||||
StorageContext,
|
||||
_exists_at_fs_path,
|
||||
get_fs_and_path,
|
||||
)
|
||||
from ray.train.v2.api.exceptions import TrainingFailedError
|
||||
from ray.util.annotations import Deprecated, PublicAPI
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
@dataclass
|
||||
class Result(ResultV1):
|
||||
"""The output of ``trainer.fit()``.
|
||||
|
||||
Attributes:
|
||||
metrics: The latest set of metrics reported by the training function
|
||||
via :func:`ray.train.report`.
|
||||
checkpoint: The latest checkpoint saved by the training function
|
||||
via :func:`ray.train.report`.
|
||||
return_value: The value returned by the user-defined training function on the
|
||||
rank 0 worker, or ``None`` if no value was returned or if training did
|
||||
not complete successfully. The return value must be serializable.
|
||||
metrics_dataframe: A DataFrame of metrics from all checkpoints saved
|
||||
during the run. Each row corresponds to a checkpoint.
|
||||
best_checkpoints: A list of ``(checkpoint, metrics)`` tuples for the
|
||||
best checkpoints saved during the run. The checkpoints retained
|
||||
are determined by :class:`~ray.train.CheckpointConfig`
|
||||
(by default, all checkpoints are kept).
|
||||
path: Path pointing to the run output directory on persistent storage.
|
||||
This can point to a remote storage location (e.g. S3) or to a
|
||||
local location on the head node.
|
||||
error: The execution error of the training run, if the run finished
|
||||
in error. This is a :class:`~ray.train.v2.api.exceptions.TrainingFailedError`
|
||||
wrapping the original exception.
|
||||
"""
|
||||
|
||||
checkpoint: Optional[Checkpoint]
|
||||
error: Optional[TrainingFailedError]
|
||||
best_checkpoints: Optional[List[Tuple[Checkpoint, Dict[str, Any]]]] = None
|
||||
return_value: Optional[Any] = None
|
||||
|
||||
@PublicAPI(stability="alpha")
|
||||
def get_best_checkpoint(
|
||||
self, metric: str, mode: str
|
||||
) -> Optional["ray.train.Checkpoint"]:
|
||||
return super().get_best_checkpoint(metric, mode)
|
||||
|
||||
@classmethod
|
||||
def from_path(
|
||||
cls,
|
||||
path: Union[str, os.PathLike],
|
||||
storage_filesystem: Optional[pyarrow.fs.FileSystem] = None,
|
||||
) -> "Result":
|
||||
"""Restore a training result from a previously saved training run path.
|
||||
|
||||
Args:
|
||||
path: Path to the run output directory
|
||||
storage_filesystem: Optional filesystem to use for accessing the path
|
||||
|
||||
Returns:
|
||||
Result object with restored checkpoints and metrics
|
||||
"""
|
||||
fs, fs_path = get_fs_and_path(str(path), storage_filesystem)
|
||||
|
||||
# Validate that the experiment directory exists
|
||||
if not _exists_at_fs_path(fs, fs_path):
|
||||
raise RuntimeError(f"Experiment folder {fs_path} doesn't exist.")
|
||||
|
||||
# Remove trailing slashes to handle paths correctly
|
||||
# os.path.basename() returns empty string for paths with trailing slashes
|
||||
fs_path = fs_path.rstrip("/")
|
||||
storage_path, experiment_dir_name = os.path.dirname(fs_path), os.path.basename(
|
||||
fs_path
|
||||
)
|
||||
|
||||
storage_context = StorageContext(
|
||||
storage_path=storage_path,
|
||||
experiment_dir_name=experiment_dir_name,
|
||||
storage_filesystem=fs,
|
||||
read_only=True,
|
||||
)
|
||||
|
||||
# Validate that the checkpoint manager snapshot file exists
|
||||
if not _exists_at_fs_path(
|
||||
storage_context.storage_filesystem,
|
||||
storage_context.checkpoint_manager_snapshot_path,
|
||||
):
|
||||
raise RuntimeError(
|
||||
f"Failed to restore the Result object: "
|
||||
f"{CHECKPOINT_MANAGER_SNAPSHOT_FILENAME} doesn't exist in the "
|
||||
f"experiment folder. Make sure that this is an output directory created by a Ray Train run."
|
||||
)
|
||||
|
||||
checkpoint_manager = CheckpointManager(
|
||||
storage_context=storage_context,
|
||||
checkpoint_config=CheckpointConfig(),
|
||||
)
|
||||
|
||||
# When we build a Result object from checkpoints, the error is not loaded.
|
||||
return cls._from_checkpoint_manager(
|
||||
checkpoint_manager=checkpoint_manager,
|
||||
storage_context=storage_context,
|
||||
)
|
||||
|
||||
@classmethod
|
||||
def _from_checkpoint_manager(
|
||||
cls,
|
||||
checkpoint_manager: CheckpointManager,
|
||||
storage_context: StorageContext,
|
||||
error: Optional[TrainingFailedError] = None,
|
||||
) -> "Result":
|
||||
"""Create a Result object from a CheckpointManager."""
|
||||
latest_checkpoint_result = checkpoint_manager.latest_checkpoint_result
|
||||
if latest_checkpoint_result:
|
||||
latest_metrics = latest_checkpoint_result.metrics
|
||||
latest_checkpoint = latest_checkpoint_result.checkpoint
|
||||
else:
|
||||
latest_metrics = None
|
||||
latest_checkpoint = None
|
||||
best_checkpoints = [
|
||||
(r.checkpoint, r.metrics)
|
||||
for r in checkpoint_manager.best_checkpoint_results
|
||||
]
|
||||
|
||||
# Provide the history of metrics attached to checkpoints as a dataframe.
|
||||
metrics_dataframe = None
|
||||
if best_checkpoints:
|
||||
metrics_dataframe = pd.DataFrame([m for _, m in best_checkpoints])
|
||||
|
||||
return Result(
|
||||
metrics=latest_metrics,
|
||||
checkpoint=latest_checkpoint,
|
||||
error=error,
|
||||
path=storage_context.experiment_fs_path,
|
||||
best_checkpoints=best_checkpoints,
|
||||
metrics_dataframe=metrics_dataframe,
|
||||
_storage_filesystem=storage_context.storage_filesystem,
|
||||
)
|
||||
|
||||
@property
|
||||
@Deprecated
|
||||
def config(self) -> Optional[Dict[str, Any]]:
|
||||
raise DeprecationWarning(
|
||||
"The `config` property for a `ray.train.Result` is deprecated, "
|
||||
"since it is only relevant in the context of Ray Tune."
|
||||
)
|
||||
Reference in New Issue
Block a user