edgeR 基本原理与特点:准似然 F 检验、经验贝叶斯、TMM 归一化

聊完 DESeq2,咱们来正经看看 edgeR。说实话,这两个工具名字听起来像兄弟,但底层逻辑差别不小。edgeR 是更早一批的差分表达分析工具,到现在还在广泛用,说明它有真本事。

edgeR 的核心思想:从计数到统计

edgeR 做的其实就一件事:判断一个基因在不同条件下的表达量变化,到底是生物学差异还是技术噪音。它的假设和 DESeq2 很像——都认为 RNA-seq 计数服从负二项分布。但 edgeR 的推导路径更“直接”一些。

我个人习惯把 edgeR 的处理流程分成三步:

  1. 归一化——纠正不同样本之间的测序深度和文库组成差异,用的是 TMM 方法。
  2. 分散估计——通过经验贝叶斯方法,借用所有基因的信息来稳定每个基因的分散参数。
  3. 统计检验——用准似然 F 检验或精确检验,计算每个基因的 p 值。

嗯,这里要注意,edgeR 最新版本主推的是准似然 F 检验(QL F-test),而不是早期版本里的精确检验。原因很简单——QL 方法对分散估计的稳健性更好。

一句话总结:edgeR 用负二项分布建模计数,用 TMM 处理文库偏差,用经验贝叶斯借力打力,最后用 QL F 检验给出结果。

TMM 归一化:为什么要多此一举?

很多初学者会问:DESeq2 用中位数比值归一化,edgeR 用 TMM(Trimmed Mean of M-values),到底谁对?

我在项目里对比过这两种方法。实际上它们都在解决同一个问题:不同样本之间,除了生物学差异,还有测序深度和 RNA 组成的影响。举个真实的例子——如果某个样本里高表达基因特别多,那其他基因的读数就会相对变少,看起来像下调了,其实不是。

TMM 的思路很简单:先选一个参考样本(比如所有样本的中位数库),然后对每个样本,删除两端极端的基因(trim),只保留中间部分的 log-fold-change,加权平均得到一个缩放因子。这个缩放因子就是该样本相对于参考样本的校正系数。

# edgeR 默认使用 TMM 归一化
library(edgeR)
y <- DGEList(counts = counts, group = group)
y <- calcNormFactors(y, method = "TMM")
# 查看归一化因子
y$samples$norm.factors

实际用的时候,TMM 和 DESeq2 的 median-of-ratios 结果往往非常接近。但 edgeR 的 TMM 在文库大小差异很大或噪声比较多的情况下,稍微稳健一点。

一个小技巧:如果你发现某个样本的 TMM 归一化因子明显偏离 1(比如 0.8 或 1.3),最好检查一下这个样本的质量。我遇到过好几次,归一化因子异常其实是样本污染的预兆。

经验贝叶斯:借力打力的智慧

RNA-seq 数据有个典型问题——基因数量几万个,但每个基因的重复样本可能只有两三个。你想想看,基于两三个重复去估计一个基因的方差,那结果怎么可能靠谱?

edgeR 的解决方案是经验贝叶斯收缩。它的做法分两步:

  1. 先算所有基因的初始分散估计,得到一个全局趋势(比如分散随表达量变化的曲线)。
  2. 然后对每个基因,把它的个体分散往这条趋势线上拉(shrink),拉多少取决于该基因的原始数据量。

这就像你给一个新手 chef 调味——他自己的判断可能偏差大,但让他参考老师的平均水平,就能做出差不多的菜。edgeR 就是那个老师。

边缘似然函数的具体推导我就不展开了,但你要知道:edgeR 里用的是准似然(quasi-likelihood)模型,它在经验贝叶斯的基础上,额外引入了一个准似然分散参数(phi),用来捕获基因特异性的方差变化。这就是 QL F 检验的基础。

参数 含义 edgeR 里的命名
common dispersion 所有基因共有的分散 common.dispersion
trended dispersion 随表达量变化的分散均值 trended.dispersion
tagwise dispersion 每个基因自己的分散(经验贝叶斯收缩后) tagwise.dispersion
quasi-likelihood dispersion QL 模型的额外分散(phi) QL.dispersion

我曾经被朋友问:为什么 edgeR 要搞这么多个分散?我的回答是:每个分散对应数据里的一个不确定性来源。Common 是基线,trended 是全局模式,tagwise 是个体调整,QL 是最后的保险。层次越多,检验越稳健。

准似然 F 检验:edgeR 的终极武器

准似然 F 检验是 edgeR 3.x 版本以后的主推方法,替代了以前的精确检验。它的核心逻辑和线性模型有点像:

  • 对每个基因拟合一个负二项广义线性模型,把条件、批次等因子放进去。
  • 用准似然分散 phi 来调整模型中的方差。
  • 通过 F 检验比较全模型和简化模型的残差。

为什么用 F 检验而不是卡方?因为 F 检验能更好地处理小样本情况,而且对分散估计的不确定性更鲁棒。

# QL F 检验的标准流程
y <- estimateDisp(y, design)
fit <- glmQLFit(y, design)
qlf <- glmQLFTest(fit, coef = 2)  # 比较感兴趣的系数
topTags(qlf)

回忆一下,DESeq2 用的是 Wald 检验(或者 LRT 似然比检验)。这两个各有优劣。Wald 检验计算快,但需要分散估计准确;QL F 检验计算稍慢,但允许分散有一定波动,不那么容易假阳性。

一个坑:如果你用的 edgeR 版本比较旧(3.0 之前),默认的 exactTest() 是精确检验,准似然方法需要手动调用。建议升级到最新版,直接用 QL F 检验。

edgeR 的完整工作流程

下面这张图是我自己画的,把 edgeR 从原始计数到差异基因的链条放一块了。你盯着看两分钟,后面写代码就不慌了。

edgeR 差异表达分析流程 原始计数矩阵 创建 DGEList TMM 归一化 经验贝叶斯分散估计 QL 模型拟合 QL F 检验 注意 重复组内只有2-3个 样本时,经验贝叶斯 收缩效果最明显。 避免直接使用 naive 方差估计。

实际经验:什么时候选 edgeR 而不是 DESeq2?

我个人的经验是:如果样本量很小(比如每组 2 个重复),edgeR 的 QL F 检验比 DESeq2 的 Wald 检验更不容易假阳性。但反过来,如果样本量大(每组 10+),两者结果基本一致,这时我更看重计算速度——edgeR 快那么一点点。

还有一个场景:如果你的数据里有很多零计数基因,edgeR 不会像 DESeq2 那样做独立的零膨胀处理。edgeR 假设所有零都是负二项分布的自然结果。我遇到过一批植物转录组数据,里边有大量基因在某个处理条件下全零,edgeR 的表现其实不错,因为它不额外惩罚零。

最后给个关键提示:不论选 edgeR 还是 DESeq2,归一化方法的一致性一定要检查。我之前做跨平台比较时,发现一个包用 TMM、另一个用 RLE,结果差异基因列表从 500 个变成 1200 个。你说吓不吓人?