跳转到内容

11.5.2 Seq2Seq 模型

Seq2Seq 编码器解码器瓶颈图

  • 理解 Seq2Seq 和分类类任务的根本差别
  • 理解 encoder 和 decoder 各自负责什么
  • 通过可运行示例建立“编码再生成”的直觉
  • 理解 Seq2Seq 为什么成为很多生成任务的基础结构

Seq2Seq 这节最适合新人的理解顺序不是“先看模型细节”,而是先看清任务形态变了什么:

flowchart LR
A["输入一段文本"] --> B["编码器先读懂它"]
B --> C["内部表示"]
C --> D["解码器一步步生成输出"]

所以这节真正想解决的是:

  • 为什么“文本到文本”任务和分类任务根本不是一类问题
  • 为什么要把系统拆成 encoder 和 decoder 两部分

它更像:

  • 输入一串 token
  • 输出另一串 token

例如:

  • “我爱学习” -> “I love studying”

为什么普通分类器不适合做这类任务?

Section titled “为什么普通分类器不适合做这类任务?”

因为分类器输出通常是固定集合里的一个标签。 而 Seq2Seq 任务的输出:

  • 长度不固定
  • 内容不固定
  • 生成过程有顺序依赖

分类像给作文打一个分数。 Seq2Seq 更像把中文作文重新写成英文作文。


二、编码器和解码器分别在做什么?

Section titled “二、编码器和解码器分别在做什么?”

它负责:

  • 读入输入序列
  • 把输入压成内部表示

它负责:

  • 基于编码结果
  • 一步一步生成输出序列

因为这类任务天然是:

  • 先理解输入
  • 再构造输出

这和单纯分类不一样。


三、先跑一个“编码后生成”的最小示例

Section titled “三、先跑一个“编码后生成”的最小示例”
translation_memory = {
"": "I",
"": "love",
"学习": "study",
}
def encode(source_tokens):
return {"source_tokens": source_tokens, "length": len(source_tokens)}
def decode(encoded):
output = []
for token in encoded["source_tokens"]:
output.append(translation_memory.get(token, "<unk>"))
return output
source = ["", "", "学习"]
encoded = encode(source)
target = decode(encoded)
print("encoded:", encoded)
print("decoded:", target)

预期输出:

Terminal window
encoded: {'source_tokens': ['我', '爱', '学习'], 'length': 3}
decoded: ['I', 'love', 'study']

这只是玩具级词典 decoder,但它把 Seq2Seq 的形状展示出来了:先把整个输入编码起来,再由 decoder 生成一个输出序列。

这个例子最重要的启发是什么?

Section titled “这个例子最重要的启发是什么?”

它说明 Seq2Seq 的核心流程是:

  1. 输入不直接变成最终答案
  2. 中间先过一层编码表示
  3. 再由解码器生成输出

新人第一次学 Seq2Seq,最该先记什么?

Section titled “新人第一次学 Seq2Seq,最该先记什么?”

最值得先记住的是:

  1. encoder 更像“先把输入读懂”
  2. decoder 更像“根据理解结果一步步写输出”
  3. 输出不是固定标签,而是一个有顺序的生成过程

四、Seq2Seq 最常见的难点是什么?

Section titled “四、Seq2Seq 最常见的难点是什么?”

早期 encoder-decoder 的一个典型问题是:

  • 整个输入被压成单个固定长度向量

输入一长,信息容易丢失。

这意味着:

  • 前一步错了
  • 后面也容易跟着错

这也是为什么后面会引入注意力机制

Section titled “这也是为什么后面会引入注意力机制”

注意力的核心目的之一,就是让解码器在生成时不必只依赖一个固定向量, 而是可以动态查看输入不同位置。

这节和后面注意力机制的关系是什么?

Section titled “这节和后面注意力机制的关系是什么?”

这节最该先立住的是:

  • Seq2Seq 的“编码 -> 解码”主线

而下一节注意力要解决的,正是这里的核心瓶颈:

  • 固定长度表示太容易丢信息

典型输入输出映射任务。

输入长文,输出短文。

输入与输出不是同一份文本,但有明确对应关系。


误区一:Seq2Seq 就只是“翻译模型”

Section titled “误区一:Seq2Seq 就只是“翻译模型””

翻译只是最经典例子。 它本质上适用于更广的“文本到文本”任务。

误区二:有编码器和解码器就已经足够

Section titled “误区二:有编码器和解码器就已经足够”

如果没有注意力和更强表示,长输入问题会很明显。

误区三:生成任务只要会输出就行

Section titled “误区三:生成任务只要会输出就行”

Seq2Seq 任务真正难的是:

  • 对输入忠实
  • 生成合理
  • 保持结构

学完这一页,至少保留这张证据卡:

源目标
源文本、目标文本和任务类型
解码输出
生成的摘要、翻译、转写或序列结果
对齐说明
注意力、CTC 路径、coverage,或复制的源证据
失败检查
遗漏、重复、幻觉、对齐错误或评估薄弱
期望产出
生成文本,以及事实性或对齐性复核说明

这节最重要的是把 Seq2Seq 理解成:

一类先编码输入、再逐步生成输出的结构,它是翻译、摘要和很多文本生成任务的基础范式。

只要这个结构主线清楚,后面学注意力和 T5 时就会很自然。


  • Seq2Seq 是“输入序列 -> 输出序列”的基础结构
  • encoder / decoder 是为了解决“先理解,再生成”
  • 注意力机制的出现,正是为了补 Seq2Seq 最核心的信息瓶颈

  1. 把示例里的词典扩成 5~10 个词,再试几个句子。
  2. 为什么说 Seq2Seq 的输出不是固定长度、也不是固定标签集?
  3. 想一想:如果输入非常长,为什么“只压成一个向量”会吃力?
  4. 用自己的话解释:encoder 和 decoder 各自负责什么?
解题思路与讲解
  1. 扩展字典后,玩具生成器能覆盖更多输入词,但仍会在未见词和词序上失败。
  2. Seq2Seq 输出不是固定长度,因为 decoder 会一步步生成 token,直到停止条件,而不是从固定标签集合里选一个。
  3. 把长输入压成一个向量很难,因为细节、顺序和长距离依赖都在争夺有限表示空间。
  4. encoder 负责读取输入并形成表示;decoder 使用这个表示和已经生成的输出继续生成目标序列。