当前位置: 首页 > news >正文

NLP学习路线图(二十七):Transformer编码器/解码器

一、Transformer概览:抛弃循环,拥抱注意力

传统RNN及其变体(如LSTM、GRU)处理序列数据时存在顺序依赖的瓶颈:必须逐个处理序列元素,难以并行计算,且对长程依赖建模能力较弱。Transformer的革命性在于:

  1. 完全基于自注意力机制:直接计算序列中任意两个元素之间的关系强度,无视距离

  2. 并行化计算:序列所有元素同时参与计算,极大提升训练效率。

  3. 堆叠层结构:通过多层堆叠(通常6层或更多),逐步提取更复杂的特征和表示。

Transformer的整体架构图是其精髓的直观体现:

输入序列 -> [编码器] -> 中间表示 -> [解码器] -> 输出序列(N个相同层)         (N个相同层)
  • 编码器:负责理解压缩输入序列(如源语言句子),将其转化为富含上下文信息的中间表示(Context Representation)

  • 解码器:负责生成输出序列(如目标语言句子)。它利用编码器提供的中间表示,并结合自身已生成的部分,一步步预测下一个元素(自回归生成)。

二、编码器(Encoder):信息的深度理解与融合

编码器由 N 个(通常N=6)结构完全相同的层堆叠而成。每一层都包含两个核心子层:

  1. 多头自注意力机制层(Multi-Head Self-Attention Layer)

  2. 前馈神经网络层(Position-wise Feed-Forward Network, FFN)

每个子层周围都应用了关键的残差连接(Residual Connection) 和 层归一化(Layer Normalization)。即每个子层的输出是 LayerNorm(Sublayer(x) + x)

1. 输入嵌入与位置编码(Input Embedding & Positional Encoding)
  • 输入嵌入:将输入序列中的每个词(或子词)token映射为一个d_model维(如512、768、1024)的稠密向量(词向量)。例如:

    # 假设词汇表大小 vocab_size=10000, d_model=512
    embedding_layer = nn.Embedding(10000, 512)
    input_embeddings = embedding_layer(input_ids)  # shape: [batch_size, seq_len, 512]

    位置编码(Positional Encoding, PE):由于Transformer本身没有循环或卷积结构,它无法感知序列元素的顺序。位置编码将序列中每个位置的索引信息注入到输入嵌入中。其公式为:

    PE(pos, 2i)   = sin(pos / 10000^(2i/d_model))
    PE(pos, 2i+1) = cos(pos / 10000^(2i/d_model))
    • pos:词在序列中的位置(0, 1, 2, ..., seq_len-1)。

    • i:维度索引(0 <= i < d_model/2)。

    • 使用正弦和余弦函数能保证模型轻松学习到相对位置关系(如 PE(pos+k) 可以表示为 PE(pos) 的线性变换)。

    • 最终输入Input = Input_Embedding + Positional_Encoding。相加后输入张量维度为 [batch_size, seq_len, d_model]

2. 核心组件:自注意力机制(Self-Attention)

自注意力让序列中的每个词都能直接关注到序列中的所有其他词(包括自身),动态计算它们之间的相关性权重,并据此加权聚合信息。

  • 核心概念:Query, Key, Value (Q, K, V)

    • 每个输入词向量(Input)通过三个独立的线性变换生成:

      • Query(Q):代表当前词在“询问”什么信息。

      • Key(K):代表其他词能“提供”什么信息的关键标识。

      • Value(V):代表其他词实际“携带”的信息内容。

    • 线性变换:Q = Input * W^QK = Input * W^KV = Input * W^VW^Q, W^K, W^V 是可学习参数矩阵,维度通常为 [d_model, d_k](Q, K)和 [d_model, d_v](V),常设 d_k = d_v = d_model / hh 是头数。

  • 注意力分数计算与权重分配

    1. 计算 Q 与 K 的点积:Scores = Q * K^T (维度: [batch_size, h, seq_len, seq_len])。点积越大表示 Query 和 Key 越相关。

    2. 缩放(Scale)Scores = Scores / sqrt(d_k)。防止点积结果过大导致softmax梯度消失。

    3. 掩码(可选,在编码器自注意力中通常不需要):在解码器中会用到,防止看到未来信息。

    4. Softmax归一化Attention_Weights = softmax(Scores, dim=-1)。将分数转换为和为1的概率分布,表示每个 Key(对应每个词)对当前 Query(当前词)的重要性权重。

    5. 加权求和Output = Attention_Weights * V (维度: [batch_size, h, seq_len, d_v])。这一步就是用权重对 Value 向量进行加权求和,得到当前 Query 词的新表示,它融合了所有其他词的信息。

    公式总结

    Attention(Q, K, V) = softmax(Q * K^T / sqrt(d_k)) * V
  • 多头注意力(Multi-Head Attention):这是Transformer性能强大的关键。

    • 将 d_model 维的 Q, K, V 分割成 h 个头(如h=8),每个头在降维后的空间(d_k, d_k, d_v)中进行独立的注意力计算。

    • 好处

      • 并行计算:多个头可并行计算。

      • 捕捉不同子空间信息:不同的头可以学习关注序列中不同类型的关系(如语法关系、指代关系、语义关系)。一个头可能关注局部依赖,另一个头可能关注长距离依赖。

    • 合并输出:将 h 个头的输出拼接(concat)起来,再通过一个线性层 W^O 映射回 d_model 维:MultiHead(Q, K, V) = Concat(head1, ..., headh) * W^OW^O 维度为 [h * d_v, d_model]。 

3. 前馈神经网络(Position-wise FFN)

自注意力层输出后,会经过一个前馈神经网络。它对序列中的每个位置独立、相同地进行变换。

  • 结构:通常是两层线性变换,中间加一个ReLU激活函数:

    FFN(x) = max(0, x * W1 + b1) * W2 + b2
    • W1 维度 [d_model, d_ff](如d_ff=2048)。

    • W2 维度 [d_ff, d_model]

    • b1, b2 是偏置项。

  • 作用:为每个位置的特征提供非线性变换能力,增强模型的表示能力。可以看作是在每个词的位置上独立应用一个小型MLP。

4. 残差连接与层归一化(Add & Norm)
  • 残差连接(Add):将子层(自注意力层或FFN层)的输入直接加到其输出上:y = Sublayer(x) + x

    • 核心作用

      • 缓解梯度消失:深层网络中,梯度可以直接通过残差路径回传。

      • 保留原始信息:即使子层没学到新东西,输入信息也能无损传递。

  • 层归一化(LayerNorm):对单个样本特征维度d_model)上进行归一化。

    LayerNorm(x) = γ * (x - μ) / sqrt(σ² + ε) + β

  • μ, σ² 是特征维度上的均值和方差。

  • γ, β 是可学习的缩放和偏移参数。

  • ε 是防止除零的小常数。

  • 作用:稳定训练过程,加速收敛。它作用于每个样本的每个位置的特征向量上。

5. 编码器层堆叠

经过 N 个这样的编码器层(每层包含自注意力 + FFN,以及Add&Norm)处理后,输入序列被逐步转化为高度抽象、富含全局上下文信息的表示。最后一层编码器的输出即为整个输入序列的中间表示(Context Representation),它将被传递给解码器使用。

 

三、解码器(Decoder):自回归生成的艺术

解码器同样由 N 个(通常与编码器层数相同)结构相同的层堆叠而成。解码器层结构与编码器层相似,但包含三个核心子层

  1. (带掩码的)多头自注意力层(Masked Multi-Head Self-Attention Layer)

  2. 多头编码器-解码器注意力层(Multi-Head Encoder-Decoder Attention Layer)

  3. 前馈神经网络层(Position-wise FFN)

同样,每个子层周围都有残差连接和层归一化。

1. 输入:目标序列嵌入与位置编码
  • 解码器的输入是目标序列(如待生成的翻译句子)的嵌入表示(加上位置编码)。

  • 关键点:在训练时,我们使用完整的目标序列右移一位(Shifted Right)作为输入(例如,输入是 <sos> I love NLP,期望输出是 I love NLP <eos>)。在推理时,则是自回归的:输入起始符(如<sos>),预测第一个词;然后将预测出的词作为输入,预测下一个词,依此类推。

2. 核心组件1:掩码多头自注意力(Masked Multi-Head Self-Attention)
  • 目的:让解码器在预测位置 i 时,只能看到位置 1 到 i-1 的信息(即只能看到已生成的部分),而不能看到位置 i 及之后的信息(未来信息)。

  • 实现机制 - 注意力掩码:在计算 Q * K^T 得到注意力分数矩阵后,在softmax之前,将未来位置对应的分数设置为一个极大的负数(如 -1e9)。

    # 伪代码示例:创建下三角掩码矩阵(主对角线及以下为0,以上为 -inf)
    mask = torch.tril(torch.ones(seq_len, seq_len))  # 下三角矩阵,元素为1
    mask = mask.masked_fill(mask == 0, float('-inf'))  # 将0的位置替换为 -inf
    Scores = Q * K^T / sqrt(d_k) + mask  # 加上掩码
    Attention_Weights = softmax(Scores, dim=-1)
  • 作用:确保解码器的自回归生成特性,使其在训练和推理时的行为一致。

3. 核心组件2:编码器-解码器注意力(Encoder-Decoder Attention)
  • 目的:让解码器在生成目标序列的每个词时,能够聚焦于输入序列(源序列)中最相关的部分

  • Q, K, V的来源

    • Query (Q):来自解码器上一子层(掩码自注意力层)的输出。代表解码器当前要生成词的位置在“询问”什么。

    • Key (K) 和 Value (V):来自编码器最后一层的输出(即整个输入序列的中间表示)。代表源序列提供的所有信息。

  • 计算过程:与多头注意力机制完全一致:EncoderDecoderAttention(Q, K, V) = softmax(Q * K^T / sqrt(d_k)) * V。这里没有掩码。

  • 意义:这是连接源语言和目标语言的桥梁。解码器通过此机制动态地、有选择地从源序列中提取信息,指导当前目标词的生成。例如,在翻译时,生成某个目标词时,注意力权重可能高度集中在源句中对应的词或相关词上。

4. 前馈神经网络(FFN)与 Add & Norm
  • 与编码器中的FFN子层完全相同,独立作用于每个位置。

  • 同样应用残差连接和层归一化。

5. 解码器层堆叠与输出

经过 N 个解码器层处理后,得到解码器顶层的输出(维度 [batch_size, target_seq_len, d_model])。该输出通过一个线性层(将 d_model 维映射到目标词汇表大小维)和一个 Softmax层,计算出在目标词汇表上每个位置的概率分布:

# 伪代码
output_logits = linear(decoder_output)  # shape: [batch_size, target_seq_len, target_vocab_size]
output_probs = softmax(output_logits, dim=-1)

 模型的目标是最大化正确目标词序列的似然概率,通常使用交叉熵损失函数进行训练。

四、编码器与解码器的协同工作流程(以机器翻译为例)

  1. 输入处理(编码器)

    • 源语言句子 "I love NLP" 被分词、嵌入并添加位置编码。

    • 输入序列 [<sos>, I, love, NLP, <eos>] 送入编码器。

    • 经过多层编码器处理,得到富含整个源句信息的中间表示(Context Tensor)

  2. 初始化解码器

    • 解码器初始输入通常只包含起始符 <sos>(及其位置编码)。

  3. 自回归生成(解码器)

  • Step 1 (输入: <sos>)
  • 解码器掩码自注意力层:仅关注 <sos>
  • 编码器-解码器注意力层:基于 <sos> 的 Query,从编码器的中间表示(Context Tensor)中计算注意力权重,聚焦于源句的相关部分(可能整个句子的信息都会被加权考虑)。
  • FFN层处理。
  • 输出层预测第一个目标词的概率分布。假设概率最高的是中文词 "我"。
  • Step 2 (输入: <sos>, "我")
  • 掩码自注意力:关注 <sos> 和 "我"。
  • 编码器-解码器注意力:基于 "我" 的 Query,再次从 Context Tensor 中计算注意力权重(此时权重分布可能与 Step 1 不同)。
  • FFN层处理。
  • 输出层预测第二个词。假设预测为 "喜欢"。
  • Step 3 (输入: <sos>, "我", "喜欢")
  • 掩码自注意力:关注 <sos>, "我", "喜欢"。
  • 编码器-解码器注意力:基于 "喜欢" 的 Query,从 Context Tensor 中提取信息(可能高度聚焦于源句的 "love")。
  • FFN层处理。
  • 输出层预测第三个词。预测为 "NLP"。
  • Step 4 (输入: <sos>, "我", "喜欢", "NLP")
  • ... 过程同上。
  • 输出层预测下一个词。预测为结束符 <eos>
  • 结束:生成序列 <sos> 我 喜欢 NLP <eos>,去除起始符得到最终翻译 "我喜欢 NLP"。 

五、Transformer架构的核心优势

  1. 强大的长程依赖建模:自注意力机制允许序列中任意两个元素直接交互,彻底克服了RNN处理长序列时信息衰减的难题。

  2. 卓越的并行计算能力:序列所有元素在自注意力层和FFN层中同时计算,训练速度远超RNN/CNN。

  3. 灵活的注意力机制:多头注意力可捕获不同语义子空间的关系;编码器-解码器注意力实现动态源-目标对齐。

  4. 可扩展性强:堆叠更多层(如12、24、48层)、增大 d_model、增加头数 h 等,能显著提升模型容量和性能,为大模型时代奠定基础。

  5. 通用性:虽然最初为机器翻译设计,但其架构通用性使其在文本分类、问答、摘要、语音识别、图像生成(ViT)等众多领域大放异彩。


六、总结:理解与生成的完美协奏

Transformer的编码器和解码器是理解其强大能力的关键:

  • 编码器如同一位精通源语言的读者,通过层层递进的自注意力阅读整个输入序列,抽丝剥茧,最终形成一个蕴含全局语义和细节的“思维导图”(中间表示)。

  • 解码器如同一位精通目标语言的作者,在创作(生成目标序列)时:

    1. 时刻回顾自己已经写了什么(掩码自注意力)。

    2. 不断参考编码器提供的“思维导图”,精准找到与当前要写内容最相关的源信息(编码器-解码器注意力)。

    3. 融合这两部分信息,构思并写下最合适的下一个词(FFN + 输出层)。

 

 

 

相关文章:

  • 如何让AI自己检查全文?使用OCR和LLM实现自动“全文校订”(可DIY校订规则)
  • 获1.3亿美元融资,NewLimit利用机器学习指导表观遗传程序设计,延长人类健康寿命研究已有初级成果
  • 程序代码篇---智能家居传感器
  • scss(sass)中 的使用说明
  • 并查集专题
  • Python|GIF 解析与构建(5):手搓截屏和帧率控制
  • 思尔芯携手Andes晶心科技,加速先进RISC-V 芯片开发
  • 华为仓颉语言初识:并发编程之同步机制(上)
  • 当丰收季遇上超导磁测量:粮食产业的科技新征程
  • Redis 主从 + 哨兵集群部署
  • 智慧水务发展迅猛:从物联网架构到AIoT系统的跨越式升级
  • Redis配合唯一序列号实现接口幂等性方案
  • App/uni-app 离线本地存储方案有哪些?最推荐的是哪种方案?
  • uniapp 安卓 APP 后台持续运行(保活)的尝试办法
  • H_Prj06 8088单板机的串口
  • TDengine 开发指南——无模式写入
  • matlab不同版本对编译器的要求(sfunction 死机)
  • 储能方案设计:鹧鸪云模拟软件优势尽显
  • HTTP 请求协议简单介绍
  • 豆包和deepseek 元宝 百度ai区别是什么
  • 高质量发展/网站优化推广公司
  • 网站建设 cms 下载/百度竞价推广专员
  • VPS做镜像网站/seo优化标题
  • 数据网站建设工具模板/抖音搜索seo排名优化
  • 2019年建设什么网站好/seo搜索优化怎么做
  • 如何建设一个彩票网站/软件培训机构有哪些?哪个比较好