Evaluation¶
Every metric on this page is computed end to end, on real predictions, in the getting-started notebook — including the recoverability split below and what it looks like when a model behaves.
The prediction cache¶
Every figure and every quoted number reads one frozen npz rather than a live model, so a plotting tweak cannot quietly change a result.
specsr-roman evaluate cache --out outputs/pred_cache.npz
specsr-roman evaluate metrics --cache outputs/pred_cache.npz
specsr-roman evaluate figures --cache outputs/pred_cache.npz --outdir outputs/figures
Regenerate the cache deliberately when the chain changes — never by accident while tuning a plot.
Metrics¶
from specsr_roman.evaluation import line_amplitude_recovery, redshift_summary
redshift_summary(cache["z_pred"], cache["z_true"])
line_amplitude_recovery(cache["sr2"], cache["hr"], cache["line_snr"],
z=cache["z_true"], wave_um=cache["wl_um"])
Sample statistics use every spectrum; the lines are judged only where they
are detected. Redshift accuracy is computed on the whole held-out split. A
line enters the amplitude metric only if its own integrated S/N reaches 2
(MIN_BEST_LINE_SNR): passing z and wave_um applies that
(detected_line_mask), and the bins start there. Below it the data carry no
strong signal, so the metric says nothing about what the model draws there.
redshift_summary reports NMAD, median |Δz|/(1+z), catastrophic fraction and
N. Report all of them: a model can shrink NMAD while pushing more objects past
the catastrophic threshold, and NMAD alone hides alias structure entirely.
Read the recoverability split first¶
line_amplitude_recovery bins rows by their best line’s integrated S/N:
Bin |
Integrated line S/N |
|---|---|
|
2–3 |
|
3–6 |
|
> 6 |
Report the bins separately. A single averaged amplitude ratio mixes marginal detections with strong ones and hides how the recovery depends on the data.
per_line_amplitude_recovery is the diagnostic companion: same idea, scored
per transition rather than per row, so a failure can be attributed to a
specific line. The two use different definitions and should not be compared to
each other.
Figures¶
Key |
What it shows |
|---|---|
|
HR / LR / SR2 overlay with a zoom inset on the blended complex |
|
residual maps sorted by z, with rest-frame line tracks |
|
per-line S/N, SR2 against the LR input |
|
z_pred vs z_true — read the off-diagonal alias stripes |
|
signal and residual power spectra |
from specsr_roman.evaluation.figures import make_figures
make_figures(cache, which=["spectra", "redshift"], outdir="figures/")
One panel per redshift configuration¶
SR2 places its lines at the redshifts it is given, so its evaluation depends on
the redshift head behind it. specsr_roman.evaluation.band_figures.BANDS lists
four configurations (three Roman bands; the same with Rubin at one-year and at
ten-year depth; nine bands and no spectrum), each with its own SR2 checkpoint
and prediction cache (outputs/pred_cache.npz for the first,
outputs/pred_cache_<key>.npz for the others; all four are on the Hub).
specsr-roman evaluate band-figures # every figure below, plus band_metrics.json
# from the v0.6.x reserved-test caches (pred_cache_<config>.npz in one directory)
specsr-roman evaluate band-figures --cache-dir path/to/caches \
--response-dir path/to/lr_restored --outdir outputs/figures
The example spectra (band_figures.HARD_CASES) are in the reserved test
partition. Their cache rows are found through each cache’s dataset_row, and
their 2D cutouts are dispersed once into --cutouts (this needs grizli and
the raw detector images).
File |
What it shows |
|---|---|
|
one galaxy, the output under each configuration |
|
SR2 minus target, sorted by z, and its scatter |
|
signal and residual power spectra |
|
recovered flux fraction per recoverability bin |
|
Gaussian-fit line flux against the target, input and SR2 |
|
per-line S/N, SR2 against the input |
|
the prior-dominance response exponent per bin |
The line-flux comparison is the one the others cannot replace. S/N never looks
at the target, so only flux against the target says whether a line is right.
The fit (specsr_roman.evaluation.linefit) is the one of the JWST companion
package. A configuration whose cache is missing is left out of the figures.
Audits¶
Worth re-running after any retrain — this is the code that backs the honesty claims.
Photometry ablation¶
specsr-roman evaluate ablation
Answers: how much of the redshift accuracy is the spectrum? Because photometry enters standardised with statistics baked into the checkpoint, “drop a band” is exactly “feed it its training mean” — so this needs no retraining.
The v0.6.0 reserved-test Roman chain has NMAD 0.00133 and 0.67% outliers. The older release’s colour-ablation numbers describe older weights. Re-run ablations on the appropriate three-way partition before quoting new numbers.
Warning
Read the no-photometry row as an upper bound, not as the information floor. This head was trained with colours, so mean-imputing them measures the deployed chain in a degraded mode — not a grism-only model, which is a separate experiment that has not been run.
Prior dominance (inverse crime)¶
specsr-roman evaluate prior --max-sources 500
The training targets are simulated SEDs. A model can score well on every reconstruction metric by learning that manifold rather than measuring anything, and no reconstruction metric distinguishes the two.
This probes off-manifold sensitivity. Scale a recovered line in the truth by a factor f — off the
manifold — forward-model the difference onto the observed spectrum, re-run, and
measure
$$ r = \frac{\log(L_\mathrm{pred}’ / L_\mathrm{pred})}{\log f} $$
r = 1 means the model tracked the change; r = 0 means it produced the same
line regardless.
Read it carefully. Where the injected change is genuinely below the noise,
low r is the correct behaviour — falling back on the prior is what a
calibrated model should do when the data says nothing. Bin by detectability and
judge r only where the information is present. Aggregate r mixes marginal and strong detections; inspect the injected-change
S/N breakdown as well as the original-line bins.
Version 0.6.1 completes the audits of these weights. The Roman SR2 deployed line-response exponent is 0.098 (galaxy-grouped 95% bootstrap interval 0.089–0.106; 0.255 for strong lines), compared with 1 for proportional recovery. The nominal central 68% redshift interval covers 98.7% of test truths. Spectral coverage is 75.5% within 1σ overall and 92.1% within 1.96σ in detected-line regions. These are diagnostics; no recalibration was fitted on the test data. Full audits, normalization controls and records document the remaining limitations. Output line fluxes and ratios are not yet calibrated measurements.
Use --split-mode three_way --partition test with the released checkpoint
names. Deployed legacy_lr restoration is the primary physical response.
The target_fixed convention is a normalized-output control, not a corrected
physical response or a fraction of information attributable to a prior.