hydraflow 0.3.2__py3-none-any.whl → 0.3.4__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- hydraflow/__init__.py +11 -3
- hydraflow/config.py +13 -0
- hydraflow/context.py +1 -1
- hydraflow/param.py +4 -1
- hydraflow/run_collection.py +3 -13
- hydraflow/run_data.py +32 -9
- hydraflow/utils.py +25 -0
- {hydraflow-0.3.2.dist-info → hydraflow-0.3.4.dist-info}/METADATA +1 -1
- hydraflow-0.3.4.dist-info/RECORD +16 -0
- hydraflow-0.3.2.dist-info/RECORD +0 -16
- {hydraflow-0.3.2.dist-info → hydraflow-0.3.4.dist-info}/WHEEL +0 -0
- {hydraflow-0.3.2.dist-info → hydraflow-0.3.4.dist-info}/licenses/LICENSE +0 -0
hydraflow/__init__.py
CHANGED
@@ -1,19 +1,27 @@
|
|
1
1
|
"""Integrate Hydra and MLflow to manage and track machine learning experiments."""
|
2
2
|
|
3
|
-
from .context import chdir_artifact,
|
3
|
+
from .context import chdir_artifact, chdir_hydra_output, log_run, start_run, watch
|
4
4
|
from .mlflow import list_runs, search_runs, set_experiment
|
5
5
|
from .progress import multi_tasks_progress, parallel_progress
|
6
6
|
from .run_collection import RunCollection
|
7
|
-
from .utils import
|
7
|
+
from .utils import (
|
8
|
+
get_artifact_dir,
|
9
|
+
get_hydra_output_dir,
|
10
|
+
get_overrides,
|
11
|
+
load_config,
|
12
|
+
load_overrides,
|
13
|
+
)
|
8
14
|
|
9
15
|
__all__ = [
|
10
16
|
"RunCollection",
|
11
17
|
"chdir_artifact",
|
12
|
-
"
|
18
|
+
"chdir_hydra_output",
|
13
19
|
"get_artifact_dir",
|
14
20
|
"get_hydra_output_dir",
|
21
|
+
"get_overrides",
|
15
22
|
"list_runs",
|
16
23
|
"load_config",
|
24
|
+
"load_overrides",
|
17
25
|
"log_run",
|
18
26
|
"multi_tasks_progress",
|
19
27
|
"parallel_progress",
|
hydraflow/config.py
CHANGED
@@ -44,12 +44,25 @@ def iter_params(config: object, prefix: str = "") -> Iterator[tuple[str, Any]]:
|
|
44
44
|
if config is None:
|
45
45
|
return
|
46
46
|
|
47
|
+
if isinstance(config, list) and all(isinstance(x, str) for x in config):
|
48
|
+
config = _from_dotlist(config)
|
49
|
+
|
47
50
|
if not isinstance(config, DictConfig | ListConfig):
|
48
51
|
config = OmegaConf.create(config) # type: ignore
|
49
52
|
|
50
53
|
yield from _iter_params(config, prefix)
|
51
54
|
|
52
55
|
|
56
|
+
def _from_dotlist(config: list[str]) -> dict[str, str]:
|
57
|
+
result = {}
|
58
|
+
for item in config:
|
59
|
+
if "=" in item:
|
60
|
+
key, value = item.split("=", 1)
|
61
|
+
result[key.strip()] = value.strip()
|
62
|
+
|
63
|
+
return result
|
64
|
+
|
65
|
+
|
53
66
|
def _iter_params(config: object, prefix: str = "") -> Iterator[tuple[str, Any]]:
|
54
67
|
if isinstance(config, DictConfig):
|
55
68
|
for key, value in config.items():
|
hydraflow/context.py
CHANGED
@@ -239,7 +239,7 @@ class Handler(PatternMatchingEventHandler):
|
|
239
239
|
|
240
240
|
|
241
241
|
@contextmanager
|
242
|
-
def
|
242
|
+
def chdir_hydra_output() -> Iterator[Path]:
|
243
243
|
"""Change the current working directory to the hydra output directory.
|
244
244
|
|
245
245
|
This context manager changes the current working directory to the hydra output
|
hydraflow/param.py
CHANGED
@@ -34,7 +34,10 @@ def match(param: str, value: Any) -> bool:
|
|
34
34
|
if isinstance(value, tuple) and (m := _match_tuple(param, value)) is not None:
|
35
35
|
return m
|
36
36
|
|
37
|
-
if isinstance(value,
|
37
|
+
if isinstance(value, str):
|
38
|
+
return param == value
|
39
|
+
|
40
|
+
if isinstance(value, int | float):
|
38
41
|
return type(value)(param) == value
|
39
42
|
|
40
43
|
return param == str(value)
|
hydraflow/run_collection.py
CHANGED
@@ -24,12 +24,12 @@ from itertools import chain
|
|
24
24
|
from typing import TYPE_CHECKING, Any, Concatenate, ParamSpec, TypeVar, overload
|
25
25
|
|
26
26
|
from mlflow.entities import RunStatus
|
27
|
-
from polars.dataframe import DataFrame
|
28
27
|
|
29
28
|
import hydraflow.param
|
30
|
-
from hydraflow.config import
|
29
|
+
from hydraflow.config import iter_params
|
31
30
|
from hydraflow.run_data import RunCollectionData
|
32
31
|
from hydraflow.run_info import RunCollectionInfo
|
32
|
+
from hydraflow.utils import load_config
|
33
33
|
|
34
34
|
if TYPE_CHECKING:
|
35
35
|
from collections.abc import Callable, Iterator
|
@@ -516,7 +516,7 @@ class RunCollection:
|
|
516
516
|
in the collection.
|
517
517
|
|
518
518
|
"""
|
519
|
-
return (func(
|
519
|
+
return (func(load_config(run), *args, **kwargs) for run in self)
|
520
520
|
|
521
521
|
def map_uri(
|
522
522
|
self,
|
@@ -599,16 +599,6 @@ class RunCollection:
|
|
599
599
|
|
600
600
|
return {key: RunCollection(runs) for key, runs in grouped_runs.items()}
|
601
601
|
|
602
|
-
@property
|
603
|
-
def config(self) -> DataFrame:
|
604
|
-
"""Get the runs' configurations as a polars DataFrame.
|
605
|
-
|
606
|
-
Returns:
|
607
|
-
A polars DataFrame containing the runs' configurations.
|
608
|
-
|
609
|
-
"""
|
610
|
-
return DataFrame(self.map_config(collect_params))
|
611
|
-
|
612
602
|
|
613
603
|
def _param_matches(run: Run, key: str, value: Any) -> bool:
|
614
604
|
params = run.data.params
|
hydraflow/run_data.py
CHANGED
@@ -4,10 +4,13 @@ from __future__ import annotations
|
|
4
4
|
|
5
5
|
from typing import TYPE_CHECKING
|
6
6
|
|
7
|
-
from
|
7
|
+
from polars.dataframe import DataFrame
|
8
|
+
|
9
|
+
from hydraflow.config import collect_params
|
8
10
|
|
9
11
|
if TYPE_CHECKING:
|
10
|
-
from
|
12
|
+
from collections.abc import Iterable
|
13
|
+
from typing import Any
|
11
14
|
|
12
15
|
from hydraflow.run_collection import RunCollection
|
13
16
|
|
@@ -19,16 +22,36 @@ class RunCollectionData:
|
|
19
22
|
self._runs = runs
|
20
23
|
|
21
24
|
@property
|
22
|
-
def params(self) ->
|
25
|
+
def params(self) -> dict[str, list[str]]:
|
23
26
|
"""Get the parameters for each run in the collection."""
|
24
|
-
return
|
27
|
+
return _to_dict(run.data.params for run in self._runs)
|
25
28
|
|
26
29
|
@property
|
27
|
-
def metrics(self) ->
|
30
|
+
def metrics(self) -> dict[str, list[float]]:
|
28
31
|
"""Get the metrics for each run in the collection."""
|
29
|
-
return
|
32
|
+
return _to_dict(run.data.metrics for run in self._runs)
|
30
33
|
|
31
34
|
@property
|
32
|
-
def config(self) ->
|
33
|
-
"""Get the
|
34
|
-
|
35
|
+
def config(self) -> DataFrame:
|
36
|
+
"""Get the runs' configurations as a polars DataFrame.
|
37
|
+
|
38
|
+
Returns:
|
39
|
+
A polars DataFrame containing the runs' configurations.
|
40
|
+
|
41
|
+
"""
|
42
|
+
return DataFrame(self._runs.map_config(collect_params))
|
43
|
+
|
44
|
+
|
45
|
+
def _to_dict(it: Iterable[dict[str, Any]]) -> dict[str, list[Any]]:
|
46
|
+
"""Convert an iterable of dictionaries to a dictionary of lists."""
|
47
|
+
data = list(it)
|
48
|
+
if not data:
|
49
|
+
return {}
|
50
|
+
|
51
|
+
keys = []
|
52
|
+
for d in data:
|
53
|
+
for key in d:
|
54
|
+
if key not in keys:
|
55
|
+
keys.append(key)
|
56
|
+
|
57
|
+
return {key: [x.get(key) for x in data] for key in keys}
|
hydraflow/utils.py
CHANGED
@@ -86,3 +86,28 @@ def load_config(run: Run) -> DictConfig:
|
|
86
86
|
"""
|
87
87
|
path = get_artifact_dir(run) / ".hydra/config.yaml"
|
88
88
|
return OmegaConf.load(path) # type: ignore
|
89
|
+
|
90
|
+
|
91
|
+
def get_overrides() -> list[str]:
|
92
|
+
"""Retrieve the overrides for the current run."""
|
93
|
+
return HydraConfig.get().overrides.task
|
94
|
+
|
95
|
+
|
96
|
+
def load_overrides(run: Run) -> list[str]:
|
97
|
+
"""Load the overrides for a given run.
|
98
|
+
|
99
|
+
This function loads the overrides for the provided Run instance
|
100
|
+
by downloading the overrides file from the MLflow artifacts and
|
101
|
+
loading it using OmegaConf. It returns an empty config if
|
102
|
+
`.hydra/overrides.yaml` is not found in the run's artifact directory.
|
103
|
+
|
104
|
+
Args:
|
105
|
+
run (Run): The Run instance for which to load the overrides.
|
106
|
+
|
107
|
+
Returns:
|
108
|
+
The loaded overrides as a list of strings. Returns an empty list
|
109
|
+
if the overrides file is not found.
|
110
|
+
|
111
|
+
"""
|
112
|
+
path = get_artifact_dir(run) / ".hydra/overrides.yaml"
|
113
|
+
return [str(x) for x in OmegaConf.load(path)]
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.3
|
2
2
|
Name: hydraflow
|
3
|
-
Version: 0.3.
|
3
|
+
Version: 0.3.4
|
4
4
|
Summary: Hydraflow integrates Hydra and MLflow to manage and track machine learning experiments.
|
5
5
|
Project-URL: Documentation, https://github.com/daizutabi/hydraflow
|
6
6
|
Project-URL: Source, https://github.com/daizutabi/hydraflow
|
@@ -0,0 +1,16 @@
|
|
1
|
+
hydraflow/__init__.py,sha256=HVVsSRK2BXtHdoueFNRva924th49_lCV5zYb2c8qdaw,811
|
2
|
+
hydraflow/asyncio.py,sha256=-i1C8KAmNDImrjHnk92Csaa1mpjdK8Vp4ZVaQV-l94s,6634
|
3
|
+
hydraflow/config.py,sha256=dRG4cFqDH0vBX109q0C46jiXdvbYoYgu651D6KlmmxQ,3021
|
4
|
+
hydraflow/context.py,sha256=p1UYHvSCPrp10cBn9TUI9mXMv0h_I0Eou24Wp1rZZ0k,8740
|
5
|
+
hydraflow/mlflow.py,sha256=JELqXFCJ9MsEJaQWT5dyleTFk8BHL7cQwW_gzhkPoIg,8729
|
6
|
+
hydraflow/param.py,sha256=CO-6PRlnHo-7hlY_P6j_cGlC7vPY6t-Rr7p3OqeqDyU,1995
|
7
|
+
hydraflow/progress.py,sha256=zvKX1HCN8_xDOsgYOEcLLhkhdPdep-U8vHrc0XZ-6SQ,6163
|
8
|
+
hydraflow/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
9
|
+
hydraflow/run_collection.py,sha256=OiPibp8zM4gpsvqpHr9sBh4_1zmHRuXfPcmen7xND-s,24792
|
10
|
+
hydraflow/run_data.py,sha256=qeFX1iRvNAorXA9QQIjzr0o2_82TI44eZKp7llKG8GI,1549
|
11
|
+
hydraflow/run_info.py,sha256=sMXOo20ClaRIommMEzuAbO_OrcXx7M1Yt4FMV7spxz0,998
|
12
|
+
hydraflow/utils.py,sha256=qNN0JDbQJweTkcRMpZwMXTIuK_LVpoDJ2rOwfe01f3U,3500
|
13
|
+
hydraflow-0.3.4.dist-info/METADATA,sha256=DJuHernRtS9IjpWRqCIt-yDXdFBDioSf3f3-T15D-yI,3840
|
14
|
+
hydraflow-0.3.4.dist-info/WHEEL,sha256=1yFddiXMmvYK7QYTqtRNtX66WJ0Mz8PYEiEUoOUUxRY,87
|
15
|
+
hydraflow-0.3.4.dist-info/licenses/LICENSE,sha256=IGdDrBPqz1O0v_UwCW-NJlbX9Hy9b3uJ11t28y2srmY,1062
|
16
|
+
hydraflow-0.3.4.dist-info/RECORD,,
|
hydraflow-0.3.2.dist-info/RECORD
DELETED
@@ -1,16 +0,0 @@
|
|
1
|
-
hydraflow/__init__.py,sha256=6sfM1ashUkfrNf7lOR7raFYhG8YdOAJR-JgRNL_IVo8,698
|
2
|
-
hydraflow/asyncio.py,sha256=-i1C8KAmNDImrjHnk92Csaa1mpjdK8Vp4ZVaQV-l94s,6634
|
3
|
-
hydraflow/config.py,sha256=6V5omJ3-h9-ZwVpM5rTA4FqE_mu8urTy9OqV4zG79gw,2671
|
4
|
-
hydraflow/context.py,sha256=412884e84qIEYtbxJT4roYsKfldGaTKzgo6Q1FAsT5U,8733
|
5
|
-
hydraflow/mlflow.py,sha256=JELqXFCJ9MsEJaQWT5dyleTFk8BHL7cQwW_gzhkPoIg,8729
|
6
|
-
hydraflow/param.py,sha256=QkLeQvt5ZF3GyRGnhP66o0GElc1ZOOCxCL7PdyfIUbA,1939
|
7
|
-
hydraflow/progress.py,sha256=zvKX1HCN8_xDOsgYOEcLLhkhdPdep-U8vHrc0XZ-6SQ,6163
|
8
|
-
hydraflow/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
9
|
-
hydraflow/run_collection.py,sha256=0SCParNkSoXw7Ule-FH3az578Hhu-1TKGyrFNXxTciU,25082
|
10
|
-
hydraflow/run_data.py,sha256=ZXVr0PHyufH9wwyQYWtpE4_MheAC2ArTW_J1TTMQ4iI,983
|
11
|
-
hydraflow/run_info.py,sha256=sMXOo20ClaRIommMEzuAbO_OrcXx7M1Yt4FMV7spxz0,998
|
12
|
-
hydraflow/utils.py,sha256=aRdBdToKfvHhN2qFiRzPHIdQxS7cTpZREQeP8HreAfI,2676
|
13
|
-
hydraflow-0.3.2.dist-info/METADATA,sha256=RktfWMufNqrMU2CBSbmVxwE_e7VPbLhVYQHgBKXuh9Q,3840
|
14
|
-
hydraflow-0.3.2.dist-info/WHEEL,sha256=1yFddiXMmvYK7QYTqtRNtX66WJ0Mz8PYEiEUoOUUxRY,87
|
15
|
-
hydraflow-0.3.2.dist-info/licenses/LICENSE,sha256=IGdDrBPqz1O0v_UwCW-NJlbX9Hy9b3uJ11t28y2srmY,1062
|
16
|
-
hydraflow-0.3.2.dist-info/RECORD,,
|
File without changes
|
File without changes
|