news 2026/9/12 3:59:37

knowledge-work-plugins scvi-tools 技能详解:基于 scVI 与 scANVI 的单细胞转录组批次效应校正与数据集整合实战

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
knowledge-work-plugins scvi-tools 技能详解:基于 scVI 与 scANVI 的单细胞转录组批次效应校正与数据集整合实战

knowledge-work-plugins scvi-tools 技能详解:基于 scVI 与 scANVI 的单细胞转录组批次效应校正与数据集整合实战

【免费下载链接】knowledge-work-pluginsOpen source repository of plugins primarily intended for knowledge workers to use in Claude Cowork项目地址: https://gitcode.com/GitHub_Trending/kn/knowledge-work-plugins

导读

本文是 bio-research/skills/scvi-tools 技能中「scRNA-seq 整合(scrna_integration)」参考文档的深度展开,系统讲解如何用 scVI(无监督)与 scANVI(半监督、利用细胞类型标签)实现单细胞转录组数据的批次效应去除与跨数据集整合。读者将掌握从数据预处理、HVG 选择、模型训练、隐空间提取到整合质量评估、差异表达分析的完整实操链路,并学会复用仓库中scripts/下的命令行脚本(如 integrate_datasets.py)以最小化重复编码。

背景:单细胞数据为何需要整合

单细胞测序数据几乎必然携带批次效应(batch effects),来源包括:

  • 不同的供体/患者(donor/patient);
  • 不同的实验批次(experimental batch);
  • 不同的测序技术(如 10x v2 与 v3);
  • 不同的研究(study)之间采集与建库差异。

scVI 与 scANVI 通过变分自编码器(VAE)学习一个共享隐空间(shared latent space):在该空间中批次效应被去除,同时生物变异(细胞类型差异)得以保留。后续的聚类、UMAP 可视化、细胞类型标注与差异表达都可以基于这个干净的隐空间进行。

模型选型:scVI 还是 scANVI

模型适用场景是否需要标签
scVI无标签可用、探索性分析不需要
scANVI已有部分/全部标签,希望更好地保留生物学结构需要(允许部分标注)

从 SKILL.md 的快速决策树也可以看到:无标签 → 走 scVI;有细胞类型标签且要做整合/标签迁移 → 走 scANVI。scANVI 本质上是 scVI 的扩展:先训练 scVI,再以细胞类型标签做半监督微调,从而在去批次的同时用标签约束隐空间,减少“过度校正”导致的生物学信号丢失。

scVI 无监督整合工作流

Step 1:准备数据(拼接与原始计数)

import scvi import scanpy as sc # Load datasets adata1 = sc.read_h5ad("dataset1.h5ad") adata2 = sc.read_h5ad("dataset2.h5ad") # Add batch annotation adata1.obs["batch"] = "batch1" adata2.obs["batch"] = "batch2" # Concatenate adata = sc.concat([adata1, adata2], label="batch") # Ensure we have raw counts # If data is normalized, recover from .raw if hasattr(adata, 'raw') and adata.raw is not None: adata = adata.raw.to_adata() # Store counts adata.layers["counts"] = adata.X.copy()

关键约束:scvi-tools 的所有模型都要求整数原始计数(raw integer counts),而不是归一化后的浮点数据。因此必须在使用sc.pp.normalize_total等归一化之前先把原始计数存进adata.layers["counts"]。仓库中的 data_preparation.md 给出了更完整的检验方法:

import numpy as np # X dtype 与整数性检查 print(f"X dtype: {adata.X.dtype}") print(f"X contains integers: {np.allclose(adata.X.data, adata.X.data.astype(int))}")

仓库的 validate_adata.py 会在数据非整数时报错(Data does not contain integers (raw counts required)),并推荐通过adata.raw.to_adata()恢复原始计数或显式指定包含原始计数的 layer。

Step 2:跨批次 HVG 选择

# Select HVGs considering batch sc.pp.highly_variable_genes( adata, n_top_genes=2000, flavor="seurat_v3", batch_key="batch", layer="counts" ) # Subset to HVGs adata = adata[:, adata.var["highly_variable"]].copy()

多批次数据推荐使用flavor="seurat_v3"并传入batch_key,这样选出的高变基因是在各批次间都稳定的基因,而不是被某个批次单独驱动的基因;layer="counts"保证 HVG 选择基于原始计数。HVG 数量经验范围是 2000~4000(见 data_preparation.md)。值得注意:scVI 训练本身并不强制要求 HVG,但合理筛选能显著降低显存占用与训练时间,并常带来更稳定的整合结果。

Step 3:注册数据并训练 scVI

# Register data with scVI scvi.model.SCVI.setup_anndata( adata, layer="counts", batch_key="batch" ) # Create model model = scvi.model.SCVI( adata, n_latent=30, # Latent dimensions n_layers=2, # Encoder/decoder depth gene_likelihood="nb" # negative binomial (or "zinb") ) # Train model.train( max_epochs=200, early_stopping=True, early_stopping_patience=10, batch_size=128 ) # Plot training history model.history["elbo_train"].plot()

setup_anndata()是 scvi-tools 1.x 的核心 API(0.x 中是scvi.data.setup_anndata,已弃用),它将countslayer 与batch列注册进模型。gene_likelihood决定基因表达的概率分布:"nb"(负二项分布)是 scRNA-seq 的标准选择,"zinb"(零膨胀负二项)适合额外建模过高比例的 dropout。若数据中存在大量全零细胞/基因,会导致 NaN 损失,需先过滤。

仓库中的 train_model.py 将上述过程封装为可直接复用的函数train_scvi(adata, batch_key, n_latent, n_layers, max_epochs),默认开启early_stopping=True, early_stopping_patience=10,并在训练后把隐表示写入adata.obsm["X_scVI"]、保存模型与训练曲线图。

Step 4:提取整合表示并聚类可视化

# Get latent representation adata.obsm["X_scVI"] = model.get_latent_representation() # Use for clustering and visualization sc.pp.neighbors(adata, use_rep="X_scVI", n_neighbors=15) sc.tl.umap(adata) sc.tl.leiden(adata, resolution=1.0) # Visualize integration sc.pl.umap(adata, color=["batch", "leiden"], ncols=2)

注意这里的 UMAP/Leiden 都是基于X_scVI隐表示而非原始基因表达或 PCA。若隐表示缺失,cluster_embed.py 会自动按["X_scANVI", "X_scVI", "X_totalVI", "X_PeakVI", "X_MultiVI"]的顺序探测可用表示,全部缺失时回退到 PCA。

Step 5:保存与加载模型

# Save model for later use model.save("scvi_model/") # Load model model = scvi.model.SCVI.load("scvi_model/", adata=adata)

加载时必须传入与训练时一致的adata(至少包含相同的基因集与 batch 信息),因为模型的解码器维度与基因数绑定。

scANVI 半监督整合工作流

scANVI 在 scVI 基础上引入细胞类型标签,用于更好地保留生物学结构,也支持把标签从标注细胞迁移到未标注细胞。

Step 1:准备带标签的数据

# Labels should be in adata.obs # Use "Unknown" for unlabeled cells print(adata.obs["cell_type"].value_counts()) # For partially labeled data # Mark unlabeled cells adata.obs["cell_type_scanvi"] = adata.obs["cell_type"].copy() # adata.obs.loc[unlabeled_mask, "cell_type_scanvi"] = "Unknown"

scANVI 天然支持部分标注:未标注的细胞统一标记为"Unknown",模型会对这部分细胞做标签预测(见 Step 3 的predict())。

Step 2 Option A:从头训练 scANVI

# Setup for scANVI scvi.model.SCANVI.setup_anndata( adata, layer="counts", batch_key="batch", labels_key="cell_type" ) # Create model scanvi_model = scvi.model.SCANVI( adata, n_latent=30, n_layers=2 ) # Train scanvi_model.train(max_epochs=200)

Step 2 Option B:从 scVI 初始化 scANVI(推荐)

# First train scVI scvi.model.SCVI.setup_anndata(adata, layer="counts", batch_key="batch") scvi_model = scvi.model.SCVI(adata, n_latent=30) scvi_model.train(max_epochs=200) # Initialize scANVI from scVI scanvi_model = scvi.model.SCANVI.from_scvi_model( scvi_model, labels_key="cell_type", unlabeled_category="Unknown" # For partially labeled data ) # Fine-tune scANVI (fewer epochs needed) scanvi_model.train(max_epochs=50)

Option B 是文档推荐的路径,也是仓库脚本的默认实现:先让无监督的 scVI 收敛到合理的隐空间,再叠加标签监督做微调。微调阶段只需少量 epoch(仓库实现中为max_epochs // 4,如 200 → 50),因为模型已经接近解空间。注意from_scvi_model要求传入的 scVI 模型基于同一份adata,且labels_key列必须存在于adata.obs

Step 3:获取结果(隐表示 + 标签预测)

# Latent representation adata.obsm["X_scANVI"] = scanvi_model.get_latent_representation() # Predicted labels for unlabeled cells predictions = scanvi_model.predict() adata.obs["predicted_cell_type"] = predictions # Prediction probabilities soft_predictions = scanvi_model.predict(soft=True) # Visualization sc.pp.neighbors(adata, use_rep="X_scANVI") sc.tl.umap(adata) sc.pl.umap(adata, color=["batch", "cell_type", "predicted_cell_type"])

predict()返回每个细胞最可能的细胞类型;soft=True返回概率矩阵,可用于评估预测置信度。predicted_cell_type是 scANVI 完成标签迁移(label transfer)的直观产出,也是 integrate_datasets.py 中plot_integration()自动识别的绘图列之一。

整合质量评估

视觉评估:整合前后对比

import matplotlib.pyplot as plt fig, axes = plt.subplots(1, 3, figsize=(15, 4)) # Before integration (on PCA) sc.pp.pca(adata) sc.pl.pca(adata, color="batch", ax=axes[0], title="Before (PCA)", show=False) # After scVI sc.pp.neighbors(adata, use_rep="X_scVI") sc.tl.umap(adata) sc.pl.umap(adata, color="batch", ax=axes[1], title="After scVI", show=False) # After scANVI sc.pp.neighbors(adata, use_rep="X_scANVI") sc.tl.umap(adata) sc.pl.umap(adata, color="batch", ax=axes[2], title="After scANVI", show=False) plt.tight_layout()

评估标准:好的整合 = 各批次充分混合(按 batch 着色无明显分群)同时细胞类型结构保持(按 cell_type/leiden 着色依然清晰)。只满足前者可能是过度校正。

定量指标(scib-metrics)

# pip install scib-metrics from scib_metrics.benchmark import Benchmarker bm = Benchmarker( adata, batch_key="batch", label_key="cell_type", embedding_obsm_keys=["X_pca", "X_scVI", "X_scANVI"] ) bm.benchmark() bm.plot_results_table()

embedding_obsm_keys同时传入 PCA(整合前基线)与 scVI/scANVI 隐表示,即可横向对比整合前后及不同模型的 batch mixing 与 bio conservation 指标。仓库 model_utils.py 还提供了一套轻量自实现:evaluate_integration()计算silhouette_label(越高越好)、silhouette_batch(越低越好)与基于 50 近邻的batch_mixingcompare_integrations()则用silhouette_label - silhouette_batch给出综合的integration_score,适合在不引入额外依赖时快速横向比较多种嵌入。

差异表达分析(batch 感知)

scVI 的differential_expression基于生成模型推断,天然扣除批次效应,适合在整合后的隐空间模型上直接做组间差异分析:

# DE between groups de_results = model.differential_expression( groupby="cell_type", group1="T cells", group2="B cells" ) # Filter significant de_sig = de_results[ (de_results["is_de_fdr_0.05"] == True) & (abs(de_results["lfc_mean"]) > 1) ] print(de_sig.head(20))

结果列中is_de_fdr_0.05是 FDR < 0.05 的显著性标记,lfc_mean是平均 log2 倍数变化,bayes_factor是贝叶斯因子(也常作为排序依据)。仓库的 differential_expression.py 封装了该能力,支持三种用法:

# 一键对全部 cluster 做 one-vs-rest DE python scripts/differential_expression.py model/ adata.h5ad de_results.csv --groupby leiden # 指定两组比较 python scripts/differential_expression.py model/ adata.h5ad de_results.csv \ --groupby cell_type --group1 "T cells" --group2 "B cells" # 每个 cluster 只保留 top 50 python scripts/differential_expression.py model/ adata.h5ad de_results.csv \ --groupby leiden --n-genes 50 --plot

其中--plot会额外生成火山图(Volcano plot)。model_utils.py 的get_marker_genes()则基于lfc_mean > 0.5过滤并按lfc_mean降序提取每个群体的标记基因。

进阶:多分类协变量

batch_key外,scVI 支持把donortechnology等更多分类变量作为协变量注册:

# Include additional covariates beyond batch scvi.model.SCVI.setup_anndata( adata, layer="counts", batch_key="batch", categorical_covariate_keys=["donor", "technology"] ) model = scvi.model.SCVI(adata, n_latent=30) model.train()

典型用法是把供体(donor)作为额外分类协变量吸收,batch只保留实验/技术层面的差异;也可传入连续协变量(continuous_covariate_keys,如percent_mito),详见 data_preparation.md。

训练调优建议

大数据集(>100k 细胞)

model.train( max_epochs=100, # Fewer epochs needed batch_size=256, # Larger batches train_size=0.9, # Less validation early_stopping=True )

大数据集收敛更快,epoch 数可以缩减,同时增大 batch size 以充分利用 GPU 吞吐。

小数据集(<10k 细胞)

model = scvi.model.SCVI( adata, n_latent=10, # Smaller latent space n_layers=1, # Simpler model dropout_rate=0.2 # More regularization ) model.train( max_epochs=400, batch_size=64 )

小数据集容易过拟合:减小隐维度、减浅网络、提高 dropout 正则,并适当增加 epoch。仓库 validate_adata.py 会在细胞数 <1000 时给出警告,提示深度学习模型在 >5000 细胞时效果更稳。

监控训练

# Check training curves import matplotlib.pyplot as plt fig, ax = plt.subplots() ax.plot(model.history["elbo_train"], label="Train") ax.plot(model.history["elbo_validation"], label="Validation") ax.set_xlabel("Epoch") ax.set_ylabel("ELBO") ax.legend() # Should see convergence without overfitting

理想曲线是训练与验证 ELBO 均单调收敛;若验证曲线回升(变差)说明开始过拟合,early stopping 会自动截断。仓库 model_utils.py 的plot_training_history()在 ELBO 之外还会绘制 reconstruction loss 曲线;train_model.py 训练结束即自动保存training_history.png

完整整合管线(可复用函数)

参考文档给出了一个完整的integrate_datasets()函数(多数据集拼接 → HVG → scVI/scANVI 自动选型 → 隐表示 → 聚类),仓库 integrate_datasets.py 将其扩展为生产级 CLI。函数签名与用法:

def integrate_datasets( adatas, batch_key="batch", labels_key=None, n_top_genes=2000, n_latent=30 ): """Integrate multiple scRNA-seq datasets. ...""" # 逐数据集打 batch 标签 -> sc.concat 拼接 -> 存 counts layer # -> seurat_v3 + batch_key 选 HVG -> 按标签有无走 scANVI/scVI # -> 写 X_scANVI / X_scVI -> neighbors + UMAP + leiden return adata, model # Usage adatas = { "study1": sc.read_h5ad("study1.h5ad"), "study2": sc.read_h5ad("study2.h5ad"), "study3": sc.read_h5ad("study3.h5ad") } adata_integrated, model = integrate_datasets( adatas, labels_key="cell_type" ) sc.pl.umap(adata_integrated, color=["batch", "leiden", "cell_type"])

而仓库脚本integrate_datasets.py额外做了三件文档未覆盖的事,体现了“实战可用”的完备性:

  1. 基因交集处理:拼接前先对所有数据集取var_names交集(common_genes),避免不同研究间基因集不一致导致拼接错位;
  2. batch 命名校验--batch-names数量必须与数据集数量一致,否则抛ValueError
  3. 完整产物落盘:训练后自动保存integrated.h5ad、模型目录与integration.png拼图。

其完整 CLI 用法:

# 基础整合(自动分配 dataset_0, dataset_1, ...) python scripts/integrate_datasets.py results/ data1.h5ad data2.h5ad data3.h5ad # 自定义批次名 python scripts/integrate_datasets.py results/ *.h5ad --batch-names ctrl,treat1,treat2 # 带细胞类型标签(自动走 scANVI) python scripts/integrate_datasets.py results/ *.h5ad --labels-key cell_type # 其他参数:--n-hvgs 2000 --n-latent 30 --max-epochs 200

端到端 CLI 工作流

仓库 SKILL.md 把参考文档的每个步骤映射为独立脚本,可串联成一条不写 Python 代码的完整流程:

# 1. 校验输入数据(整数计数、batch 列、HVG、batch 规模),--suggest 给出模型建议 python scripts/validate_adata.py raw.h5ad --batch-key batch --suggest # 2. 数据准备:QC 过滤 + HVG 选择 + counts layer python scripts/prepare_data.py raw.h5ad prepared.h5ad --batch-key batch --n-hvgs 2000 # 3. 训练模型(scvi / scanvi 等,由 --model 决定) python scripts/train_model.py prepared.h5ad results/ --model scvi --batch-key batch # 4. 在隐空间上聚类与可视化 python scripts/cluster_embed.py results/adata_trained.h5ad results/ --resolution 0.8 # 5. 差异表达 python scripts/differential_expression.py results/model results/adata_clustered.h5ad results/de.csv --groupby leiden

其中validate_adata.py的校验报告会覆盖:数据是否为整数计数、是否含 NaN/负值、稀疏度、batch 数量(仅 1 个 batch 时警告无需校正、<50 细胞的 batch 建议合并)、标签稀有度(<30 细胞的类型提示学习不充分)、HVG 数量(推荐 2000~4000)等,是进入训练前最有价值的“体检”步骤。

常见问题排查

问题原因解决方案
批次不混合共有基因太少增加 HVG 数量,检查各数据集基因重叠
过度校正生物学变异被误删改用带标签的 scANVI
训练发散学习率过高降低 lr,增大 batch_size
NaN loss数据质量差检查并过滤全零细胞/基因
内存不足细胞数过多减小 batch_size,使用 GPU

从源码看(train_model.py 的train_scvi与 model_utils.py 的train_scvi),仓库脚本统一采用early_stopping=True+patience=10的组合,能在一定程度上自动规避训练发散与过拟合;而 NaN loss 的根本预防在于训练前用validate_adata.py排除全零细胞与 NaN。环境与 GPU 相关的坑(CUDA 版本不匹配、PyTorch 与 CUDA 对应关系、显存不足)可进一步参考 environment_setup.md。

小结

以 scrna_integration.md 为核心,本技能提供了一条从「原始 h5ad 多数据集」到「干净隐空间 + 聚类 + DE 结果」的完整整合链路:无标签探索选 scVI,有(部分)标签选 scANVI(推荐从 scVI 初始化再微调);用setup_anndata注册countslayer 与batch_key,在X_scVI/X_scANVI隐表示上完成聚类与可视化,并以 scib-metrics 或 silhouette 指标量化整合质量。仓库scripts/下 7 个脚本(validate_adataprepare_datatrain_modelcluster_embeddifferential_expression)可将整条流程无代码落地,而model_utils.py的函数级 API 则适合在自定义 Notebook 管线中直接调用。

【免费下载链接】knowledge-work-pluginsOpen source repository of plugins primarily intended for knowledge workers to use in Claude Cowork项目地址: https://gitcode.com/GitHub_Trending/kn/knowledge-work-plugins

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/12 3:59:04

MOD44B植被覆盖数据在中国生态评估中的应用

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/12 3:58:54

缓存无关数据结构:原理、实现与性能优化

1. 缓存无关数据结构核心思想解析在《Handbook of Data Structures and Applications》这本经典著作中&#xff0c;缓存无关数据结构&#xff08;Cache-Oblivious Data Structures&#xff09;被作为现代算法设计的重要范式进行深入探讨。这种数据结构设计方法最精妙之处在于&a…

作者头像 李华
网站建设 2026/9/12 3:57:15

古诗文填空高效备考:三维解析与科学记忆法

1. 项目背景与核心价值初中古诗文大会作为上海地区最具影响力的学科竞赛之一&#xff0c;每年吸引数万学生参与。2026年赛事在即&#xff0c;填空题作为考察古诗文积累的核心题型&#xff08;占比约40%&#xff09;&#xff0c;其备考效率直接决定参赛成绩。传统备考存在三大痛…

作者头像 李华
网站建设 2026/9/12 3:54:08

AI Agent开发实战:问数项目基础设施搭建全指南

《LCODER之AI Agent开发实战一》系列走到了第二篇&#xff0c;今天聊聊基础设施搭建。上一篇讲的是把问数项目的整体需求和技术选型定下来&#xff0c;这篇要动真格的了——在写任何一条Agent业务逻辑之前&#xff0c;先把地基打牢。为什么我要单独拿出一篇来讲基础设施&#x…

作者头像 李华
网站建设 2026/9/12 3:52:21

高效图片转PDF合并工具开发指南

1. 项目背景与需求解析 在数字化办公场景中&#xff0c;将纸质文档电子化已成为刚需。我最近帮财务部门处理了300多页的报销单据扫描归档工作&#xff0c;深刻体会到一款高效的图片转PDF合并工具的重要性。这类工具的核心价值在于解决三个痛点&#xff1a;碎片化图片管理困难、…

作者头像 李华