Graph Energy Matching (GEM)

July 9, 2026 ยท View on GitHub

Graph Energy Matching unconditional MOSES sampling animation

Official repository for Graph Energy Matching: Transport-Aligned Energy-Based Modeling for Graph Generation.

This v0.1 code release focuses on unconditional molecular graph sampling from the MOSES dataset. It covers:

  • transport-loss training on MOSES
  • transport + contrastive fine-tuning
  • unconditional MOSES FCD/metrics
  • unconditional MOSES sampling animations

For the continuous-data Energy Matching codebase, including a 2D toy Jupyter notebook, see EnergyMatching and its toy example.

Setup

conda env create -f environment.yaml

Data (MOSES)

MOSES CSVs are downloaded automatically on first use and cached under data/moses/moses_pyg/.

Checkpoints

The exact MOSES checkpoint used for the paper/demo will be released soon.

Train Transport Loss

Start from scratch and use transport loss only:

python src/gem/train_gem_ebm_fm.py \
  --config-name gem_ebm_fm_moses_ver3.yaml \
  train.max_iters=390000 \
  train.batch_size=128 \
  fm.batch_size=128 \
  train.save_every=30000 \
  train.lambda_fm=1.0 \
  train.lambda_cl=0.0 \
  train.cl_steps=0 \
  train.resume=null \
  train.init_ckpt=null \
  viz.enabled=false \
  viz.run_during_training=false \
  ++sample.evaluate=false

Tune Mixing Proposal Sampler

After transport-loss training, calibrate the mixing proposal sampler so it can traverse the learned energy landscape. The resulting parameters can be used for contrastive fine-tuning.

python src/gem/cali_params.py \
  --config-name cali_params_moses.yaml \
  train.resume=/path/to/transport/checkpoint.pt \
  train.init_ckpt=null \
  cali.search.n_trials=100 \
  cali.N_noise=32 \
  cali.N_data=0 \
  cali.chain_warmup.steps=225 \
  cali.steps=200

For a new transport checkpoint, replace the calibrated sampler values below: train.dl_beta, train.dl_lambda_X, and train.dl_lambda_E.

Fine-Tune Transport + Contrastive

Start from a transport-loss checkpoint:

python src/gem/train_gem_ebm_fm.py \
  --config-name gem_ebm_fm_moses_ver3.yaml \
  train.init_ckpt=/path/to/transport/checkpoint.pt \
  train.resume=null \
  dataset.filter=true \
  train.max_iters=500 \
  train.lr=1e-5 \
  train.batch_size=128 \
  fm.batch_size=128 \
  train.save_every=100 \
  train.lambda_fm=1.0 \
  train.lambda_cl=0.1 \
  train.cl_warmup_iters=100 \
  train.cl_loss_threshold=0.2 \
  train.cl_steps=200 \
  train.proposal=dlangevin_vec \
  train.dl_beta=8.76576 \
  train.dl_lambda_X=0.326323 \
  train.dl_lambda_E=2.36417 \
  train.gamma_train=0.5 \
  train.chain_warmup.enabled=true \
  train.chain_warmup.steps=225 \
  train.chain_warmup.proposal=simple_ver2 \
  train.chain_warmup.simple_n_edits=1 \
  viz.enabled=false \
  viz.run_during_training=false \
  ++sample.evaluate=false

Use train.init_ckpt to start fine-tuning from transport weights. To continue an interrupted fine-tune run, use train.resume=... train.init_ckpt=null.

Evaluate FCD And Metrics

This writes metrics_over_time.json, metrics_over_time.csv, and generated SMILES tables:

python src/gem/metrics_over_time.py \
  --config-name gem_metrics_over_time_moses.yaml \
  metrics_run.checkpoint=/path/to/model.pt \
  metrics_run.total_samples=25000 \
  metrics_run.batch_size=512 \
  metrics_run.fcd_reference_size=25000 \
  metrics_run.steps='[0,50,100,200,350]'

MOSES unconditional animation

python src/gem/animate_energy.py \
  --config-name gem_ebm_animation_moses_public.yaml \
  viz.checkpoint=/path/to/model.pt

Citation

If you use this code, please cite the Graph Energy Matching paper. The MOSES dataset is from Polykovskiy et al. (2020).

Parts of the graph transformer, MOSES data processing, molecular metrics, and discrete flow-matching utilities are adapted from DeFoG (Qin et al., 2025).

@article{balcerak2026graphenergymatching,
  title={Graph Energy Matching: Transport-Aligned Energy-Based Modeling for Graph Generation},
  author={Balcerak, Michal and Shit, Suprosanna and Prabhakar, Chinmay and Kaltenbach, Sebastian and Albergo, Michael S. and Du, Yilun and Menze, Bjoern},
  journal={arXiv preprint arXiv:2603.23398},
  year={2026}
}