第4章 蛋白质组学数据基础:质谱数据、肽段鉴定、蛋白质丰度矩阵

聊到蛋白质组学,很多人第一反应是“啊,质谱”。没错,质谱就是蛋白质组学最主力的数据来源。但说实话,我刚入行时对着那堆 m/z 和强度值完全懵了——这玩意儿怎么能变成深度学习能用的张量?这一章咱们就把这层窗户纸捅破。

4.1 质谱数据长什么样?

质谱的本质很简单:把肽离子按质荷比(m/z)分开,记录每个 m/z 处有多少离子(强度)。输出就是一个二维谱图,横轴 m/z,纵轴强度。

实际项目中你遇到的往往是 RAW 或者 mzML 格式。我建议初学者先别碰二进制格式,直接从 mzXML 或 mzML 的文本化版本入手。下面是常见格式对比:

格式特点典型处理工具
RAW(Thermo)二进制,厂商锁定Thermo RawFileReader
mzMLHUPO-PSI 标准,XMLpymzML, ProteoWizard
mzXML早期开放格式Trans-Proteomic Pipeline
MGF纯文本谱图列表几乎任何工具

我记得第一次做大规模分析时,数据量 50GB 起。你不能把整个质谱原始数据全塞进 GPU——那几百亿个数据点多半是噪音。咱们要的是经过提取的肽段谱图(MS2)和对应的定量信息。

小技巧:用 ProteoWizard 的 msConvert 可以把 RAW 转成 mzML,同时做 peak picking。命令行如下(别复制错了):

msconvert --mzML --filter "peakPicking true 1-" input.raw -o output_dir

加 --zlib 可以压缩大小,我一般会加。

4.2 肽段鉴定——从谱图到序列

质谱仪打到肽段上,产生碎片离子。肽段鉴定就是拿这些碎片模式去和理论谱图匹配。最常见的算法是 SEQUEST、Mascot、Andromeda(MaxQuant 用的),还有现在的深度学习工具比如 DeepMass、Prosit。

为什么我单独提这段?因为很多组学模型训练的数据集就是直接拿鉴定结果当标签。如果鉴定步骤本身有错,模型学到的就是天书。

我曾在一个项目里遇到过这件事:某公共数据库的肽段鉴定 FDR 设到了 5%,结果模型训练完看起来 AUPRC 很高,但实际预测全是假阳性。搞得我排查了两周。从那以后我经手的项目,鉴定 FDR 必须 ≤ 1%,最好 0.5%。

鉴定结果通常存成 pepXML 或 mzid 格式,核心字段就是:

  • 扫描号(Scan)
  • 肽段序列
  • 电荷状态
  • 置信度分数(比如 XCorr, e-value, q-value)

4.3 蛋白质丰度矩阵——你的训练目标

肽段鉴定后,接下来是把肽段映射到蛋白质,并算出每个蛋白质在各样本里的丰度。这就得到了丰度矩阵:行是蛋白质,列是样本,单元格里是丰度值(通常是对数转换后的 TMT 报告离子强度或 LFQ intensity)。

这个矩阵就是深度学习模型的核心训练数据了。

  • 输入:蛋白质序列特征(比如 embedding)或其他组学特征
  • 输出:这个蛋白质在疾病/正常条件下的差异丰度
  • 注意:矩阵里缺失值非常多——质谱有天然“缺失采样”问题

避坑指南:不要直接把原始强度值丢给 GPU。我试过不归一化就训练,Loss 下不去。必做步骤:

  1. log2 转换(让数据接近正态)
  2. 分位数归一化(消除批次效应)
  3. 缺失值处理(我倾向于用 KNN imputation 而非填零)

4.4 数据组织与输入管道

拿到丰度矩阵后,为了喂给 GPU,你得设计一个能高效读取的数据管道。这里我分享一个在实践中打磨过的策略:

# 以 PyTorch 为例,但思路通用
dataset = ProteomicsDataset(protein_ids, expression_data, sample_labels)
dataloader = DataLoader(dataset, batch_size=32, 
                         num_workers=8, pin_memory=True)

但千万别把整个矩阵都加载进内存再 shuffle——尤其当你处理的是 10 万蛋白 × 1000 样本时,内存直接爆掉。我一般会做一个内存映射文件(memory-mapped)或者用 h5py 按批次读取。

# 使用 h5py 存储丰度矩阵
import h5py
f = h5py.File('proteomics.h5', 'w')
f.create_dataset('expression', shape=(n_proteins, n_samples),
                 dtype='float32', compression='gzip')
f.create_dataset('protein_ids', shape=(n_proteins,), dtype='S20')

实际加载时只 select 当前 batch 需要的行,配合 GPU 的 pinned memory 做异步传输——这样可以掩盖 IO 延迟。

你自己想想:一次推理一个样本和一次推理一个 batch,训练速度差多少?我见过有人单样本循环跑了一天一夜还没跑完,改成 batch 后两小时搞定。

4.5 全流程可视化:从质谱原始输出到丰度矩阵

下面我用一张图把整个数据流串起来。这也是我每次给新同学讲时必定先画的框架。

蛋白质组学数据管道: 质谱 → 丰度矩阵 质谱原始数据 谱图预处理 肽段鉴定 蛋白质推断 丰度矩阵 GPU 加速模型训练 峰提取、去同位素、校正 序列匹配、FDR 过滤 缺失值插补、归一化

4.6 实际项目中的常见坑

  • 蛋白质 ID 不一致:不同数据库(UniProt、RefSeq)ID 格式不同,合并前必须统一映射。我有个脚本专门做这件事。
  • 肽段到蛋白质的归纳(protein inference):同源肽段会被多个蛋白质共享,这叫“ambiguously assigned peptide”。我建议删除这些共享肽段,不然会引入噪声。
  • 批次效应:TMT 多批次实验之间的丰度漂移非常明显。用 ComBat 或 limma 调整是必须的。

核心总结:质谱数据经过谱图预处理、肽段鉴定、蛋白推断三步,才能得到可训练的丰度矩阵。矩阵里缺失多、噪声大,但 GPU 训练的前提是先把数据组织好——管道设计比模型设计更容易被忽略。把这一步做扎实,模型训练就成功了一半。