1. 前言上一篇我们已经进入了机器翻译这一部分也搞清楚了几个关键点机器翻译是一个序列到序列任务数据通常是平行语料输入是源语言句子输出是目标语言句子两边通常要分别建词表还要处理bos、eos、pad等特殊符号但新的问题立刻就来了既然输入序列和输出序列不是同一种语言也不一定等长那模型该怎么设计这就引出了序列到序列学习里最经典的基础框架编码器-解码器Encoder-Decoder架构它的核心思想非常直观先把输入序列“读懂并压缩”成一个中间表示再根据这个表示一步步生成输出序列。这套思想不仅用于机器翻译后面很多任务也都能看到它的影子。2. 为什么机器翻译不能直接套普通语言模型先回忆一下前面的语言模型。语言模型做的是根据前文预测下一个 token例如输入前几个字符/词输出下一个字符/词它的输入和输出本质上都在同一个序列里。但机器翻译不一样。例如输入i love deep learning输出我 喜欢 深度 学习这里有几个明显不同2.1 输入和输出属于不同语言源句和目标句不是同一 token 空间。2.2 输入输出长度不固定一个英文句子翻成中文后长度可能变长也可能变短。2.3 输出不是“输入右移一位”语言模型标签可以直接由输入右移构造而机器翻译完全不是这个逻辑。所以机器翻译必须有一种新的建模方式让模型先理解输入再生成输出。这正是编码器-解码器架构要解决的问题。3. 什么是编码器-解码器架构编码器-解码器架构可以简单理解为两部分编码器Encoder解码器Decoder它们的分工非常明确。3.1 编码器负责读取输入序列并把它转换成一种内部表示。例如在机器翻译里输入英文句子编码器把整句英文“看完”形成一个中间语义表示3.2 解码器负责根据这个中间表示逐步生成目标序列。例如根据编码器给出的表示一个词一个词地生成中文翻译所以这套架构本质上是在做输入序列理解 → 中间表示 → 输出序列生成4. 为什么“编码”和“解码”这个说法很贴切这个名字其实非常形象。编码Encode就是把原始输入序列的信息压缩进模型内部的某种表示里。有点像读完一句话后脑子里形成了对这句话的理解解码Decode就是从这个内部表示出发逐步还原出目标序列。有点像你已经理解了英文句子的意思再把它用中文表达出来所以“编码器-解码器”这个名字并不是抽象术语而是非常符合任务直觉的。5. 机器翻译中的编码器在做什么在机器翻译里编码器的任务可以概括成一句话把源语言句子变成一个对后续翻译有用的表示。例如源句子是i love deep learning编码器会按顺序读入这些词并通过循环神经网络等结构把它们的信息不断累积。最终得到的可以是最后一个隐藏状态一组中间隐藏状态或更一般的上下文表示在最基础的 Seq2Seq 思想里常常先把这个结果看成源句子的语义摘要6. 机器翻译中的解码器在做什么解码器的任务则是根据编码器给出的表示逐步生成目标语言序列。例如目标句子应该是我 喜欢 深度 学习解码器通常不是一次把整个句子全吐出来而是按时间步生成第一个目标词第二个目标词第三个目标词…直到生成eos也就是说解码器本质上也是一个序列模型只不过它生成序列时会依赖编码器提供的上下文已经生成的前面目标词7. 编码器-解码器最核心的思想是什么如果只抓一句最重要的话那就是把“读输入”和“写输出”分开。这比把所有事情塞进一个网络里要清晰得多。编码器负责“读懂输入”输入序列可以长短不一但最终会变成内部表示。解码器负责“生成输出”输出序列也可以长短不一并且逐步生成。这使得模型天然适合处理输入输出长度不同输入输出模态不同甚至输入输出语言不同所以这套架构非常通用。8. 编码器-解码器为什么特别适合序列到序列任务因为序列到序列任务的本质就是给定一个输入序列输出另一个序列。例如机器翻译英文句子 → 中文句子文本摘要长文本 → 短摘要对话生成用户输入 → 回复语句语音识别声学特征序列 → 文本序列这些任务共同的问题是输入序列长度不固定输出序列长度不固定输入和输出不一定在同一个空间而编码器-解码器正好天生适合这种映射。9. 最基础的编码器通常怎么实现在李沐这条线里最基础的编码器通常可以先用RNN / GRU / LSTM来实现。例如把源句子 token 一个个输入编码器编码器不断更新隐藏状态最后把最终隐藏状态看作整个句子的表示所以最初级的编码器其实可以理解成一个负责“读完整句”的循环网络它读完以后把“我已经理解了这句话”的结果交给解码器。10. 最基础的解码器通常怎么实现解码器通常也可以用RNN / GRU / LSTM来实现。不过和编码器不同的是解码器在生成目标词时通常要依赖三类信息10.1 编码器提供的上下文表示这是源句子的“语义基础”。10.2 上一时刻的隐藏状态这是解码器自己的历史记忆。10.3 上一时刻输出的目标 token因为生成是逐步进行的当前词通常依赖前面已经生成的词。所以解码器本质上是一个带条件约束的生成模型11. 为什么解码器生成时常常要用bos目标句子生成不能凭空开始所以通常要给解码器一个起始标志bos这表示现在开始生成目标序列。例如机器翻译时第一步输入bos解码器预测第一个目标词第二步再把第一个词作为下一步输入继续生成后续词直到输出eos所以bos的作用就是生成的起点12. 为什么解码器可以逐步生成句子因为它本质上仍然是一个序列模型。在时间步t解码器会结合之前生成的内容当前内部状态编码器提供的上下文来预测当前位置应该输出什么。所以整个过程非常像语言模型只不过它不是“纯靠自己续写”而是在源句语义的条件下生成目标句。这也是为什么大家常说解码器像“有条件的语言模型”13. 编码器-解码器最基础的 Seq2Seq 直觉在最经典、最基础的 Seq2Seq 思想里我们常常会这样理解编码器把整个源句压缩成一个上下文向量。解码器只依赖这个上下文向量再一步步生成目标句。这种想法很优雅也非常具有启发性因为它第一次把“序列到序列映射”系统化了。但它也埋下了一个问题如果输入句子很长只靠一个固定长度上下文向量真的装得下全部信息吗这也是后面注意力机制会登场的原因。不过在当前这一节先把基础框架理解清楚最重要。14. 编码器-解码器中的“上下文”是什么“上下文context”在这里通常指编码器传递给解码器的中间语义表示它可以是编码器最后时刻的隐藏状态多层状态组合更一般的编码结果在最基础版本里我们常把它简化理解成源句子的压缩语义摘要解码器就是基于这个摘要去翻译。15. 为什么说编码器-解码器是一种通用框架因为它并不依赖“机器翻译”这一个任务本身。它更像是一种任务组织方式先把输入序列编码再把输出序列解码。所以只要任务符合“输入序列 → 输出序列”的形式它就有可能用这套框架。例如机器翻译摘要生成对话生成语音到文本图像描述图像编码 文本解码所以编码器-解码器的意义不只是某个具体模型而是一种非常有影响力的建模思想。16. 李沐这一节最想让你理解什么这一节的重点不是立刻去推复杂公式而是帮你建立这样一条主线第一机器翻译需要序列到序列建模不是简单语言模型。第二最自然的办法就是把输入处理和输出生成分开这就是编码器和解码器的分工。第三编码器负责“读懂”解码器负责“表达”。第四这套框架非常通用不只属于机器翻译。所以这一节本质上是在帮你完成从“循环网络单元”到“完整序列到序列系统”的升级。17. 编码器-解码器和前面内容怎么接起来这条线其实是非常顺的。前面学语言模型知道了如何逐步生成 token。前面学 RNN/GRU/LSTM知道了如何建模序列和状态递推。前面学机器翻译数据集知道了任务是“源句子 → 目标句子”。到这一节终于把这些东西组装起来编码器读源句解码器写目标句所以编码器-解码器并不是横空出世的新概念而是前面一大串知识拼装后的自然结果。18. 本节总结这一节我们学习了编码器-解码器架构核心内容可以总结为以下几点。18.1 编码器-解码器是典型的序列到序列建模框架特别适合机器翻译这类任务。18.2 编码器负责把输入序列转成内部表示可以理解为对源句子的语义编码。18.3 解码器负责根据编码结果逐步生成输出序列它通常是条件化的序列生成模型。18.4 这套框架不只适用于机器翻译很多输入序列到输出序列的任务都能套用。18.5 这一节是在为后面的具体实现和注意力机制铺路先有基础框架后面才能继续增强。19. 学习感悟这一节特别关键因为它让序列建模第一次真正从“单条序列理解”走向了“序列到序列转换”。以前我们学的更多是预测下一个 token处理一个序列本身而编码器-解码器开始回答更复杂的问题如何把一种表达方式转换成另一种表达方式。这已经非常接近“真正的智能任务”了。因为翻译、摘要、问答本质上都不是单纯记忆而是理解输入再组织输出。从这个角度看编码器-解码器是序列建模里一个非常重要的里程碑。