Skip to content

Transformer 编码器与解码器

整体结构

        输入句子                        输出句子
       "我爱吃饭"                      "I love eating"
           │                                 ▲
           ▼                                 │
    ┌─────────────┐                 ┌─────────────────┐
    │             │                 │                 │
    │   编码器     │────────────────▶│    解码器        │
    │  Encoder    │   语义向量       │   Decoder       │
    │             │                 │                 │
    └─────────────┘                 └─────────────────┘
    
    负责"理解"输入                   负责"生成"输出

编码器:理解输入

任务是把输入句子压缩成一个富含语义的向量表示

输入:  我    爱    吃    饭
        │     │     │     │
        ▼     ▼     ▼     ▼
      词嵌入(把词变成向量)
        │     │     │     │
        ▼     ▼     ▼     ▼
   ┌──────────────────────────┐
   │     自注意力机制           │  ← 每个词都去看其他所有词(双向)
   └──────────────────────────┘
        │     │     │     │
        ▼     ▼     ▼     ▼
       h我   h爱   h吃   h饭     ← 每个词的向量都包含了整句的上下文

编码器输出的不是一个词,是每个位置的上下文向量

解码器:生成输出

一个词一个词地生成翻译结果。

已生成:  <start>   I    love

                              ▼ 预测下一个词
                    ┌─────────────────────┐
                    │  masked 自注意力     │  ← 只能看已生成的词(单向)
                    └─────────────────────┘


                    ┌─────────────────────┐
                    │  交叉注意力          │  ← 去问编码器:"我的意思是啥?"
                    │  cross-attention    │     读取 h我 h爱 h吃 h饭
                    └─────────────────────┘


                           "eating"

两者核心区别

编码器的自注意力:双向,可以看全句
  我 ←──────────▶ 饭
  每个词看所有词

解码器的自注意力:单向,只能看左边
  I ──▶ love ──▶ eating
  不能看未来(防止作弊)

交叉注意力:连接两者的桥梁

解码器独有的一层,编码器没有:

解码器生成 "eating" 时:
  Query 来自解码器(当前生成状态)
  Key/Value 来自编码器输出(h我 h爱 h吃 h饭)

  注意力权重:我:0.1  爱:0.1  吃:0.7  饭:0.1

                             重点关注"吃",所以生成 eating

不同任务用不同组合

任务用哪部分例子
翻译、摘要编码器 + 解码器原始 Transformer、T5
文本理解/分类只用编码器BERT
文本生成只用解码器GPT、Claude

Built with VitePress