ACTIVA: 使用内省变分自编码器实现自动细胞类型识别的逼真单细胞 RNA-seq 生成
Tutorials and datasets:
Workflow:
1、使用预处理数据进行模型训练
2、使用训练好的模型进行数据生成和评估
3、使用其他数据集和预训练模型进行模型微调
模型训练
1、下载预处理数据
因为数据使用了Amazon S3 (Simple Storage Service)云储存服务
需要在环境中安装AWS CLI (Amazon Web Services Command Line Interface)来支持S3链接下载
安装和配置 AWS CLI
curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip"
unzip awscliv2.zip
sudo ./aws/install
下载数据到工作区
# 1. 创建目标文件夹
mkdir activa_preprocessed_data
cd activa_preprocessed_data
# 2. 下载 Brain Small 数据集 (.h5)
aws s3 cp s3://activa-material/PreprocessedData/20kBrainSmall_preprocessed.h5 . --no-sign-request
# 3. 下载 68K PBMC 数据集 (.h5ad)
aws s3 cp s3://activa-material/PreprocessedData/68kPBMC_preprocessed.h5ad . --no-sign-request
# 4. 下载 NeuroCOVID 数据集 (.h5ad)
aws s3 cp s3://activa-material/PreprocessedData/NeuroCovid/NeuroCOVID_PreProcessedUsingScGAN_Sparse.h5ad . --no-sign-request
这里的存储桶是公开可读的(对于研究数据通常如此),可以通过在命令中添加 --no-sign-request
标志来告诉 AWS CLI 不需要使用凭证进行签名请求。
如果是私有访问需要身份验证,可以注册AWS 账户,并生成 Access Key ID 和 Secret Access Key,回到工作区运行配置命令,并按提示输入您的密钥和区域
aws configure
2、下载模型并安装依赖
下载模型
使用git clone克隆模型到工作区
git clone https://github.com/SindiLab/ACTIVA.git
安装依赖
创建虚拟环境(在autodl中)
# 创建一个新的 Python 3.8 环境
conda create -n activa_env python=3.8 -y
# 更新bashrc中的环境变量(仅在autodl中需要)
conda init bash && source /root/.bashrc
# 激活新环境
conda activate activa_env
在虚拟环境中安装依赖
pip install -r requirements.txt
本地安装包(运行setup.py)
pip install -e .
3、训练模型
修改数据文件位置
在ACTIVA.py中找到导入数据的地方
例如
elif opt.example_data == '20k brain':
train_data_loader, valid_data_loader = Scanpy_IO('/home/ubuntu/scGAN_ProcessedData/MADE_BY_scGAN/20Kneurons_2KTest.h5',
由于这里默认使用硬编码地址,需要改成自己数据文件的存放地址
# 修改 NeuroCOVID:
train_data_loader, valid_data_loader = Scanpy_IO('/root/activa_preprocessed_data/NeuroCOVID_PreProcessedUsingScGAN_Sparse.h5ad',
# 修改 68K PBMC
train_data_loader, valid_data_loader = Scanpy_IO('/root/activa_preprocessed_data/68kPBMC_preprocessed.h5ad',
# 20K Brain Small
train_data_loader, valid_data_loader = Scanpy_IO('/root/activa_preprocessed_data/20kBrainSmall_preprocessed.h5',
开始训练
CUDA_VISIBLE_DEVICE=0,1,2,3,4,5,6,7 python ACTIVA.py --example_data "20k brain" --lr 0.0002 --lr_e 0.0002 --lr_g 0.0002 --nEpochs 500 --tensorboard --outf './brain_small_train_logs'
CUDA_VISIBLE_DEVICES
控制当前进程可见的 GPU 设备。0,1,2,3,4,5,6,7
告诉程序可以使用这些编号的 GPU。由于程序没有启用多卡并行,它将默认使用 Device 0。
--example_data
选择要运行的预定义示例数据集。"20k brain"
对应 brain small 数据集。
--lr
ACTIVA 模型的整体学习率(通常用于 Adam 优化器)。
--lr_e
编码器(Encoder)的学习率。
--lr_g
解码器(Generator/Decoder)的学习率。
--nEpochs
训练的总轮数(Epochs)。
--tensorboard
启动训练可视化。
--outf
tensorboard日志输出位置。
此外还有参数:
--batchSize
定义输入批次大小。增大 batch size 可以利用更多 GPU 显存,加快收敛,但也可能需要更多内存(RAM/VRAM)。
--workers
数据加载的子进程数。如果内存出现问题,可以尝试减少这个值。
--data_type "scanpy"
数据格式(Scanpy/Seurat AnnData 或 CSV)。
--m_plus
判别器部分的边界(Margin)值。
--weight_neg
负样本权重,用于 IntroVAE 损失。
--weight_rec
重构损失(Reconstruction Loss)权重。
--weight_kl
KL 散度损失(KL Divergence Loss)权重。
--num_vae
在开始对抗训练前,进行纯 VAE 训练的轮数(Warm-up)。
--tensorboard
启用 TensorBoard 日志记录。强烈推荐启用以便可视化训练过程。
--outf
TensorBoard 日志和检查点(Checkpoint)的输出目录。
--print_frequency
ACTIVA 训练统计信息打印的频率(Batch 迭代次数)。
--save_iter
模型检查点保存的间隔(Epochs)。
Tensorboard训练可视化
在训练命令后添加--tensorboard --outf './brain_small_train_logs'字样,会将训练日志输出到指定文件夹。
随后可以在训练过程中或者训练结束后,在工作区新建终端中输入以下代码
# 激活您的环境(如果尚未激活)
conda activate activa_env
# 启动 TensorBoard 服务器
tensorboard --logdir=./covid_logs --port=6006
然后在本地电脑的终端中输入ssh指令连接远程服务器
# 仅为示例,请以自己的服务器为准
ssh -CNg -L 6006:127.0.0.1:6006 root@connect.cqa1.seetacloud.com -p 36483
连接成功后可以通过浏览器访问端口看到可视化窗口
http://localhost:6006
生成数据
生成合成的单细胞RNA测序数据:Tutorials/ACTIVA/ACTIVA-Generating-scRNAseq.ipynb at main · SindiLab/Tutorials
特定细胞类型RNA测序数据:Tutorials/ACTIVA/ManifoldAnalysis_20kBrainSmall.ipynb at main · SindiLab/Tutorials
报错记录
RuntimeError: CUDA error: device-side assert triggered
RuntimeError: CUDA error: device-side assert triggered
Assertion `t >= 0 && t < n_classes` failed.
这个断言 (Assertion
) 是 PyTorch 在 GPU 上执行 交叉熵损失计算 (nll_loss_forward_reduce_cuda_kernel_2d
) 时触发的。它表示您的数据标签(Target, 也就是 t
)的值超出了预期的类别范围。
🚨 错误分析:标签越界
错误原因
断言条件:
t >= 0 && t < n_classes
(标签t
必须大于等于 0 且小于类别总数n_classes
)您的类别数: 脚本成功读取并设置了
==> Number of classes 16
(n_classes = 16
)。实际问题: 在训练分类器时,您的数据加载器(
train_data_loader
)输出了一个标签(t
)的值 大于或等于 16。
可能的场景:
标签未从 0 开始编码: 数据集中的标签可能从 1 开始编码到 16(即标签为 1,2,…,16)。如果 PyTorch 期望 0,1,…,15,那么标签 16 就会导致断言失败。
数据包含未过滤的类别: 您的数据文件 (
NeuroCOVID_PreProcessedUsingScGAN_Sparse.h5ad
) 中包含第 17 个(或更多)细胞类型,但您的脚本却将类别数硬编码为 16。
您需要将代码中对 opt.number_of_classes
的引用,替换为在脚本中实际存储类别数的变量。
1. 定位正确的变量
在 ACTIVA.py
文件中,搜索类别数 16
所在的代码行。您应该能找到类似这样的逻辑:
Python
# ACTIVA.py (在 main() 函数中,数据加载之后)
# ...
number_of_classes = 16 # 或者从数据中获取的变量
# ...
2. 修改 train_classifier
函数
由于 number_of_classes
是在 main()
函数中或全局定义的,但在 train_classifier()
函数中无法直接访问,您需要将它作为参数传递给 train_classifier()
。
步骤 2.1:更新 train_classifier
函数签名
将 train_classifier
函数的定义修改为接受类别数作为参数:
Python
# ACTIVA.py (约 250 行左右)
# 修改前
def train_classifier(epoch, iteration, batch, cur_iter):
# 修改后
def train_classifier(epoch, iteration, batch, cur_iter, number_of_classes):
# ... 函数体
步骤 2.2:在 main
函数中调用时传递参数
找到 main()
函数中调用 train_classifier
的位置(约 510 行),并传递类别数:
# ACTIVA.py (在 main() 函数中,约 510 行左右)
# 假设 number_of_classes 已经被正确定义为 16
train_classifier(epoch, iteration, batch, cur_iter, number_of_classes)
步骤 2.3:修正 train_classifier
函数体中的代码
现在,您可以使用传递进来的 number_of_classes
变量来替换 opt.number_of_classes
。
在您之前添加的代码行(ACTIVA.py
约 277 行)中进行修改:
# ACTIVA.py (在 train_classifier 函数内)
# ...
# 2. 检查标签是否从 1 开始 (例如:1到16),如果是,则减去 1
# 我们假设最大的标签是 16,最小的是 1
# if true_labels.max() > 15: # 原始代码可以保留此行
if true_labels.max() >= number_of_classes:
true_labels = true_labels - 1
# 3. 再次检查,如果仍有标签越界(例如 > 15),则将其截断为 15
# 注意这里用传递进来的 number_of_classes 替换了 opt.number_of_classes
true_labels = torch.clamp(true_labels, min=0, max=number_of_classes - 1)
info = f"\n====> Classifier Cur_iter: [{cur_iter}]: Epoch[{cf_epoch}]({iteration}/{len(train_data_loader)}): time: {time.time()-start_time:4.4f}: "
# ...