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 用。
图里那个虚线路径,就是“归一化和批次校正都跳过,原始定量数据直接喂模型”——这种搞法在学术界被叫“garbage in, garbage out”。我见过有人这么干过,审稿人回复里第一条就是质疑数据处理流程。别走那条路。
6. 小汇总:给新手的检查清单
- 读入数据第一件事:检查各样本总 reads 数,画出分布图,找离群。
- 归一化前:确认你的下游分析需要整数计数还是浮点数。
- 外部验证前:一定要确认训练集和验证集的批次信息。如果批次不一致,要么合并校正,要么确认模型对这些差异鲁棒。
- 重复样本:区分清楚是技术重复还是生物学重复。如果区分不了,默认按生物学重复处理,宁可保守也不要激进。
- 日志记录:每步数据处理,用什么参数,什么版本的工具,全部记下来。外部验证出了问题,你能往回追溯。
嗯,这些内容听起来基础,但我在实际项目中见过太多人在这上面翻车。数据是模型的根基,根基不稳,后面再花哨的技术也白搭。下一块内容,我们会具体聊怎么把这些特性用到外部验证流程里,搭建一套可靠的评估框架。今天就到这儿,你们先消化一下这些概念。