scvi-tools 是一套面向单细胞组学的深度生成模型封装(Gayoso 等,2022;github.com/scverse/scvi-tools,BSD-3-Clause 许可)。其中单细胞 RNA 测序的核心模型为 scVI(无监督、批次校正的隐空间嵌入)与 scANVI(在 scVI 基础上增加分类头,用于半监督的细胞类型标签迁移)。两者都要求输入原始整数 UMI 计数,并输出低维的 X_scVI / X_scANVI,可直接用于 scanpy 的 neighbors → leiden → umap 流程。
一、主要能力
-
scVI:批次校正的隐空间嵌入。示例流程如下:读取 h5ad 数据;在归一化/log1p 之前先把原始计数保存到 adata.layers["counts"];归一化与 log1p 仅供 HVG 选择与绘图使用;挑选高变基因时使用 batch_key;随后以 setup_anndata 指定 layer="counts" 与 batch_key,构建 SCVI 模型(如 n_latent=30)并训练(max_epochs=200、early_stopping、accelerator="gpu"、devices=1);最后用 get_latent_representation() 写入 adata.obsm["X_scVI"],用 get_normalized_expression(library_size=1e4) 写入 adata.layers["scvi_normalized"]。
-
scANVI:从部分标注的参考数据迁移标签。可通过 SCANVI.from_scvi_model 由已有 scVI 模型构建,指定 labels_key 与 unlabeled_category(如 "Unknown"),训练后写入 adata.obsm["X_scANVI"],并以 predict() 得到 adata.obs["pred_cell_type"]。注意 accelerator="gpu", devices=1 是 PyTorch-Lightning 写法;旧版 use_gpu= 参数已在 scvi-tools 1.x 移除,使用会抛 TypeError。
-
差异表达分析:调用 model.differential_expression(groupby="leiden", group1="3", mode="change", delta=0.25)。如需一对多比较,应省略 group2——"rest" 是 scanpy rank_genes_groups 的约定,不是 scvi-tools 的;在 scvi-tools 中 group2 是字面类别名,写 "rest" 会匹配零个细胞。从 scvi-tools 1.4 起默认 mode="vanilla",其列包括 proba_m1、proba_m2、bayes_factor、scale1、scale2、raw_mean1、raw_mean2、non_zeros_proportion1、non_zeros_proportion2、raw_normalized_mean1、raw_normalized_mean2、comparison、group1、group2,不含 lfc_、proba_de、is_de_fdr_。若需要 lfc_mean / lfc_median / proba_de / is_de_fdr_0.05,应传 mode="change"。排序可按 proba_de(若刻意使用 vanilla 模式则按 bayes_factor)。
二、输出格式
adata.obsm["X_scVI"] 为 n_cells × n_latent 的批次校正嵌入;adata.obsm["X_scANVI"] 为标签感知嵌入(能更好分离已知类别);adata.obs["pred_cell_type"] 为 scANVI 预测的每细胞标签;adata.layers["scvi_normalized"] 为解码后的、按文库大小归一化的表达;差异表达数据框则在 mode="change" 下提供每基因的 lfc_* / proba_de。
三、远程计算
超过 5 万细胞建议使用 A100 级 GPU。预置的 singlecell_gpu Modal 环境包含 scvi-tools 1.4.2、scanpy 1.11.5、anndata 0.11.4;先通过 compute_details({provider: 'byoc:modal', mode: 'read'}) 读取当前镜像引用,再用 host.compute.create('byoc:modal', provider_params=...) 创建计算实例并 submit_job 提交任务(inputs 指定数据与脚本、command="python pipeline.py"、outputs=["out/**"])。任务提交后内核不阻塞,需调用 wait_for_notification 等待通知;收到 compute_done 后使用 save_artifacts(payload["featured_files"])。若要获取完整结果字典,需重新进入内核,单独绑定 compute 句柄(而非 job)并调用 attach_job(job_id).result(),因为 .close() 在句柄上而非 job 上。注意 h5ad_safe_obs 辅助函数只会自动加载到本地分析内核,在 Modal 上运行的 pipeline.py 需在脚本顶部粘贴该辅助函数(或内联 pd.Index(np.asarray(..., dtype=object)) 转换)后再调用 .write_h5ad()。
四、常见问题与排查
-
差异表达默认 mode="vanilla"(scvi-tools ≥1.4):若按 lfc_mean / proba_de 排序会报 KeyError,应传 mode="change",或在 vanilla 模式下按 bayes_factor 排序。
-
adata.obs 使用 string[pyarrow](ArrowStringArray)时,.write_h5ad() 会报 IORegistryError;应在写入前用 adata.obs = h5ad_safe_obs(adata.obs)(必要时也处理 adata.var)。仅用 .astype(str) 不够,因为对 pyarrow 支撑的 Index/Series 仍返回 Arrow 支撑的数组,需经 np.asarray(..., dtype=object) 往返转换。anndata.settings.allow_write_nullable_strings = True 也无法覆盖 Arrow 字符串。
-
use_gpu= 参数:在 1.x 中已移除,会报 TypeError;请用 accelerator="gpu", devices=1。
-
将 log 归一化数据传给 setup_anndata:会产生静默错误结果,scVI 的负二项似然需要原始整数计数。应在 normalize/log1p 前把计数存入 adata.layers["counts"],并传 layer="counts"。
-
layer="counts" 指向 log/浮点数据时,会报非负整数相关的 ValueError 或负二项损失发散,需恢复原始计数。
-
报 MisconfigurationException: No supported gpu backend found 表示无可用 CUDA,可去掉 accelerator/devices 回退 CPU,或改用远程计算。
-
编写摘要或打印时出现 UnicodeEncodeError:容器缺少 LANG 使 Python 默认 ASCII,可用 encoding="utf-8" 打开文件,或在脚本顶部 sys.stdout.reconfigure(encoding="utf-8")。预置 singlecell_gpu 环境已设 PYTHONIOENCODING=utf-8,仅自建镜像会遇到。
-
job 句柄报 AttributeError: object has no attribute 'close':因为把 .close() 叫在了 job 上,应单独绑定 compute 句柄并对其调用 close。
五、后续步骤
可在 X_scVI 上用 scanpy 聚类(sc.pp.neighbors(use_rep="X_scVI") → sc.tl.leiden → sc.tl.umap);若要做空间解卷积,可在 scRNA-seq 参考上训练 cell2location / DestVI / Tangram。
关于收费、价格与平台可用性,资料未提供相关信息。