Skip to content

Commit 195d67b

Browse files
committed
Update evaluation pipeline
1 parent 74fe4a5 commit 195d67b

File tree

3 files changed

+25
-30
lines changed

3 files changed

+25
-30
lines changed

docs/reference/evaluate_pipeline.md

Lines changed: 21 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
> **TL;DR**
44
> *Sync*: return a scalar or a dict ⟶ NePS records it automatically.
5-
> *Async*: return `None`, launch a job, and call `neps.save_callback()` when the job finishes.
5+
> *Async*: return `None`, launch a job, and call `neps.save_pipeline_results()` when the job finishes.
66
77
---
88

@@ -57,7 +57,6 @@ All other values raise a `TypeError` inside NePS.
5757

5858
```python
5959
from pathlib import Path
60-
import subprocess
6160
import neps
6261

6362
def evaluate_pipeline(
@@ -67,9 +66,8 @@ def evaluate_pipeline(
6766
learning_rate: float,
6867
optimizer: str,
6968
):
70-
# 1) write a Slurm script into the trial dir
71-
sh = pipeline_directory / "run.sh"
72-
sh.write_text(f"""#!/bin/bash
69+
# 1) write a Slurm script
70+
script = f"""#!/bin/bash
7371
#SBATCH --time=0-00:10
7472
#SBATCH --job-name=trial_{pipeline_id}
7573
#SBATCH --partition=bosch_cpu-cascadelake
@@ -82,10 +80,9 @@ python run_pipeline.py \
8280
--pipeline_id {pipeline_id} \
8381
--root_dir {root_directory}
8482
""")
85-
sh.chmod(0o755)
8683

8784
# 2) submit and RETURN None (async)
88-
subprocess.check_call(["sbatch", str(sh)])
85+
sumit_job(script)
8986
return None # ⟵ signals async mode
9087
```
9188

@@ -101,17 +98,22 @@ parser.add_argument("--optimizer")
10198
parser.add_argument("--pipeline_id")
10299
parser.add_argument("--root_dir")
103100
args = parser.parse_args()
104-
105-
# … do heavy training …
106-
val_loss = 0.1234
107-
wall_clock_cost = 180 # seconds
108-
109-
result = {
110-
"objective_to_minimize": val_loss,
111-
"cost": wall_clock_cost,
112-
}
113-
114-
neps.save_callback(
101+
try:
102+
# … do heavy training …
103+
val_loss = 0.1234
104+
wall_clock_cost = 180 # seconds
105+
result = {
106+
"objective_to_minimize": val_loss,
107+
"cost": wall_clock_cost,
108+
}
109+
except Exception as e:
110+
result = {
111+
"objective_to_minimize": val_loss,
112+
"cost": wall_clock_cost,
113+
"exception": e
114+
}
115+
116+
neps.save_pipeline_results(
115117
user_result=result,
116118
pipeline_id=args.pipeline_id,
117119
root_directory=Path(args.root_dir),
@@ -143,6 +145,6 @@ Use them to handle warm‑starts, logging and result persistence.
143145

144146
* [x] Return scalar **or** dict **or** `None`.
145147
* [x] Include `cost` when using cost budgets.
146-
* [x] When returning `None`, make sure **exactly one** call to `neps.save_callback` happens.
148+
* [x] When returning `None`, make sure **exactly one** call to `neps.save_pipeline_results` happens.
147149
* [x] Save checkpoints and artefacts in `pipeline_directory`.
148150
* [x] Handle resume via `previous_pipeline_directory`.

neps/runtime.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -38,8 +38,8 @@
3838
OnErrorPossibilities,
3939
OptimizationState,
4040
SeedSnapshot,
41-
State,
4241
Trial,
42+
UserResult,
4343
WorkerSettings,
4444
evaluate_trial,
4545
)
@@ -674,9 +674,9 @@ def _save_results(
674674
raise RuntimeError(f"Trial '{trial_id}' not found in '{root_directory}'")
675675

676676
report = trial.set_complete(
677-
report_as=State.SUCCESS.value
677+
report_as=Trial.State.SUCCESS.value
678678
if result.exception is None
679-
else State.CRASHED.value,
679+
else Trial.State.CRASHED.value,
680680
objective_to_minimize=result.objective_to_minimize,
681681
cost=result.cost,
682682
learning_curve=result.learning_curve,

neps/state/pipeline_eval.py

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -378,15 +378,12 @@ def _eval_trial(
378378
default_report_values: DefaultReportValues,
379379
fn: Callable[..., Any],
380380
**kwargs: Any,
381-
) -> Report:
381+
) -> Report | None:
382382
start = time.monotonic()
383383
try:
384384
user_result = fn(**kwargs, **trial.config)
385-
<<<<<<< HEAD
386-
=======
387385
if user_result is None:
388386
return None
389-
>>>>>>> 2e3dfbce (add async evaluation)
390387
# Something went wrong in evaluation
391388
except Exception as e:
392389
duration = time.monotonic() - start
@@ -435,11 +432,7 @@ def evaluate_trial(
435432
*,
436433
evaluation_fn: Callable[..., Any],
437434
default_report_values: DefaultReportValues,
438-
<<<<<<< HEAD
439-
) -> tuple[Trial, Report]:
440-
=======
441435
) -> tuple[Trial, Report | None]:
442-
>>>>>>> 2e3dfbce (add async evaluation)
443436
"""Evaluates a trial from a user and parses the results into a `Report`."""
444437
trial_location = Path(trial.metadata.location)
445438
prev_trial_location = (

0 commit comments

Comments
 (0)