大模型开发实战:深入理解解码器中的注意力机制
背景:从 Seq2Seq 到 Transformer
随着深度学习在自然语言处理领域的不断突破,序列到序列(Sequence-to-Sequence, Seq2Seq)模型逐渐成为主流。早期的统计机器翻译主要依赖短语匹配和语言模型,效果往往受限。2014 年 Google 提出的基于注意力机制的 Seq2Seq 模型带来了突破性进展,开启了神经机器翻译的新时代。
2017 年 Transformer 模型横空出世,它完全摒弃了 RNN 和 CNN 结构,纯粹基于注意力机制构建。这一架构不仅在机器翻译任务上表现卓越,更为计算机视觉、语音识别等领域提供了新的思路。如今,预训练大模型如 GPT、BERT 等,凭借其强大的泛化能力在各种下游任务中脱颖而出,而注意力机制正是这些模型的核心组成部分。
注意力机制的核心逻辑
注意力机制的本质是解决长序列依赖问题。在传统循环网络中,信息需要通过时间步逐步传递,容易导致梯度消失或遗忘早期信息。注意力机制允许模型在处理当前词时,直接关注输入序列中的任意位置,通过计算权重来聚合相关信息。
具体来说,我们通常将输入映射为查询(Query)、键(Key)和值(Value)三个向量。模型通过计算 Query 与 Key 的相似度来确定注意力权重,再对 Value 进行加权求和。这种机制让模型能够动态地聚焦于上下文中的关键信息,而不是平均对待所有输入。
import torch
import torch.nn.functional as F
def scaled_dot_product_attention(query, key, value, mask=None):
# 计算 Q 和 K 的点积
scores = torch.matmul(query, key.transpose(-2, -1))
# 缩放因子,防止梯度消失
d_k = query.size(-1)
scores /= (d_k ** 0.5)
# 应用掩码(如果有)
if mask is not None:
scores = scores.masked_fill(mask == 0, -1e9)
# Softmax 归一化得到权重
attn_weights = F.softmax(scores, dim=-1)
# 加权求和
output = torch.matmul(attn_weights, value)
return output, attn_weights
这段代码展示了缩放点积注意力的基本流程。实际工程中,这里有个细节需要注意:缩放因子 d_k 的选择是为了控制方差,避免 Softmax 进入饱和区导致梯度消失。如果忽略这一步,深层网络训练可能会变得非常困难。
解码器中的自注意力与交叉注意力
在大模型的解码器部分,注意力机制分为两种:自注意力(Self-Attention)和交叉注意力(Cross-Attention)。
自注意力用于捕捉解码器内部生成的序列依赖关系。由于生成过程是自回归的,我们需要使用掩码(Mask)来确保当前位置只能看到之前的输出,防止'作弊'看到未来信息。这通常通过下三角矩阵实现。
交叉注意力则连接编码器与解码器。解码器的 Query 来自当前生成状态,而 Key 和 Value 来自编码器的输出。这使得解码器能够根据已生成的内容,去检索编码器中相关的源信息。这种设计让模型具备了强大的对齐能力,无论是翻译还是文本摘要都能精准定位关键片段。

