scvi-tools 深度学习单细胞分析:常见问题

scvi-tools 深度学习单细胞分析:常见问题

Written By
技能练习生
技能练习生

快速解决你遇到的问题

本章汇总了 scvi-tools 使用中最常见的问题和解决方案,涵盖安装、训练、分析和调试的各个环节。

6.1 安装与环境问题

Q1: 安装失败或版本冲突

问题

ERROR: Could not find a version that satisfies the requirement scvi-tools

解决方案

# 1. 使用 conda 创建新环境(推荐)
conda create -n scvi python=3.10 -y
conda activate scvi

# 2. 安装稳定版
pip install scvi-tools

# 3. 或安装开发版(包含最新功能)
pip install git+https://github.com/scverse/scvi-tools.git

# 4. 验证安装
python -c "import scvi; print(scvi.__version__)"

常见错误

  • Python 版本不兼容:确保 Python ≥ 3.8
  • PyTorch 版本冲突:scvi-tools 会自动安装兼容版本
  • 权限问题:使用 pip install --user 或虚拟环境

Q2: GPU 加速不可用

问题

UserWarning: GPU available but not used. To use GPU, please set use_gpu=True

检查 GPU

import torch
print(f"CUDA available: {torch.cuda.is_available()}")
print(f"CUDA version: {torch.version.cuda}")
print(f"GPU count: {torch.cuda.device_count()}")

# 列出可用 GPU
for i in range(torch.cuda.device_count()):
    print(f"GPU {i}: {torch.cuda.get_device_name(i)}")

解决方案

# 如果 CUDA 不可用,安装 GPU 版本的 PyTorch
# 1. 检查 CUDA 版本
nvidia-smi

# 2. 安装对应的 PyTorch(以 CUDA 11.8 为例)
pip install torch --index-url https://download.pytorch.org/whl/cu118

# 3. 重新安装 scvi-tools
pip install scvi-tools --force-reinstall

显存不足

# 减少批大小
model.train(batch_size=64, use_gpu=True)

# 或使用 CPU(较慢但稳定)
model.train(use_gpu=False)

6.2 数据准备问题

Q3: 训练后批次效应仍然存在

可能原因

  1. batch_key 参数未正确指定
  2. 模型未充分训练
  3. 批次差异太大,需要更强的模型

诊断步骤

# 1. 检查 batch_key 是否正确
print(adata.obs['batch'].unique())
# 应该看到不同的批次标签

# 2. 检查训练曲线
import matplotlib.pyplot as plt
plt.plot(model.history['elbo_train'], label='Train')
plt.plot(model.history['elbo_validation'], label='Validation')
plt.xlabel('Epoch')
plt.ylabel('ELBO')
plt.legend()
plt.show()

# 如果曲线未收敛,增加训练轮数
model.train(max_epochs=400)

解决方案

# 方案 1:增加训练轮数
model.train(max_epochs=500)

# 方案 2:增加潜在维度
model = scvi.model.SCVI(adata, latent_dim=40)

# 方案 3:使用更强的模型(sysVI)
import scvi
from scvi.model import SYMFIZI  # 用于极端批次效应

Q4: "Layer not found" 错误

问题

KeyError: 'Layer "counts" not found in anndata layers'

原因:未正确设置原始计数层

解决方案

# 检查现有层
print(f"Available layers: {list(adata.layers.keys())}")

# 如果 counts 层不存在,创建它
if 'counts' not in adata.layers:
    # 确保 X 是原始计数
    adata.layers['counts'] = adata.X.copy()

# 如果 X 已归一化,需要重新加载原始数据
# 或检查是否在其他层中保存了原始计数
# adata.layers['counts'] = adata.layers['raw_counts'].copy()

# 验证数据类型
print(f"Data type: {adata.layers['counts'].dtype}")
# 应该是整数类型(int32, int64)

Q5: 高变基因选择失败

问题

ValueError: No highly variable genes found

原因:数据质量差或参数设置不当

解决方案

# 1. 检查数据质量
print(f"Total genes: {adata.n_vars}")
print(f"Total cells: {adata.n_obs}")
print(f"Sparsity: {(adata.X == 0).sum() / adata.X.size * 100:.1f}%")

# 2. 预过滤
sc.pp.filter_cells(adata, min_counts=1000)
sc.pp.filter_genes(adata, min_cells=20)

# 3. 调整高变基因参数
sc.pp.highly_variable_genes(
    adata,
    n_top_genes=2000,
    batch_key='batch',
    flavor='seurat_v3',
    layer='counts',
    subset=True
)

# 4. 验证
print(f"HVGs found: {adata.var['highly_variable'].sum()}")

6.3 训练问题

Q6: 训练损失不下降

症状:ELBO 曲线平坦或震荡

诊断

# 1. 查看训练历史
plt.plot(model.history['elbo_train'])
plt.title('Training Loss')
plt.show()

# 2. 检查数据分布
import seaborn as sns
sample = adata.layers['counts'][0].toarray().flatten()
sns.histplot(sample, bins=50)
plt.xlim(0, sample.mean() * 3)
plt.title('Count distribution')
plt.show()

# 3. 检查异常值
print(f"Max count: {adata.layers['counts'].max()}")
print(f"Mean count: {adata.layers['counts'].mean()}")

解决方案

# 方案 1:调整学习率
model.train(
    max_epochs=100,
    plan_kwargs={'lr': 1e-3}  # 降低学习率
)

# 方案 2:增加批大小
model.train(
    batch_size=512,
    use_gpu=True
)

# 方案 3:重新初始化模型
model = scvi.model.SCVI(adata, latent_dim=30)
model.train(max_epochs=400)

Q7: 训练过程中内存溢出

问题

RuntimeError: CUDA out of memory

解决方案

# 方案 1:减少批大小
model.train(batch_size=64, use_gpu=True)

# 方案 2:使用梯度累积
model.train(
    batch_size=64,
    accumulate_grad_batches=4  # 等效于 batch_size=256
)

# 方案 3:使用 CPU
model.train(use_gpu=False)

# 方案 4:减少高变基因数量
sc.pp.highly_variable_genes(adata, n_top_genes=1000, ...)

Q8: 训练速度慢

优化方案

# 1. 使用 GPU(最重要)
model.train(use_gpu=True)

# 2. 增大批大小
model.train(batch_size=512, use_gpu=True)

# 3. 减少高变基因
sc.pp.highly_variable_genes(adata, n_top_genes=1000, ...)

# 4. 减少训练轮数(使用早停)
model.train(
    max_epochs=200,
    early_stopping=True,
    early_stopping_patience=10
)

# 5. 使用数据加载器多进程
model.train(
    data_loader_kwargs={
        'num_workers': 4,
        'batch_size': 256
    }
)

6.4 结果分析问题

Q9: 聚类结果不理想

症状:聚类太多或太少,细胞类型混杂

解决方案

# 方案 1:调整分辨率
sc.tl.leiden(adata, resolution=0.3)  # 减少聚类
sc.tl.leiden(adata, resolution=1.5)  # 增加聚类

# 方案 2:使用不同的潜在表示维度
# 重新训练模型,调整 latent_dim
model = scvi.model.SCVI(adata, latent_dim=50)

# 方案 3:调整邻居参数
sc.pp.neighbors(
    adata,
    use_rep='X_scvi',
    n_neighbors=15,  # 默认 15
    method='umap'
)

# 方案 4:尝试不同的聚类算法
sc.tl.louvain(adata, resolution=0.8)

Q10: 差异表达分析报错

问题

KeyError: 'Group not found in observations'

解决方案

# 1. 检查 groupby 列是否存在
print(adata.obs.columns)
print(adata.obs['leiden'].unique())

# 2. 确保是字符串类型
adata.obs['leiden'] = adata.obs['leiden'].astype(str)

# 3. 检查组名是否正确
de_results = model.differential_expression(
    groupby='leiden',
    group1='0',  # 确保这些组存在
    group2='1'
)

# 4. 列出可用的组
print("Available groups:")
print(adata.obs['leiden'].value_counts())

Q11: 标签转移准确率低

症状:scANVI 预测的细胞类型不准确

诊断

# 1. 检查参考数据质量
ref_adata = adata[adata.obs['cell_type'] != 'Unknown']
print(f"Reference cells: {ref_adata.n_obs}")
print(f"Cell types: {ref_adata.obs['cell_type'].value_counts()}")

# 2. 检查预测置信度
import pandas as pd
pred_probs = scanvi_model.predict(soft=True)
confidence = pred_probs.max(axis=1)

print(f"Mean confidence: {confidence.mean():.2f}")
print(f"Low confidence (<0.5): {(confidence < 0.5).sum()} cells")

# 可视化置信度分布
import seaborn as sns
sns.histplot(confidence, bins=50)
plt.xlabel('Prediction confidence')
plt.show()

解决方案

# 方案 1:增加参考数据
# 确保每个细胞类型至少有 100 个细胞

# 方案 2:增加训练轮数
scanvi_model.train(max_epochs=200)

# 方案 3:调整潜在维度
model = scvi.model.SCVI(adata, latent_dim=40)
scanvi_model = scvi.model.SCANVI.from_scvi_model(model, ...)

# 方案 4:过滤低置信度预测
high_conf_mask = adata.obs['prediction_confidence'] > 0.8
adata_filtered = adata[high_conf_mask]

6.5 模型保存与加载

Q12: 模型加载失败

问题

ValueError: AnnData object not compatible with saved model

原因:基因顺序或数量不一致

解决方案

# 方案 1:确保基因顺序一致
# 保存模型时同时保存基因列表
import json
with open('model_genes.json', 'w') as f:
    json.dump(adata.var_names.tolist(), f)

# 加载时验证
with open('model_genes.json', 'r') as f:
    model_genes = json.load(f)

# 如果需要,对齐基因
adata = adata[:, model_genes]

# 方案 2:使用模型的 setup_anndata
model.setup_anndata(adata, layer='counts', batch_key='batch')

# 方案 3:保存整个 adata 对象
adata.write('adata_with_model.h5ad')

Q13: 版本兼容性问题

问题:旧版本模型无法在新版本中加载

解决方案

# 检查模型版本
import scvi
print(f"scvi-tools version: {scvi.__version__}")

# 方案 1:升级模型
# 加载模型并重新保存
model = scvi.model.SCVI.load('old_model/', adata)
model.save('new_model/', overwrite=True)

# 方案 2:降降 scvi-tools(不推荐)
pip install scvi-tools==0.20.0  # 使用旧版本

# 方案 3:重新训练(推荐)
# 确保 reproducibility
import random
import numpy as np
import torch

random.seed(42)
np.random.seed(42)
torch.manual_seed(42)

model = scvi.model.SCVI(adata)
model.train(max_epochs=400)
model.save('retrained_model/', overwrite=True)

6.6 性能优化

Q14: 大数据集(>100K 细胞)处理

优化策略

# 方案 1:分批训练
subset = adata[:50000, :]
model = scvi.model.SCVI(subset)
model.train(max_epochs=200)

# 然后用全数据微调
model.setup_anndata(adata)
model.train(max_epochs=100)

# 方案 2:使用流式加载
model.train(
    max_epochs=400,
    data_loader_kwargs={
        'batch_size': 1024,
        'num_workers': 4
    }
)

# 方案 3:减少高变基因
sc.pp.highly_variable_genes(
    adata,
    n_top_genes=1500,  # 减少到 1500
    batch_key='batch',
    subset=True
)

# 方案 4:使用 GPU + 大批大小
model.train(
    batch_size=1024,
    use_gpu=True,
    accumulate_grad_batches=4
)

Q15: 多数据集整合最佳实践

推荐流程

# 1. 分别 QC 各数据集
for adata in adata_list:
    sc.pp.filter_cells(adata, min_counts=1000)
    sc.pp.filter_genes(adata, min_cells=20)

# 2. 合并时保留细粒度批次信息
for i, adata in enumerate(adata_list):
    adata.obs['batch'] = f'{adata.obs["lab"]}_{adata.obs["tech"]}_{i}'

# 3. 使用较高的潜在维度
model = scvi.model.SCVI(adata_combined, latent_dim=40)

# 4. 充分训练
model.train(
    max_epochs=500,
    early_stopping=True,
    early_stopping_patience=20
)

# 5. 验证整合效果
import scvi.tools
lisi = scvi.tools.compute_lisi(
    adata_combined,
    label_keys=['batch'],
    embed_key='X_scvi'
)
print(f"Mean LISI: {lisi.mean():.2f}")

6.7 调试技巧

获取帮助信息

# 查看模型文档
help(scvi.model.SCVI)

# 查看训练参数
model.get_anndata_manager()

# 检查数据配置
print(model.adata_manager.data_registry)

日志记录

import logging
logging.basicConfig(level=logging.INFO)

# 启用详细日志
model.train(
    max_epochs=100,
    logger=True,
    log_every_n_steps=10
)

常用检查清单

# ✅ 数据检查清单
print("=== Data Checklist ===")
print(f"Shape: {adata.shape}")
print(f"Batch key exists: {'batch' in adata.obs.columns}")
print(f"Counts layer exists: {'counts' in adata.layers.keys()}")
print(f"Data type: {adata.layers['counts'].dtype}")
print(f"Batch distribution:\n{adata.obs['batch'].value_counts()}")

# ✅ 模型检查清单
print("\n=== Model Checklist ===")
print(f"Model trained: {model.is_trained_}")
print(f"Latent dim: {model.latent_dim}")
print(f"Training epochs: {model.n_epochs}")

# ✅ 结果检查清单
print("\n=== Results Checklist ===")
print(f"Latent representation: {'X_scvi' in adata.obsm.keys()}")
print(f"Clustering exists: {'leiden' in adata.obs.columns}")

6.8 资源与社区

获取帮助

  1. 官方文档https://docs.scvi-tools.org/
  2. GitHub Issueshttps://github.com/scverse/scvi-tools/issues
  3. Discord 社区https://discord.gg/vSBqYSs7Dw
  4. 教程https://docs.scvi-tools.org/en/stable/tutorials/index.html

报告 Bug

# 报告 Bug 时提供以下信息
import scvi
import scanpy as sc
import torch

print("=== System Info ===")
print(f"scvi-tools: {scvi.__version__}")
print(f"scanpy: {sc.__version__}")
print(f"PyTorch: {torch.__version__}")
print(f"CUDA: {torch.version.cuda}")
print(f"Python: {import sys; sys.version}")

print("\n=== Data Info ===")
print(f"Shape: {adata.shape}")
print(f"Layers: {list(adata.layers.keys())}")

print("\n=== Error ===")
# 复制粘贴完整的错误信息

教程总结

恭喜你完成了 scvi-tools 完整教程!现在你应该能够:

  • ✅ 理解 scvi-tools 的核心价值和应用场景
  • ✅ 独立完成 scVI/scANVI 分析项目
  • ✅ 处理多模态数据(CITE-seq、Multiome)
  • ✅ 进行标签转移和参考映射
  • ✅ 排查常见问题和优化性能

下一步学习建议

  1. 实践项目:用你自己的数据集完成一个完整分析
  2. 深入特定模型:选择与你研究最相关的模型深入学习
  3. 参与社区:在 GitHub 上提问或贡献代码
  4. 跟踪更新:关注 scvi-tools 的版本更新和新功能

祝你在单细胞深度学习的旅程中收获满满!

参考资源

  • scvi-tools 官方文档
  • scvi-tools GitHub
  • scverse 生态系统