Repository navigation
Fix CSR Spearman scores and pbmc_multiome failures, add a seed to all methods - #83
Merged
Merged
Conversation
…rman scores dynutils::spearman_rank_sparse() ranks along the compressed dimension, which is a column only for CSC. ss_opm writes its predictions as CSR, so its per-cell and per-gene Spearman correlations were computed on ranks along the wrong axis on every dataset. Convert the solution and the prediction to CSC after reading them, and add a component test that scores a prediction as CSR and as CSC against dense ranks. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…bit-integer LAPACK scipy's 32-bit-integer OpenBLAS Cholesky reports the kernel matrix as not positive definite once a half of the batches holds more than ~30-46k cells, so the method failed on pbmc_multiome ATAC -> GEX in 0.2.0. Also ask for veryhighmem (118 GB peak) and veryhightime (GEX -> ATAC hit hightime's 8 hours). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
split() densified whole training and validation folds (143 GB for the ATAC input of pbmc_multiome), so ATAC -> GEX failed on it in every run since run_2026-08-14. utils.SparseRows serves one batch at a time as dense tensors through a BatchSampler, drawing the same batches as DataLoader(shuffle=True) did; the unused counts layers are dropped after reading. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Rerunning the benchmark did not reproduce its predictions: guanlab_dengkw_pm's and knnr_py's truncated SVDs, the lmds landmarks of lm and knnr_r, random_predict, the scvi-tools and pynndescent steps of cellmapper, and the training of simple_mlp, novel, babel and senkin_tmp's networks were unseeded. src/utils/seed.py seeds python, numpy, torch and tensorflow and makes them use deterministic GPU algorithms (also for the already seeded ss_opm, scipenn and scbutterfly); the R components call set.seed(). Methods without one get a --seed argument (default 0). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
rcannood
reviewed
Oct 27, 2026
rcannood
reviewed
Oct 27, 2026
…l, not its integer width
5 of 8 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Describe your changes
Fixes the wrong Spearman scores and the three failed runs of 0.2.0, and adds a
--seedto all methods, controls andrun_benchmark.correlation: Spearman scores of CSR matricesdynutils < 1.0.13 ranks a CSR matrix along the wrong axis. In 0.2.0 this hit
ss_opm, which writes CSR, on every dataset, and every method on GEX -> ATAC, whose solution is stored as CSR.dynutils 1.0.13 fixes this, but the metric also converts both matrices to CSC, so the scores don't depend on the dynutils version in the image. A new component test (
test_prediction_layout.py) scores a prediction as CSR and as CSC, and checks both against dense ranks.Scoring the 176 predictions of the rerun with and without this fix, only
mean_spearman_per_cellandmean_spearman_per_genechange:ss_opm, every datasetguanlab_dengkw_pm: failed on bothpbmc_multiomedatasetsLinAlgError: Internal potrf return info = [49313]. The kernel ridge regression is now solved withnumpy.linalg.solve()instead ofscipy.linalg.cho_factor(). Where the Cholesky works, the coefficients agree to 6e-13.cho_factor()fails at 66k cells withSkylakeXon the Cascade Lake workers of de.NBI, and succeeds withHaswell(on an AMD CPU, or withOPENBLAS_CORETYPE=Haswellon the same worker).numpy.linalg.solve()works on those same workers: at 66k cells on a Cascade Lake worker withSkylakeX,cho_factor()failed with the same49313, andsolve()took 270 s on 30 threads, with a largest residual of 9e-13.hightime. The component now asks forveryhightimeandveryhighmem. In the rerun, ATAC -> GEX peaked at 112 GB and took 2.5 h, and GEX -> ATAC took 6.6 h on 30 cores.simple_mlp: failed onpbmc_multiomeATAC -> GEXsplit()densified whole folds, 143 GB for this dataset. The inputs and targets now stay sparse and only one batch at a time is densified, drawing the same batches as before. Training now takes 25 min.Seeding
Rerunning the benchmark changed many scores by up to 0.02, because several methods had unseeded steps.
--seedis part of the method and control method apis (default 0). Wrappers forward it to their train component.run_benchmark --seedpasses it to every method and control. Aseedin a paramset takes precedence.src/utils/seed.pyseeds python, numpy, torch and tensorflow, and switches them to deterministic GPU algorithms.guanlab_dengkw_pm(was 1000),novel(1),ss_opmandsenkin_tmp(42) andscbutterfly(19193), so their predictions differ from those in the rerun above.--seeddoesn't change the data splits and SVDs that keep a fixed seed: theKFoldofsenkin_tmp, the batch SVD ofss_opm, the LSI ofnoveland the validation split ofscbutterfly.Checklist before requesting a review
I have performed a self-review of my code
Check the correct box. Does this PR contain:
Proposed changes are described in the CHANGELOG.md
CI Tests succeed and look good!
numpy.linalg.solve()works onpbmc_multiome-sized systems on a de.NBI worker