提醒补图
从Seq2Seq 讲起
1. 模型结构
Seq2Seq 由 Encoder-Decoder 结构 组成:
- Encoder(编码器)
- 处理输入序列(如 “we are eating bread”)。
- 通过循环神经网络(RNN/LSTM/GRU)生成一系列隐藏状态
。 - 处理完最后一个单词后,输出 最终隐藏状态
。 - 这个最终隐藏状态 作为上下文向量 c 传递给解码器。
- Decoder(解码器)
- 接收 初始隐藏状态
(可以通过 c 计算得到)。 - 依次生成目标语言的单词(如 “estamos comiendo pan”)。
- 生成方式:
- 先输入特殊起始标记 [START](即
)。 - 结合上一个隐藏状态
、上下文向量 c、前一步输出单词 ,计算当前时间步的隐藏状态 s_t。 - 生成当前时间步的单词
,并输入下一个时间步。 - 持续执行,直到遇到 [STOP]。
2. 关键数学公式
- Encoder 计算隐藏状态:
其中
- Decoder 计算隐藏状态:
- 这里的
也是一个 RNN(或者 LSTM/GRU)。 - 需要输入:
- 之前的单词
(即上一步的输出)。 - 之前的隐藏状态
。 - 上下文向量 c,这个可以理解为编码器传递的全局信息。
3. 具体流程
- Step 1: Encoder 处理输入
- “we are eating bread” → 变成一系列隐藏状态。
- 最后一个隐藏状态 h_4 作为 上下文向量 c 传递给解码器。
- Step 2: Decoder 生成翻译
- 初始输入: 先喂入 [START],然后:
- 生成 “estamos”(y1),作为下一步的输入。
- 生成 “comiendo”(y2),继续往下传。
- 生成 “pan”(y3)。
- 生成 [STOP](y4),结束。
初始解码器隐藏状态 s0和上下文向量 c 的计算
在 Seq2Seq 结构 中,
1. 上下文向量 c
上下文向量 c 是 编码器的最终隐藏状态,即:
其中:
是编码器在处理完 最后一个输入单词 后的隐藏状态。- 它总结了整个输入序列的信息,作为解码器的全局信息传递给每个时间步。
解释:
- 在 普通 Seq2Seq(不含 Attention)的实现中,直接取
作为上下文向量。 - 在 带 Attention 的 Seq2Seq 中,c 会是一个加权求和的隐状态组合,而不是单独的
。
2. 初始解码器隐藏状态
其中:
是一个 可学习的权重矩阵。 是 偏置项。 是一个激活函数(防止值爆炸)。
解释:
- 由于编码器和解码器可能使用 不同的 RNN 结构(比如 Encoder 用 LSTM,Decoder 用 GRU),直接用 h_T 可能不合适,所以通常会经过一个**前馈层(Fully Connected Layer)**转换成解码器合适的隐藏状态。
- 有时候可以直接取 s_0 = h_T(如果编码器和解码器使用相同的 RNN 结构)。
总结
(编码器的最终隐藏状态)。 (通常需要一个前馈层)。- 这两者都来源于编码器的最终隐藏状态
,但 可能会有额外的变换。
如果是 带 Attention 机制的 Seq2Seq,那么 c 就不只是
Seq2Seq 模型的核心缺陷:信息瓶颈
即:
在经典的 Seq2Seq 模型中,上下文向量 c 是从整个输入句子提取出来的一个固定长度的向量,它在解码阶段每个时间步都会被使用。但当输入序列很长时,仅靠一个向量来表示全部信息是不够的。
Attention 的引入(为了解决这个瓶颈)
Attention 的核心思想:
与其把整句话“压缩成一个向量”,不如让解码器在每个时间步都自己决定要关注输入句子的哪些部分。
- 不再依赖唯一的 c
- Decoder 每生成一个词,就动态地对 Encoder 的每个隐藏状态
打分,计算加权和(也叫 attention vector) - 这样 Decoder 每一步都“看着”不同位置的信息 —— 信息流动不再被限制。
Attention
Cross-Attention
对齐方式
- **Dot-product Attention: 模版匹配角度理解
- General Attention:
:General attention = dot-product attention + learnable 权重变换在 dot-product 之前,先用矩阵
3. Additive Attention(Bahdanau Attention)
- 用两个不同的权重矩阵把
映射到同一个空间
- 把两个向量相加,再通过 tanh 非线性压缩(增加表达力)
- 最后用一个可学习向量 v_a 去对这个融合结果做投影 ⇒ 输出一个标量
- Bahdanau Attention 更像是一个“小型神经网络”,它不只做相似度匹配,而是学习一个复杂的“匹配函数”。不再是简单的“你像我就打高分”,而是“你哪些特征和我哪些部分组合起来后,我就认为你重要”。是一种更深层次的语义耦合计算。
soft-attention vs hard-attention
可以通过抽象出一层 attention layer, 插入到 cnn, rnn 里 “注意力”从一种启发式机制变成了一个可泛化的、高效的、端到端可训练的神经网络计算模块,它的抽象化(Query-Key-Value)和优化(用矩阵乘法加速)为 Transformer 的诞生打下了基础。
缩放因子
防止 softmax 输出过于极端,保证反向传播中梯度不会消失,训练过程更加稳定
Query-Key-Value 框架
分离 Key 和 Value 给模型带来了表达能力的解耦:
- Key 用于比对,用更适合匹配的特征空间
- Value 用于内容提取,用更丰富的语义表示
- 二者不再共享参数或表达空间,不互相限制
Self-Attention
Masked self attention
仅仅根据前面的的信息
Multi-Headed
多头注意力就是在同一个输入上,并行运行多个注意力头(多个独立 Q-K-V 计算),让模型能从多个“子空间”学习不同的注意力模式,最后把所有结果拼接(concat)起来,再线性投影得到最终输出。
头的数量(number of heads):h
每个头内部的维度:
这是每个 attention 子空间的维度
- 也就是每个 head 中 Query/Key/Value 的维度
- 假设总输入维度是
用了 8 个头
- 那每个 head 的维度通常设置为
注意:你可以自己设置
这样拼接后维度刚好对上。
把 Self-Attention 当作 CNN 里的新型操作层
- 之前的局限:传统 CNN 里的每个位置只看局部邻域(感受野小),但:
Self-Attention 层允许每个位置看整张图的所有位置(long-range dependency)
输入结构(来自 CNN)
原始输入图像 → CNN 提取特征 → 得到一个 shape 为:
C 是通道数,H × W 是空间尺寸。
Self-Attention 模块的 3 个主要分支:
名称 | 维度(每个位置) | 用途 |
---|---|---|
Query | 表示“我要问什么” | |
Key | 表示“我是谁,是否值得被关注” | |
Value | 表示“我能贡献什么内容” |
通过三个不同的
Attention 权重计算流程:
- 将 Query 和 Key 展平为矩阵:
- 将
- 同样 Key 也 reshape 为
- 点积计算相似度矩阵(注意力权重):
- 得到 shape 为
的注意力矩阵
- 表示:图中每个位置如何关注所有其他位置
- 加权 Value 向量求和:
- 将所有位置的 value 向量做加权求和,得到新特征图
输出重建 + 残差连接:
- 得到的新特征图再通过一个
卷积恢复维度到 C
- 再加上残差连接(Residual Connection):
- 保留原始特征,防止退化,训练稳定
元素 | 作用 |
---|---|
1×1 Conv | 将输入特征线性变换成 Q/K/V |
softmax(Q·Kᵀ) | 计算所有位置之间的注意力权重 |
A·V | 加权求和,整合信息 |
Residual | 保留输入,防止特征破坏 |
输出 | 和输入同尺寸的新特征图 |
这种结构就是 SAGAN(Self-Attention GAN) 中首次被用在图像生成的注意力层,后来被广泛用于图像识别、分割、检测,甚至是 ViT(Vision Transformer)的启发来源。
总结一句话:
这是一个“视觉自注意力层”,它允许图像中每个位置和所有其他位置进行全局交互,非常适合处理图像中远距离依赖(比如一只猫头和尾巴很远但有关联)。
图像生成字幕
Step 1: 用 CNN 处理图片,得到一个 feature map
- 比如输出是 3×3 的网格,每个位置有一个特征向量
- 这些向量对应图像的不同区域(视觉 patch)
Step 2: 解码器 RNN 开始生成描述(例如生成单词 “cat”)
- 初始状态为
,通常由平均池化所有 或者其他方式得到。 - 利用打分函数
对图像各个位置计算对齐分数 。 - 用 softmax 将对齐分数归一化,得到注意力权重
。 - 用这些权重加权图像特征:
- 将
、前一个词(START token) 、和隐藏状态 送入 RNN,得到 - 用
预测当前单词 (比如 “cat”)
Step 3: 继续生成下一个单词
- 进入下一轮:用
与每个 再次计算对齐分数 - 得到新的注意力分布
,新的上下文向量 - 用
, , 计算 ,并预测 - 重复这个过程直到生成句子结束(比如输出 [STOP])
直觉解释:
你可以把这个注意力机制想象成“看图写话”时的眼动过程:
我正在生成描述的第一个词,比如“cat”,此时我看向图片中有猫的那一块区域,对那部分关注度就高。
接着,当我要说“sitting on a tree”时,我又把注意力转移到图中树的位置,依此类推。
RNN vs CNN(一维卷积) vs Self-Attention
背景
假设你有一个输入序列:
我们要从这组输入中提取出有用的特征(比如做翻译、分类、总结等)。
第一种方式:RNN / LSTM
- 优点:
- 擅长建模长距离依赖(long-term dependency)
- 每个输出状态 h_t 都能从所有过去输入中学习:
缺点:
- 串行执行(计算
必须等 ) - 很难并行 → 训练速度慢,GPU 加速能力差
- 可扩展性差(scalability issue)
第二种方式:1D Convolution 《Convolutional Neural Networks for Sentence Classification》
优点:
- 可以并行计算所有位置的输出
- 适合 GPU、大模型、深层堆叠
缺点:
- 每个输出只看固定感受野(例如 3 个 token)
- 要想获得全局信息,必须堆叠很多层(层数多、难训练)
- 长距离信息传播效率差
第三种方式:Self-Attention(自注意力)
优点:
- 每个位置直接看整个序列
- 没有时间顺序限制 → 可以并行计算所有位置
- 高效利用 GPU:主要是矩阵乘法 + Softmax
缺点:
- 内存占用大:attention matrix 是
,输入越长越吃显存
属性 | RNN | 1D CNN | Self-Attention |
---|---|---|---|
是否支持长依赖 | 好 | 不行 | 非常好 |
并行性(GPU友好) | 串行 | 高并行 | 高并行 |
可扩展性 | 差 | 好 | 很好 |
参数共享 | 时序共享 | 滑动卷积共享 | 查询共享 |
缺点 | 慢,难训练 | 感受野小 | 显存大(T×T attention) |
作者的推荐和看法(总结性一句):
自注意力机制结合了 RNN 的长依赖捕捉能力 和 CNN 的高度并行性,是当前最优的序列处理机制。
虽然它显存占得多,但随着 GPU 越来越强,这不是大问题。
小技巧记忆三者:
- RNN:一层一层传话,很认真,但慢
- CNN:短距离小组讨论,快但不懂全局
- Attention:群聊广播,人人互相可见,信息同步一流
抽象出 Attention Layer
任何时候你有两组数据 —— 一组是想去“检索”的(Query),一组是你可以“提取信息”的(Key/Value)
Query来源
任务 | Q 的来源 | 含义 |
---|---|---|
Transformer 编码器 | 当前 token 的 embedding + position embedding | “这个词需要聚合哪些上下文” |
Transformer 解码器 | 当前 decoder 的隐藏状态 | “我现在准备输出一个词,我要去查和它相关的输入” |
图像描述生成 | 当前 LSTM 状态 |
“我正在生成词,我要看看图像中哪些区域重要” |
文本问答系统 | 问题 embedding | “问题是 Q,文档是输入,我要找到答案” |
ChatGPT 对话模型 | 当前对话 token 的 embedding | “当前词该从历史中提取哪些信息” |
在 Transformer 中的标准操作:
在 Self-Attention 中,Q、K、V 都是从输入向量 X(比如 embedding)映射出来的:
也就是说:
- Q 来自输入序列本身,表示“每个位置想获取的信息”
- 它和 K 比较,找到“我要从哪里获取信息”
- 然后从 V 中提取信息做融合
结果 y 的含义
这些 y_i 是聚合后的信息结果,是每个 query 想要“从输入中收集到”的上下文表示。它们会被传给神经网络的下一层,作为新表示、用于预测、分类、生成等任务。
Attention Layer 本质上做了什么?
以图中结构为例,每个
- 都会从 Key-Value 对中提取出自己想要的信息
- 得到输出向量
- 这些
就是 attention 之后的结果 —— 也就是整个 Attention Layer 的 输出 Y
Y 的作用取决于你把 Attention Layer 放在什么位置:
1:放在 Transformer 编码器中
- 输入是 token 的 embedding
- 每个
是 token i 在当前层聚合完上下文后的表示 - 这些
会被送到下一层 Transformer block,继续做多头注意力 + FFN
2:放在 Transformer 解码器中
- 输入是当前 decoder 的隐藏状态(比如想生成某个词)
是该状态从 encoder 输出中聚合出的上下文(cross-attention)- 被用于下一步词的生成(比如预测 “seagull”)
3:放在图像描述任务中
- Query 是 decoder 的语言状态
- 输出
是图像区域特征的加权组合 - 被用来生成下一个词的输入
4:用作一般信息融合层
- Query 是用户行为序列的表示,Input 是候选商品
- 输出的
是聚合完商品特征后的推荐意图向量 - 送入 MLP 做点击率预测
CNN & RNN & Self-Attention
属性 | RNN | 1D CNN | Self-Attention |
---|---|---|---|
是否支持长依赖 | 好 | 不行 | 非常好 |
并行性(GPU友好) | 串行 | 高并行 | 高并行 |
可扩展性 | 差 | 好 | 很好 |
参数共享 | 时序共享 | 滑动卷积共享 | 查询共享 |
缺点 | 慢,难训练 | 感受野小 | 显存大(T×T attention) |