Transformer架构回顾:自注意力机制、多头注意力、位置编码、编码器-解码器结构
讲ADMET分子表示学习之前,咱必须先搞定Transformer。这东西是地基。我这些年做药物发现项目,碰到过不少团队把分子扔进Transformer就跑,结果效果稀烂——说白了,就是没搞懂这四个核心组件在干什么。这一章咱们就把它们拆开,一个一个嚼碎。
2.1 自注意力机制:模型如何理解上下文?
自注意力(Self-Attention)是Transformer的魂。它的核心思想很简单:对于序列里的每个元素,让它跟所有其他元素算一遍“相关性”,然后根据这个相关性加权聚合信息。
我第一次看这篇论文时,觉得这玩意儿跟化学里的分子间作用力很像。你想,一个原子的性质不是自己决定的,而是被周围配位环境影响的。自注意力就是在干这件事——每个token都能“看到”整个序列。
数学上,它分三步走:
- 把每个输入token映射成三个向量:查询Q、键K、值V。
- 用Q和K的点积算注意力分数,然后过softmax归一化。
- 用归一化后的权重去加权求和V,得到输出。
| 组件 | 符号 | 维度 | 我理解它的方式 |
|---|---|---|---|
| 查询(Query) | Q | N × dₖ | 好比是“我想找什么” |
| 键(Key) | K | N × dₖ | 好比是“我有什么特征” |
| 值(Value) | V | N × dᵥ | 好比是“我能贡献什么” |
公式长这样:
Attention(Q, K, V) = softmax(QKᵀ / √dₖ) V
那个除以√dₖ的操作,我刚开始觉得可有可无。直到有一次我在做分子性质预测时,注意力分数全炸了——因为dₖ大了之后点积的方差也跟着大,softmax就变成one-hot了,梯度直接消失。嗯,从那以后我再也不敢省略这个缩放因子。
2.2 自注意力机制的深度解析
咱们用个具体的例子。假设输入序列有3个分子SMILES:C、O、N。它们的embedding维度是4。自注意力过程就是:
- 每个token的嵌入向量分别乘以三个权重矩阵Wq、Wk、Wv,生成Q、K、V。
- Q的第一行跟K的所有行做点积,得到注意力分数[0.5, 1.2, -0.3]。
- 缩放后变成[0.25, 0.6, -0.15],然后softmax得到[0.30, 0.45, 0.25]。
- 最后用这个权重去加权V矩阵的各行。
输出就是所有token信息的加权混合。这不就是化学里的“离域π键”么?每个原子都掺了点邻居的电子云。
我个人经验:做ADMET预测时,自注意力的效果高度依赖初始化的好坏。我习惯用Xavier初始化,而不是默认的随机均匀。尤其是在分子序列比较短(比如10-50个原子)时,这个选择影响很明显。
2.3 多头注意力:从多个角度理解分子
单头自注意力有个局限——它只看一种“相关性”。就像分析分子,你可能同时关注:电负性差异、空间位阻、氢键供体/受体。这些是不同层面的交互模式。
多头注意力(Multi-Head Attention)就是解决这个问题的。它把Q、K、V分别切分成h个头,每个头独立算自注意力,然后把结果拼起来再投影一次。
MultiHead(Q, K, V) = Concat(head₁, ..., headₕ) Wₒ
其中 headᵢ = Attention(QWqⁱ, KWkⁱ, VWvⁱ)
我在项目中实测过,8个头对大多数分子任务已经够用。但要注意,头数越多参数也越多,过拟合风险跟着涨。药化数据本来就少,我有一次把头数从8调到16,验证集的R²直接掉了0.05。
| 注意力类型 | 参数量 | 感受野 | 适用场景 |
|---|---|---|---|
| 单头注意力 | 少 | 全局但单一视角 | 小数据集、快速验证 |
| 多头注意力 | 中等 | 全局且多视角 | 大分子、多任务学习 |
| 局部窗口注意力 | 少 | 局部窗口 | 超长序列(如蛋白) |
| 稀疏注意力 | 中等 | 选择性全局 | 长序列+效率优先 |
2.4 位置编码:给分子序列引入空间感
自注意力对序列顺序是天然不敏感的。你想想看,如果把SMILES中C和O换个位置,自注意力返回的结果在排列变换下是一致的——这在化学上就是灾难,CCC和CCO完全是不同的分子。
位置编码(Positional Encoding)就是给每个token打上一个“位置标签”。
Transformer原文用的是正弦余弦编码:
PE(pos, 2i) = sin(pos / 10000^(2i / d_model))
PE(pos, 2i+1) = cos(pos / 10000^(2i / d_model))
为什么是正弦余弦?我当时琢磨了很久。后来想通了:不同频率的正弦波能让模型区分不同尺度的位置关系。低频分量对应长期依赖,高频分量对应局部结构。就好比分子里,低频决定骨架,高频决定侧链构象。
避坑指南:我曾经尝试用可学习的位置编码替换正弦编码,发现效果差不多。但如果序列长度超出训练时的最大长度,可学习编码就会崩。所以做ADMET时,我建议至少把最大序列长度设到512,留够余量。
还有一种叫RoPE(旋转位置编码),它把位置信息直接编码到Q和K的旋转矩阵里,不占用额外的embedding维度。很多后来的分子大模型都在用它。
2.5 编码器-解码器结构:编码+生成的两阶段框架
原始Transformer是编码器-解码器架构。编码器把输入序列变成上下文表示,解码器基于这个表示逐步生成输出。
在ADMET预测任务里,我们通常只要编码器——输入分子SMILES,输出一个固定维度的分子表征向量。但理解解码器也很重要,因为分子生成任务(如逆合成分析)需要它。
编码器由多层堆叠而成,每层包含一个多头注意力和一个前馈网络。注意,这里有残差连接和层归一化:
sub_layer_output = LayerNorm(x + Sublayer(x))
残差连接解决了深层网络的退化问题。我调参时经常看到,层数从4加到8,训练损失还能继续降,就是残差连接的功劳。
解码器多了一层“交叉注意力”——它让解码器在生成每个token时都能“偷看”编码器的输出。这在分子属性预测中一般不出现,但在分子生成和序列到序列任务里是标配。
注意:解码器的自注意力必须加mask,防止看到未来的token。这个mask是对角线以下全为负无穷的上三角矩阵。我曾经忘了加这个mask,结果模型直接学会了复制粘贴输入——测试集上表现完美,换一个分子序列就崩了。
下面这张图总结了本章的核心逻辑:
这张图我把编解码器结构和内部子层都拆开了。从上往下看:输入经过位置编码后进入编码器,编码器通过多头自注意力和FFN提取特征。解码器则多了一层交叉注意力来融合编码器的信息。对ADMET任务来说,我们通常只取编码器最后一层的输出作为分子表示。
我的习惯:做分子性质预测时,我会取编码器CLS token的表示,或者对所有token的表示做平均池化。具体哪个好?我建议你在验证集上试一下——这没有银弹,不同的数据集最优策略差很多。