理解DESeq2统计模型:负二项分布与缩并估计
咱们直接切入正题。DESeq2 的核心,就是用一个数学模型来描述基因表达数据。你想想看,RNA-seq 的计数数据有个很讨厌的特性——方差比均值大得多。这不是普通的泊松分布能搞定的。DESeq2 选用了 负二项分布,又叫 NB 分布,正是因为这个分布多了一个离散参数,能兜住那种“过度离散”的现象。
我刚开始用的时候,也犯过嘀咕:为什么非要用 NB?直接用泊松省事多了。后来在项目里处理一批 replicate 差异很大的样本,才发现泊松根本压不住方差,假阳性满天飞。嗯,从那以后我彻底服了 NB。
负二项分布:均值与方差的亲密关系
NB 分布的数学形式我就不展开了,但你需要记住一个关键公式:
方差 = 均值 + 离散度 × 均值²
这个离散度参数(记作 α,或者用 DESeq2 里的 dispersion)决定了方差超过均值的幅度。α 越大,数据越“散”;α = 0 时,NB 退化为泊松。你想想看,如果所有基因的 α 都设成同一值,那估计起来多简单?但现实是每个基因都有自己的脾气——有些基因表达稳定,α 很小;有些基因受噪声影响大,α 很大。
关键点:DESeq2 不是为每个基因独立估计离散度的。它利用所有基因的信息,对离散度做“缩并估计”(shrinkage estimation)。这就是它威力所在。
缩并估计:借力打力的贝叶斯智慧
怎么理解缩并?我举个例子。你有一个基因,只有 3 个 replicate,数据波动很大。如果你只用这 3 个点估计它的离散度,结果会非常不靠谱。但是,如果你同时看到其他几千个基因的离散度分布——大多数基因的离散度集中在某个区间——那你就可以把这个基因的估计值“拉”向这个集中区间。这就叫缩并。
DESeq2 采用 经验贝叶斯 策略:先用所有基因估计一个离散度的先验分布(通常是 Gamma 分布),然后对每个基因的离散度做后验估计。说白了,就是给每个基因一个“修正因子”,避免极端值带来的误导。
个人经验:我遇到过一组数据,其中某个基因在对照组和实验组都只有 1 个 replicate(剩下是技术重复)。如果不缩并,那个基因的 P 值几乎全是 0.9999——它被判定为非差异。缩并后,它一举成为前 50 的差异基因。后来 qPCR 验证,确实显著。缩并救活了它。
DESeq2 中的两步估计流程
下面这张图概括了 DESeq2 如何从原始计数走到最终差异检验。注意,离散度估计是卡在中间的关键一步。
控制缩并效果的几个参数
| 参数 | 作用 | 我常用的设置 |
|---|---|---|
fitType |
选择拟合先验分布的方式:parametric(默认,假设均值-离散度曲线为平滑曲线)、local(非参数局部回归)、mean(直接对每个表达水平分组计算均值) |
样本量大时用 parametric;样本少且基因表达范围广时换 local |
minReplicatesForReplace |
当某个条件(组)内 replicate 数少于该值时,DESeq2 会用缩并值替代原始离散度估计 | 默认是 Inf(全部替换),但我习惯设为 3,留一点原始信息 |
useT |
是否用 t 分布计算 P 值;TRUE 时对缩并离散度的不确定性做额外校正 |
小样本(n ≤ 5)时开启,大样本按默认 |
我曾经踩过一次坑:在做时间序列分析时,每个时间点只有 2 个生物学重复,却把 fitType 设成了 parametric。结果拟合曲线被少数基因带偏,导致大量假阴性。后来换成 local 才稳住。所以参数没有绝对的好,要看数据集的总体分布特征。
实际操作:如何修改参数
在 DESeqDataSet 建成后,你可以直接用 estimateDispersions 或者通过 DESeq 函数传递参数。下面是我常用的代码块:
dds <- DESeqDataSetFromMatrix(
countData = counts,
colData = coldata,
design = ~ condition
)
# 手动控制缩并参数
dds <- estimateDispersions(dds,
fitType = "local",
minReplicatesForReplace = 3)
# 或者直接用 DESeq() 一步到位
dds <- DESeq(dds, fitType = "parametric")
如果你想知道每个基因的最终离散度长什么样,可以在 colData 里找到 dispersion 一列。我会习惯画一个散点图看看均值-离散度关系,确认缩并有没有把离群值拉回来。
留个心眼:缩并也有副作用。如果某个基因的真实生物学变异确实非常大(比如组织特异性高表达基因),缩并可能会把它压回背景水平,导致漏检。这时候可以查看 mcols(dds)$dispersion 中的 dispersionPriorVar,看看缩并的程度是否合理。我在一篇关于免疫细胞亚群的项目中就遇到过这种情况,最后手动调高了那个基因的离散度权重。
小结:别让参数变成黑盒
负二项分布 + 缩并估计,这两样东西构成了 DESeq2 的脊梁骨。你不需要搞懂数学推导,但必须理解这背后的逻辑:为什么要缩并?缩并的力度受哪些按钮控制?
我的建议是:跑第一个分析时,全部用默认参数。然后打印出离散度分布图,看看有没有基因的离散度被异常拉高或压低。如果有,再调整 fitType 或 minReplicatesForReplace。千万别一上来就盲目改参数——你想想看,连数据长什么样都不知道,就去拧旋钮,不是瞎搞吗?