Transformer
Transformer 由注意力、前馈网络、残差、归一化和位置表示组成。
学习目标
- 一个 Encoder 层保持序列长度与表示维度
- Transformer 不加位置表示能知道词序吗?
- 说明:EncoderLayer 本身不包含词表、位置编码、任务头或完整生成训练协议。
为什么需要这个概念
Transformer 由注意力、逐位置前馈网络、残差、归一化和位置信息组成。Encoder、因果 Decoder 与 Encoder-Decoder 的可见范围和任务接口不同。
学习前需要掌握
背景与问题
序列模型需要让远处位置直接交换信息,又要能在训练中并行处理位置。Transformer 用注意力实现位置通信,再用逐位置前馈层变换特征。
概念定义
Transformer 由注意力、逐位置前馈网络、残差、归一化和位置信息组成。Encoder、因果 Decoder 与 Encoder-Decoder 的可见范围和任务接口不同。
直观理解
注意力负责把各位置需要的上下文取来,前馈层负责消化每个位置的新表示;残差路径让已有表示能够保留。
核心原理
自注意力令同一序列提供 Q、K、V,交叉注意力则由一侧提供 query、另一侧提供 key/value。Encoder 通常能看全部输入,生成式 Decoder 使用因果约束,避免训练时读取未来 token。
FFN 独立应用于每个位置,常先把 D 维扩到较大隐藏维,再投回 D。残差要求子层输出维度对齐,LayerNorm 放置位置形成 Pre-LN 或 Post-LN 配方;这些结构不能只用“有注意力”概括。
标准稠密全局注意力的分数数目随长度平方增长,计算还受特征维度影响;长上下文会显著增加内存。没有任何位置信息的自注意力本身不能区分一般的排列顺序。框架 EncoderLayer 也不会自动替你添加位置编码。
数学表达
核心公式
FFN 对每个位置独立应用;分数项数量表示稠密自注意力的一个内存来源,完整计算成本还依赖特征维度。
变量含义
Nbatch sizeD/H特征或隐藏维度
计算步骤
- 1在输入加入一个明确的演示位置项。
- 2注意力输出仍为 (2,4,8)。
- 3FFN 逐位置经 8→16→8,残差后 shape 不变。
代码对应位置
示例 1一个 Encoder 层保持序列长度与表示维度的最小验证:使用完整构造输入核对一个 Encoder 层保持序列长度与表示维度,输出只表示本例计算。
变量解释
| 变量 | 含义 |
|---|---|
N | batch size |
D/H | 特征或隐藏维度 |
完整数值示例
一个 Encoder 层保持序列长度与表示维度
已知条件
- 输入 N=2,L=4,D=8
- 两头注意力,每头 4 维,FFN 隐藏维度 16
计算步骤
- 在输入加入一个明确的演示位置项。
- 注意力输出仍为 (2,4,8)。
- FFN 逐位置经 8→16→8,残差后 shape 不变。
计算结果
Encoder 层输出为 (2,4,8),输入无需变成单一向量。
处理前后对比
- EncoderLayer 本身不包含词表、位置编码、任务头或完整生成训练协议。
一个 Encoder 层保持序列长度与表示维度
本例位置项仅用位置编号除以 10,目的是显式提醒位置来源,不是推荐替代成熟正弦、学习式或旋转位置方案。nn.TransformerEncoderLayer 接收的已经是隐藏表示,Embedding 与位置处理在外部完成。
若任务是整句分类,还需添加带 mask 的池化或特定分类 token;若是语言建模,还需因果 mask、目标移位和词表输出头。一个层的前向形状正确不等于完整任务已经建好。
计算与实现步骤
- 在输入加入一个明确的演示位置项。
- 注意力输出仍为 (2,4,8)。
- FFN 逐位置经 8→16→8,残差后 shape 不变。
代码实现
示例 1
一个 Encoder 层保持序列长度与表示维度的最小验证
example_01.py用途:使用完整构造输入核对一个 Encoder 层保持序列长度与表示维度,输出只表示本例计算。
import torch
from torch import nn
torch.manual_seed(7)
layer = nn.TransformerEncoderLayer(8, 2, dim_feedforward=16, dropout=0., batch_first=True, norm_first=True)
layer.eval()
x = torch.zeros(2, 4, 8)
demo_position = torch.arange(4, dtype=torch.float32)[None, :, None] / 10
with torch.inference_mode():
y = layer(x + demo_position)
print("input:", tuple(x.shape), "output:", tuple(y.shape))
print("finite:", bool(torch.isfinite(y).all()))代码解析
解析始终位于完整代码下方,并按实际代码段逐项对应。
输入数据与任务
使用完整构造输入核对一个 Encoder 层保持序列长度与表示维度,输出只表示本例计算。
y- 目标标签或连续目标值。
Step 1 · 1–11 行
导入当前步骤需要的数值计算、预处理、模型或评价工具。依赖集中写在代码开头,便于复现。
import torch
from torch import nn
torch.manual_seed(7)
layer = nn.TransformerEncoderLayer(8, 2, dim_feedforward=16, dropout=0., batch_first=True, norm_first=True)
layer.eval()
x = torch.zeros(2, 4, 8)
demo_position = torch.arange(4, dtype=torch.float32)[None, :, None] / 10
with torch.inference_mode():
y = layer(x + demo_position)
print("input:", tuple(x.shape), "output:", tuple(y.shape))
print("finite:", bool(torch.isfinite(y).all()))预期输出或运行结果
input: (2, 4, 8) output: (2, 4, 8) finite: True
常见错误 · 4 条
- 没有位置表示
- padding 参与池化
- 架构与预训练权重不匹配
- 确认样本轴、特征轴以及 X 与 y 的第一维完全对应。
实际应用
- 文本编码与因果语言建模
- 视觉 patch 或跨模态序列融合
常见错误
- 没有位置表示
- padding 参与池化
- 架构与预训练权重不匹配
常见问题
Transformer 不加位置表示能知道词序吗?
一般自注意力只根据内容混合,缺少区分排列的充分位置信息;因果可见性有部分顺序约束,但通常仍需按架构配方提供位置机制。
这个示例能说明什么边界?
EncoderLayer 本身不包含词表、位置编码、任务头或完整生成训练协议。
推荐学习资料
Dive into Deep Learning
把数学、图示、文字与可执行代码结合,系统覆盖深度学习基础和现代模型。
Zhang / Lipton / Li / Smola · D2L.ai
资料笔记
Attention Is All You Need
提出完全基于注意力机制的 Transformer 架构,并用于序列建模和机器翻译。
Vaswani et al. · arXiv / NeurIPS