ai-WEEK6_transfomer编码器
1.思维流程图
1 | 编码器: 解码器: |
一.编码器、解码器的核心模块
| 对比维度 | 编码器 | 解码器 | 核心区别 |
|---|---|---|---|
| 输入 | 源语言句子(如 “I love you”) | 目标语言句子右移一位(如 “ | 编码器看原文,解码器看译文(训练时) |
| Embedding | 有 | 有 | 完全相同,各自有自己的词表 |
| 位置编码 | 有 | 有 | 完全相同,公式一样 |
| 子层1 | 多头自注意力(无掩码) | 带掩码的多头自注意力 | 编码器看全句;解码器只能看已生成的部分 |
| 子层2 | 前馈网络 | 交叉注意力 | 编码器没有交叉注意力;解码器用它查编码器输出 |
| 子层3 | — | 前馈网络 | 解码器多一个前馈子层 |
| 残差连接 | 每个子层各1次 | 每个子层各1次 | 规则相同:x + Dropout(子层(x)) |
| 层归一化 | 每个子层各1次 | 每个子层各1次 | 规则相同 |
| 输出 | 上下文向量(给解码器用) | 每个位置的预测概率 | 编码器输出是中间产物;解码器输出是最终结果 |
| 处理模式 | 并行一次看完 | 训练时并行+掩码,推理时串行逐词生成 | 编码器不需要掩码,解码器必须防偷看 |
| 核心作用 | 理解输入 | 生成输出 | 一个读,一个写 |
| 模块 | 一句话职责 |
|---|---|
| Embedding | 把词变成向量 |
| 位置编码 | 告诉模型谁在前谁在后 |
| 编码器自注意力 | 双向理解原文每个词的上下文 |
| 解码器掩码自注意力 | 单向理解已生成的内容,不偷看未来 |
| 交叉注意力 | 解码器查编码器:原文里有什么我能用的 |
| 前馈网络 | 每个词独立消化吸收刚才得到的信息 |
| 残差 + 层归一化 | 保底 + 稳定,保证深层堆叠不崩 |
二.Transformer编码器与解码器各层作用详解
1. Embedding 层
编码器:把源语言词的索引(如 “love” → 5)映射成稠密向量 [0.8, -0.1, 0.4, -0.3]。
解码器:把目标语言词的索引(如 “爱” → 7)映射成稠密向量。
为什么各自独立:源语言和目标语言通常词表不同,”love” 和 “爱” 是不同的索引,需要各自的 Embedding 表。
2. 位置编码
作用完全一样:给每个位置的词向量叠加一个独一无二的“位置指纹”,让模型知道词的先后顺序。
为什么两边都要:编码器需要知道 “I” 在 “love” 前面;解码器需要知道 “我” 在 “爱” 前面。位置信息在 Embedding 之后就丢失了,两边都要重新注入。
3. 子层1:多头自注意力
编码器:无掩码
每个词可以看到句子中所有其他词。
比如 “love” 可以同时看到 “I”(左边)和 “you”(右边)。
作用:双向理解上下文。
解码器:带掩码
每个词只能看到自己和自己左边的词,看不到右边(未来)。
比如生成 “爱” 时,只能看到 ““ 和 “我”,不能看到还没生成的 “你”。
作用:模拟推理时的自回归生成,防止模型作弊。
掩码怎么做:在 scores 矩阵上,把未来位置填成 -1e9,softmax 后权重趋近于零。
4. 子层2:编码器的前馈网络 vs 解码器的交叉注意力
编码器:前馈网络
自注意力让词之间交流后,每个词需要自己消化吸收融合来的信息。
512 → 2048 → ReLU → Dropout → 512。每个词独立处理,互不影响。
作用:消化上下文,非线性变换。
解码器:交叉注意力
Q 来自解码器自己的当前状态(“我需要什么信息?”)。
K 和 V 来自编码器的输出(“输入句子里有什么信息?”)。
解码器每生成一个词,都要“抬头看”一遍编码器的整个输出,决定该从原文哪个位置取信息。
作用:把输入句子的信息注入到生成过程中。这是编码器和解码器之间的唯一信息通道。
5. 子层3:解码器的前馈网络
交叉注意力之后,词已经融合了来自编码器的信息,需要再次独立消化。
和编码器的前馈完全一样:512 → 2048 → ReLU → Dropout → 512。
作用:对融合了原文信息后的表示做最后的非线性加工。
6. 残差连接 + 层归一化
编码器和解码器规则完全一样:每个子层后面都做 LayerNorm(x + Dropout(子层(x)))。
编码器有2个子层,所以2套残差+归一化。
解码器有3个子层,所以3套残差+归一化。
作用
残差连接:保底机制,梯度直通车道,防止深层训练崩溃。
层归一化:数值标准化,防止分布逐层偏移。
三.例子
1 | 设定: |
流程图
1 | ═══════════════════════════════════════════════════════════════ |
代码
1 | import torch |
| 流程图节点 | 代码对应行 |
|---|---|
| 编码器Embedding+位置编码 | enc_embed, enc_pos |
| 编码器子层1(自注意力) | TransformerEncoderLayer 里的 self_attn |
| 编码器子层2(前馈) | TransformerEncoderLayer 里的 feed_forward |
| 解码器Embedding+位置编码 | dec_embed, dec_pos |
| 解码器子层1(带掩码自注意力) | self_attn(tgt, tgt, tgt, tgt_mask) |
| 掩码生成 | generate_square_subsequent_mask |
| 解码器子层2(交叉注意力) | cross_attn(tgt, memory, memory) ← Q来自tgt,K/V来自memory |
| 解码器子层3(前馈) | feed_forward |
| 输出投影 | nn.Linear(d_model, vocab_size_tgt) |