第4章 Pair Representation的构建:残基对特征与相对位置编码
好,咱们直接进入正题。EvoFormer模块里,除了我们前面聊过的单链表示,另一半核心就是Pair Representation。这东西,说白了就是模型用来理解“残基两两之间是什么关系”的。
你想想看,预测蛋白质结构,光知道每个氨基酸长什么样是不够的。你得知道第15位的亮氨酸和第32位的天冬氨酸之间,到底是空间上挨得近,还是序列上离得远,还是它们之间可能形成个氢键。Pair Representation,就是专门用来编码这些“成对”信息的。
4.1 为什么需要Pair Representation?
刚开始做结构预测时,我也有个疑问:既然单链表示已经包含了每个残基的序列特征和进化信息,为什么还要搞个Pair Rep?这不是重复造轮子吗?
后来我亲手跑了一个对比实验,才发现问题的关键。单链表示里,残基信息是独立的。第15位的特征就是第15位的,它不会天然知道第32位是啥。要让模型理解“15和32之间的关系”,你就得把这两个位置的特征结合起来,再做一些复杂的交互计算。Pair Representation,就是这个“结合”和“交互”的载体。
从架构角度看,EvoFormer里一共有三条信息流:单链表示(1D)、Pair表示(2D)、以及结构模块里的坐标。三者之间互相更新。Pair表示像个信息枢纽,单链里的注意力要依赖它来提供“偏置”,而结构模块里的三角化更新,也要靠Pair来表示来提供约束。
4.2 残基对特征:原始输入的构建
Pair Representation的原始输入从哪里来?通常不是从零开始随机初始化,而是通过两种方式拼接:
- 序列特征的外积:将单链表示中每个残基的特征向量做外积,得到一个矩阵。说白了,就是把两个一维向量乘成一个二维矩阵,用来捕捉“残基对”级别的相关性。
- 预计算的结构约束:比如从模板结构里提取的残基对距离、角度、以及接触图。这些信息直接告诉模型,在已知的同源结构中,这两个残基大概处于什么空间关系。
避坑指南:我曾经在项目里,只用了外积特征作为Pair Rep的输入,结果模型收敛非常慢。后来发现,缺少了模板距离的约束,模型几乎是从头学“什么是空间接触”。加上了预计算的距离特征后,收敛速度直接提升了40%左右。切记,先验知识能帮大忙。
具体的输入特征,一般包含以下内容:
| 特征来源 | 编码方式 | 维度(每对) |
|---|---|---|
| 残基类型组合 | One-hot 编码,例如 (GLY, ALA) 组合 | 21×21=441 |
| 相对序列位置 | Sinusoidal 位置编码 + 截断 | 64 |
| MSA 共进化特征 | 伪似然估计或互信息矩阵 | 128 |
| 模板距离/角度 | 分箱离散化或高斯径向基 | 64 |
这些特征会被拼接到一起,然后通过一层线性变换,映射到一个统一的隐藏维度(通常是128或256)。这就是Pair Representation的原始初始状态。
你可能会问:“为什么需要这么多来源?”嗯,因为你越早把多源的信息喂给模型,它就越少从头猜测。不同来源的特征,覆盖了不同的“关系”层面:序列层面的(残基类型)、进化层面的(共进化)、结构层面的(模板距离)。让模型在训练初期就能同时看到这三张牌。
4.3 相对位置编码的计算逻辑
这是Pair Rep里最容易写错的部分。我说的“相对位置编码”,不是Transformer里那种添加在序列特征上的位置向量。这里是特指:对于每一对残基 (i, j),它们之间的序列索引差 (j - i)。
在AlphaFold论文里,他们用得是一种贪心编码方式。我先给你看一段伪代码,方便理解:
def relpos_encoding(i, j, max_rel_dist=32):
# d 是序列位置差值
d = j - i
# 剪切到 [-max_rel_dist, max_rel_dist]
d_clipped = min(max(d, -max_rel_dist), max_rel_dist)
# 映射到 [0, 2*max_rel_dist] 区间
bin_idx = d_clipped + max_rel_dist
# 对每个差值 bin,用可学习的向量表示
table = nn.Embedding(2 * max_rel_dist + 1, 64)
return table(bin_idx) # 输出一个 64 维向量
看见没?核心逻辑就是:差值 → 截断 → 单点嵌入。它不像经典Transformer那样用三角函数,而是用了一个可学习的查找表。每个相对位置差值,对应一个唯一的嵌入向量。
为什么要截断?因为实际蛋白质中,两残基相隔很远(比如超过32个残基)时,它们之间的空间位置相关性就已经非常弱了。再往后,每增加一个残基距离,对结构的贡献几乎为零。截断能帮助模型把注意力集中在局部范围内,减少噪声。
另外一点:这个编码是加性的。它会作为偏置直接加到Pair Representation的对应元素上。也就是说,初始的Pair Rep里包含了:残基类型特征 + 共进化特征 + 模板特征 + 这个相对位置编码。
到了这一步,Pair Representation才算构建完毕,可以送入后续的三角形自注意力和更新块了。
4.4 结构总结:一张图看懂Pair Rep构建
我知道光看文字和代码容易晕。下面这张SVG图,把整个构建流程画了一遍:
这张图里我刻意把“初始Pair Rep”之后的三角形注意力和更新都留白了,因为那些是后面章节的内容。今天,构建这一步做完,模型就有了一个形状为 [N_res, N_res, hidden_dim] 的完整张量。每个元素都携带了:它自己的相对位置、残基类型组合、进化联系、以及模板结构信息。
有了这个基础,EvoFormer才算真正有了“空间关系”的概念。接下来的每一层迭代,都是在这个关系图上不断做推断和修正。