第3章 特征提取原理:从原始序列和模板中提取特征

哎,聊到特征提取,很多教程一上来就甩公式。但我觉得,先把根基打牢更重要。你想想,AlphaFold里的EvoFormer为什么能预测得那么准?说白了,就是它把人能想到的、能算出来的各种特征,全都喂给了模型。这一章,我们就聊聊这些特征是怎么从原始数据里“榨”出来的。

3.1 从序列到数字:One-hot编码

蛋白质序列就是一串字母,模型不认识字母,只认数字。所以第一步,就是把这串字母变成模型能消化的东西。最直接的方法,就是One-hot编码。

One-hot的原理很简单: 20种标准氨基酸,每种用一个20维的向量表示。这个向量里,只有该氨基酸对应的位置是1,其他都是0。比如丙氨酸(A)可能对应第一个位置是1,其他19个位置是0。

举个例子,序列 “ACD” 经过One-hot会是这个样子:

氨基酸 A: [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
氨基酸 C: [0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
氨基酸 D: [0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]

我刚接触这个领域时,觉得One-hot这么简单,能有啥用?后来在项目里吃过亏才知道,它虽然“笨”,但胜在无偏和完备。模型可以在训练过程中自己学习到哪些氨基酸是相似的,不需要我们人为定义。

不过,你也要注意,One-hot编码有两个明显的坑:

  • 稀疏性: 一个序列有L个残基,每个残基用20维表示,那这个矩阵就是L × 20的,绝大部分元素都是0。这会让模型很难学到有效特征。
  • 没有语义信息: 它只告诉你“这是什么氨基酸”,但没告诉你“这个位点上的氨基酸重不重要”。
个人习惯: 我一般把One-hot当作“地基”。后续不管是加PSSM还是其他特征,都是在它的基础上堆叠。千万不要因为觉得它太基础就不用了。

3.2 进化信息的金矿:PSSM

One-hot搞定了“是什么”,但没回答“这个位置有多重要”。PSSM就是来解决这个问题的。

PSSM全称是位置特异性得分矩阵。 它是怎么来的?拿你的目标序列去跟一个大型蛋白质序列数据库(比如UniRef100)做多序列比对。比对结果中,每个位点上,20种氨基酸出现的频率是不一样的。PSSM就是把这些频率信息,转换成一个得分矩阵。

这里面有个关键点:进化保守性。某个位点上,如果所有同源序列几乎都是同一个氨基酸,那这个位点得分就很高,说明它对于蛋白质结构和功能很重要。反之,如果什么氨基酸都能出现,得分就很低。

一个标准的PSSM矩阵,形状也是L × 20。但里面的值不再是0或1,而是经过对数比值转换后的得分。数值越高,表示该氨基酸在该位置的保守性越强。

我建议你记住这个对比:

特征 One-hot PSSM
信息类型 离散的、身份信息 连续的、进化信息
数值范围 {0, 1} [-∞, +∞](通常归一化到[-1, 1])
计算成本 极低 高(需要多序列比对)
对空位处理 无 可以反映插入/缺失区域
避坑指南: 我曾经在一个项目里只用了PSSM,觉得它信息量大。结果模型收敛慢,而且泛化能力差。后来发现,PSSM的数值范围差异非常大,不归一化直接丢给模型,会让优化过程很不稳定。我现在习惯的做法是:PSSM出来先做一遍Z-score归一化,再跟One-hot拼起来。

3.3 向真实世界学习:模板特征

序列信息再多,也是“纸上谈兵”。真正能告诉模型蛋白质应该长什么样的,是实验测出来的结构,也就是模板。EvoFormer在提取模板特征时,不是直接拿结构坐标,而是提取那些对模型训练更友好的特征。

我从模板里通常提取这几类信息:

  • 残基对的距离图: 这是最核心的。把模板里每两个Cβ原子之间的距离算出来,形成一个L × L的距离矩阵。模型本质上是在预测这个。
  • 主链二面角: ϕ和ψ角。这两个角度决定了主链的走向,属于非常强的先验知识。
  • 掩码信息: 不是所有模板都能覆盖整个序列。哪些位置有模板匹配、哪些没有,这个信息也要喂给模型,不然它会“乱猜”。

这里有个坑——我之前踩过。模板结构可能有局部错误或不一致性。比如你用PDB里2.0Å分辨率的模板和一个3.5Å分辨率的模板,它们在某些环区的结构可能完全不同。EvoFormer的处理方式是用多个模板取平均,但内部其实还有一个可学习的“模板注意力”机制,来自动给质量高的模板更高的权重。

3.4 汇流成河:构建初始特征张量

好,现在我们有了一堆特征:One-hot、PSSM(都是L × 20的矩阵)、模板特征(L × L的距离图、L × 2的二面角等)。怎么把它们组合起来,变成一个模型能一次性处理的“大矩阵”?

EvoFormer的做法很巧妙,它把特征分成两个层面:节点特征和边特征。

  • 节点特征(Pairwise representation): 描述“这个残基本身是什么”。比如,把One-hot和PSSM沿着特征维度拼接,形成一个L × (20 + 20) = L × 40的特征。这个就是初始的节点特征。
  • 边特征(Pairwise representation): 描述“两个残基之间的关系”。比如,模板距离图L × L,再加上其他残基对特征(比如相对位置、轴向旋转角等),拼成一个L × L × C的三维张量。

构建的过程,可以这样理解:

# 伪代码示意
L = seq_length
one_hot = create_one_hot(sequence)       # L x 20
pssm = get_pssm(sequence)                # L x 20
node_feat = concat([one_hot, pssm], axis=-1)  # L x 40

# 模板特征
template_dist = get_template_dist(seq, pdb_id) # L x L
relative_pos = compute_relative_positions(seq) # L x L
edge_feat = stack([template_dist, relative_pos], axis=-1) # L x L x 2
个人经验: 我在第一次实现这个流程时,犯了个低级错误——忘记对PSSM做序列对齐。如果多序列比对的gap导致PSSM的索引跟目标序列对不上,模型会学到完全错误的信息。我的建议是:在构建特征张量之前,一定要再三确认所有特征的索引都是对齐的。

3.5 一张图总结特征提取流程

为了让你更直观地理解,我把整个流程画了张图。它展示了从最原始的输入(序列和模板)到最终初始特征张量的完整路径。

特征提取流程:从原始输入到初始特征张量 原始序列 (FASTA) 模板结构 (PDB) One-Hot (L×20) PSSM (L×20) 距离图 (L×L) 二面角 (L×2) 特征组合与拼接 初始特征张量 节点特征: L×40 (1-hot+PSSM) 边特征: L×L×C (模板+位置信息) 最终:两个分支并行输入EvoFormer 注意:所有索引必须严格对齐! 如果有gap,务必做插值或mask。 PSSM需要归一化后再拼接。

3.6 小结:核心概念串一串

这一章我们讲了三个核心概念:

  1. One-hot编码:最基础的“身份证明”,告诉模型每个位置是什么氨基酸。
  2. PSSM:进化信息的浓缩,告诉模型哪些位置是保守的、重要的。
  3. 模板特征:来自实验结构的先验知识,告诉模型真实的蛋白质空间是什么样。

这三类特征最终被组合成L × C的节点特征和L × L × C的边特征,构成EvoFormer的“初始输入”。这个过程看似简单,但我这几年折腾下来,发现很多人翻车都翻在对齐和归一化上。希望你能少走弯路。