RNA-seq 数据特点:读取计数、归一化、批次效应、技术重复与生物学重复

做 RNA-seq 数据验证,第一关不是模型,是数据本身。我见过太多人一上来就怼深度学习,结果被原始数据的“坑”直接教做人。今天咱们就掰扯清楚 RNA-seq 数据到底长什么样,有哪些脾气。

1. 读取计数(Read Counts)—— 一切的基础

RNA-seq 测序出来,第一步得到的是计数矩阵。行是基因(或转录本),列是样本,每个格子是个整数,代表比对到这个基因上的 reads 数量。说白了,就是数数——每个基因被“数”到多少次。

关键特性:计数数据本质是离散的,而且是过离散(overdispersion)的。方差往往大于均值,这在统计建模时必须考虑。

我个人习惯拿到原始计数后,先做三件事:

  • 检查测序深度:各样本的总 reads 数差异是否在 3 倍以内?超出这个范围就要警惕。
  • 看低表达基因比例:超过 50% 的基因平均计数 < 10?那就需要过滤策略。
  • 查零膨胀情况:特别对于单细胞数据,零的比例可能高达 90%。

我曾经接手一个项目,合作伙伴给的“clean data”里,有个样本的总 reads 数只有其他样本的十分之一。他们说是“技术原因”。嗯,这基本等于说“数据不能用”。从那以后,我接数据第一件事就是画总计数分布图。

避坑指南:原始计数最好不要直接用于差异表达分析。很多方法(如 DESeq2)要求输入的是整数计数,而非归一化后的浮点数。强行输入归一化值会破坏统计模型的假设。

2. 归一化(Normalization)—— 让样本之间能比

为什么要归一化?很简单:两个样本测序深度不一样,你不能直接拿原始 count 比较。

举个例子:样本 A 测了 2000 万 reads,样本 B 测了 1000 万 reads。就算所有基因表达完全一样,A 的 count 也会是 B 的 2 倍。这显然不是生物学差异。

常用的归一化方法有这些:

方法 核心思想 适用场景
CPM / RPKM / FPKM 按文库大小和基因长度缩放 样本间粗略比较(已逐渐被淘汰)
TPM 先按基因长度归一化,再按文库缩放 基因间、样本间比较
DESeq2 的 median of ratios 考虑文库大小和 RNA 组成 差异表达分析的主流方法
TMM (edgeR) 去除高表达、高差异基因后计算缩放因子 差异表达分析的另一主流方法

我记得有一次做跨平台验证,一个用 RPKM,一个用 TPM,直接对比例子数据,画出来的散点图像毛线团。后来统一重算成 TPM,才算看清了趋势。

注意:RPKM/FPKM 有个臭名昭著的缺陷——不同样本间总计数会因高表达基因的“抢资源”而产生偏差。这也是为什么主流分析 pipeline 现在很少用它们做差异分析了。

归一化在外部验证环节也很重要。模型训练时用的归一化方法,验证时也要用同样的参数去转数据,否则模型看到的特征空间直接变了。

# 示例:Python 中如何重现 DESeq2 的归一化
# 这只是示意,实际建议用 DESeq2 的 R 包
def deseq2_normalize(count_matrix):
    # 1. 计算几何均值(按行,排除零)
    # 2. 计算每个样本相对于几何均值的比值
    # 3. 取中位数作为缩放因子
    # 4. 原始计数除以缩放因子
    return normalized_counts

3. 批次效应(Batch Effect)—— 不是你实验的问题,但一定是你的问题

批次效应是 RNA-seq 数据里躲不开的“幽灵”。不同测序批次、不同操作人员、不同试剂批次,都会引入系统性差异。这些差异与生物学差异纠缠在一起,处理不好,你的模型学到的可能只是“批次识别器”。

为什么它这么重要?因为外部验证的本质,就是用“新数据”检验模型。如果新数据来自不同批次,而模型没有处理好批次效应,那么验证结果会极其惨烈。

我有个血泪教训:团队花三个月训练了一个癌症分型模型,在原始数据集上 AUC 0.95。兴冲冲地拿外界公开数据一测,AUC 直接掉到 0.6。问题出在哪?训练数据全是 Illumina HiSeq 2500 测的,外部数据是 NovaSeq 6000 测的。基因表达量分布完全不同,模型完全“蒙圈”。

检测批次效应可以用主成分分析(PCA)或 t-SNE:

  • 用批次变量对 PCA 结果着色
  • 如果样本按照批次而不是生物学分组聚在一起,那批次效应很严重
  • 计算批次对表达量方差的贡献比例(如 R 包 variancePartition)

常见的校正方法包括:ComBat、limma::removeBatchEffect、以及基于回归的方法。但要注意:校正前一定要确保训练集和验证集可以一起校正,或者验证集能用训练集的参数来校正。

# R 中使用 ComBat 进行批次校正(示意)
# library(sva)
# adjusted_matrix <- ComBat(dat = expression_matrix, batch = batch_vector)

4. 技术重复与生物学重复 —— 你测了几次?你到底测了谁?

这两个概念经常被混淆,但在模型验证中,它们决定了你的结论有多可靠。

技术重复:同一管 RNA,分成两等份,分别建库测序。差异来自实验操作和技术误差。

生物学重复:同一条件下,不同个体的样本分别处理、建库、测序。差异既包括技术误差,也包括个体间的生物学变异。

重复类型 变异的来源 在模型验证中的作用
技术重复 建库、测序、操作 评估模型对测量噪声的鲁棒性
生物学重复 个体差异 + 技术误差 评估模型在新个体上的泛化能力

我之前遇到一个案例:有人在同一个病人的肿瘤样本上做了 3 次 RNA-seq,作为 3 个“肿瘤样本”喂进模型。结果模型在外部验证时准确率暴跌。为什么?因为那 3 个“样本”本质上只有一个生物学样本,模型捕捉到的更多是技术噪声,而不是真正泛化的肿瘤特征。

给验证的建议:

  • 外部验证集最好来自不同的实验室、不同测序平台
  • 至少要有 3 个生物学重复(每个组别)
  • 如果模型在技术重复上表现好,在生物学重复上表现差,那说明过拟合了技术噪声

5. 一张图总结 RNA-seq 数据的“坑”

下面这张图梳理了从原始测序到外部验证的数据流,以及每个阶段最容易出问题的环节。你们可以把它贴在工位旁,当 checklist 用。

RNA-seq 数据流与验证注意事项 原始测序数据 (FASTQ) 比对 (BAM/SAM) 定量 (计数矩阵) 归一化 (TPM/RPKM...) 批次效应校正 模型训练 外部验证 常见“捷径” — 危险! 检查点:数据验证 检查点:模型验证 外部验证要点: 1. 验证集与训练集是否来自同一平台/批次? 2. 归一化参数是否重置?还是直接套用了训练集参数? 3. 生物学重复是否足够支撑统计推断?

图里那个虚线路径,就是“归一化和批次校正都跳过,原始定量数据直接喂模型”——这种搞法在学术界被叫“garbage in, garbage out”。我见过有人这么干过,审稿人回复里第一条就是质疑数据处理流程。别走那条路。

6. 小汇总:给新手的检查清单

  1. 读入数据第一件事:检查各样本总 reads 数,画出分布图,找离群。
  2. 归一化前:确认你的下游分析需要整数计数还是浮点数。
  3. 外部验证前:一定要确认训练集和验证集的批次信息。如果批次不一致,要么合并校正,要么确认模型对这些差异鲁棒。
  4. 重复样本:区分清楚是技术重复还是生物学重复。如果区分不了,默认按生物学重复处理,宁可保守也不要激进。
  5. 日志记录:每步数据处理,用什么参数,什么版本的工具,全部记下来。外部验证出了问题,你能往回追溯。

嗯,这些内容听起来基础,但我在实际项目中见过太多人在这上面翻车。数据是模型的根基,根基不稳,后面再花哨的技术也白搭。下一块内容,我们会具体聊怎么把这些特性用到外部验证流程里,搭建一套可靠的评估框架。今天就到这儿,你们先消化一下这些概念。