Skip to content

HEALPix Curriculum - #2795

Open
TillHae wants to merge 22 commits into
ecmwf:developfrom
TillHae:thauer/develop/healpix-curriculum
Open

HEALPix Curriculum#2795
TillHae wants to merge 22 commits into
ecmwf:developfrom
TillHae:thauer/develop/healpix-curriculum

Conversation

@TillHae

@TillHae TillHae commented Sep 1, 2026

Copy link
Copy Markdown
Contributor

Description

This adds a HEALPix curriculum to our training pipeline. During my bachelor thesis, I found that starting at a lower HEALPix Level (HL) and stepping it up during training cuts early compute time by almost 95%, all without hurting the final model performance.

How it works

  • Easy config: Uses the healpix_curriculum parameter to set how many isteps each HL should run for.
  • Dynamic streams: Uses OmegaConf interpolation (e.g., streams_directory: "${curriculum_streams.${healpix_level}}") so the datasets swap automatically as the HL goes up.
  • Auto-restarts: run_train.py now handles the transitions. When a stage ends, it stops the mini-epoch, saves a checkpoint and immediately starts the next stage within the same Slurm job.

FYI

  • Configs: I threw in config_curriculum.yml just to make reviewing the OmegaConf logic easier. Before merging it can be deleted so we don't clutter the repo with new configs.

Issue Number

Closes #2794

@kctezcan

Is this PR a draft? Mark it as draft.

Checklist before asking for review

  • I have performed a self-review of my code
  • My changes comply with basic sanity checks:
    • I have fixed formatting issues with ./scripts/actions.sh lint
    • I have run unit tests with ./scripts/actions.sh unit-test
    • I have documented my code and I have updated the docstrings.
    • I have added unit tests, if relevant
  • I have tried my changes with data and code:
    • I have run the integration tests with ./scripts/actions.sh integration-test
    • (bigger changes) I have run a full training and I have written in the comment the run_id(s): launch-slurm.py --time 60
    • (bigger changes and experiments) I have shared a hegdedoc in the github issue with all the configurations and runs for this experiments
  • I have informed and aligned with people impacted by my change:
    • for config changes: the MatterMost channels and/or a design doc
    • for changes of dependencies: the MatterMost software development channel

FastEvaluation

  • I have updated the public documentation if necessary

@github-actions github-actions Bot added infra Issues related to infrastructure model Related to model training or definition (not generic infra) labels Sep 1, 2026
@TillHae

TillHae commented Sep 2, 2026

Copy link
Copy Markdown
Contributor Author
n8cvp0hb_train_avg

Here are the results I got from my test run. It works pretty good! I had some problems with the configs and auto-restarting after a transition, but was able to make everything work with some help from AI.

I will do a self-review of my code on Friday.

@TillHae

TillHae commented Sep 9, 2026

Copy link
Copy Markdown
Contributor Author

I will do a self-review of my code on Friday.

Took me some time to get back to it, but it looks good.

@kctezcan do you have time to review it?

@TillHae
TillHae marked this pull request as ready for review September 9, 2026 09:07

@clessig clessig left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the implementation. Some high-level comments for the moment.

dist.all_reduce(l_seed, op=torch.distributed.ReduceOp.SUM)
cf.data_loader_rng_seed = l_seed.item()

if dist.is_initialized():

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is this change in the PR? It seems unrelated to the functionality that is targeted.

assert isinstance(c, Config)
c = _sanitize_time_keys(c)

if c.get("healpix_curriculum"):

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we avoid this in config.py? And very specific functionality there turned out to be problematic.

@@ -0,0 +1,11 @@
healpix_curriculum:

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you explain what this config means / describes


try:
trainer.run(cf, devices)
from_run_id_iter = None

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This block does not belong to run_train.py. What is done here?

if self.cf.general.istep > 0 and is_root():
logger.info(f"Continuing run with learning rate: {self.lr_scheduler.get_lr()}")

if hasattr(self.cf, "healpix_curriculum") and self.cf.healpix_curriculum and is_root():

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be performed in a separate function


self.cf.general.istep += 1

if hasattr(self.cf, "healpix_curriculum") and self.cf.healpix_curriculum:

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's try to avoid this complexity in the main training loop. Can you make a suggestion?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

infra Issues related to infrastructure model Related to model training or definition (not generic infra)

Projects

Status: No status

Development

Successfully merging this pull request may close these issues.

HEALPix curriculum

2 participants