Sequence2Sequence
Sequence-to-Sequence(简称 Seq2Seq) 是一种用于序列到序列(Sequence → Sequence)映射任务的深度学习模型结构。
它最早由 Google 在 2014 年提出,用于 机器翻译(Machine Translation),后来广泛应用于各种需要“输入一个序列、输出另一个序列”的任务中。

🧩 一、核心思想
Seq2Seq 模型的目标是:
给定一个输入序列\(X = (x_1, x_2, ..., x_T\)),生成一个输出序列$ Y = (y_1, y_2, ..., y_{T'})$。
其中输入序列和输出序列:
- 长度可以不同;
- 含义可以不同;
- 输出依赖于输入的整个上下文。
⚙️ 二、基本结构
Seq2Seq 通常由两部分组成:
1️⃣ 编码器(Encoder)
- 接收输入序列;
- 将其压缩为一个固定长度的向量(称为“上下文向量” context vector)。
通常使用循环神经网络(RNN)、长短时记忆(LSTM)或门控循环单元(GRU)实现:
\(h_t = f(x_t, h_{t-1})\)
最终输出一个向量 \(h_T\),代表整个输入序列的语义信息。
2️⃣ 解码器(Decoder)
- 接收编码器输出的上下文向量;
- 逐步生成目标序列(一个词接一个词)。
在生成每个输出时,解码器会考虑:
\(s_t = g(y_{t-1}, s_{t-1}, c)\)
其中:
- \(y_{t-1}\):前一步输出;
- \(s_{t-1}\):前一步隐藏状态;
- c:编码器的上下文向量。

💡 三、带注意力机制(Attention)的 Seq2Seq
原始 Seq2Seq 有一个缺陷:
把整个输入压缩成一个固定向量,当句子太长时,信息会丢失。
于是引入了 注意力机制(Attention):
- 解码时,不再只依赖一个固定向量;
- 而是动态计算输入序列中每个位置的“相关性权重”,从而更准确地生成输出。
公式上,解码器在生成第 t个词时,会计算一个加权的上下文:
\(c_t = \sum_i \alpha_{t,i} h_i\)
其中 $\alpha_{t,i} $ 表示第 i 个输入词对当前输出的关注程度。
📚 四、典型应用
| 任务 | 输入序列 | 输出序列 | 
|---|---|---|
| 机器翻译 | 一种语言的句子 | 另一种语言的句子 | 
| 文本摘要 | 原文 | 摘要 | 
| 聊天对话 | 用户输入 | 回复 | 
| 语音识别 | 声音信号序列 | 文字序列 | 
| 图像描述 | 图像特征序列 | 描述文字序列 | 
🧠 五、与 Transformer 的关系
后来出现的 Transformer 模型(比如 BERT、GPT)其实也是 Seq2Seq 的改进版:
- 它抛弃了 RNN,改用纯注意力(Self-Attention)机制;
- 拥有更强的并行性和长程依赖建模能力;
- 经典的 Transformer 结构也是 Encoder + Decoder 两部分。
Encode
🧩 一、什么是“编码”(Encode)
在 Seq2Seq 模型里,编码(encoding) 就是把 输入序列(比如一句话、一段语音) 转换成一个内部向量表示(vector representation) 的过程。
换句话说:
Encode 的目标是:理解输入序列的语义,并把它表示成模型能理解的“数字形式”。
⚙️ 二、编码过程
假设输入序列是:
\(X = (x_1, x_2, ..., x_T)\)
每个 \(x_i\) 是一个词或特征向量。
编码器(Encoder)通过神经网络(通常是 \(RNN/LSTM/GRU\) 或 Transformer Encoder)逐步处理输入序列,并产生隐藏状态:
\(h_t = f(x_t, h_{t-1})\)
其中:
- \(h_t\):第 t 步的隐藏状态(表示模型到目前为止理解的语义)
- f:RNN 或 LSTM 的计算函数
- \(h_{t-1}\):上一时刻的隐藏状态
经过所有时间步后,编码器得到最后一个隐藏状态 \(h_T\),它包含了整个输入序列的信息,这个向量就叫 上下文向量(Context Vector)。
🧠 三、形象理解
可以把 编码器(Encoder) 想成一个“理解器”:
| 类比 | 含义 | 
|---|---|
| 输入句子 | “我 爱 北京 天安门” | 
| 编码器 | 把句子读一遍、理解其语义 | 
| 输出 | 一个向量,代表“我爱北京天安门”这句话的整体意思 | 
这个向量就是“被编码后的信息”——它不再是文字,而是数学形式的语义表示。
💡 四、为什么要编码
因为计算机无法直接理解文字或语音,必须把它们转化成“向量”,才能进行:
- 翻译(解码)
- 分类
- 生成回复
- 情感分析 等任务。
编码后的信息携带了:
- 顺序关系(语法结构);
- 语义特征(含义);
- 上下文依赖(词之间关系)。
🔍 五、示例
假设输入是句子:
"I love NLP"
经过嵌入层和 LSTM 编码器:
| 词 | 向量输入(embedding) | 隐藏状态(LSTM输出) | 
|---|---|---|
| I | [0.1, 0.4, ...] | h₁ | 
| love | [0.5, 0.9, ...] | h₂ | 
| NLP | [0.3, 0.7, ...] | h₃ | 
最终:
h3=编码器输出的语义向量\((Context Vector)h_3 = \text{编码器输出的语义向量(Context Vector)}\)
解码器将用这个向量去“生成”目标句子,比如中文的“我爱自然语言处理”。
🧭 六、扩展:Transformer 的编码
在 Transformer 模型中,编码器不再用循环结构,而是使用 自注意力机制(Self-Attention) 来捕捉序列中每个词与其他词的关系。
例如:
- “love” 会关注 “I” 和 “NLP”
- 每个词都能与句子中其他词“交互”以理解上下文。
这样得到的编码向量比传统 LSTM 的“单个向量”更丰富、更完整。



Layer Norm
“Layer Normalization(层归一化,简称 LayerNorm)” 是深度学习中非常常见的一种 标准化技术,尤其在 Transformer、BERT、GPT 等模型 里几乎无处不在。
下面我一步步讲清楚它的 原理、公式、直觉理解和作用。
🧩 一、背景:为什么需要归一化(Normalization)
在神经网络中,每一层的输出分布会不断变化,这种现象叫 “内部协变量偏移(Internal Covariate Shift)”。
它会导致:
- 训练不稳定;
- 收敛慢;
- 对学习率敏感。
于是出现了几种归一化方法,比如:
- BatchNorm(批归一化)
- LayerNorm(层归一化)
- InstanceNorm、GroupNorm 等。
它们的核心思想都是:
“让神经元的输出分布保持稳定(均值为0,方差为1)。”标准正态分布
⚙️ 二、LayerNorm 的原理
LayerNorm 是对每个样本的所有神经元在同一层中进行归一化。
假设输入为一个向量:
\(x = [x_1, x_2, ..., x_H]\)
(比如一个隐藏层的输出,长度为 H)
我们计算:
我们计算:
\(\mu = \frac{1}{H}\sum_{i=1}^{H} x_i \quad\text{(均值)}\sigma = \sqrt{\frac{1}{H}\sum_{i=1}^{H}(x_i - \mu)^2} \quad\text{(标准差)}\)
然后归一化:
\(\hat{x}_i = \frac{x_i - \mu}{\sigma}\)
最后乘以可学习参数:
\(y_i = \gamma \hat{x}_i + \beta\)
其中:
- \(\gamma\):缩放系数(scale)
- \(\beta\):平移系数(shift)
- 它们是可训练的参数,可以恢复模型表达能力。
🧠 三、直观理解
LayerNorm 的操作是:
“对单个样本内部的一整层神经元做标准化。”
举个例子:
| 样本 | 神经元输出 | 归一化方式 | 
|---|---|---|
| BatchNorm | 对一个神经元在整个 batch 中求均值和方差 | 横向归一化 | 
| LayerNorm | 对一个样本的所有神经元求均值和方差 | 纵向归一化 | 
👉 所以 LayerNorm 不依赖 batch 大小,这点非常关键。
它能在:
- RNN / Transformer / 自注意力模型
 中稳定工作,而 BatchNorm 在这些结构中效果差。
📊 四、公式对比:BatchNorm vs LayerNorm
| 对比项 | BatchNorm | LayerNorm | 
|---|---|---|
| 归一化维度 | 在 batch 方向 | 在特征维度 | 
| 是否依赖 batch size | ✅ 是 | ❌ 否 | 
| 常用于 | CNN | RNN / Transformer | 
| 训练推理一致性 | 不一致(需保存均值方差) | 一致 | 
BatchNorm: 对“同一神经元在一批样本中”标准化,适合 CNN;
LayerNorm: 对“单个样本的所有特征”标准化,适合 Transformer、RNN 等序列模型。
🧠 五、在 Transformer 中的作用
Transformer 中每个子层都有:
\(\text{LayerNorm}(x + \text{SubLayer}(x))\)
也就是说:
- 先通过自注意力或前馈层;
- 加上残差(Residual Connection);
- 再做 LayerNorm。
作用:
- 保持数值稳定;
- 防止梯度爆炸/消失;
- 加速收敛;
- 提高泛化能力。
Encode 总体过程

Residual(残差) 是深度学习中非常重要的概念,尤其是在 ResNet、Transformer 等现代神经网络里,是能“让深层网络真正学得动”的关键机制。
🧩 一、Residual 是什么?
Residual 的中文叫 “残差”,
在神经网络里,它通常表示 “输入与输出之间的差”,也就是:
\(\text{Residual} = \text{Output} - \text{Input}\)
而所谓 “残差连接(Residual Connection)” 或 “跳跃连接(Skip Connection)”,
是指在神经网络的某一层中,直接把输入加到输出上:
\(y = F(x) + x\)
其中:
- x:输入(input)
- F(x):通过若干层后的变换结果(通常是卷积、注意力、前馈层等)
- y:最终输出
⚙️ 二、为什么要加上 Residual(设计动机)
在传统深层网络中,层数一多会出现:
- 梯度消失 / 爆炸
- 网络难以训练
- 准确率反而下降
而 ResNet 的提出者(Kaiming He)发现:
与其强迫每一层去学习一个“全新的映射” H(x),
不如让它学习一个“残差映射”:F(x)=H(x)−x
也就是:只学习“比输入多出来的那部分变化”。
因此整个层的输出变成:
\(H(x) = F(x) + x\)
🧠 三、直觉理解
可以把 Residual 理解为:
“让模型更容易学会‘变化’而不是‘全部’。”
比如:
- 如果某一层其实不需要改变输入(理想情况是输出≈输入),
 那么只要让 F(x)=0,就能直接得到 y=x。
- 这就相当于网络自动学会“保留信息”而不是“重新造轮子”。
Decode
🧩 一、什么是 Decode(解码)
Decode(解码) 是指:
将编码后的语义表示(隐藏向量)一步步“翻译”或“生成”成目标序列的过程。
在结构上:
Encoder 负责理解输入,Decoder 负责生成输出。
🌍 举个例子:机器翻译
比如翻译:
输入(英语):I love you
输出(中文):我 爱 你
- 
Encoder 读入 “I love you”,把它变成一个隐藏表示(理解句子含义); 
- 
Decoder 再根据这个隐藏表示,逐步生成输出序列: 第一步:输出“我” 第二步:输出“爱” 第三步:输出“你”
⚙️ 二、Decoder 的输入与输出机制
解码器本质上是一个序列生成器。
假设目标输出序列是 \(y_1, y_2, \dots, y_T\)
Decoder 要做的事是学习:
\(P(y_1, y_2, \dots, y_T | x)\)
即:
在给定输入序列 x 的情况下,生成目标序列的条件概率。
🧩 每个时间步(step)上:
Decoder 会做以下操作:
- 接收:
- 上一步的输出$ y_{t-1}$
- 编码器的上下文向量(来自 Encoder)
- 自己的隐藏状态 \(h_{t-1}\)
 
- 输出:
- 当前词的预测概率分布 \(P(y_t | y_{<t}, x)\)
- 更新隐藏状态 \(h_t\)
 
整个过程是“一步步生成句子”。
🧠 三、直观理解
| 模块 | 作用 | 类比 | 
|---|---|---|
| Encoder | 理解输入内容 | “听懂”一句话 | 
| Decoder | 生成输出内容 | “把意思说出来” | 
👉 Encoder 是“理解”,Decoder 是“表达”。
在翻译任务中,一个“理解输入语言”,另一个“输出目标语言”。
🔁 四、Decoder 的结构
根据模型类型不同,解码器的内部结构略有不同。
| 类型 | 解码器结构 | 
|---|---|
| RNN / LSTM Seq2Seq | RNN 单元循环生成词 | 
| Transformer Decoder | 自注意力 + 编码器注意力 + 前馈层 | 
🧠 Transformer Decoder 的核心组成:
每一层包含三部分:
- Masked Self-Attention(自注意力)
 只能看到自己前面的词,防止“偷看答案”。
- Cross-Attention(交叉注意力)
 从 Encoder 的输出中获取信息。
- Feed-Forward + Residual + LayerNorm
图示结构如下:
         ┌────────────────────────────────────┐│          Encoder 输出向量          │└──────────────┬─────────────────────┘│┌────────────▼────────────┐│ Cross-Attention 层      │ ←── 结合 Encoder 信息├─────────────────────────┤│ Masked Self-Attention   │ ←── 看自己前面的词├─────────────────────────┤│ Feed Forward + LayerNorm│└─────────────────────────┘│输出下一个词
🔤 五、生成过程示例(以 Transformer 为例)
假设我们要生成句子 “我爱你”:
- 输入 <BOS>(开始标志)
- Decoder 预测第一个字 → “我”
- 再输入 “我”,预测第二个字 → “爱”
- 再输入 “我爱”,预测第三个字 → “你”
- 直到输出 <EOS>(结束标志)
这叫 自回归生成(autoregressive generation)。

📘 六、数学上 Decoder 的概率展开:
\(P(y|x) = \prod_{t=1}^{T} P(y_t | y_{<t}, x)\)
也就是说,Decoder 在每个时间步根据:
- 上下文(Encoder 输出)
- 之前生成的词(自己的输出)
- 当前隐藏状态
 来预测下一个词。
Encode 和 Decoode 的过程对比图

Mashed Self-attention
🌟 一、Self-Attention(自注意力)回顾
在自注意力中,一个序列(例如句子)中的每个词都会对整个序列的所有词计算注意力权重,从而捕捉全局上下文信息。
也就是说,位置 i 的词可以“看到”输入序列中所有位置的词,包括后面的词。
🚫 二、为什么要“Mask”(掩码)
在 Decoder(生成阶段),模型是逐步生成的,比如:
生成第3个词时,只知道前2个词,不能看到第4个、5个……未来的词。
如果让模型在注意力中访问未来信息(右边的词),那就会泄露答案(信息泄漏)。
因此我们要“遮住(mask)”未来的部分 —— 这就是 Masked Self-Attention。
⚙️ 三、工作原理(掩码的机制)
掩码的核心就是在计算注意力权重时,用一个上三角矩阵 Mask,将未来位置的注意力分数设置为非常小的值(例如 -∞),从而在 Softmax 后接近 0。
例如,对于长度为 5 的序列:
| 当前词位置 | 可见的词 | 被 Mask 的词 | 
|---|---|---|
| 1 | [1] | [2,3,4,5] | 
| 2 | [1,2] | [3,4,5] | 
| 3 | [1,2,3] | [4,5] | 
这样,模型在训练和生成时都只能看到已经生成的内容。
🧠 四、公式层面
设注意力分数矩阵为
\(\text{scores} = \frac{QK^T}{\sqrt{d_k}}\)
加上掩码矩阵 M(未来位置为 -∞):
\(\text{masked\_scores} = \text{scores} + M\)
再计算 softmax:
\(\text{Attention}(Q,K,V) = \text{softmax}(\text{masked\_scores})V\)
🧩 五、总结对比
| 类型 | 能看到的部分 | 用途 | 
|---|---|---|
| Self-Attention | 整个序列(双向) | Encoder(理解) | 
| Masked Self-Attention | 仅前面部分(单向) | Decoder(生成) | 

AT 和 Nat Decode
AT 和 NAT Decode,指的是在 序列生成模型(Sequence-to-Sequence, Seq2Seq) 中两种不同的 解码策略:
- AT:Autoregressive Translation(自回归解码)
- NAT:Non-Autoregressive Translation(非自回归解码)
这两个概念最常出现在 机器翻译(Machine Translation) 或 文本生成(Text Generation) 的 Transformer 模型中。
我们一步步看👇
🌟 一、AT(Autoregressive Translation,自回归解码)
🧩 原理:
一步一步地生成输出序列。
每次生成一个词时,模型会 依赖之前已经生成的词。
公式表示:
\(P(Y|X) = \prod_{t=1}^{T} P(y_t | y_{<t}, X)\)
意思是:第 t 个词的概率取决于前面所有词 $y_{<t} $和输入句子 \(X\)。
🧠 举例:
输入英文:
“I love China.”
AT 解码输出中文:
“我 → 爱 → 中国”
生成过程是:
- 先生成“我”
- 再用“我”预测“爱”
- 再用“我 爱”预测“中国”
⚙️ 优点:
✅ 生成质量高(因为考虑上下文依赖)
✅ 已经是 Transformer、GPT、BERT-decoder 等的标准做法
❌ 缺点:
🚫 速度慢 —— 因为必须一个词一个词生成,不能并行。
(每次的输出依赖上一次)
⚡ 二、NAT(Non-Autoregressive Translation,非自回归解码)
🧩 原理:
一次性并行生成整个输出序列,不依赖之前生成的词。
公式:
\(P(yt∣X)P(Y|X) = \prod_{t=1}^{T} P(y_t | X)\)
意思是:每个词的生成只依赖输入 X,而不依赖前面生成的词。
🧠 举例:
输入:“I love China.”
NAT 解码:
模型同时预测所有词的位置和内容,直接输出 “我 爱 中国”
⚙️ 优点:
✅ 生成速度快很多 —— 因为所有词并行生成
✅ 特别适合实时翻译、大规模推理等场景
❌ 缺点:
🚫 质量通常低于 AT —— 因为丢失了词与词之间的依赖信息,容易出现语序混乱或缺词。
🧩 三、对比总结表
| 特性 | AT (自回归) | NAT (非自回归) | 
|---|---|---|
| 生成方式 | 按顺序逐词生成 | 一次性并行生成 | 
| 是否依赖前文 | 是 | 否 | 
| 速度 | 慢 | 快 | 
| 翻译质量 | 高 | 略低 | 
| 常见模型 | Transformer、GPT、BART | MaskPredict、FlowSeq、GLAT | 
🧠 四、类比帮助理解
| 类比 | 说明 | 
|---|---|
| AT 像人写作文 | 一句一句地写,每句话都会考虑前面的内容 | 
| NAT 像机器填空 | 一次性把所有句子位置都填上,速度快但容易缺乏连贯性 | 

Cross attention
在 Transformer 中,Cross-Attention(交叉注意力) 是连接 Encoder(编码器) 和 Decoder(解码器) 的“桥梁”。
让我们来系统地理解它👇
🌟 一、什么是 Cross-Attention?
Cross-Attention(交叉注意力) 是一种注意力机制,
用于让 Decoder(解码器)关注 Encoder 的输出信息。
简单说:
Decoder 在生成输出时,会“去看”输入序列的编码结果,从中找出与当前生成词最相关的部分。
⚙️ 二、它在 Transformer 结构中的位置
Transformer 的 Decoder 每层都有三个子层:
- Masked Self-Attention(关注已生成的词)
- Cross-Attention(关注输入序列) ✅
- Feed Forward 网络
Cross-Attention 就是第 2 个子层。
它让解码器的当前状态与编码器的输出“交互”,从而结合输入信息生成下一个词。
🧠 三、工作原理(核心公式)
Cross-Attention 的输入是:
- Query (Q):来自 Decoder 当前层(解码器自己的表示)
- Key (K):来自 Encoder 的输出
- Value (V):同样来自 Encoder 的输出
计算:
\(\text{Attention}(Q, K, V) = \text{softmax}\left(\frac{QK^T}{\sqrt{d_k}}\right)\)
区别在于:
- Self-Attention 用的是 Q、K、V 都来自同一序列(自己看自己)
- Cross-Attention 用的是 Q 来自解码器,而 K、V 来自编码器(看别人)
🔍 四、直观理解
想象一个英文翻译任务:
输入(Encoder 看到的):
I love China
输出(Decoder 正在生成):我 爱 中国
在生成“爱”这个词时,
Decoder 通过 Cross-Attention 去“关注”输入序列的哪些词最相关:
- 对应 “love” → 高权重
- 对应 “I” 和 “China” → 低权重
这样 Decoder 就能正确地生成与输入语义匹配的词。
🧩 五、图示类比(文字版)
| 类型 | Query 来自 | Key / Value 来自 | 用途 | 
|---|---|---|---|
| Self-Attention | 本层输入 | 本层输入 | 让模型理解自身序列内部关系 | 
| Masked Self-Attention | 本层输入(遮未来) | 本层输入(遮未来) | 用于 Decoder 生成序列 | 
| Cross-Attention | Decoder | Encoder 输出 | 让输出关注输入(翻译、生成等) | 
💡 六、总结一句话
Cross-Attention = Decoder 看 Encoder 的眼睛。
它让生成的每个词都能“看回去”输入句子,理解上下文含义。

通过FC后输出 机

Beam Search
🌟 一、Beam Search 是什么?
Beam Search 是一种改进版的贪心搜索(Greedy Search),
用于 在语言生成中寻找最可能的输出序列(例如机器翻译、摘要生成、文本生成等)。
🧩 二、背景:为什么需要搜索?
在序列生成中,模型实际上在预测:
\(P(Y|X) = P(y_1|X) \cdot P(y_2|y_1,X) \cdot P(y_3|y_1,y_2,X) \cdots\)
输出的每一个词都取决于前面的词。
所以整个输出空间是巨大的,比如每个位置有 50,000 个可能词,句子长 10 个词,那就有$ 50,000^{10}$ 种可能的组合 —— 不可能都算一遍。
于是我们需要“搜索”:
- 不能太慢;
- 又尽量找到概率最大的序列。
⚙️ 三、几种常见策略
| 方法 | 特点 | 
|---|---|
| Greedy Search | 每一步都选当前概率最大的词(快但可能错过全局最优) | 
| Beam Search | 每步保留前 k 个最优候选(折中方案 ✅) | 
| Sampling / Top-k / Top-p | 随机采样,适合生成多样性文本(如 ChatGPT) | 
🔢 四、Beam Search 的核心思想
假设 Beam Size = k
(即“束宽度”,每步保留概率最高的 k 条路径)
流程如下:
- 初始:开始时只有一个起始符 <BOS>。
- 第一步:模型预测下一个词的所有概率,取前 k 个最高的词,作为 k 条“候选句子”。
- 第二步:对每条候选句子,再扩展出它们可能的下一个词,并计算新的句子概率。
 继续选出全局 top k。
- 重复直到生成 <EOS>(结束符)或达到最大长度。
最后,取概率最高的一条句子作为最终输出。
📘 例子
假设 beam size = 2
输入句子:"I love"
模型预测:
| 第一步预测 | 概率 | 
|---|---|
| you | 0.6 | 
| it | 0.3 | 
| him | 0.1 | 
→ 保留 top 2(you, it)
第二步(分别扩展):
| 当前句子 | 下一个词 | 句子概率 | 
|---|---|---|
| I love you | so | 0.6×0.4=0.24 | 
| I love you | too | 0.6×0.3=0.18 | 
| I love it | very | 0.3×0.5=0.15 | 
| I love it | much | 0.3×0.3=0.09 | 
→ 取概率最高的 2 条路径继续搜索。
🧠 五、注意两点技巧
- 
对数概率 
 实际上我们计算时会用 log 概率:\(\log P(y_1,y_2,...,y_t) = \sum_{i=1}^{t} \log P(y_i | y_{<i}, X)\) 避免数值下溢。 
- 
长度惩罚(Length Penalty) 
 避免模型偏向短句(因为短句概率乘积更大),通常加一个:\(\frac{\log P}{(5 + |Y|)^\alpha / (5 + 1)^\alpha}\) 
🧩 六、总结对比表
| 特性 | Greedy Search | Beam Search | 
|---|---|---|
| 每步保留 | 1 个最优路径 | k 个最优路径 | 
| 精度 | 可能错过全局最优 | 更接近全局最优 | 
| 速度 | 快 | 稍慢(取决于 k) | 
| 多样性 | 无 | 可通过增加 k 提高 | 
| 常用场景 | 简单任务 | 翻译、摘要、问答生成 | 
💬 七、一句话总结
Beam Search 就像多人赛跑,保留前 k 名继续跑。
最后谁的“总概率”最高,谁就是模型选出的最终输出。

训练的时候给些错的东西
这样有随机概率,模型可能会更好
