2. sctransform算法原理:参数化负二项回归

好了,咱们正式开始啃这块硬骨头。

很多做单细胞的朋友,上来就直接跑SCTransform()。但你要问我,不懂原理就去调参,迟早要翻车。我之前帮一个团队排查批次效应,他们跑了SCTransform,结果聚类还是按样本分群。一看日志,参数没调对,正则化强度设得太高,生物信号被当噪声抹掉了。

所以,花半小时搞懂它背后的数学直觉,绝对值。

为什么是负二项?

单细胞数据最让人头疼的特征是什么?过离散。

你想想看,同一个基因在不同细胞里的UMI计数,方差往往远大于均值。这在泊松分布下是解释不了的——泊松要求方差等于均值。现实数据呢?方差经常是均值的几倍甚至几十倍。

我记得第一次处理10X数据时,画了个基因表达量的分布图,拖了个长长的尾巴。当时就知道,泊松肯定没戏。

负二项分布 (NB) 自带一个色散参数,可以同时建模均值和方差。公式长这样:

Var(Y) = μ + μ² / θ

其中 θ 是色散参数。θ 越小,过离散越严重。当 θ 趋近无穷大时,负二项就退化为泊松。

核心理解: 泊松是负二项的特例。单细胞数据几乎总是过离散的,所以我们必须用负二项。这不是学术洁癖,这是数据本身的要求。

参数化模型怎么建模?

sctransform并没有用传统的广义线性模型那套框架。它的建模思路很直接,说白了就是三步:

  1. 学习全局参数:根据所有基因在所有细胞里的表达,估计出一套通用参数。
  2. 逐基因建模:对每个基因,拟合一个负二项回归模型,以UMI测序深度作为协变量。
  3. 提取残差:用模型预测值减去观测值,得到"标准化"后的残差。

但问题来了:如果对两万个基因逐个跑负二项回归,计算量太大了。我当年在集群上跑过一次,等了两个小时还没出结果。

sctransform的聪明之处在于,它用了一个参数化技巧,把拟合过程大大简化了。

参数化负二项回归的细节

sctransform模型假设:对于基因 g 在细胞 c 中的UMI计数 Y_{gc},其分布为:

Y_{gc} ~ NB(μ_{gc}, θ_g)
其中: log(μ_{gc}) = β_{0g} + β_{1g} * log(UMI_total_c)

这里的 log(UMI_total_c) 就是每个细胞的总UMI测序深度取对数。为什么要用对数?因为测序深度和表达量之间,基本上是幂律关系,取对数之后变成线性,好拟合。

然后重点来了:sctransform假设这些回归系数(β₀和β₁)与基因的均值之间,存在一个平滑的非线性关系。

换句话说,sctransform先用一小部分基因(默认2000个)拟合出完整的回归模型,然后通过核回归,预测出所有基因的回归系数。

避坑指南:我曾经在只有5000个细胞的小数据集上,强行调整了参数,让sctransform用所有基因做完整拟合。结果运行时间暴涨了5倍,但最终的聚类结果跟默认参数没差别。所以,除非你的数据非常特殊,否则默认的2000个基因子集就够用了。

模型拟合的完整流程

我整理了一张流程图,把整个参数化建模过程串起来:

sctransform参数化负二项回归流程 原始UMI计数矩阵 1. 选择2000个高度可变基因 计算每个细胞log(总UMI) 2. 逐基因拟合负二项回归 log(μ) = β₀ + β₁ * log(UMI_total) 估计每个基因的β₀, β₁, θ 3a. 参数平滑 核回归估计所有基因参数 3b. 正则化 利用先验分布收缩参数 4. 计算Pearson残差 (观测 - 预测) / √方差 标准化残差矩阵 (下游输入) 关键洞察 残差≈0 → 基因表达完全由测序深度解释 残差>0 → 存在真实的生物学上调

残差的计算方式

模型拟合完成后,每个基因都有了完整的参数。接下来计算Pearson残差:

z_{gc} = (y_{gc} - μ̂_{gc}) / √(μ̂_{gc} + μ̂_{gc}² / θ̂_g)

这个残差z_{gc},就是你最终拿去做降维、聚类的输入值。

为什么不用原始的logCPM、TPM?因为那些方法没能把测序深度的影响完全剥离。sctransform的残差,去除的是"由测序深度带来的表达量变化",保留的是"超出预期的那部分信号"。

重要警告:Pearson残差的取值范围理论上可以是正无穷或负无穷。但实践中绝大多数的值都在[-3, 3]区间内。如果你看到大量超过这个范围的值,说明你的模型拟合有问题,或者数据中存在严重的异常细胞。我排查过一个案例,是因为部分细胞的双细胞率过高,导致残差爆炸。

参数对比表

我把sctransform与传统标准化方法的核心差异,整理成了一张表:

对比维度 LogNormalize sctransform
基础分布假设 泊松(隐含) 负二项(显式建模过离散)
协变量处理 离差缩放因子 直接回归建模测序深度
方差处理 全局缩放 基于正则化的基因特异方差
残差性质 log(CPM), 方差不稳定 Pearson残差, 方差稳定
计算效率 极快 较快(因参数化加速)
批次校正集成 需要额外步骤 内置 (SCTransform v2)

回归系数的生物学解释

说到这里,有朋友可能会问:「你花了这么大力气去拟合β₀和β₁,这两个系数到底代表什么?」

我个人习惯这么理解:

  • β₀:截距项。反映的是这个基因的基础表达水平。直白点说,就是在测序深度取平均对数的情况下,这个基因预期会有多高表达。
  • β₁:斜率项。反映的是基因对测序深度的敏感程度。如果β₁接近1,说明该基因的表达量和测序深度完全成正比——这种基因往往是非特异性的背景基因(比如线粒体基因)。
  • θ:色散参数。决定这个基因在不同细胞间的波动程度。θ越小,基因的噪音越大。

我记得在分析肾脏单细胞数据时,β₁特别大的基因大多是核糖体蛋白基因。这说明这些基因的表达量高度依赖于细胞总体转录活性,而不是细胞类型特异的信号。在做降维之前,把这类基因的残差压低,反而让真实的细胞类型标记基因的信号更突出。

一句话总结: 参数化负二项回归不是玄学。它让每个基因的标准化过程有了一个"专属模型"。你只需要提供一个测序深度,模型就能告诉你:这个表达量,是正常的测序深度效应,还是真实的生物学信号。

嗯,原理部分就讲这么多。下一层,我们会把这点理论拆成代码,一行一行跑通。