Upload README.md
Browse files
README.md
ADDED
|
@@ -0,0 +1,127 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# NativeSpecZ-FM-76M
|
| 2 |
+
|
| 3 |
+
A 76M-parameter unimodal foundation model for DESI spectra. Trained from scratch on 97,332 DESI EDR spectra. No AION weights, no pretrained encoder β everything is ours.
|
| 4 |
+
|
| 5 |
+
## What it does
|
| 6 |
+
|
| 7 |
+
1. **Redshift prediction** (deliverable a) β predicts cosmological redshift z from a DESI spectrum
|
| 8 |
+
2. **Masked spectrum reconstruction** (deliverable b) β reconstructs missing pixel regions of a spectrum
|
| 9 |
+
|
| 10 |
+
## Architecture
|
| 11 |
+
|
| 12 |
+
`HybridSpecZ` (defined in `code/hybrid_redshift.py`):
|
| 13 |
+
- 8-channel raw-flux input encoding (flux, ivar, validity mask, LSF, log-wavelength, gradient, line score, corruption indicator)
|
| 14 |
+
- Conv stem: 3 stride-2 residual blocks (8Γ downsampling)
|
| 15 |
+
- 12-layer pre-norm transformer (d_model=640, heads=10)
|
| 16 |
+
- `[CLS]` + `[Z_MASK]` tokens prepended β **Approach B**: z token always masked, never receives true z
|
| 17 |
+
- Bin-residual z head + pixel-level reconstruction head β **Approach A**: z head trained jointly with encoder
|
| 18 |
+
- 76,475,836 parameters total
|
| 19 |
+
|
| 20 |
+
## How it was trained
|
| 21 |
+
|
| 22 |
+
- **Data**: 97,332 DESI spectra (MultimodalUniverse/desi, deduplicated against the held-out test set by `object_id`)
|
| 23 |
+
- **Resumed** from a base 75M checkpoint, fine-tuned for 5 epochs (~30,000 steps)
|
| 24 |
+
- **AdamW**, lr 1e-5 β 7e-7 cosine, batch=16, grad_clip=1.0
|
| 25 |
+
- **Moderate instrument-shift augmentation** (the "safe" recipe):
|
| 26 |
+
- crop 35%, throughput 45%, noise 25%, resolution 20%, downsample 12%
|
| 27 |
+
- bad_window 25%, line_dropout 15%, span_dropout 15%
|
| 28 |
+
- **Loss**: rec_weight 0.5, z_weight 1.0, z_bin_weight 0.45, z_nll_weight 0.03
|
| 29 |
+
- **Mask ratio**: 0.15 train, 0.25-0.30 eval
|
| 30 |
+
- **High-z boost**: 1.5Γ weight above z=1.0
|
| 31 |
+
|
| 32 |
+
The augmentation simulates non-DESI instrument characteristics during training, which is the cleanest way to encourage cross-instrument generalization without using non-DESI data.
|
| 33 |
+
|
| 34 |
+
## Headline results
|
| 35 |
+
|
| 36 |
+
### DESI held-out (n=2500, deduped from training)
|
| 37 |
+
|
| 38 |
+
| Metric | Value |
|
| 39 |
+
|---|---:|
|
| 40 |
+
| MAE(z) | **0.0516** |
|
| 41 |
+
| Median AE | 0.00212 |
|
| 42 |
+
| RMSE | 0.189 |
|
| 43 |
+
| Pearson r | **0.936** |
|
| 44 |
+
| NMAD | 0.0019 |
|
| 45 |
+
| Cat \|dz\|/(1+z)>0.01 | 13.5% |
|
| 46 |
+
| Cat \|dz\|/(1+z)>0.05 | 9.0% |
|
| 47 |
+
| Cat \|dz\|/(1+z)>0.15 | 6.8% |
|
| 48 |
+
| Acc \|dz\|<0.10 | 90.6% |
|
| 49 |
+
| Acc \|dz\|<0.20 | 92.3% |
|
| 50 |
+
| Acc \|dz\|<0.30 | 93.6% |
|
| 51 |
+
| Masked recon MSE (mask=0.25) | 0.037 |
|
| 52 |
+
| Masked recon MSE (mask=0.30) | 0.437 |
|
| 53 |
+
|
| 54 |
+
### Cross-instrument generalization
|
| 55 |
+
|
| 56 |
+
| Dataset | n | MAE(z) | NMAD | AION-base MAE |
|
| 57 |
+
|---|---:|---:|---:|---:|
|
| 58 |
+
| **DESI held-out** | 2500 | **0.052** | 0.0019 | 0.074 (AION loses) |
|
| 59 |
+
| **SDSS (real non-DESI)** | 2000 | 0.382 | 0.385 | 0.127 |
|
| 60 |
+
| **VIPERS (real non-DESI)** | 2000 | **0.172** | 0.087 | 0.274 (AION loses) |
|
| 61 |
+
|
| 62 |
+
We beat AION-base on **DESI** by 30% and on **VIPERS** by 37%. SDSS is harder for our raw-flux architecture; for SDSS-style inputs, the AION-tokenizer-based variants in our ensemble are better.
|
| 63 |
+
|
| 64 |
+
## Folder structure
|
| 65 |
+
|
| 66 |
+
```
|
| 67 |
+
NativeSpecZ-FM-76M_Submission/
|
| 68 |
+
βββ NativeSpecZ-FM-76M.ipynb β demo notebook (load model, run eval, plot results)
|
| 69 |
+
βββ README.md β this file
|
| 70 |
+
βββ REPORT.md β full methodology + results write-up
|
| 71 |
+
βββ weights/
|
| 72 |
+
β βββ best.pt β 292 MB model checkpoint
|
| 73 |
+
β βββ training_args.json β all hyperparameters
|
| 74 |
+
β βββ best_metrics.json β training-time eval metrics
|
| 75 |
+
βββ code/
|
| 76 |
+
β βββ hybrid_redshift.py β model architecture + collator + training loop
|
| 77 |
+
βββ eval_results/
|
| 78 |
+
β βββ desi_2500_metrics.json β test-set metrics in friend-style format
|
| 79 |
+
βββ plots/
|
| 80 |
+
βββ friend_style_scatter.png β Pearson r=0.9358 scatter (matches friend's format)
|
| 81 |
+
βββ friend_style_reconstruction.png β 4-panel masked recon overlay
|
| 82 |
+
βββ comparison_vs_aion.png β MAE bar chart vs AION-base
|
| 83 |
+
βββ comparison_3way_desi.png β 6-metric chart: us vs AION vs friend
|
| 84 |
+
βββ foundation_evidence.png β cross-instrument robustness ratio
|
| 85 |
+
βββ dashboard.png β 6-panel model summary
|
| 86 |
+
βββ multi_mask_reconstruction.png β rec quality vs mask ratio
|
| 87 |
+
βββ stress_curve.png β instrument-shift robustness
|
| 88 |
+
```
|
| 89 |
+
|
| 90 |
+
## How to reload the model
|
| 91 |
+
|
| 92 |
+
```python
|
| 93 |
+
import torch, sys
|
| 94 |
+
sys.path.append("code")
|
| 95 |
+
from hybrid_redshift import HybridSpecZ
|
| 96 |
+
|
| 97 |
+
ckpt = torch.load("weights/best.pt", map_location="cuda", weights_only=False)
|
| 98 |
+
a = ckpt["args"]
|
| 99 |
+
model = HybridSpecZ(
|
| 100 |
+
d_model=a["d_model"], conv_width=a["conv_width"], layers=a["layers"],
|
| 101 |
+
heads=a["heads"], dropout=a["dropout"], z_bins=a["z_bins"],
|
| 102 |
+
stem_stride=a["stem_stride"], rec_hidden_mult=a["rec_hidden_mult"],
|
| 103 |
+
rec_refine_width=a["rec_refine_width"], rec_refine_kernel=a["rec_refine_kernel"],
|
| 104 |
+
layerscale_init=a["layerscale_init"], prediction_mode=a["prediction_mode"],
|
| 105 |
+
bin_temperature=a["bin_temperature"], residual_scale=a["residual_scale"],
|
| 106 |
+
candidate_topk=a["candidate_topk"],
|
| 107 |
+
).cuda()
|
| 108 |
+
model.load_state_dict(ckpt["model"], strict=True)
|
| 109 |
+
model.eval()
|
| 110 |
+
```
|
| 111 |
+
|
| 112 |
+
See `NativeSpecZ-FM-76M.ipynb` for the full inference + evaluation pipeline.
|
| 113 |
+
|
| 114 |
+
## Hugging Face
|
| 115 |
+
|
| 116 |
+
Model also available at `tempAstro/NativeSpecZ-FM-76M` on Hugging Face.
|
| 117 |
+
|
| 118 |
+
## Submission checklist
|
| 119 |
+
|
| 120 |
+
- [x] Approach A (joint z-head training, encoder shaped by z)
|
| 121 |
+
- [x] Approach B (always-masked z token)
|
| 122 |
+
- [x] Redshift prediction working (MAE 0.052 on held-out DESI)
|
| 123 |
+
- [x] Masked spectrum reconstruction working (rec MSE 0.037 at 25% mask)
|
| 124 |
+
- [x] Cross-instrument testing on real non-DESI data (SDSS + VIPERS)
|
| 125 |
+
- [x] Unimodal β DESI spectra + z only, no imaging
|
| 126 |
+
- [x] No AION pretrained weights used
|
| 127 |
+
- [x] Single-model submission with notebook + weights + report
|