feat: Add DRVI#3866
Conversation
…ative binomial in DRVI
Resolve CHANGELOG.md conflict (keep DRVI entry alongside new main entries). Jax removal and the external cyclic-loader refactor from main auto-merged cleanly with the DRVI additions. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…loader and improve docstrings
…ve interpretability; add tests for decoder reuse weights and split aggregation.
|
The code is ready for review. Here are some TODOs in my list that will be issues in the next few days:
After the first iteration of review/changes, I will finally run the DRVI benchmark to make sure it performs the same. |
ori-kron-wis
left a comment
There was a problem hiding this comment.
overall looks very good. several few points to think about
for more information, see https://pre-commit.ci
# Conflicts: # CHANGELOG.md
|
Are there any notable differences between this implementation and the drvi-py standalone one? I trained models with drvi-py and am considering whether to re-train with this implementation once it's merged/released. Thanks! |
|
Hi @cvduffy, I'm not changing any of DRVI's logic for the scvi-tools port, which means no retraining will be needed! I'll also do my best to add a function/snippet in drvi-py for backward compatibility, making it easy to move already-trained models over to the new scvi-tools version (but this may take a bit of time). |
|
@ori-kron-wis Only two things from my side:
|
@moinfar Lets not change scvi-tools' n_epochs_kl_warmup right now to be reproducible (perhaps on a new branch) and add the additional DRVITrainingPlan class to DRVI |
|
Thanks for the comments. It makes sense to keep changes minimal for now and set n_epochs_kl_warmup manually. One update: I benchmarked this port against DRVI on drvi-py. It looked good, but the results were not identical. So, in this commit (632ee48), I fixed one difference that I missed: decoder should not have dropout. There is still one minor difference in the dispersion initialization that I prefer not to change to be more similar to scvi. But if the results were significantly different, I would change that as well and benchmark again. I am running the benchmark again and will get back to you soon. |
Do you think we can push it today or tomorrow? As we want to have it in the new release which is ready. |
|
Yes. The branch can be merged. Details: |
|
@moinfar What about DRVITrainingPlan then? We keep it manually for now? |
|
Yes. I think you also suggested keeping it manual. Right? I am totally fine with it. If you prefer the DRVITrainingPlan, I can create it in minutes (already a git patch). |
Sorry, yes, there was a misunderstanding - let's add DRVITrainingPlan as its a good practice to have it and it guarantees the correct usage as you described. |
|
No worries. Thanks for the clarification. |
Backport PR #3866: Add DRVI Co-authored-by: Amir Ali Moinfar <moinfar.amirali@gmail.com>
|
@cvduffy |
Add DRVI
This PR adds DRVI as
scvi.external.DRVI.This is a rewrite of #3699, reusing scvi-tools functionality and removing extras as much as possible.
Design:
DRVInow subclassesscvi.model.SCVIdirectly and only changes what is actually different:DecoderDRVIextendsDecoderSCVI,SplitFCLayersextendsFCLayers). Disentanglement is induced in the decoder — the latent is reshaped inton_split_latentindependent groups, each decoded separately, then aggregated.batch_representation="embedding"), RNASeqMixin, size factors, minified mode, scArches transfer, training via a datamodule, andsetup_anndata.To enable the decoder swap without forking
FCLayers,scvi.nn.FCLayersgained a few small overridable seams (_build_layer,_apply_layer,_apply_batch_norm). These are behavior-preserving for existing models (SCVI, ...) —SplitFCLayersoverrides them to use per-split weights.Likelihoods
In addition to scvi's
nb,zinbandpoisson, DRVI adds log-space nb:pnb(default of DRVI) — parametrized NB, same mean asnbbut evaluated in log space via the newLogNegativeBinomialdistribution (should be numerically more stable but equivalent to scvi'sNegativeBinomial).normal/normal_unit_var— Gaussian with the mean modeled directly (no library/softmax), forcontinuous / log-normalized input.
Interpretability
Because the decoder is additive over splits, each latent dimension's contribution to every gene can be measured directly. The included methods —
set_latent_dimension_stats,calculate_interpretability_scores,get_interpretability_scores— quantify these contributions and extract top genes per dimension.Dependencies
Adds
stacked-linear>=0.2.0(used for the parallel per-split linear layers). That package requires no dependencies other than PyTorch. Also, the same logic can be included as a snippet instead.