satijalabsctransform包的github网址:https://github.com/ChristophH/sctransform
sctransform作者发表的论文:https://genomebiology.biomedcentral.com/articles/10.1186/s13059-019-1874-1
sctransform中的vst方法:https://rawgit.com/ChristophH/sctransform/supp_html/supplement/variance_stabilizing_transformation.html
在seurat如何使用sctransform:https://satijalab.org/seurat/articles/sctransform_vignette.html
注:vst方法(Variance stabilizing transformation),可通过'?sctransform::vst'详细了解
一、sctransform简介
seurat包的sctransform函数调用sctransform::vst。sctransform包是由纽约基因组中心Rahul Satija实验室的Christoph Hafemeister开发(也是satijalab实验室出品),使用正则化负二项式回归(regularized negative binomial regression)对单细胞UMI表达数据进进行建模,以消除由于测序深度引起的变化。该方法首先使用测序深度作为自变量和UMI计数作为响应或因变量为每个基因构建广义线性模型 (GLM)。 然后根据基因表达对参数估计进行正则化(或调整)。 使用正则化参数应用第二轮负二项式回归。 该模型的输出(残差)是每个基因的标准化表达水平。 SCTransform方法学习基因集特定的特征( gene-group specific factors),而不是使用常数因子来标准化所有基因。 这些基因集特征分别针对低、中和高表达基因,消除了技术变异的影响,同时保留了真正的生物异质性。
该软件包的核心功能已集成到Seurat包中。与传统的lognormalize归一化方法相比,它集成了NormalizeData(), FindVariableFeatures(),ScaleData()三个函数的功能,是单细胞基因count矩阵预处理的替代方法。 结果保存在一个新的assay中(默认命名为 SCT),包含:
- seurat_obj[['SCT']]@counts:矫正后的counts;
- seurat_obj[['SCT']]@data:矫正后的counts通过log1p(counts)处理后的data;
-
seurat_obj[['SCT']]@scale.data:pearson残差;
sctransform::vst 中间结果保存在seurat_obj[['SCT']]@misc中。
我们先从比较浅的教材出发,一层层去了解和熟悉sctransform算法背后的逻辑,来回答以下几个问题
- 什么情况下SCTransform是优于全局scale归一化方法(global scaling normalization)
- SCTransform的工作原理
- 在执行SCTransform分析中要注意哪些
二、seurat分析使用sctransform
教程链接:https://satijalab.org/seurat/articles/sctransform_vignette.html
单细胞RNA-seq数据中的生物异质性通常会受到包括测序深度在内的技术因素的影响。在每个细胞中检测到的分子数量在细胞之间可能存在显着的差异,即使在同一细胞类型中也是如此。scRNA-seq数据需要进行有效的预处理和标准化以消除这种实验技术来源的变异性。在Hafemeister and Satija, 2019文章中引入了一个建模框架,用scRNA-seq 实验的UMI计数数据进行归一化和方差稳定化转化。同时也改进了常见的下游分析,如高可变基因选择、降维和差异基因分析。
library(Seurat)
library(ggplot2)
library(sctransform)
加载数据并创建 Seurat 对象
pbmc_data <- Read10X(data.dir = "../data/pbmc3k/filtered_gene_bc_matrices/hg19/")
pbmc <- CreateSeuratObject(counts = pbmc_data)
应用sctransform归一化
- 这一命令替换NormalizeData(),ScaleData()和FindVariableFeatures();
- 转换后的数据将存储在SCT assay中,运行sctransform后将'SCT'设置为默认assay;
- 在标准化处理中,我们还可以去除混杂的变异来源,例如线粒体百分比;
# store mitochondrial percentage in object meta data
pbmc <- PercentageFeatureSet(pbmc, pattern = "^MT-", col.name = "percent.mt")
# run sctransform
pbmc <- SCTransform(pbmc, vars.to.regress = "percent.mt", verbose = FALSE)
最新版本sctransform还支持使用glmGamPoi包,这大大提高了算法学习过程的速度。可以指定调用方法method="glmGamPoi"。
if (!requireNamespace("BiocManager", quietly = TRUE)) install.packages("BiocManager")
BiocManager::install("glmGamPoi")
pbmc <- SCTransform(pbmc, method = "glmGamPoi", vars.to.regress = "percent.mt", verbose = FALSE)
怎么理解glmGamPoi?
gmlGamPoi的设计目的:在任意大小的数据集上拟合Gamma-Poisson广义线性模型;比替代方法更快,例如DESeq2或edgeR。
执行PCA和UMAP降维
# These are now standard steps in the Seurat workflow for visualization and clustering
pbmc <- RunPCA(pbmc, verbose = FALSE)
pbmc <- RunUMAP(pbmc, dims = 1:30, verbose = FALSE)
pbmc <- FindNeighbors(pbmc, dims = 1:30, verbose = FALSE)
pbmc <- FindClusters(pbmc, verbose = FALSE)
DimPlot(pbmc, label = TRUE) + NoLegend()
教程中,通过marker基因在umap聚类图可视化基因的表达量,显示marker基因在不同的cluster上有清晰的分离,很适合细胞类型鉴定,与标准 Seurat 工作流程相比,sctransform归一化揭示了更清晰的生物学特异性。在此不详述,我们主要关注算法本身。
问题1:为什么我们在使用sctransform时可以选择更多的PC?
标准Seurat分析流程,我们对此数据集只关注前10个PC,但我们强调nPC=10,与PC数目设置得更高,下游结果是相似的。但是,我们发现在使用 sctransform时,通常会将此参数设置得更高而越有利。这是因为sctransform分析流程执行了更有效的标准化,从数据中强烈地去除技术带来的影响。
使用log-normalization归一化后,测序深度的变化仍然是一个混杂因素,这种影响可以微妙地影响更高的PC。在 sctransform 中,这种影响大大减轻,这意味着更高的PC更有可能代表微妙但与生物学相关的异质性来源——因此sctransform可能会改善下游分析。
此外,sctransform默认返回 3,000个高可变基因,而不是 2,000个。基本原理是相似的,额外的高可变基因不太可能由跨细胞的技术差异所引起的,而可能是代表更微妙的生物波动。一般而言,我们发现使用sctransform产生的结果对这些参数的依赖性较小(实际上,当使用转录组中的所有基因时,我们获得了几乎相同的结果,尽管使用所有基因这确实降低了计算效率)。这可以帮助用户生成更可靠的结果,此外,还可以搭建具有相同参数的标准分析管道,快速应用于新数据集:
pbmc <- CreateSeuratObject(pbmc_data) %>%
PercentageFeatureSet(pattern = "^MT-", col.name = "percent.mt") %>%
SCTransform(vars.to.regress = "percent.mt") %>%
RunPCA() %>%
FindNeighbors(dims = 1:30) %>%
RunUMAP(dims = 1:30) %>%
FindClusters()
我的理解是,sctransform分析流程不需要关注PC数目,和高可变基因数目这些参数,而反复调参,使用默认的参数即可,便于搭建标准分析流程。
问题2:sctransform处理后的标准化值存储在哪里?
如论文中所述,sctransform使用“正则化负二项式回归”计算scRNA-seq数据中的技术噪声模型。该模型的残差是归一化数值,可以是正值也可以是负值。给定细胞中给定基因的正残差表明,鉴于该基因在细胞群中的平均表达和细胞测序深度,我们观察到的UMI比预期的多,而负残差则表明相反。
sctransfrom 的结果存储在'SCT' assay中。
pbmc[["SCT"]]@scale.data包含残差(归一化值),并直接用作PCA 的输入。请注意,这个矩阵是非稀疏矩阵,因此如果为所有基因存储,可能会占用大量内存。为了节省内存,我们只为高可变基因存储这些值,方法是在SCTransform()函数调用中默认设置 return.only.var.genes = TRUE 。
协助基因可视化和解释。我们还将Pearson残差转换回“校正后的”UMI 计数counts。“校正后的”UMI 计数counts可以这样理解,假设所有细胞的测序深度一致,我们希望观察到的 UMI计数(原始counts),通过sctransfrom算法剔除测序实验变异后,矫正后的counts。
“矫正后”的UMI计数存储在pbmc[["SCT"]]@counts中。我们将这些校正计数进行log-normalized,归一化版本存储在pbmc[["SCT"]]@data,这对基因表达量可视化非常有帮助。
可以使用校正的log-normalized计数counts(也就是pbmc[["SCT"]]@data)进行差异表达分析和整合分析。但是,原则上,最好直接对残差(存储在scale.data中)执行这些计算。目前,Seurat v3不支持此功能,但很快就会支持应用scale.data做差异基因等分析。
三、sctransform vs lognormalize
我们通过阅读作者的论文,了解sctransform和lognormalize方法上的差异。
3.1 为什么要Normalization?
在单细胞RNA-seq (scRNA-seq) 数据的分析中,进行有效的预处理和标准化非常关键,但是也很有挑战性。 原始UMI计数不能直接用于比较细胞之间的基因表达,因为它们会被技术和“无趣”的生物变异所混淆。 特别是,观察到的测序深度(每个细胞检测到的基因或分子的数量)在细胞之间可能存在显着差异,即使在同一细胞类型内,分子计数的变化可能跨越一个数量级。 虽然现在在scRNA-seq中广泛使用唯一分子标识符 (UMI) 消除了 PCR 扩增偏差,但仍需要通过标准化以消除其他技术变化的影响,如测序深度、细胞裂解和逆转录效率等带来的变异。其实在bulk RNA-seq分析中同样存在,但由于scRNA-seq数据的极度稀疏性,这类问题会更严重。
单细胞标准化的主要目标是消除技术效应对潜在分子计数的影响,同时保留真正的生物学变异。具体来说,作者建议经过有效归一化分析流程处理的数据集应具有以下特征:
- 一般来说,基因的标准化表达水平不应与细胞的总测序深度相关。 下游分析流程(降维、差异表达)也不应受测序深度变化的影响。
- 归一化基因(跨细胞)的方差应主要反映生物异质性,与基因丰度或测序深度无关。
例如,标准化后具有高方差的基因应在不同细胞类型之间差异表达,而看家基因应表现出低方差。 此外,在考虑深度测序的细胞或浅测序的细胞时,基因的方差应该是相似的。
3.2 两种主流的标准化方法
方法1:全局scale归一化方法(global scaling normalization):即基于缩放因子的归一化方法。确定单个细胞的“大小因素”(size factors),通过对每个细胞进行统一缩放,这些方法假设数据集中所有细胞的潜在 RNA 含量是恒定的,并且可以对所有基因应用单个缩放因子,以便将技术噪音与生物细胞间的变异性区分开来。lognormalize标准化属于此类。
方法2:使用概率方法对分子计数进行建模,sctransform属于此类型。他们认为不同的基因组别(gene group)不能被相同的常数因子归一化,质疑基于缩放因子的归一化方法,缩放因子是如何计算的。sctransform的“正则化负二项式回归”的残差代表了有效归一化的数据值,不再受技术特征的影响,但保留了由不同生物状态驱动的异质性。最后,证明这些归一化值能够进行下游分析,例如降维和差异表达测试,结果不会被细胞测序深度混淆。
这两种方法也是目前seurat主要的标准化处理方法。
3.3 单一缩放因子不能有效地标准化低表达和高表达的基因
为了探究单细胞测序深度的影响程度,作者从10x Genomics官网下载了不同组织的5个数据集,共33,148 个人类外周血单核细胞 (PBMC) ,查看log-normalization方法标准化处理的有效性。
图A:细胞总UMI计数(“测序深度”)的分布图;每个细胞平均 1891个UMI(中位数)。
图B:根据基因在数据集中的平均表达量将基因分为6组,即Gene group1-group6高中低表达组。
图C:x轴是每个细胞的总UMI数(“测序深度”),y轴是观察到的基因UMI数目,为每个基因拟合一条平滑线,黑色线表示均值拟合线,彩色区域表示四分位距。能很明显的看出,这6个Gene group均表现出非标准化表达量(基因UMI计数,y轴)和细胞测序深度(x轴)之间存在很强的线性关系。
图D:我们应用scaled log-normalized处理(后面简称log-normalization)后的标准化表达值,和图C一样绘图,y轴是缩放的log归一化值,而非原始的基因UMI计数。6个Gene group处理后的均值拟合线趋势不一致。
图E:观察基因变异方差来源与细胞测序深度的关系;作者的做法是将6个Gene group,又按照细胞的总UMI计数将细胞群分成5个大小相同的组(Cell Group), Cell Group1-5,其中Cell Group1的测序深度最大,Group2-5其他依次降低。评价一个有效标准化的数据是,每个细胞对Gene group的方差贡献率应该是一样的,20%。
结论:log-normalization这种方法虽然减轻了测序深度和基因表达量之间的关系,但我们发现具有不同总体丰度的基因在log-normalization处理后表现出不同的模式,并且只有底部三组(Gene group4-group6)的低/中丰度基因被有效地归一化,高丰度基因归一化无效。作者在人脑RNA数据集也发现了相同的模式。默认的lognormalize归一化仅适用于中低表达基因。
3.4 将正则化负二项式回归应用于单细胞归一化
作者发现使用负二项式分布对单细胞数据进行建模会导致过度拟合,再此不细说。
此后,作者引入正则化负二项式回归模型应用于单细胞归一化,pearson残差有效地标准化了技术差异,同时保留了生物变异。说明一下,pearson残差可以理解为sctransform标准化。
图A和B:同3.3上图,但是y轴是Pearson残差,对scRNA-seq 数据的归一化处理明显优于log-normalization。特别是图B,每个cell group对Gene group的方差贡献率几乎一致。
图C:比较log-normalization和Pearson残差两种标准化处理方法,计算6个Gene group的Pearson残差和细胞总UMI计数之间Pearson相关性,绘制箱线图。Pearson残差这个方法的中位数几乎为0,也就是说Pearson残差和总细胞 UMI计数(测序深度)几乎无关。
结论:图A-C都表明,与log-normalization相比,Pearson残差的表达量和方差与测序深度无关,运用正则化NB回归的Pearson残差,对scRNA-seq数据进行了有效的归一化。这应该消除技术变异但保留生物异质性,同时避免了模型过度拟合数据。
四、小结
4.1 为什么我们要标准化scRNA-seq基因表达值?
- 我们根据基因表达谱的差异对细胞进行聚类
- 基因表达值的差异应反映细胞间的生物学变异
- 单细胞基因表达值是噪音数据
- 测序深度(每个细胞的UMI数量)在细胞之间存在显着差异
- 标准化的基因表达值应与测序深度无关
4.2 全局scale标准化(Global scaling normalization)
计算方法:
- 将细胞中基因的UMI计数除以该细胞中的UMI总数
- 将上面的比值乘以scale 因子(默认为10,000)
- 对结果取自然对数进行转换,这将每个细胞缩放到10,000这个转录本总数
问题:全局scale标准化的问题是对高表达基因不能有效的归一化
- 默认的lognormalize归一化仅适用于中低表达基因
- 高表达基因的表达值与测序深度相关
4.3 Sctransform
方法:使用正则化负二项式回归对单细胞 RNA-seq数据进行归一化和方差稳定化处理
优势:对高表达基因,Sctransform可以更好地处理这个问题
下面,我们回答第一个问题:
问:什么情况下SCTransform是优于全局scale归一化方法(global scaling normalization)
答: 对高表达基因,全局scale标准化不能有效的归一化,Sctransform可以更好地处理这个问题;