Tasks/Math & Scientific Computing/Astrophysics

Classify astronomical transients/variables from their light curves

Classify transients and variables from their light curves

photometric_transient_classMath & Scientific ComputingAstrophysics
instruction.mdthis is what the agent is given

You inherit a feature-blind baseline: for every object it predicts the training-set class-frequency prior, completely ignoring every light-curve observation and every metadata column it was given. Your goal is to lower the weighted multi-class log-loss of your predicted class probabilities against the true class; a sealed verifier re-trains and re-runs your solver on a HIDDEN batch of objects and scores it (lower is better).

Hard Constraints

  • You may only edit code under /app/methods/main/; you may add sibling .py modules.
  • Keep the entrypoint signatures train(train_records) -> None and predict(test_records) -> list[dict], where the returned list has one entry per OBJECT in test_records, in the same order as test_records (positional, not keyed by any ID field).
  • The environment provides numpy + pandas + scikit-learn + scipy + lightgbm and the standard library. Both images carry the same set, byte-identical: the stack you develop against is the stack you are graded on. Other third-party packages -- including xgboost, catboost and the deep-learning frameworks (torch, tensorflow, jax) -- are NOT installed, and there is no network at grading time to fetch them, so importing one raises ModuleNotFoundError inside the grading subprocess and the run scores 0. Build your solution on the libraries listed above.
  • Your submission is graded under a wall-clock budget. The verifier re-runs your train() + predict() on the sealed batch in a subprocess capped at 19200 s, inside a container declared at 8 CPUs / 6144 MiB of memory; the whole verifier stage is capped at 25200 s. The sealed batch is roughly 2.4x the size of the visible training set, so a pipeline that just fits inside your own self-check can still overrun at grading time. Budget for that; a run killed by the time or memory cap produces no predictions and scores 0. Note that the CPU allowance is a share, not a reservation: on a busy host the same pipeline can take noticeably longer than it did in your own self-check.
  • /dev/shm is only 64 MiB (the container default) and cannot be enlarged. A multiprocessing.shared_memory segment larger than that is created successfully and only faults on the first write, killing the process with SIGBUS and no traceback. If you parallelise, pass large arrays through /tmp-backed files (or just use n_jobs on scikit-learn estimators, which does not rely on /dev/shm).
  • Your solver must be deterministic given the shipped data -- the verifier calls train() then predict() fresh in its own process; unseeded randomness makes your local self-check unrepresentative of the graded run (seed every model you fit).
  • Network access is restricted to the model API by an allowlist enforced outside your container. Solve the task from the data shipped in /app/data; sourcing labels from any external source is out of bounds, and the allowlist makes it unreachable rather than merely discouraged. The sealed verifier runs with no network at all.
  • Your submitted methods/main/ must contain only small .py source files. The verifier rejects (reward 0) any submission that does not look like code: any non-.py file, any symlink, or a total submission size over the guard's byte cap is rejected outright.

What You Have

  • /app/data/train_metadata.csv: 7,848 labelled astronomical objects (a simulated LSST-precursor survey's spectroscopically-confirmed sample). Columns: object_id, ra, decl (sky position, degrees), ddf_bool (1 if observed in the deep-drilling field, a smaller/higher-cadence survey footprint), hostgal_specz / hostgal_photoz / hostgal_photoz_err (spectroscopic / photometric redshift estimate of the host galaxy, and the photo-z's uncertainty; a spectroscopic redshift is a much more expensive measurement to obtain than a photometric one and is not always available -- when it isn't, this column is coded with a negative sentinel value rather than being left blank), distmod (distance modulus, or a -9 sentinel for Galactic objects with no meaningful cosmological distance -- purely Galactic objects also have hostgal_photoz = 0), mwebv (Milky Way dust extinction along the line of sight), and target (the true class -- your training label).
  • /app/data/train_lightcurves.csv: the actual brightness measurements for those same 7,848 objects. Columns: object_id, mjd (observation time, Modified Julian Date), passband (an integer 0-5, one of six wavelength filters -- roughly ultraviolet-to-infrared, LSST's u,g,r,i,z,y bands), flux / flux_err (measured brightness and its uncertainty -- a difference-imaging flux, i.e. relative to a reference template, so negative values are normal noise, not an error), detected_bool (1 if this particular observation triggered the survey's detection significance threshold). Each object has on the order of 100-300 observations spread unevenly across the six bands and however long the object was monitored.
  • /app/methods/main/solver.py: the baseline solver (predicts the training- set class-frequency prior for every object) -- this directory is what gets graded. Improve it in place or rewrite the algorithm entirely. Matching the baseline earns nothing.
  • /app/force_score.py: the exact weighted log-loss formula the verifier uses, including the full class list and per-class weight table (the formula and weights are public; only the true held-out classes are sealed).
  • /app/lightcurve_io.py: a small loader that turns the flat CSVs into the records your train()/predict() receive -- read it to see the exact record shape (see "What You Submit" below); you do not need to modify it.
  • /app/selfcheck.py: a free, unlimited local dry-run (python /app/selfcheck.py) that fits on a stratified internal split of the visible objects and prints the proxy weighted log-loss. It is a proxy only -- the real held-out set is a different, larger batch of objects, so do not overfit to this split.

What You Submit

Edit /app/methods/main/solver.py, keeping the contract:

def train(train_records: list[dict]) -> None:
    # Called once, on the labelled re-training objects. Each element is one
    # dict PER OBJECT (not per observation row):
    #   {"object_id": str, "ra": float, "decl": float, "ddf_bool": int,
    #    "hostgal_specz": float, "hostgal_photoz": float,
    #    "hostgal_photoz_err": float, "distmod": float, "mwebv": float,
    #    "lightcurve": [{"mjd": float, "passband": int, "flux": float,
    #                     "flux_err": float, "detected_bool": int}, ...],
    #    "target": int}   # true class label -- your training target
    # Fit whatever state you need and stash it (module globals are fine).
    ...

def predict(test_records: list[dict]) -> list[dict]:
    # test_records: same shape as train_records, WITHOUT "target".
    # Return one dict per object, SAME ORDER as test_records (positional).
    # Each dict maps {class_label: probability}. See force_score.py for the
    # full 15-class list (14 classes seen in training + one "anomaly" class
    # that appears ONLY in the held-out set, with zero training examples --
    # you must still emit some probability mass for it). Missing classes
    # default to probability 0; rows need not already sum to 1 (they are
    # renormalized before scoring) but should be a genuine probabilistic
    # guess, not a constant/garbage row.
    ...

There is no submit step and no per-attempt feedback on the real held-out set -- iterate against selfcheck.py, then leave your best solver.py in place; it is graded once at the end.

How It Is Judged

After your run, the grader copies your methods/main/ into a sealed verifier, spawns a fresh process that imports it and calls train() on the sealed re-training objects, then predict() on a HIDDEN batch of objects you never saw, and scores the weighted multi-class log-loss of your predicted probabilities against the true class (lower is better):

  • Per-object log-loss is -log(p_true_class) (probabilities are clipped and renormalized to sum to 1 first).
  • The mean log-loss is taken within each true class separately (so a rare class with a handful of held-out objects counts equally to a class with thousands).
  • The per-class means are combined in a weighted average (most classes weight 1; five "rare/interesting" classes weight 2 -- see force_score.py for the exact table), normalized by the sum of weights actually present in the held-out slice.

Your score improves monotonically as the weighted log-loss falls, so driving it down is always the goal, and there is real headroom between the shipped baseline and a well-engineered solution. Any crash, wrong output length, wrong output order, or a row with no positive probability mass anywhere scores the whole submission 0.

Metric

weighted multi-class log-loss on the sealed held-out objects · lower is better

-log(p_true) averaged within each true class, then a weighted mean over present classes (weight 2 for five rare ones)

anchorvisible setheld-outreward
Bshipped starter (class-freq prior)3.40113.29170.00
Rauthor reference solution0.91241.28230.30
Sauthor SOTA solver0.5743000.9861270.60
Uperfect prediction001.00
normalisation
m >= B0
B > m >= R0.3 * (ln(B) - ln(m)) / (ln(B) - ln(R))
R > m >= S0.3 + 0.3 * (ln(R) - ln(m)) / (ln(R) - ln(S))
S > m > U0.6 + 0.4 * (1 - ((m - U) / (S - U))^p)
m <= U1

m = this run's held-out metric  ·  B = shipped starter (class-freq prior)  ·  R = author reference solution  ·  S = author SOTA solver  ·  U = perfect prediction

B/R/S/U and p = 2.0 come from the sealed anchors.json. One log-loss over the whole batch, so no per-case mapping. Guard trip or crash = 0.

Rollouts

212 minwall clock
-spend
-tokens
7versions, 7 kept
0.54 0.56 0.58 0.60 0.62 0.64 0 40 80 120 160 agent step (this harness reports no tokens or timestamps) 5-fold TUNE-CV weighted log-loss, lower is better author SOTA solver · visible · 0.574300 v0 v1 v2 v3 v5 v13 v15
keptrevertedno scoreturning point
  1. v0Shipped class-frequency-prior baseline, constant p99 = 0.10not measured
  2. v1Gal/exgal LightGBM on 259 hand features, 5-fold bag, no hostgal_speczMetric-matched J_c/n_c weights, photo-z only: spec-z is always present in train but sentinel-coded in the hidden batch.0.635
  3. v2Fine rest-frame phase bins, exgal templates, SN specialist, OOF temperatureSN subtypes 42/52/62/67 carried 75% of the known-class loss, so they get their own model and per-fold templates.0.5776
  4. v3Kernel-smoothed rest-frame flux grid, 4 bands x 11 phases; SN blend 0.450.5652
  5. v5Drop ra/dec/galactic coords; heavier regularization on the large LightGBMsTreats release-to-release transfer as the risk: sky position cannot carry over, and the wide models were the overfit ones.0.5418
  6. v13Class-99 mass split 0.05 galactic / 0.125 extragalactic, mean near 0.10selfcheck 0.5566
  7. v15Extra SN-specialist sample weight on class 52 (x1.35) and 67 (x1.25)0.5372

7 snapshots in 212 min; this harness reports no token or cost data. Nine further experiments (v4, v6-v12, v14) were reverted unsnapshotted.

On the hidden set

held-out metricreward
shipped starter (class-freq prior)3.29170.00
author reference solution1.28230.30
author SOTA solver0.9861270.60
perfect prediction01.00
this run0.83330.7144
223 minwall clock
$62.09spend
96.6Mtokens
29versions, 23 kept
0.75 1.50 2.25 3.00 $0 $15 $30 $45 $60 cumulative spend on the run seed-0 self-check weighted log-loss, lower is better author SOTA solver · visible · 0.574300 v0 v1 v2 v3 v4 v5 v6 v7 v8 v9 v10 v11 v12 v13 v14 v15 v16 v17 v18 v19 v20 v21 v22 v23 v24 v25 v26 v27 v28
keptrevertedno scoreturning point
  1. v0Shipped class-frequency-prior baseline3.40111 min · $0.22
  2. v1First macro-weighted LightGBM; feature block emitted 49 values, asserted 48failed before the fit4 min · $0.45
  3. v2Repaired feature schema (419 features); one 450-tree weighted LightGBMFirst model that ran: 419 metadata, global and per-band summaries under one deterministic LightGBM weighted to the metric.0.76915 min · $0.60
  4. v3Global probability power calibration p^0.70, chosen on 3-fold OOF0.68957 min · $0.88
  5. v4Hierarchical models split on the exact host-photoz galactic boundary0.670111 min · $1.28
  6. v5228 redshift-corrected event-shape and multiband profile features (647)0.592717 min · $1.96
  7. v6Recalibrate the power 0.65 to 0.675 for the new morphology features0.592819 min · $2.16
  8. v7Switch to a randomized-threshold (ExtraTrees-mode) LightGBM, 600 treesA model-family study on fixed folds, not another feature block: randomized split thresholds beat boosting at every leaf count.0.545924 min · $2.85
  9. v8Randomized-tree capacity search: 7 leaves, 900 trees, p^0.870.507132 min · $4.01
  10. v9Shallower still: a single 1200-tree, 3-leaf model with p^1.160.503938 min · $5.07
  11. v10Regularized vector scaling learned from 3-fold OOF inside train()0.489542 min · $5.67
  12. v11230 common-scale colour, SNR and band-alignment features (877 total)0.465348 min · $6.72
  13. v12Geometric blend at weight 0.60 with a tuned 500-tree ExtraTrees forest0.450361 min · $9.41
  14. v13Class-99 mass from a standardized negative confidence marginTurns the unseen anomaly class into detection: leave-one-class-out pseudo-anomalies give a margin fed to a 2-parameter logistic.0.434771 min · $11.56
  15. v14330 Gaussian-kernel profile/colour features at 5/15/30-day bandwidths0.438676 min · $12.77
  16. v1558 extinction-corrected magnitude, luminosity and photo-z transforms0.527880 min · $13.77
  17. v16Leakage-safe fold-local importance pruning and refit to 300 features0.44389 min · $15.96
  18. v17SN specialist over {42,52,62,67,90}, 50% geometric conditional blend0.431794 min · $17.39
  19. v18Retune the vector-calibration L2 for the final ensemble, 0.03 to 0.010.427898 min · $18.63
  20. v19Internal calibration/anomaly cross-fitting raised from 3 folds to 50.4287103 min · $20.12
  21. v20Anomaly audit widened to nine pseudo-classes; cap 0.75 to 0.60anomaly only .2869/.2864121 min · $24.97
  22. v2112 galactic-only Lomb-Scargle period, phase and harmonic features0.4266131 min · $29.04
  23. v22Domain-aware WFD calibration; global calibration kept for sparse DDF0.4269139 min · $31.88
  24. v23Routed fallback model for objects whose spectroscopic redshift is missing0.4269156 min · $40.24
  25. v24Contract hardening: empty batches, degenerate/non-finite time axesunchanged, not re-scored158 min · $40.76
  26. v25Deterministic joint multiband Bazin fit, 10 features, extragalactic only0.4216174 min · $47.81
  27. v26Shared-epoch Bazin fit with six passband amplitudes and baselines (19)0.4242192 min · $55.38
  28. v27Component retune: SN blend 0.50 to 0.70, extragalactic L2 0.01 to 0.0030.4211204 min · $60.37
  29. v28Six galactic-frame sky-coordinate features for photo-z-zero objects0.503221 min · $61.88

29 versions in 223 min for $62.09 against 21 in 81 min at high effort. From v13 on the self-check moved only 0.4347 to 0.4211; v28 was reverted.

On the hidden set

held-out metricreward
shipped starter (class-freq prior)3.29170.00
author reference solution1.28230.30
author SOTA solver0.9861270.60
perfect prediction01.00
this run0.83520.7131
136 minwall clock
$59.31spend
101.8Mtokens
21versions, 19 kept
0.75 1.50 2.25 3.00 $0 $15 $30 $45 cumulative spend on the run seed-0 self-check weighted log-loss, lower is better author SOTA solver · visible · 0.574300 v0 v1 v2 v3 v4 v5 v6 v7 v8 v9 v10 v11 v12 v13 v14 v15 v16 v17 v18 v19 v20
keptrevertedno scoreturning point
  1. v0Shipped class-frequency-prior baseline, no observed features3.40112 min · $0.38
  2. v1563 metadata, per-band, cadence, colour features; class-balanced LightGBMTransfer-safe feature set by construction: object id, spectroscopic redshift and raw sky position left out of a 700-tree fit.0.78055 min · $0.84
  3. v2Temperature 1.25 to 1.60 after three tuning splits agreed on 1.55-1.650.748310 min · $1.66
  4. v3Exact photo-z/distmod galactic routing; group temperatures 1.10 and 1.800.735113 min · $2.37
  5. v4Extragalactic 24-leaf model replaced by a 5-/8-/12-leaf calibrated blendTreats the extragalactic branch as overfit rather than underfeatured: three shallow models averaged instead of one deep one.0.656121 min · $4.13
  6. v5Pooled OOF power and intercept calibration on the extragalactic branch0.636927 min · $5.50
  7. v637 per-band temporal quantile, width, asymmetry and rise/fall features0.619629 min · $5.99
  8. v7Near-simultaneous cross-filter colour and SNR summaries, 15 band pairs0.610533 min · $7.25
  9. v8Rest-frame phase samples around per-band and shared high-SNR peaks0.597538 min · $8.88
  10. v9Dropped the 8- and 12-leaf components; T=0.925, refreshed intercepts0.601445 min · $11.20
  11. v1020% entropy random-forest diversity blend, then recalibration0.600155 min · $15.31
  12. v11Top-two-margin logistic novelty reserve replaces the constant p99=0.10Class-99 mass becomes a function of the top-two margin, fit on 42 leave-class-out runs and judged on synthetic held classes.0.615366 min · $19.82
  13. v12Trigger-span block widened: detection quantiles, gaps, episode widths0.606670 min · $21.44
  14. v1320% conditional blend from a 5-way core-SN specialist (42/52/62/67/90)0.602879 min · $26.15
  15. v14Nine one-vs-rest learners; broad weights multiclass/OvR/RF .55/.30/.150.604888 min · $31.04
  16. v15Core conditional blend 20%/T=0.60 to 15%/T=0.500.604793 min · $33.66
  17. v1620 inverse-variance/SNR-energy aggregates and excess-variance stats0.607597 min · $35.81
  18. v17Weighted Lomb-Scargle summaries for galactic objects, column-isolated0.6127107 min · $42.02
  19. v18Multiclass temperature 0.925 to 0.900 to match the calibrated probabilities0.6039111 min · $44.07
  20. v19OOF power/intercept calibration of the galactic branch, after novelty0.5909119 min · $48.97
  21. v20Galactic calibration-factor bound relaxed from exp(+-2) to exp(+-4)0.5888129 min · $54.33

21 versions in 136 min for $59.31. v1 and v4 are most of the drop; v16 and v17 were reverted and one seed was reserved to v18.

On the hidden set

held-out metricreward
shipped starter (class-freq prior)3.29170.00
author reference solution1.28230.30
author SOTA solver0.9861270.60
perfect prediction01.00
this run0.88250.6796
81 minwall clock
$13.49spend
19.9Mtokens
21versions, 18 kept
0.75 1.50 2.25 3.00 $0 $3 $6 $9 $12 cumulative spend on the run seed-0 self-check weighted log-loss, lower is better author SOTA solver · visible · 0.574300 v0 v1 v2 v3 v4 v5 v6 v7 v8 v9 v10 v11 v12 v13 v14 v15 v16 v17 v18 v19 v20
keptrevertedno scoreturning point
  1. v0Shipped class-frequency-prior baseline, constant anomaly floor 0.103.40110 min · $0.18
  2. v1377 metadata/per-band/colour features + inverse-frequency weighted LightGBMOne 600-tree LightGBM over per-band and colour summaries, weighted by inverse class frequency to match the metric's averaging.0.91343 min · $0.47
  3. v2Soften known-class probabilities with temperature T=1.50.776 min · $0.73
  4. v3Temperature raised to T=1.7 after two extra seed sweeps0.757311 min · $1.22
  5. v4140 redshift/luminosity and peak-aligned temporal morphology features0.68512 min · $1.40
  6. v5Anomaly mass from a clipped batch-normalized product(1 - p_known)known-class only 0.687119 min · $2.13
  7. v6Hard-route on the photoz sentinel; separate 5- and 9-class LightGBMsGalactic and extragalactic objects separate exactly from metadata, so each group gets its own model over its own class list.0.66723 min · $2.76
  8. v7Group-specific temperatures, T=1.0 galactic and T=1.8 extragalactic0.663124 min · $2.93
  9. v872 features: SNR-squared peak weighting, percentile widths, area balance0.652826 min · $3.20
  10. v940 five-phase rest-frame colour-evolution features on a shared flux scale0.648228 min · $3.43
  11. v10Regularize the extragalactic branch: 900 trees, lr 0.025, L2 1.5, no ensemble0.630233 min · $4.27
  12. v11Group-wise vector scaling: temperature plus per-class logit biasesDrops the global temperature for a per-class logit shift within each group; fit on seed 0, left untouched on the other splits.0.45738 min · $5.00
  13. v125-class ordinary-SN specialist blended 75% inside the SN family0.452745 min · $6.18
  14. v13Omit zero-count classes from the LightGBM class_weight maps0.452753 min · $7.52
  15. v14Group-aware anomaly reserve: fixed 0.08 galactic, product rule extragalactic0.452457 min · $8.27
  16. v1550 signed-log colour and extinction-adjusted peak features0.451559 min · $8.68
  17. v16Refit the vector-scaling parameters on the final specialist/colour posterior0.450864 min · $9.62
  18. v1710-50% ExtraTrees blend in the broad extragalactic branchseed-1 blends 0.46-0.5269 min · $10.43
  19. v18Per-band cumulative flux-time quantiles and half-max rise/fall/asymmetry0.447873 min · $11.39
  20. v19Per-band derivative quantiles, extrema and sign fractions (48)0.4575 min · $11.90
  21. v2011-phase fine per-band rest-frame interpolated templates (66)0.450878 min · $12.52

21 versions in 81 min for $13.49, the cheapest and fastest run. v1 and v11 are almost the whole drop; after v12 the self-check moved 0.005.

On the hidden set

held-out metricreward
shipped starter (class-freq prior)3.29170.00
author reference solution1.28230.30
author SOTA solver0.9861270.60
perfect prediction01.00
this run1.12080.4537
25 minwall clock
$0.72spend
2.8Mtokens
1versions, 1 kept

No trajectory curve: this run left one comparable self-check measurement, so there is nothing to plot against spend. The versions and what each one changed are below.

  1. v1Gal/exgal split, 183 features, 5-fold LightGBM ensemble, anomaly floor 0.10Replaces the prior-only baseline with per-band light-curve summaries under a galactic/extragalactic split.0.720725 min · $0.67

One snapshot in 25 min for $0.72; the run ended while writing a v2 feature script. v1 feeds hostgal_specz and raw sky position to the model.

On the hidden set

held-out metricreward
shipped starter (class-freq prior)3.29170.00
author reference solution1.28230.30
author SOTA solver0.9861270.60
perfect prediction01.00
this run1.82800.1872
720 minwall clock
$28.37spend
42.5Mtokens
12versions, 10 kept
0.75 1.50 2.25 3.00 $0 $7.5 $15 $22 cumulative spend on the run seed-0 self-check weighted log-loss, lower is better author SOTA solver · visible · 0.574300 v0 v1 v2 v3 v4 v5 v6 v7 v8 v9 v10 v11
keptrevertedno scoreturning point
  1. v0Shipped baseline: training-set class-frequency prior for every object3.40113 min · $0.47
  2. v1300+ hand-built light-curve features; split galactic/extragalactic LightGBMsPer-band moments, SNR, chi2, detection spans and rest-frame rise/fall into two LightGBMs split on hostgal_photoz == 0.0.550949 min · $2.73
  3. v2Per-band Bazin fits, plus a tuned anomaly rule for the unseen class 990.549170 min · $4.57
  4. v3Train-time augmentation: every object re-simulated 6x further awayAttacks train-to-test shift: objects re-simulated dimmer and time-dilated on their own cadence, re-noised, at half weight.0.5163115 min · $7.09
  5. v4Lomb-Scargle periodogram features for galactic objectsCV worsened, not run147 min · $8.53
  6. v52-D Gaussian-process (time x wavelength) smoothing of each light curveOne interpolated flux surface per object replaces hand-cut summaries; peaks, widths, fluences, colours read off a rest-frame grid.0.4257242 min · $11.12
  7. v6Anomaly rule refit on ten leave-one-class-out pseudo-anomaly runs0.4257273 min · $12.32
  8. v7GP features at three rest-frame timescales (6, 20, 60 days) instead of onemeasured only at v8344 min · $14.54
  9. v8Engineering hardening: BLAS thread pinning, float32 blocks, canonical rows0.4043521 min · $22.21
  10. v9GP shape normalised by each band's own peak; magnitudes at photoz +- errablation, no gain533 min · $23.25
  11. v10Rare classes get 12 augmented copies instead of 60.4038546 min · $23.95
  12. v11Hierarchical extragalactic head, blended 0.7 with the flat 9-class model0.3931605 min · $26.23

12 versions in 12 h for $28.37. Most wall time is full-scale dry runs and 5-fold CV, not edits; the 720-min cap cut the run off mid-experiment.

On the hidden set

held-out metricreward
shipped starter (class-freq prior)3.29170.00
author reference solution1.28230.30
author SOTA solver0.9861270.60
perfect prediction01.00
this runnot scored0