jsonify-optuna 0.1.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.
- jsonify_optuna-0.1.0/.gitignore +7 -0
- jsonify_optuna-0.1.0/.python-version +1 -0
- jsonify_optuna-0.1.0/PKG-INFO +102 -0
- jsonify_optuna-0.1.0/README.md +94 -0
- jsonify_optuna-0.1.0/examples/basic_jsonify.py +22 -0
- jsonify_optuna-0.1.0/examples/filter_and_attrs.py +36 -0
- jsonify_optuna-0.1.0/examples/load_study_example.py +45 -0
- jsonify_optuna-0.1.0/examples/multi_objective.py +30 -0
- jsonify_optuna-0.1.0/jsonify_optuna/__init__.py +5 -0
- jsonify_optuna-0.1.0/jsonify_optuna/jsonify_optuna.py +109 -0
- jsonify_optuna-0.1.0/pip-publish.sh +3 -0
- jsonify_optuna-0.1.0/pyproject.toml +43 -0
- jsonify_optuna-0.1.0/tests/__init__.py +0 -0
- jsonify_optuna-0.1.0/tests/conftest.py +6 -0
- jsonify_optuna-0.1.0/tests/test_jsonify.py +209 -0
- jsonify_optuna-0.1.0/tests/test_load_study.py +92 -0
- jsonify_optuna-0.1.0/uv.lock +1237 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
3.13
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: jsonify-optuna
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Convert an Optuna Study into a JSON-serializable dict.
|
|
5
|
+
Requires-Python: >=3.9
|
|
6
|
+
Requires-Dist: optuna>=4.9.0
|
|
7
|
+
Description-Content-Type: text/markdown
|
|
8
|
+
|
|
9
|
+
# jsonify-optuna
|
|
10
|
+
|
|
11
|
+
Convert an [Optuna](https://github.com/optuna/optuna) Study into a plain, JSON-serializable Python dict.
|
|
12
|
+
|
|
13
|
+
## Installation
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
pip install jsonify-optuna
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
## Usage
|
|
20
|
+
|
|
21
|
+
Convert an in-memory study to a JSON-friendly dict:
|
|
22
|
+
|
|
23
|
+
```python
|
|
24
|
+
import optuna
|
|
25
|
+
from jsonify_optuna import jsonify
|
|
26
|
+
from optuna.trial import TrialState
|
|
27
|
+
|
|
28
|
+
def objective(trial):
|
|
29
|
+
x = trial.suggest_float("x", -10.0, 10.0)
|
|
30
|
+
return x ** 2
|
|
31
|
+
|
|
32
|
+
study = optuna.create_study(direction="minimize")
|
|
33
|
+
study.optimize(objective, n_trials=20)
|
|
34
|
+
result = jsonify(study, states=[TrialState.COMPLETE])
|
|
35
|
+
# This includes all the trials.
|
|
36
|
+
result = jsonify(study)
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
If you have a study stored in a backend, you can load it as follows:
|
|
40
|
+
|
|
41
|
+
```python
|
|
42
|
+
from jsonify_optuna import load_study
|
|
43
|
+
|
|
44
|
+
# From an RDB (SQLite, PostgreSQL, etc.)
|
|
45
|
+
study = load_study(rdb_url="sqlite:///example.db", study_name="my_study")
|
|
46
|
+
|
|
47
|
+
# From a journal file
|
|
48
|
+
study = load_study(journal_path="journal.log", study_name="my_study")
|
|
49
|
+
|
|
50
|
+
# From a storage object directly
|
|
51
|
+
study = load_study(storage=my_storage, study_name="my_study")
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
> [!NOTE]
|
|
55
|
+
> When the storage contains exactly one study, `study_name` can be omitted.
|
|
56
|
+
|
|
57
|
+
## API Reference
|
|
58
|
+
|
|
59
|
+
### `jsonify(study, *, states=None, deepcopy=True)`
|
|
60
|
+
|
|
61
|
+
| Parameter | Type | Description |
|
|
62
|
+
|-----------|------|-------------|
|
|
63
|
+
| `study` | `optuna.Study` | The study to convert. |
|
|
64
|
+
| `states` | `list[TrialState] \| None` | Filter trials by state. `None` includes all states. |
|
|
65
|
+
| `deepcopy` | `bool` | Whether to deep-copy trials from storage. Default `True`. |
|
|
66
|
+
|
|
67
|
+
Returns a dict with:
|
|
68
|
+
|
|
69
|
+
| Key | Type | Description |
|
|
70
|
+
|-----|------|-------------|
|
|
71
|
+
| `directions` | `list[str]` | `"minimize"` or `"maximize"` per objective. |
|
|
72
|
+
| `user_attrs` | `dict` | Study-level user attributes. |
|
|
73
|
+
| `metric_names` | `list[str] \| None` | Metric names if set, else `None`. |
|
|
74
|
+
| `trials` | `list[dict]` | Trial dicts (see below). |
|
|
75
|
+
| `best_trial_indices` | `list[int]` | Indices into `trials` for Pareto-front trials. |
|
|
76
|
+
|
|
77
|
+
Each trial dict contains:
|
|
78
|
+
|
|
79
|
+
| Key | Type | Description |
|
|
80
|
+
|-----|------|-------------|
|
|
81
|
+
| `state` | `str` | `"complete"`, `"pruned"`, `"fail"`, `"running"`, or `"waiting"`. |
|
|
82
|
+
| `values` | `list[float] \| None` | Objective values. `None` if not complete. |
|
|
83
|
+
| `params` | `dict` | Parameter name-value pairs. |
|
|
84
|
+
| `user_attrs` | `dict` | Trial-level user attributes. |
|
|
85
|
+
| `intermediate_values` | `dict[int, float]` | Step-value pairs from `trial.report()`. |
|
|
86
|
+
| `distributions` | `dict` | Parameter distributions (see below). |
|
|
87
|
+
|
|
88
|
+
Distribution formats:
|
|
89
|
+
|
|
90
|
+
- **Int/Float**: `{"low": ..., "high": ..., "step": ..., "log": ...}`
|
|
91
|
+
- **Categorical**: `{"choices": [...]}`
|
|
92
|
+
|
|
93
|
+
### `load_study(*, study_name=None, storage=None, journal_path=None, rdb_url=None)`
|
|
94
|
+
|
|
95
|
+
| Parameter | Type | Description |
|
|
96
|
+
|-----------|------|-------------|
|
|
97
|
+
| `study_name` | `str \| None` | Study name. Optional when storage has exactly one study. |
|
|
98
|
+
| `storage` | `BaseStorage \| None` | An Optuna storage object. |
|
|
99
|
+
| `journal_path` | `str \| None` | Path to a journal log file. |
|
|
100
|
+
| `rdb_url` | `str \| None` | SQLAlchemy-style database URL. |
|
|
101
|
+
|
|
102
|
+
Exactly one of `storage`, `journal_path`, or `rdb_url` must be provided.
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
# jsonify-optuna
|
|
2
|
+
|
|
3
|
+
Convert an [Optuna](https://github.com/optuna/optuna) Study into a plain, JSON-serializable Python dict.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
pip install jsonify-optuna
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Usage
|
|
12
|
+
|
|
13
|
+
Convert an in-memory study to a JSON-friendly dict:
|
|
14
|
+
|
|
15
|
+
```python
|
|
16
|
+
import optuna
|
|
17
|
+
from jsonify_optuna import jsonify
|
|
18
|
+
from optuna.trial import TrialState
|
|
19
|
+
|
|
20
|
+
def objective(trial):
|
|
21
|
+
x = trial.suggest_float("x", -10.0, 10.0)
|
|
22
|
+
return x ** 2
|
|
23
|
+
|
|
24
|
+
study = optuna.create_study(direction="minimize")
|
|
25
|
+
study.optimize(objective, n_trials=20)
|
|
26
|
+
result = jsonify(study, states=[TrialState.COMPLETE])
|
|
27
|
+
# This includes all the trials.
|
|
28
|
+
result = jsonify(study)
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
If you have a study stored in a backend, you can load it as follows:
|
|
32
|
+
|
|
33
|
+
```python
|
|
34
|
+
from jsonify_optuna import load_study
|
|
35
|
+
|
|
36
|
+
# From an RDB (SQLite, PostgreSQL, etc.)
|
|
37
|
+
study = load_study(rdb_url="sqlite:///example.db", study_name="my_study")
|
|
38
|
+
|
|
39
|
+
# From a journal file
|
|
40
|
+
study = load_study(journal_path="journal.log", study_name="my_study")
|
|
41
|
+
|
|
42
|
+
# From a storage object directly
|
|
43
|
+
study = load_study(storage=my_storage, study_name="my_study")
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
> [!NOTE]
|
|
47
|
+
> When the storage contains exactly one study, `study_name` can be omitted.
|
|
48
|
+
|
|
49
|
+
## API Reference
|
|
50
|
+
|
|
51
|
+
### `jsonify(study, *, states=None, deepcopy=True)`
|
|
52
|
+
|
|
53
|
+
| Parameter | Type | Description |
|
|
54
|
+
|-----------|------|-------------|
|
|
55
|
+
| `study` | `optuna.Study` | The study to convert. |
|
|
56
|
+
| `states` | `list[TrialState] \| None` | Filter trials by state. `None` includes all states. |
|
|
57
|
+
| `deepcopy` | `bool` | Whether to deep-copy trials from storage. Default `True`. |
|
|
58
|
+
|
|
59
|
+
Returns a dict with:
|
|
60
|
+
|
|
61
|
+
| Key | Type | Description |
|
|
62
|
+
|-----|------|-------------|
|
|
63
|
+
| `directions` | `list[str]` | `"minimize"` or `"maximize"` per objective. |
|
|
64
|
+
| `user_attrs` | `dict` | Study-level user attributes. |
|
|
65
|
+
| `metric_names` | `list[str] \| None` | Metric names if set, else `None`. |
|
|
66
|
+
| `trials` | `list[dict]` | Trial dicts (see below). |
|
|
67
|
+
| `best_trial_indices` | `list[int]` | Indices into `trials` for Pareto-front trials. |
|
|
68
|
+
|
|
69
|
+
Each trial dict contains:
|
|
70
|
+
|
|
71
|
+
| Key | Type | Description |
|
|
72
|
+
|-----|------|-------------|
|
|
73
|
+
| `state` | `str` | `"complete"`, `"pruned"`, `"fail"`, `"running"`, or `"waiting"`. |
|
|
74
|
+
| `values` | `list[float] \| None` | Objective values. `None` if not complete. |
|
|
75
|
+
| `params` | `dict` | Parameter name-value pairs. |
|
|
76
|
+
| `user_attrs` | `dict` | Trial-level user attributes. |
|
|
77
|
+
| `intermediate_values` | `dict[int, float]` | Step-value pairs from `trial.report()`. |
|
|
78
|
+
| `distributions` | `dict` | Parameter distributions (see below). |
|
|
79
|
+
|
|
80
|
+
Distribution formats:
|
|
81
|
+
|
|
82
|
+
- **Int/Float**: `{"low": ..., "high": ..., "step": ..., "log": ...}`
|
|
83
|
+
- **Categorical**: `{"choices": [...]}`
|
|
84
|
+
|
|
85
|
+
### `load_study(*, study_name=None, storage=None, journal_path=None, rdb_url=None)`
|
|
86
|
+
|
|
87
|
+
| Parameter | Type | Description |
|
|
88
|
+
|-----------|------|-------------|
|
|
89
|
+
| `study_name` | `str \| None` | Study name. Optional when storage has exactly one study. |
|
|
90
|
+
| `storage` | `BaseStorage \| None` | An Optuna storage object. |
|
|
91
|
+
| `journal_path` | `str \| None` | Path to a journal log file. |
|
|
92
|
+
| `rdb_url` | `str \| None` | SQLAlchemy-style database URL. |
|
|
93
|
+
|
|
94
|
+
Exactly one of `storage`, `journal_path`, or `rdb_url` must be provided.
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import json
|
|
4
|
+
|
|
5
|
+
import optuna
|
|
6
|
+
|
|
7
|
+
from jsonify_optuna import jsonify
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
def objective(trial: optuna.Trial) -> float:
|
|
11
|
+
x = trial.suggest_float("x", -10.0, 10.0)
|
|
12
|
+
y = trial.suggest_int("y", 1, 5)
|
|
13
|
+
return (x - 2) ** 2 + y
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
if __name__ == "__main__":
|
|
17
|
+
optuna.logging.set_verbosity(optuna.logging.WARNING)
|
|
18
|
+
study = optuna.create_study(direction="minimize")
|
|
19
|
+
study.optimize(objective, n_trials=20)
|
|
20
|
+
|
|
21
|
+
result = jsonify(study)
|
|
22
|
+
print(json.dumps(result, indent=2))
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import json
|
|
4
|
+
|
|
5
|
+
import optuna
|
|
6
|
+
from optuna.trial import TrialState
|
|
7
|
+
|
|
8
|
+
from jsonify_optuna import jsonify
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
def objective(trial: optuna.Trial) -> float:
|
|
12
|
+
x = trial.suggest_float("x", 0.0, 10.0)
|
|
13
|
+
trial.set_user_attr("note", f"trial {trial.number}")
|
|
14
|
+
for step in range(5):
|
|
15
|
+
intermediate = x + step
|
|
16
|
+
trial.report(intermediate, step)
|
|
17
|
+
if trial.should_prune():
|
|
18
|
+
raise optuna.TrialPruned()
|
|
19
|
+
return x**2
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
if __name__ == "__main__":
|
|
23
|
+
optuna.logging.set_verbosity(optuna.logging.WARNING)
|
|
24
|
+
study = optuna.create_study(
|
|
25
|
+
direction="minimize", pruner=optuna.pruners.MedianPruner()
|
|
26
|
+
)
|
|
27
|
+
study.set_user_attr("experiment", "demo")
|
|
28
|
+
study.optimize(objective, n_trials=20)
|
|
29
|
+
|
|
30
|
+
complete_only = jsonify(study, states=[TrialState.COMPLETE])
|
|
31
|
+
print(f"Study user_attrs: {complete_only['user_attrs']}")
|
|
32
|
+
print(f"Complete trials: {len(complete_only['trials'])}")
|
|
33
|
+
print(json.dumps(complete_only, indent=2))
|
|
34
|
+
|
|
35
|
+
pruned_only = jsonify(study, states=[TrialState.PRUNED])
|
|
36
|
+
print(f"\nPruned trials: {len(pruned_only['trials'])}")
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import json
|
|
4
|
+
from pathlib import Path
|
|
5
|
+
import tempfile
|
|
6
|
+
|
|
7
|
+
import optuna
|
|
8
|
+
|
|
9
|
+
from jsonify_optuna import jsonify
|
|
10
|
+
from jsonify_optuna import load_study
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
def objective(trial: optuna.Trial) -> float:
|
|
14
|
+
x = trial.suggest_float("x", -5.0, 5.0)
|
|
15
|
+
return x**2
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
if __name__ == "__main__":
|
|
19
|
+
optuna.logging.set_verbosity(optuna.logging.WARNING)
|
|
20
|
+
|
|
21
|
+
with tempfile.TemporaryDirectory() as tmpdir:
|
|
22
|
+
db_path = Path(tmpdir) / "example.db"
|
|
23
|
+
rdb_url = f"sqlite:///{db_path}"
|
|
24
|
+
study = optuna.create_study(
|
|
25
|
+
storage=rdb_url, study_name="rdb_demo", direction="minimize"
|
|
26
|
+
)
|
|
27
|
+
study.optimize(objective, n_trials=10)
|
|
28
|
+
|
|
29
|
+
loaded = load_study(rdb_url=rdb_url, study_name="rdb_demo")
|
|
30
|
+
print("=== RDB storage ===")
|
|
31
|
+
print(json.dumps(jsonify(loaded), indent=2))
|
|
32
|
+
|
|
33
|
+
journal_path = str(Path(tmpdir) / "journal.log")
|
|
34
|
+
backend = optuna.storages.journal.JournalFileBackend(journal_path)
|
|
35
|
+
storage = optuna.storages.JournalStorage(backend)
|
|
36
|
+
study = optuna.create_study(
|
|
37
|
+
storage=storage, study_name="journal_demo", direction="minimize"
|
|
38
|
+
)
|
|
39
|
+
study.optimize(objective, n_trials=10)
|
|
40
|
+
|
|
41
|
+
loaded = load_study(
|
|
42
|
+
journal_path=journal_path, study_name="journal_demo"
|
|
43
|
+
)
|
|
44
|
+
print("\n=== Journal storage ===")
|
|
45
|
+
print(json.dumps(jsonify(loaded), indent=2))
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import json
|
|
4
|
+
|
|
5
|
+
import optuna
|
|
6
|
+
|
|
7
|
+
from jsonify_optuna import jsonify
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
def objective(trial: optuna.Trial) -> tuple[float, float]:
|
|
11
|
+
lr = trial.suggest_float("lr", 1e-5, 1e-1, log=True)
|
|
12
|
+
n_layers = trial.suggest_int("n_layers", 1, 4)
|
|
13
|
+
activation = trial.suggest_categorical("activation", ["relu", "tanh", "sigmoid"])
|
|
14
|
+
loss = lr * n_layers + (0.1 if activation == "relu" else 0.5)
|
|
15
|
+
accuracy = 1.0 - loss
|
|
16
|
+
return loss, accuracy
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
if __name__ == "__main__":
|
|
20
|
+
optuna.logging.set_verbosity(optuna.logging.WARNING)
|
|
21
|
+
study = optuna.create_study(directions=["minimize", "maximize"])
|
|
22
|
+
study.set_metric_names(["loss", "accuracy"])
|
|
23
|
+
study.optimize(objective, n_trials=30)
|
|
24
|
+
|
|
25
|
+
result = jsonify(study)
|
|
26
|
+
print(f"Directions: {result['directions']}")
|
|
27
|
+
print(f"Metric names: {result['metric_names']}")
|
|
28
|
+
print(f"Total trials: {len(result['trials'])}")
|
|
29
|
+
print(f"Pareto front size: {len(result['best_trial_indices'])}")
|
|
30
|
+
print(json.dumps(result, indent=2))
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from typing import TYPE_CHECKING
|
|
4
|
+
|
|
5
|
+
import optuna
|
|
6
|
+
from optuna.trial import TrialState
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
if TYPE_CHECKING:
|
|
10
|
+
from typing import Any
|
|
11
|
+
from typing import Literal
|
|
12
|
+
from typing import TypedDict
|
|
13
|
+
|
|
14
|
+
from optuna.distributions import CategoricalChoiceType
|
|
15
|
+
|
|
16
|
+
class NumericalDistributionType(TypedDict):
|
|
17
|
+
low: int | float
|
|
18
|
+
high: int | float
|
|
19
|
+
step: int | float | None
|
|
20
|
+
log: bool
|
|
21
|
+
|
|
22
|
+
class CategoricalDistributionType(TypedDict):
|
|
23
|
+
choices: list[CategoricalChoiceType]
|
|
24
|
+
|
|
25
|
+
class TrialType(TypedDict):
|
|
26
|
+
state: Literal["running", "waiting", "completepruned", "fail"]
|
|
27
|
+
values: list[float]
|
|
28
|
+
params: dict[str, int | float | CategoricalChoiceType]
|
|
29
|
+
user_attrs: dict[str, Any]
|
|
30
|
+
intermediate_values: list[float]
|
|
31
|
+
distributions: dict[str, NumericalDistributionType | CategoricalDistributionType]
|
|
32
|
+
|
|
33
|
+
class StudyType:
|
|
34
|
+
trials: list[TrialType]
|
|
35
|
+
best_trial_indices: list[int]
|
|
36
|
+
directions: list[Literal["minimize", "maximize"]]
|
|
37
|
+
user_attrs: dict[str, Any]
|
|
38
|
+
metric_names: list[str]
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
def jsonify(
|
|
42
|
+
study: optuna.Study, *, states: list[TrialState] | None = None, deepcopy: bool = True
|
|
43
|
+
) -> StudyType:
|
|
44
|
+
states = states or [state for state in TrialState]
|
|
45
|
+
study_json = {
|
|
46
|
+
"directions": [dire.name.lower() for dire in study.directions],
|
|
47
|
+
"user_attrs": study.user_attrs,
|
|
48
|
+
"metric_names": study.metric_names,
|
|
49
|
+
}
|
|
50
|
+
best_trial_numbers = set(t.number for t in study.best_trials)
|
|
51
|
+
best_trial_indices = []
|
|
52
|
+
results = []
|
|
53
|
+
for t in study.get_trials(deepcopy=deepcopy):
|
|
54
|
+
if t.state not in states:
|
|
55
|
+
continue
|
|
56
|
+
if t.number in best_trial_numbers:
|
|
57
|
+
best_trial_indices.append(len(results))
|
|
58
|
+
dists = {}
|
|
59
|
+
for p, d in t.distributions.items():
|
|
60
|
+
if isinstance(d, optuna.distributions.CategoricalDistribution):
|
|
61
|
+
dists[p] = {"choices": d.choices}
|
|
62
|
+
continue
|
|
63
|
+
assert isinstance(
|
|
64
|
+
d, (optuna.distributions.IntDistribution, optuna.distributions.FloatDistribution)
|
|
65
|
+
)
|
|
66
|
+
dists[p] = {"low": d.low, "high": d.high, "step": d.step, "log": d.log}
|
|
67
|
+
row = {
|
|
68
|
+
"state": t.state.name.lower(),
|
|
69
|
+
"values": t.values,
|
|
70
|
+
"params": t.params,
|
|
71
|
+
"user_attrs": t.user_attrs,
|
|
72
|
+
"intermediate_values": t.intermediate_values,
|
|
73
|
+
"distributions": dists,
|
|
74
|
+
}
|
|
75
|
+
results.append(row)
|
|
76
|
+
study_json |= {"trials": results, "best_trial_indices": best_trial_indices}
|
|
77
|
+
return study_json
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
def load_study(
|
|
81
|
+
*,
|
|
82
|
+
study_name: str | None = None,
|
|
83
|
+
storage: optuna.storages.BaseStorage | None = None,
|
|
84
|
+
journal_path: str | None = None,
|
|
85
|
+
rdb_url: str | None = None,
|
|
86
|
+
) -> optuna.Study:
|
|
87
|
+
if storage is not None:
|
|
88
|
+
if rdb_url is not None or journal_path is not None:
|
|
89
|
+
raise ValueError(
|
|
90
|
+
f"storage is provided but either {rdb_url=} or {journal_path=} is also specified."
|
|
91
|
+
)
|
|
92
|
+
elif rdb_url is not None:
|
|
93
|
+
if journal_path is not None:
|
|
94
|
+
raise ValueError(f"Specify only one of {rdb_url=} or {journal_path=}.")
|
|
95
|
+
storage = optuna.storages.RDBStorage(rdb_url)
|
|
96
|
+
elif journal_path:
|
|
97
|
+
journal_file = optuna.storages.journal.JournalFileBackend(journal_path)
|
|
98
|
+
storage = optuna.storages.JournalStorage(journal_file)
|
|
99
|
+
else:
|
|
100
|
+
raise ValueError("No storage was specified.")
|
|
101
|
+
assert isinstance(storage, optuna.storages.BaseStorage), "MyPy Redefinition"
|
|
102
|
+
study_names = [study.study_name for study in storage.get_all_studies()]
|
|
103
|
+
if study_name is None and len(study_names) == 1:
|
|
104
|
+
return optuna.load_study(storage=storage, study_name=study_names[0])
|
|
105
|
+
if study_name is None:
|
|
106
|
+
raise ValueError(f"Specify `study_name` from {study_names=}.")
|
|
107
|
+
if study_name not in study_names:
|
|
108
|
+
raise ValueError(f"Specify `study_name` from {study_names=} but got {study_name=}.")
|
|
109
|
+
return optuna.load_study(storage=storage, study_name=study_name)
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["hatchling"]
|
|
3
|
+
build-backend = "hatchling.build"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "jsonify-optuna"
|
|
7
|
+
version = "0.1.0"
|
|
8
|
+
description = "Convert an Optuna Study into a JSON-serializable dict."
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
requires-python = ">=3.9"
|
|
11
|
+
dependencies = [
|
|
12
|
+
"optuna>=4.9.0",
|
|
13
|
+
]
|
|
14
|
+
|
|
15
|
+
[dependency-groups]
|
|
16
|
+
dev = [
|
|
17
|
+
"mypy>=1.19.1",
|
|
18
|
+
"pytest>=8",
|
|
19
|
+
"ruff>=0.15.21",
|
|
20
|
+
]
|
|
21
|
+
|
|
22
|
+
[tool.pytest.ini_options]
|
|
23
|
+
testpaths = ["tests"]
|
|
24
|
+
|
|
25
|
+
[tool.ruff]
|
|
26
|
+
line-length = 99
|
|
27
|
+
target-version = "py39"
|
|
28
|
+
|
|
29
|
+
[tool.ruff.lint]
|
|
30
|
+
select = [
|
|
31
|
+
"E", # pycodestyle errors
|
|
32
|
+
"W", # pycodestyle warnings
|
|
33
|
+
"F", # pyflakes
|
|
34
|
+
"I", # isort
|
|
35
|
+
"TCH", # flake8 type checking
|
|
36
|
+
]
|
|
37
|
+
|
|
38
|
+
[tool.ruff.lint.isort]
|
|
39
|
+
known-first-party = ["jsonify_optuna", "tests"]
|
|
40
|
+
lines-after-imports = 2
|
|
41
|
+
force-single-line = true
|
|
42
|
+
force-sort-within-sections = true
|
|
43
|
+
order-by-type = false
|
|
File without changes
|