- Added a
seedargument toRegDiffusionTrainerfor fully reproducible runs. When set, Python, NumPy, and PyTorch RNGs are seeded and cuDNN is put in deterministic mode. Two runs with the same seed now produce bit-identical adjacency matrices, verified across separate processes and under AMP,torch.compile, gradient accumulation, andtrain_split < 1.0. Without a seed (the default), runs remain non-deterministic.
- Fixed
RegDiffusionTrainer.train(n_steps=...)silently ignoring its argument. Both the normal and gradient-accumulation branches hardcodedn_steps=None, so training always ran for then_stepsgiven at initialization. - Fixed the L1 sparsity penalty being computed on signed adjacency values in the base
RegDiffusionmodel. Soft thresholding preserves sign, so the penalty could in principle be reduced by making inhibitory (negative) edges more negative. Both models now share a singleget_sparse_loss()that takes the mean absolute value over off-diagonal entries. In practice this does not change results — negative entries land in the soft-threshold dead zone, where both the output and its gradient are zero — and BEELINE metrics are unchanged; the penalty is now correct by construction rather than by accident. RegDiffusionME.get_sampled_sparse_loss()is renamed toget_sparse_loss()and now excludes diagonal samples, matching the base model, whoseget_adj_()masks the diagonal.- Registered the sampled adjacency index tensors (
sampled_adj_row/col_nonparam) as buffers instead ofnn.Parameter. These are integer indices, not learnable weights, and they no longer appear inmodel.parameters().state_dictkeys are unchanged, so existing checkpoints still load. - The sparse loss is no longer computed during the warmup window, where it is discarded.
- Extended the
tqdm.autoprogress-bar fix from 0.2.2 (which coveredtrainer.py) to the remaining progress bars ingrn.pyand thedatamodule, so dataset downloads and edgelist extraction also render properly in notebooks.
- Avoid large progress printing in terminal
- Added sparse matrix support for
RegDiffusionTrainer. Theexp_arrayargument now accepts scipy sparse matrices (e.g.adata.X) directly. Normalization statistics are computed in chunks and each sample is normalized on-the-fly during training, so the full dense matrix is never materialized. This enables training on datasets with 1M+ cells without excessive memory usage. - Updated CLI (
regdiffusioncommand) to handle sparseadata.Xfrom H5AD files, including sparse-safe data validation and log-transform vialog1pon non-zero entries.
- Removed three
(n_gene, n_gene)helper matrices (zeros_nonparam,eye_nonparam,mask_nonparam) fromRegDiffusion, replacing them with inline computations. Saves ~4.8 GB persistent GPU memory for 20K genes with no impact on model accuracy.
- Added
RegDiffusionME, a memory-efficient model variant enabled viamemory_efficient=TrueinRegDiffusionTrainer. Reduces peak GPU memory by ~45% with no impact on accuracy. Uses a custom autograd function for soft thresholding (boolean masks instead of float32 tensors) and sampled sparse loss (avoids materializing full adjacency matrix for L1 regularization). Benchmarked on all 7 BEELINE datasets with identical AUROC/AUPRR/EPR. - Added automatic mixed precision (AMP) support via
use_amp=TrueinRegDiffusionTrainer. Uses bfloat16 for forward pass and loss computation, reducing memory for autograd-saved activations while keeping model parameters in float32. Requires Ampere or newer GPU.
- Fixed
I_minus_A()usingself.traininstead ofself.training, causing dropout to always apply during inference - Fixed missing
selfparameter inGRN.remove_weak_edges() - Fixed
GRN.get_edgelist()incorrectly passingselftoextract_edgelist() - Fixed external logger not being assigned in
RegDiffusionTrainer.__init__() - Fixed
forward()crash whenn_celltype=Noneby adding conditional cell type embedding