minerva-opt 1.0.0__tar.gz

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.
@@ -0,0 +1,141 @@
1
+ Metadata-Version: 2.4
2
+ Name: minerva-opt
3
+ Version: 1.0.0
4
+ Summary: Hyperparameter optimization extensions for Minerva.
5
+ Author-email: Gabriel Gutierrez <gabriel.bgs00@gmail.com>
6
+ Project-URL: Bug Tracker, https://github.com/gabrielbg0/Minerva-OPT/issues
7
+ Project-URL: Homepage, https://github.com/gabrielbg0/Minerva-OPT
8
+ Keywords: Deep Learning,Hyperparameter Optimization,Machine Learning,Pytorch,Ray Tune,Research
9
+ Classifier: License :: OSI Approved :: MIT License
10
+ Classifier: Programming Language :: Python
11
+ Classifier: Programming Language :: Python :: 3
12
+ Classifier: Development Status :: 3 - Alpha
13
+ Classifier: Intended Audience :: Science/Research
14
+ Classifier: Operating System :: OS Independent
15
+ Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
16
+ Requires-Python: >=3.10
17
+ Description-Content-Type: text/markdown
18
+ Requires-Dist: minerva==0.3.10-beta
19
+ Requires-Dist: ray[tune]>=2.55
20
+ Requires-Dist: hyperopt>=0.2.7
21
+ Provides-Extra: dev
22
+ Requires-Dist: black; extra == "dev"
23
+ Requires-Dist: flake8; extra == "dev"
24
+ Requires-Dist: pytest; extra == "dev"
25
+ Requires-Dist: pytest-coverage; extra == "dev"
26
+
27
+ # Minerva-OPT
28
+
29
+ [![Auto Release](https://github.com/gabrielbg0/Minerva-OPT/actions/workflows/auto-release.yml/badge.svg)](https://github.com/gabrielbg0/Minerva-OPT/actions/workflows/auto-release.yml)
30
+
31
+ Hyperparameter optimization extensions for [Minerva](https://github.com/discovery-unicamp/Minerva), powered by [Ray Tune](https://docs.ray.io/en/latest/tune/index.html).
32
+
33
+ ## Description
34
+
35
+ Minerva-OPT provides a `RayHyperParameterSearch` pipeline that wraps Ray Tune and PyTorch Lightning to run distributed hyperparameter searches on top of any Minerva-compatible model. It supports random search, grid search, and Bayesian optimization (via HyperOpt), with early stopping through the ASHA scheduler.
36
+
37
+ ### Features
38
+
39
+ - **Drop-in Minerva pipeline**: inherits from `minerva.pipelines.base.Pipeline`, so it integrates with Minerva's logging, reproducibility, and run-status tracking out of the box.
40
+ - **Flexible search algorithms**: use Ray Tune's default random/grid search or pass any `ray.tune.search.Searcher` (e.g. `HyperOptSearch` for Bayesian optimization).
41
+ - **ASHA early stopping**: trials are stopped early based on intermediate results; `grace_period` and `max_t` are derived automatically from `max_epochs`.
42
+ - **Distributed training**: uses `RayDDPStrategy` and `RayLightningEnvironment` for multi-worker trials.
43
+ - **Checkpointing**: keeps only the best checkpoint per trial, scored on the target metric.
44
+
45
+ ## Installation
46
+
47
+ Requires Python 3.10+.
48
+
49
+ ### With uv (recommended)
50
+
51
+ ```bash
52
+ uv pip install minerva-opt
53
+ ```
54
+
55
+ ### With pip
56
+
57
+ ```bash
58
+ pip install minerva-opt
59
+ ```
60
+
61
+ ## Usage
62
+
63
+ ### Random / grid search
64
+
65
+ ```python
66
+ from ray import tune
67
+ from minerva_opt.pipelines.hyperparameter_search import RayHyperParameterSearch
68
+
69
+ search_space = {
70
+ "learning_rate": tune.loguniform(1e-4, 1e-1),
71
+ "hidden_size": tune.choice([64, 128, 256]),
72
+ }
73
+
74
+ pipeline = RayHyperParameterSearch(
75
+ model=MyLightningModel, # class, not instance — instantiated per trial as MyLightningModel(**config)
76
+ search_space=search_space,
77
+ log_dir="logs/",
78
+ )
79
+
80
+ results = pipeline.run(data=my_data_module, num_samples=20, max_epochs=50)
81
+ best = results.get_best_result()
82
+ print(best.config)
83
+ ```
84
+
85
+ ### Bayesian optimization with HyperOpt
86
+
87
+ ```python
88
+ from ray.tune.search.hyperopt import HyperOptSearch
89
+ from hyperopt import hp
90
+
91
+ search_space = {
92
+ "learning_rate": tune.loguniform(1e-4, 1e-1),
93
+ "dropout": tune.uniform(0.1, 0.5),
94
+ }
95
+
96
+ pipeline = RayHyperParameterSearch(
97
+ model=MyLightningModel,
98
+ search_space=search_space,
99
+ )
100
+
101
+ results = pipeline.run(
102
+ data=my_data_module,
103
+ search_alg=HyperOptSearch(),
104
+ num_samples=30,
105
+ max_epochs=100,
106
+ tuner_metric="val_loss",
107
+ tuner_mode="min",
108
+ )
109
+ ```
110
+
111
+ ### Key `run()` parameters
112
+
113
+ | Parameter | Default | Description |
114
+ | --------------------- | ------------ | ------------------------------------------------------ |
115
+ | `data` | — | `LightningDataModule` to train on |
116
+ | `task` | `"search"` | `"search"` to run the sweep |
117
+ | `ckpt_path` | `None` | Resume training from a checkpoint |
118
+ | `num_samples` | `10` | Number of trials to run |
119
+ | `max_epochs` | `100` | Max epochs per trial |
120
+ | `tuner_metric` | `"val_loss"` | Metric to optimize |
121
+ | `tuner_mode` | `"min"` | `"min"` or `"max"` |
122
+ | `search_alg` | `None` | Any `ray.tune.search.Searcher`; `None` = random search |
123
+ | `max_concurrent` | `4` | Max concurrent trials (when using a `search_alg`) |
124
+ | `scheduler` | ASHA | Override the trial scheduler |
125
+ | `scaling_config` | 1 GPU/worker | Override Ray `ScalingConfig` |
126
+ | `checkpoint_interval` | `1` | Save a checkpoint every N epochs |
127
+ | `debug_mode` | `False` | Disable checkpointing for fast iteration |
128
+
129
+ ## Requirements
130
+
131
+ - `minerva >= 0.3.10b0`
132
+ - `ray[tune] >= 2.55`
133
+ - `hyperopt >= 0.2.7`
134
+
135
+ ## License
136
+
137
+ MIT License. See [LICENSE](LICENSE) for details.
138
+
139
+ ## Contact
140
+
141
+ For questions or bug reports, open an issue on the [GitHub issue tracker](https://github.com/gabrielbg0/Minerva-OPT/issues).
@@ -0,0 +1,115 @@
1
+ # Minerva-OPT
2
+
3
+ [![Auto Release](https://github.com/gabrielbg0/Minerva-OPT/actions/workflows/auto-release.yml/badge.svg)](https://github.com/gabrielbg0/Minerva-OPT/actions/workflows/auto-release.yml)
4
+
5
+ Hyperparameter optimization extensions for [Minerva](https://github.com/discovery-unicamp/Minerva), powered by [Ray Tune](https://docs.ray.io/en/latest/tune/index.html).
6
+
7
+ ## Description
8
+
9
+ Minerva-OPT provides a `RayHyperParameterSearch` pipeline that wraps Ray Tune and PyTorch Lightning to run distributed hyperparameter searches on top of any Minerva-compatible model. It supports random search, grid search, and Bayesian optimization (via HyperOpt), with early stopping through the ASHA scheduler.
10
+
11
+ ### Features
12
+
13
+ - **Drop-in Minerva pipeline**: inherits from `minerva.pipelines.base.Pipeline`, so it integrates with Minerva's logging, reproducibility, and run-status tracking out of the box.
14
+ - **Flexible search algorithms**: use Ray Tune's default random/grid search or pass any `ray.tune.search.Searcher` (e.g. `HyperOptSearch` for Bayesian optimization).
15
+ - **ASHA early stopping**: trials are stopped early based on intermediate results; `grace_period` and `max_t` are derived automatically from `max_epochs`.
16
+ - **Distributed training**: uses `RayDDPStrategy` and `RayLightningEnvironment` for multi-worker trials.
17
+ - **Checkpointing**: keeps only the best checkpoint per trial, scored on the target metric.
18
+
19
+ ## Installation
20
+
21
+ Requires Python 3.10+.
22
+
23
+ ### With uv (recommended)
24
+
25
+ ```bash
26
+ uv pip install minerva-opt
27
+ ```
28
+
29
+ ### With pip
30
+
31
+ ```bash
32
+ pip install minerva-opt
33
+ ```
34
+
35
+ ## Usage
36
+
37
+ ### Random / grid search
38
+
39
+ ```python
40
+ from ray import tune
41
+ from minerva_opt.pipelines.hyperparameter_search import RayHyperParameterSearch
42
+
43
+ search_space = {
44
+ "learning_rate": tune.loguniform(1e-4, 1e-1),
45
+ "hidden_size": tune.choice([64, 128, 256]),
46
+ }
47
+
48
+ pipeline = RayHyperParameterSearch(
49
+ model=MyLightningModel, # class, not instance — instantiated per trial as MyLightningModel(**config)
50
+ search_space=search_space,
51
+ log_dir="logs/",
52
+ )
53
+
54
+ results = pipeline.run(data=my_data_module, num_samples=20, max_epochs=50)
55
+ best = results.get_best_result()
56
+ print(best.config)
57
+ ```
58
+
59
+ ### Bayesian optimization with HyperOpt
60
+
61
+ ```python
62
+ from ray.tune.search.hyperopt import HyperOptSearch
63
+ from hyperopt import hp
64
+
65
+ search_space = {
66
+ "learning_rate": tune.loguniform(1e-4, 1e-1),
67
+ "dropout": tune.uniform(0.1, 0.5),
68
+ }
69
+
70
+ pipeline = RayHyperParameterSearch(
71
+ model=MyLightningModel,
72
+ search_space=search_space,
73
+ )
74
+
75
+ results = pipeline.run(
76
+ data=my_data_module,
77
+ search_alg=HyperOptSearch(),
78
+ num_samples=30,
79
+ max_epochs=100,
80
+ tuner_metric="val_loss",
81
+ tuner_mode="min",
82
+ )
83
+ ```
84
+
85
+ ### Key `run()` parameters
86
+
87
+ | Parameter | Default | Description |
88
+ | --------------------- | ------------ | ------------------------------------------------------ |
89
+ | `data` | — | `LightningDataModule` to train on |
90
+ | `task` | `"search"` | `"search"` to run the sweep |
91
+ | `ckpt_path` | `None` | Resume training from a checkpoint |
92
+ | `num_samples` | `10` | Number of trials to run |
93
+ | `max_epochs` | `100` | Max epochs per trial |
94
+ | `tuner_metric` | `"val_loss"` | Metric to optimize |
95
+ | `tuner_mode` | `"min"` | `"min"` or `"max"` |
96
+ | `search_alg` | `None` | Any `ray.tune.search.Searcher`; `None` = random search |
97
+ | `max_concurrent` | `4` | Max concurrent trials (when using a `search_alg`) |
98
+ | `scheduler` | ASHA | Override the trial scheduler |
99
+ | `scaling_config` | 1 GPU/worker | Override Ray `ScalingConfig` |
100
+ | `checkpoint_interval` | `1` | Save a checkpoint every N epochs |
101
+ | `debug_mode` | `False` | Disable checkpointing for fast iteration |
102
+
103
+ ## Requirements
104
+
105
+ - `minerva >= 0.3.10b0`
106
+ - `ray[tune] >= 2.55`
107
+ - `hyperopt >= 0.2.7`
108
+
109
+ ## License
110
+
111
+ MIT License. See [LICENSE](LICENSE) for details.
112
+
113
+ ## Contact
114
+
115
+ For questions or bug reports, open an issue on the [GitHub issue tracker](https://github.com/gabrielbg0/Minerva-OPT/issues).
@@ -0,0 +1,3 @@
1
+ from minerva_opt.pipelines.hyperparameter_search import RayHyperParameterSearch
2
+
3
+ __all__ = ["RayHyperParameterSearch"]
@@ -0,0 +1,9 @@
1
+ from minerva_opt.callbacks.ray_callbacks import (
2
+ TrainerReportKeepOnlyLastCallback,
3
+ TrainerReportOnIntervalCallback,
4
+ )
5
+
6
+ __all__ = [
7
+ "TrainerReportKeepOnlyLastCallback",
8
+ "TrainerReportOnIntervalCallback",
9
+ ]
@@ -0,0 +1,89 @@
1
+ import os
2
+ import shutil
3
+ import tempfile
4
+ from pathlib import Path
5
+
6
+ import lightning.pytorch as L
7
+ from ray import train
8
+ from ray._common.usage.usage_lib import TagKey, record_extra_usage_tag
9
+ from ray.train import Checkpoint
10
+
11
+
12
+ class TrainerReportOnIntervalCallback(L.Callback):
13
+
14
+ CHECKPOINT_NAME = "checkpoint.ckpt"
15
+
16
+ def __init__(self, interval: int = 1) -> None:
17
+ super().__init__()
18
+ self.trial_name = train.get_context().get_trial_name()
19
+ self.local_rank = train.get_context().get_local_rank()
20
+ self.tmpdir_prefix = Path(tempfile.gettempdir(), self.trial_name).as_posix()
21
+ self.interval = interval
22
+ self.step = 0
23
+ if os.path.isdir(self.tmpdir_prefix) and self.local_rank == 0:
24
+ shutil.rmtree(self.tmpdir_prefix)
25
+
26
+ record_extra_usage_tag(TagKey.TRAIN_LIGHTNING_RAYTRAINREPORTCALLBACK, "1")
27
+
28
+ def on_train_epoch_end(self, trainer: L.Trainer, pl_module: L.LightningModule) -> None:
29
+ metrics = trainer.callback_metrics
30
+ metrics = {k: v.item() for k, v in metrics.items()}
31
+ metrics["epoch"] = trainer.current_epoch
32
+ metrics["step"] = trainer.global_step
33
+
34
+ tmpdir = Path(self.tmpdir_prefix, str(trainer.current_epoch)).as_posix()
35
+ os.makedirs(tmpdir, exist_ok=True)
36
+
37
+ if self.step % self.interval == 0:
38
+ ckpt_path = Path(tmpdir, self.CHECKPOINT_NAME).as_posix()
39
+ trainer.save_checkpoint(ckpt_path, weights_only=False)
40
+ checkpoint = Checkpoint.from_directory(tmpdir)
41
+ train.report(metrics=metrics, checkpoint=checkpoint)
42
+ else:
43
+ train.report(metrics=metrics)
44
+
45
+ trainer.strategy.barrier()
46
+
47
+ if self.local_rank == 0:
48
+ shutil.rmtree(tmpdir)
49
+
50
+ self.step += 1
51
+
52
+
53
+ class TrainerReportKeepOnlyLastCallback(L.Callback):
54
+
55
+ CHECKPOINT_NAME = "checkpoint.ckpt"
56
+
57
+ def __init__(self) -> None:
58
+ super().__init__()
59
+ self.trial_name = train.get_context().get_trial_name()
60
+ self.local_rank = train.get_context().get_local_rank()
61
+ self.tmpdir_prefix = Path(tempfile.gettempdir(), self.trial_name).as_posix()
62
+ if os.path.isdir(self.tmpdir_prefix) and self.local_rank == 0:
63
+ shutil.rmtree(self.tmpdir_prefix)
64
+
65
+ record_extra_usage_tag(TagKey.TRAIN_LIGHTNING_RAYTRAINREPORTCALLBACK, "1")
66
+
67
+ def on_train_epoch_end(self, trainer: L.Trainer, pl_module: L.LightningModule) -> None:
68
+ metrics = trainer.callback_metrics
69
+ metrics = {k: v.item() for k, v in metrics.items()}
70
+ metrics["epoch"] = trainer.current_epoch
71
+ metrics["step"] = trainer.global_step
72
+
73
+ tmpdir = Path(self.tmpdir_prefix, "last").as_posix()
74
+
75
+ # Delete previous epoch's checkpoint before writing the new one
76
+ if os.path.isdir(tmpdir):
77
+ shutil.rmtree(tmpdir)
78
+ os.makedirs(tmpdir, exist_ok=True)
79
+
80
+ ckpt_path = Path(tmpdir, self.CHECKPOINT_NAME).as_posix()
81
+ trainer.save_checkpoint(ckpt_path, weights_only=False)
82
+
83
+ checkpoint = Checkpoint.from_directory(tmpdir)
84
+ train.report(metrics=metrics, checkpoint=checkpoint)
85
+
86
+ trainer.strategy.barrier()
87
+
88
+ if self.local_rank == 0:
89
+ shutil.rmtree(tmpdir)
@@ -0,0 +1,3 @@
1
+ from minerva_opt.pipelines.hyperparameter_search import RayHyperParameterSearch
2
+
3
+ __all__ = ["RayHyperParameterSearch"]
@@ -0,0 +1,154 @@
1
+ from copy import deepcopy
2
+ from typing import Any, Dict, List, Literal, Optional
3
+
4
+ import lightning.pytorch as L
5
+ from lightning.pytorch.strategies import Strategy
6
+ from ray import tune
7
+ from ray.train import CheckpointConfig, RunConfig, ScalingConfig
8
+ from ray.train.lightning import RayDDPStrategy, RayLightningEnvironment, prepare_trainer
9
+ from ray.train.torch import TorchTrainer
10
+ from ray.tune.result_grid import ResultGrid
11
+ from ray.tune.schedulers import ASHAScheduler, TrialScheduler
12
+ from ray.tune.search import ConcurrencyLimiter
13
+ from ray.tune.search.searcher import Searcher
14
+
15
+ from minerva.pipelines.base import Pipeline
16
+ from minerva.utils.typing import PathLike
17
+ from minerva_opt.callbacks.ray_callbacks import TrainerReportOnIntervalCallback
18
+
19
+
20
+ class RayHyperParameterSearch(Pipeline):
21
+ """Hyperparameter search pipeline using Ray Tune and PyTorch Lightning.
22
+
23
+ Supports any Ray Tune search algorithm via the `search_alg` parameter in
24
+ `_search`. When no algorithm is provided, Ray's default random/grid search
25
+ is used. To use Bayesian optimization, pass a `HyperOptSearch` instance.
26
+ """
27
+
28
+ def __init__(
29
+ self,
30
+ model: type,
31
+ search_space: Dict[str, Any],
32
+ log_dir: Optional[PathLike] = None,
33
+ save_run_status: bool = True,
34
+ seed: Optional[int] = None,
35
+ ):
36
+ super().__init__(log_dir=log_dir, save_run_status=save_run_status, seed=seed)
37
+ self.model = model
38
+ self.search_space = search_space
39
+
40
+ def _search(
41
+ self,
42
+ data: L.LightningDataModule,
43
+ ckpt_path: Optional[PathLike],
44
+ devices: str = "auto",
45
+ accelerator: str = "auto",
46
+ strategy: Optional[Strategy] = None,
47
+ callbacks: Optional[List[Any]] = None,
48
+ plugins: Optional[List[Any]] = None,
49
+ num_nodes: int = 1,
50
+ debug_mode: bool = False,
51
+ scaling_config: Optional[ScalingConfig] = None,
52
+ run_config: Optional[RunConfig] = None,
53
+ tuner_metric: str = "val_loss",
54
+ tuner_mode: str = "min",
55
+ num_samples: int = 10,
56
+ scheduler: Optional[TrialScheduler] = None,
57
+ search_alg: Optional[Searcher] = None,
58
+ max_concurrent: int = 4,
59
+ max_epochs: int = 100,
60
+ checkpoint_interval: int = 1,
61
+ ) -> ResultGrid:
62
+
63
+ def _train_func(config):
64
+ dm = deepcopy(data)
65
+ model = self.model(**config)
66
+ trainer = L.Trainer(
67
+ max_epochs=max_epochs,
68
+ devices=devices,
69
+ accelerator=accelerator,
70
+ strategy=strategy or RayDDPStrategy(find_unused_parameters=True),
71
+ callbacks=callbacks or [TrainerReportOnIntervalCallback(checkpoint_interval)],
72
+ plugins=plugins or [RayLightningEnvironment()],
73
+ enable_progress_bar=False,
74
+ num_nodes=num_nodes,
75
+ enable_checkpointing=False if debug_mode else None,
76
+ )
77
+ trainer = prepare_trainer(trainer)
78
+ trainer.fit(model, dm, ckpt_path=ckpt_path)
79
+
80
+ scheduler = scheduler or ASHAScheduler(
81
+ time_attr="training_iteration",
82
+ metric=tuner_metric,
83
+ mode=tuner_mode,
84
+ max_t=max_epochs,
85
+ grace_period=max(1, max_epochs // 10),
86
+ )
87
+
88
+ scaling_config = scaling_config or ScalingConfig(
89
+ num_workers=1, use_gpu=True, resources_per_worker={"GPU": 1}
90
+ )
91
+
92
+ run_config = run_config or RunConfig(
93
+ checkpoint_config=CheckpointConfig(
94
+ num_to_keep=1,
95
+ checkpoint_score_attribute=tuner_metric,
96
+ checkpoint_score_order=tuner_mode,
97
+ )
98
+ )
99
+
100
+ if search_alg is not None:
101
+ search_alg = ConcurrencyLimiter(search_alg, max_concurrent=max_concurrent)
102
+
103
+ ray_trainer = TorchTrainer(
104
+ _train_func,
105
+ scaling_config=scaling_config,
106
+ run_config=run_config,
107
+ )
108
+
109
+ tuner = tune.Tuner(
110
+ ray_trainer,
111
+ param_space={"train_loop_config": self.search_space},
112
+ tune_config=tune.TuneConfig(
113
+ metric=tuner_metric,
114
+ mode=tuner_mode,
115
+ num_samples=num_samples,
116
+ scheduler=scheduler,
117
+ search_alg=search_alg,
118
+ ),
119
+ )
120
+
121
+ results = tuner.fit()
122
+ best = results.get_best_result()
123
+ print(f"Best config: {best.config}")
124
+ print(f"Best {tuner_metric}: {best.metrics.get(tuner_metric)}")
125
+ return results
126
+
127
+ def _test(self, data: L.LightningDataModule, ckpt_path: Optional[PathLike]) -> Any:
128
+ raise NotImplementedError(
129
+ "Load the best checkpoint from the ResultGrid returned by _search "
130
+ "and call trainer.test() directly."
131
+ )
132
+
133
+ def _run(
134
+ self,
135
+ data: L.LightningDataModule,
136
+ task: Optional[Literal["search", "test"]] = None,
137
+ ckpt_path: Optional[PathLike] = None,
138
+ **kwargs,
139
+ ) -> Any:
140
+ if task == "search" or task is None:
141
+ return self._search(data, ckpt_path, **kwargs)
142
+ elif task == "test":
143
+ return self._test(data, ckpt_path)
144
+
145
+
146
+ def main():
147
+ from jsonargparse import CLI
148
+
149
+ print("Hyper Searching")
150
+ CLI(RayHyperParameterSearch, as_positional=False)
151
+
152
+
153
+ if __name__ == "__main__":
154
+ main()
@@ -0,0 +1,141 @@
1
+ Metadata-Version: 2.4
2
+ Name: minerva-opt
3
+ Version: 1.0.0
4
+ Summary: Hyperparameter optimization extensions for Minerva.
5
+ Author-email: Gabriel Gutierrez <gabriel.bgs00@gmail.com>
6
+ Project-URL: Bug Tracker, https://github.com/gabrielbg0/Minerva-OPT/issues
7
+ Project-URL: Homepage, https://github.com/gabrielbg0/Minerva-OPT
8
+ Keywords: Deep Learning,Hyperparameter Optimization,Machine Learning,Pytorch,Ray Tune,Research
9
+ Classifier: License :: OSI Approved :: MIT License
10
+ Classifier: Programming Language :: Python
11
+ Classifier: Programming Language :: Python :: 3
12
+ Classifier: Development Status :: 3 - Alpha
13
+ Classifier: Intended Audience :: Science/Research
14
+ Classifier: Operating System :: OS Independent
15
+ Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
16
+ Requires-Python: >=3.10
17
+ Description-Content-Type: text/markdown
18
+ Requires-Dist: minerva==0.3.10-beta
19
+ Requires-Dist: ray[tune]>=2.55
20
+ Requires-Dist: hyperopt>=0.2.7
21
+ Provides-Extra: dev
22
+ Requires-Dist: black; extra == "dev"
23
+ Requires-Dist: flake8; extra == "dev"
24
+ Requires-Dist: pytest; extra == "dev"
25
+ Requires-Dist: pytest-coverage; extra == "dev"
26
+
27
+ # Minerva-OPT
28
+
29
+ [![Auto Release](https://github.com/gabrielbg0/Minerva-OPT/actions/workflows/auto-release.yml/badge.svg)](https://github.com/gabrielbg0/Minerva-OPT/actions/workflows/auto-release.yml)
30
+
31
+ Hyperparameter optimization extensions for [Minerva](https://github.com/discovery-unicamp/Minerva), powered by [Ray Tune](https://docs.ray.io/en/latest/tune/index.html).
32
+
33
+ ## Description
34
+
35
+ Minerva-OPT provides a `RayHyperParameterSearch` pipeline that wraps Ray Tune and PyTorch Lightning to run distributed hyperparameter searches on top of any Minerva-compatible model. It supports random search, grid search, and Bayesian optimization (via HyperOpt), with early stopping through the ASHA scheduler.
36
+
37
+ ### Features
38
+
39
+ - **Drop-in Minerva pipeline**: inherits from `minerva.pipelines.base.Pipeline`, so it integrates with Minerva's logging, reproducibility, and run-status tracking out of the box.
40
+ - **Flexible search algorithms**: use Ray Tune's default random/grid search or pass any `ray.tune.search.Searcher` (e.g. `HyperOptSearch` for Bayesian optimization).
41
+ - **ASHA early stopping**: trials are stopped early based on intermediate results; `grace_period` and `max_t` are derived automatically from `max_epochs`.
42
+ - **Distributed training**: uses `RayDDPStrategy` and `RayLightningEnvironment` for multi-worker trials.
43
+ - **Checkpointing**: keeps only the best checkpoint per trial, scored on the target metric.
44
+
45
+ ## Installation
46
+
47
+ Requires Python 3.10+.
48
+
49
+ ### With uv (recommended)
50
+
51
+ ```bash
52
+ uv pip install minerva-opt
53
+ ```
54
+
55
+ ### With pip
56
+
57
+ ```bash
58
+ pip install minerva-opt
59
+ ```
60
+
61
+ ## Usage
62
+
63
+ ### Random / grid search
64
+
65
+ ```python
66
+ from ray import tune
67
+ from minerva_opt.pipelines.hyperparameter_search import RayHyperParameterSearch
68
+
69
+ search_space = {
70
+ "learning_rate": tune.loguniform(1e-4, 1e-1),
71
+ "hidden_size": tune.choice([64, 128, 256]),
72
+ }
73
+
74
+ pipeline = RayHyperParameterSearch(
75
+ model=MyLightningModel, # class, not instance — instantiated per trial as MyLightningModel(**config)
76
+ search_space=search_space,
77
+ log_dir="logs/",
78
+ )
79
+
80
+ results = pipeline.run(data=my_data_module, num_samples=20, max_epochs=50)
81
+ best = results.get_best_result()
82
+ print(best.config)
83
+ ```
84
+
85
+ ### Bayesian optimization with HyperOpt
86
+
87
+ ```python
88
+ from ray.tune.search.hyperopt import HyperOptSearch
89
+ from hyperopt import hp
90
+
91
+ search_space = {
92
+ "learning_rate": tune.loguniform(1e-4, 1e-1),
93
+ "dropout": tune.uniform(0.1, 0.5),
94
+ }
95
+
96
+ pipeline = RayHyperParameterSearch(
97
+ model=MyLightningModel,
98
+ search_space=search_space,
99
+ )
100
+
101
+ results = pipeline.run(
102
+ data=my_data_module,
103
+ search_alg=HyperOptSearch(),
104
+ num_samples=30,
105
+ max_epochs=100,
106
+ tuner_metric="val_loss",
107
+ tuner_mode="min",
108
+ )
109
+ ```
110
+
111
+ ### Key `run()` parameters
112
+
113
+ | Parameter | Default | Description |
114
+ | --------------------- | ------------ | ------------------------------------------------------ |
115
+ | `data` | — | `LightningDataModule` to train on |
116
+ | `task` | `"search"` | `"search"` to run the sweep |
117
+ | `ckpt_path` | `None` | Resume training from a checkpoint |
118
+ | `num_samples` | `10` | Number of trials to run |
119
+ | `max_epochs` | `100` | Max epochs per trial |
120
+ | `tuner_metric` | `"val_loss"` | Metric to optimize |
121
+ | `tuner_mode` | `"min"` | `"min"` or `"max"` |
122
+ | `search_alg` | `None` | Any `ray.tune.search.Searcher`; `None` = random search |
123
+ | `max_concurrent` | `4` | Max concurrent trials (when using a `search_alg`) |
124
+ | `scheduler` | ASHA | Override the trial scheduler |
125
+ | `scaling_config` | 1 GPU/worker | Override Ray `ScalingConfig` |
126
+ | `checkpoint_interval` | `1` | Save a checkpoint every N epochs |
127
+ | `debug_mode` | `False` | Disable checkpointing for fast iteration |
128
+
129
+ ## Requirements
130
+
131
+ - `minerva >= 0.3.10b0`
132
+ - `ray[tune] >= 2.55`
133
+ - `hyperopt >= 0.2.7`
134
+
135
+ ## License
136
+
137
+ MIT License. See [LICENSE](LICENSE) for details.
138
+
139
+ ## Contact
140
+
141
+ For questions or bug reports, open an issue on the [GitHub issue tracker](https://github.com/gabrielbg0/Minerva-OPT/issues).
@@ -0,0 +1,12 @@
1
+ README.md
2
+ pyproject.toml
3
+ minerva_opt/__init__.py
4
+ minerva_opt.egg-info/PKG-INFO
5
+ minerva_opt.egg-info/SOURCES.txt
6
+ minerva_opt.egg-info/dependency_links.txt
7
+ minerva_opt.egg-info/requires.txt
8
+ minerva_opt.egg-info/top_level.txt
9
+ minerva_opt/callbacks/__init__.py
10
+ minerva_opt/callbacks/ray_callbacks.py
11
+ minerva_opt/pipelines/__init__.py
12
+ minerva_opt/pipelines/hyperparameter_search.py
@@ -0,0 +1,9 @@
1
+ minerva==0.3.10-beta
2
+ ray[tune]>=2.55
3
+ hyperopt>=0.2.7
4
+
5
+ [dev]
6
+ black
7
+ flake8
8
+ pytest
9
+ pytest-coverage
@@ -0,0 +1 @@
1
+ minerva_opt
@@ -0,0 +1,53 @@
1
+ [build-system]
2
+ build-backend = "setuptools.build_meta"
3
+ requires = ["setuptools>=82.0.1"]
4
+
5
+ [project]
6
+ authors = [
7
+ { name = "Gabriel Gutierrez", email = "gabriel.bgs00@gmail.com" },
8
+ ]
9
+ classifiers = [
10
+ "License :: OSI Approved :: MIT License",
11
+ "Programming Language :: Python",
12
+ "Programming Language :: Python :: 3",
13
+ "Development Status :: 3 - Alpha",
14
+ "Intended Audience :: Science/Research",
15
+ "Operating System :: OS Independent",
16
+ "Topic :: Scientific/Engineering :: Artificial Intelligence",
17
+ ]
18
+ description = "Hyperparameter optimization extensions for Minerva."
19
+ keywords = [
20
+ "Deep Learning",
21
+ "Hyperparameter Optimization",
22
+ "Machine Learning",
23
+ "Pytorch",
24
+ "Ray Tune",
25
+ "Research",
26
+ ]
27
+ license = { file = "LICENSE" }
28
+ name = "minerva-opt"
29
+ readme = "README.md"
30
+ requires-python = ">=3.10"
31
+ version = "1.0.0"
32
+
33
+ dependencies = [
34
+ "minerva==0.3.10-beta",
35
+ "ray[tune]>=2.55",
36
+ "hyperopt>=0.2.7",
37
+ ]
38
+
39
+ [tool.setuptools.packages.find]
40
+ where = ["."]
41
+ include = ["minerva_opt*"]
42
+
43
+ [project.optional-dependencies]
44
+ dev = [
45
+ "black",
46
+ "flake8",
47
+ "pytest",
48
+ "pytest-coverage",
49
+ ]
50
+
51
+ [project.urls]
52
+ "Bug Tracker" = "https://github.com/gabrielbg0/Minerva-OPT/issues"
53
+ "Homepage" = "https://github.com/gabrielbg0/Minerva-OPT"
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+