Tasks/Earth & Energy/Weather & Climate

Emulate sub-grid convective heating and precipitation from an atmospheric column's state

Emulate sub-grid convection for a climate model

climsim_convection_param Earth & Energy Weather & Climate
instruction.mdthis is what the agent is given

You inherit a feature-blind baseline: for every input row it predicts the training-set mean of each output quantity, completely ignoring the atmospheric state it was given. Your goal is to raise the R^2 of your predicted sub-grid-scale convective tendencies (higher is better, 1.0 = perfect); a sealed verifier re-trains and re-runs your solver on a HIDDEN, later block of time steps and scores it.

Hard Constraints

  • You may only edit code under /app/methods/main/; you may add sibling .py modules.
  • Keep the entrypoint signatures train(train_input: np.ndarray, train_target: np.ndarray) -> None and predict(X: np.ndarray) -> np.ndarray, where predict returns an array with one row per row of X, in the same order as X, shape (len(X), 27), every entry a finite float.
  • numpy + pandas + scikit-learn + scipy + the standard library only -- no other third-party packages (in particular, no torch/xgboost/lightgbm/catboost -- the verifier image does not have them; scikit-learn already ships several strong, multi-output-capable regressors). Any other import makes the submission score 0.
  • Your submission is graded under a wall-clock budget. The verifier re-runs your train() + predict() in a subprocess capped at 3600 s, inside a container declared at 4 CPUs / 6144 MiB; the whole verifier stage is capped at 9000 s. Grading is a much bigger job than your self-check: selfcheck.py trains on 122,880 rows and predicts 30,720, while the graded run trains on all 153,600 visible rows and predicts 336,384 rows -- about 11x the self-check's prediction workload. "It finished locally" therefore does not imply "it finishes at grading time"; size your method for the 11x. A run killed by the time or memory cap produces no predictions and scores 0.
  • Your solver must be deterministic given the shipped training 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).
  • The agent phase runs behind a network allowlist (only the model API is reachable), enforced outside your container. The public source dataset this task is built from ships every row's true target -- including whichever time period is held out for grading -- in files hosted online, so fetching it would be a real shortcut, not a hypothetical. Treat any attempt to fetch external climate datasets or model archives at runtime as against the spirit of the task even if a particular request happens not to be blocked.
  • /dev/shm is only 64 MiB (the container default, here and in the grader) and cannot be enlarged. A shared segment larger than that is created successfully and only faults on the first write, killing the process with SIGBUS and no traceback -- no output, so the submission scores 0. If you parallelise with multiprocessing.shared_memory, or hand very large arrays to joblib/loky workers, keep the data in ordinary heap memory or point the temp folder at a normal filesystem path.
  • 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_input.npy: (153600, 124) float32 array. Each row is one atmospheric column's physical state at one grid point and time: columns [0:60] = air temperature at 60 vertical levels, [60:120] = specific humidity at 60 vertical levels, [120] = surface pressure, [121] = incoming solar insolation, [122] = surface latent heat flux, [123] = surface sensible heat flux.
  • /app/data/train_target.npy: (153600, 27) float32 array, the 27 quantities you must predict, RAW physical units, same row order as train_input.npy: columns [0:26] are the heating-rate tendency at 26 mid/low-troposphere vertical levels, column [26] is the convective precipitation rate. Rows span a subsample of time steps and grid columns from a simulated year -- your held-out grading set is a different, disjoint period from the same simulation you do not otherwise have access to.
  • /app/methods/main/solver.py: the baseline solver (predicts the training-set mean of each output column for every row) -- this directory is what gets graded. Improve it in place or rewrite the algorithm entirely. Matching the baseline earns nothing.
  • /app/score.py: the exact R^2 formula the verifier uses (the formula is public; only the true held-out values are sealed). Read it to see precisely how you are scored, including the log1p transform applied to the last (precipitation) column before scoring.
  • /app/selfcheck.py: a free, unlimited local dry-run (python /app/selfcheck.py) that fits on an internal time-based split of the visible rows and prints the proxy R^2 per output column. It is a proxy only -- the real held-out period is a different, later, disjoint block of time, so do not overfit to this split.

What You Submit

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

def train(train_input: np.ndarray, train_target: np.ndarray) -> None:
    # Called once. train_input: (n, 124) float array (see above). train_target: (n, 27) float
    # array, your training targets. Fit whatever state you need and stash it (module globals are
    # fine -- a fresh process calls train() then predict()).
    ...

def predict(X: np.ndarray) -> np.ndarray:
    # X: (m, 124) float array, FEATURES ONLY. Return an (m, 27) array, one predicted row per input
    # row, SAME ROW ORDER as X, RAW units (do not apply the log1p transform yourself).
    ...

There is no submit step and no per-attempt feedback on the real held-out period -- 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 visible re-training rows, then predict() on a HIDDEN, later block of time steps you never saw, and scores it with the R^2 formula in score.py (higher is better, 1.0 = perfect):

for each of the 27 output columns, compute a per-grid-point R^2 over the held-out time window (comparing your prediction to the true value, relative to that grid point's own temporal variance), average across grid points (excluding grid points whose true value is nearly constant over the window -- see score.py), then average across the 27 columns. The last column (precipitation) is scored in log1p space.

Your score improves monotonically as this R^2 rises, so driving it up is always the goal -- there is real headroom between the shipped baseline and a well-tuned solution, including past what a plain off-the-shelf regressor reaches. Any crash, wrong-shape output, or a non-finite prediction scores the whole submission 0.

Metric

27-channel mean R^2 on the sealed later time block · higher is better

Per-grid-point R^2 for 26 heating levels plus PRECC (log1p space), each floored at -1, then averaged.

anchorvisible setheld-outreward
Bper-column median constant-0.2248-0.43560.00
Rreference solution0.14250.13060.30
SSOTA solution0.42780.44900.60
Utheoretical bound1.00001.00001.00
normalisation
m <= B0
B < m <= R0.3 * (u(B) - u(m)) / (u(B) - u(R))
R < m <= S0.3 + 0.3 * (u(R) - u(m)) / (u(R) - u(S))
m > S0.6 + 0.4 * (m - S) / (U - S)

m = this run's held-out metric  ·  B = per-column median constant  ·  R = reference solution  ·  S = SOTA solution  ·  U = theoretical bound

u(x) = log(1 - x). Lower segments are linear in log error; the top is linear in R^2 because U = 1 is a hard bound. Mapped once, capped at 1.

Rollouts

720 minwall clock
$23.12spend
34.9Mtokens
5versions, 5 kept
0.27 0.30 0.33 0.36 0.39 0.42 $0 $4 $8 $12 $16 cumulative spend on the run self-check proxy: 27-channel mean R^2, higher is better SOTA solution · visible · 0.4278 v1 v2 v3 v4 v5
keptrevertedno scoreturning point
  1. v1numpy MLP 256x2, dropout 0.2, 8 seeds, samples weighted by 1/grid-point varianceThe metric divides each error by that grid point's own variance, so weights become 1/var; effective n falls to ~13%.0.280145 min · $3.50
  2. v2Blend the net ensemble 50/50 with per-channel HistGradientBoosting treesTwo families with different biases, both fitted under the metric's weights. Trees stay per channel; channels weigh equally.0.2982176 min · $8.88
  3. v3Trees get first vertical differences of T and q; pre-binned features cut each fit 5xVertical differences expose the lapse rate and moisture gradient the raw profile hides. Tuning metric 0.200 -> 0.247.self-check not run337 min · $13.55
  4. v4Tree capacity re-tuned with the freed budget (127 leaves, l2=20); blend 0.750.3492434 min · $15.08
  5. v5Same difference features for the nets; re-blend 0.6/0.4; chunked float32 predict0.3594503 min · $17.00

Five snapshots over 8.4 h, the last at $17.00 of $23.12. Grid one-hots, per-grid climatology, lagged and PCA features were dropped unversioned.

On the hidden set

held-out metricreward
per-column median constant-0.43560.00
reference solution0.13060.30
SOTA solution0.44900.60
theoretical bound1.00001.00
this run0.40350.5478
138 minwall clock
$30.25spend
49.9Mtokens
26versions, 19 kept
-0.50 -0.25 0 0.25 0.50 $0 $7.5 $15 $22 $30 cumulative spend on the run self-check proxy: 27-channel mean R^2, higher is better SOTA solution · visible · 0.4278 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
keptrevertedno scoreturning point
  1. v0Shipped baseline: global target mean per column-0.57261 min · $0.23
  2. v1ExtraTrees multi-output, 64 trees, leaf 4; precipitation fitted in log1p space0.20952 min · $0.35
  3. v2Separate 26-output tendency and precipitation forests; 10% grid-climatology blend0.21455 min · $0.71
  4. v3Back to one shared 27-output forest, 128 trees, leaf 8, blend 7.5%0.22799 min · $1.19
  5. v4Standardised 256x128 MLP with early stopping-0.229113 min · $1.71
  6. v5Physical features: T x q, q - T, six-level layer summaries, vertical gradientsHand the forest what convection responds to -- moisture-temperature contrast and vertical structure -- not 124 raw numbers.0.263116 min · $2.05
  7. v6Append 28 per-grid input-climatology features; target blend down to 2.5%0.265619 min · $2.57
  8. v7Standardise transformed targets so tree splits weight channels like the metric0.265823 min · $3.17
  9. v8T-conditioned humidity anomalies, finer gradients, column moisture, flux terms0.279927 min · $3.78
  10. v9Eight PCA modes per profile, deep-layer humidity integrals, instability contrasts0.28640 min · $5.66
  11. v10Fit 16 standardised tendency PCA modes plus precip, reconstruct the profile0.286343 min · $6.24
  12. v11Per-grid inverse temporal-variance sample weights, clipped to [0.5, 2]Align the loss with the scorer, which normalises by each grid point's variance. First version with precipitation above zero.0.292646 min · $6.82
  13. v12Widen the metric-weight clip to [0.25, 4]0.289748 min · $7.29
  14. v1364-tree precipitation specialist averaged with the shared model in log space0.294455 min · $8.55
  15. v14Previous/next time-step increments for humidity, low-level T, surface forcing0.293759 min · $9.48
  16. v1540 moisture interactions with latent, sensible and solar surface forcing0.294563 min · $10.45
  17. v16Residualise on 50% of each grid's target climatology, restore after fitting0.277967 min · $11.47
  18. v17Forest counts 128/64 -> 192/96, nothing else changed0.295374 min · $13.07
  19. v18Precipitation specialist min_samples_leaf 8 -> 120.295484 min · $15.50
  20. v19Face/u/v and cyclic encodings of the fixed 384-column index0.291389 min · $16.67
  21. v20Add a 96-tree metric-weighted specialist for levels 16-250.298297 min · $18.82
  22. v21Add a 96-tree upper-level (L00-L07) specialistkilled, exit 137 at 289s106 min · $21.09
  23. v22Reallocate to 128 shared + 64 precip + 64 lower + 64 upper trees, blended 50%Height bands are different regression problems: three narrow forests on the memory that one wide one, and v21, overran.0.3046111 min · $22.37
  24. v23Specialist blend weights derived from the shared/specialist error covariance0.3068116 min · $23.88
  25. v24Chunk prediction into exact 64x384-row blocks to bound feature memory0.3068124 min · $26.13
  26. v25Scale min_samples_leaf with training size (10/15 at grading scale)0.3068136 min · $29.70

26 snapshots in 2h18 for $30.25. Two full-size rehearsals died with exit 137 -- v21 and a v24 dry run -- forcing the leaf scaling in v25.

On the hidden set

held-out metricreward
per-column median constant-0.43560.00
reference solution0.13060.30
SOTA solution0.44900.60
theoretical bound1.00001.00
this run0.34930.4906
131 minwall clock
-spend
-tokens
9versions, 9 kept
-0.9 -0.6 -0.3 0 0.3 0 20 40 60 80 agent step (this harness reports no tokens or timestamps) tuning-split combined R^2 (val 256-320), higher is better SOTA solution · visible · 0.4278 v0 v1 v2 v3 v4 v5 v6 v7 v8
keptrevertedno scoreturning point
  1. v0Shipped baseline: feature-blind mean predictor-0.8988
  2. v1ExtraTrees 50 trees depth 24 on physical features; HGB precipitation in log1pFirst use of the column state, with precipitation given its own model in the space the scorer reads.0.1843
  3. v2More trees, CAPE features, per-grid residual Ridge, 3-fold precipitation scale0.1865
  4. v3Two vertical heads, levels 0-19 and 20-25, on curated mid-troposphere featuresNear-surface heating answers to different inputs than the mid troposphere; give each band its own forest.0.1983
  5. v4Three vertical heads (0-9 / 10-19 / 20-25), 60/60/55 trees0.2077
  6. v5Two-seed ensemble of the 3-head forest, 50 trees each, vertical smoothing0.2149
  7. v6Per-grid precipitation scale 0.10 + 0.50 x training rain fractionShrink precipitation toward zero where a column rarely rains, so dry grid points stop dominating per-point R^2.0.2215
  8. v7Second shallow HGB for precipitation, blended 0.6/0.4only precip re-scored
  9. v8Precipitation blends 0.3 HGB + 0.2 HGB2 + 0.5 ExtraTrees, all in log1ponly precip re-scored

Nine snapshots over 131 min; the harness logs no token or cost figures. The clean holdout was read only at v0 and v7.

On the hidden set

held-out metricreward
per-column median constant-0.43560.00
reference solution0.13060.30
SOTA solution0.44900.60
theoretical bound1.00001.00
this run0.32650.4679
78 minwall clock
$13.18spend
17.0Mtokens
11versions, 10 kept
0.915 0.930 0.945 0.960 0.975 $0 $2.5 $5 $7.5 $10 cumulative spend on the run structured forward surrogate combined R^2, higher is better SOTA solution · visible: 0.4278 · off this scale v0 v1 v2 v3 v4 v5 v6 v7 v8 v9 v10
keptrevertedno scoreturning point
  1. v0Shipped baseline: feature-blind training-column meanno data, LFS stubs1 min · $0.15
  2. v1192-tree deterministic ExtraTrees, channels standardised, precipitation in log1p0.91915 min · $0.52
  3. v2Per-grid target centering and variance scaling; 224 trees; RH proxy and gradientsNormalise targets per grid point so tree splits see the same scaling the scorer applies when it divides by that point's variance.0.95768 min · $0.76
  4. v3Add an MLP; per-channel blend weights set on a 20% forward-time split, then refitA net and a forest fail differently; let a forward-in-time split choose the mix per channel instead of one global weight.0.9701914 min · $1.25
  5. v4Moist-static-energy parcel instability plus current-time global input summaries0.97065220 min · $1.80
  6. v5Forward split also picks output-manifold PCA rank and strength, no-op included0.97166426 min · $2.63
  7. v6Extra selection stage for target-variance shrinkage and MLP width0.97142430 min · $3.30
  8. v7Guarded temporal branch: state deltas must clear +0.002 internally to switch on0.97166436 min · $4.02
  9. v8Eight HGB regressors on leading target components, blend gated at +0.00020.97207853 min · $7.02
  10. v9HGB admitted only when the independent rank selector picks rank <= 16A high-rank falsification slice caught v8's boosters firing and losing; admit them only on independently detected low rank.0.97207859 min · $8.44
  11. v10Refit boosters on all rows using provisional early-stop iteration counts x1.100.97216668 min · $10.46

11 snapshots in 78 min for $13.18. Both shipped .npy files were 133-byte Git-LFS pointers, so the real proxy never ran on any version.

On the hidden set

held-out metricreward
per-column median constant-0.43560.00
reference solution0.13060.30
SOTA solution0.44900.60
theoretical bound1.00001.00
this run0.28820.4316
67 minwall clock
$0.51spend
2.1Mtokens
9versions, 9 kept
-0.50 -0.25 0 0.25 0.50 $0 $0.1 $0.2 $0.3 $0.4 cumulative spend on the run self-check proxy: 27-channel mean R^2, higher is better SOTA solution · visible · 0.4278 v0 v1 v2 v3 v4 v5 v6 v7 v8
keptrevertedno scoreturning point
  1. v0Shipped baseline: constant mean predictor-0.57261 min · $0.04
  2. v1Ridge on standardised inputs, precipitation target in log1p space-0.4611 min · $0.07
  3. v2Per-channel HistGradientBoosting, 50 iterationsDrop the linear fit: the response of convection to a column profile is not a linear map.0.11882 min · $0.10
  4. v3Same trees at 100 iterations0.1333 min · $0.12
  5. v4Vertical first differences plus per-profile mean and stdVertical differences expose the lapse rate and moisture gradient the raw 60-level profile hides.0.22866 min · $0.17
  6. v5Second differences, surface and top terms, interactions; 150 iterations0.250711 min · $0.21
  7. v6Back to 120 iterations for runtime margin0.247521 min · $0.27
  8. v7max_leaf_nodes 63; per-channel sequential loop printing progress0.264832 min · $0.34
  9. v8Cumulative profile integrals; lr 0.08, l2 0.5, 150 iterationsColumn-integrated water and heat below each level, the quantity that sets available convective energy.0.265858 min · $0.47

Nine snapshots in 58 min for $0.47 of $0.51. A tenth version retuned the precipitation channel to 0.2633 and was reverted unsnapshotted.

On the hidden set

held-out metricreward
per-column median constant-0.43560.00
reference solution0.13060.30
SOTA solution0.44900.60
theoretical bound1.00001.00
this run0.26180.4076