Transformer 架构 - 位置编码层原理介绍
1 课程概览
本课介绍位置编码层原理。Transformer 的 Multi-Head Attention 每个词都能看到,但不知道词的顺序。位置编码通过 sin/cos 函数给每个词加位置信息,让模型区分"我爱你"和"你爱我"。公式分奇偶维度:偶数维度用 sin,奇数维度用 cos。
2 核心概念与定义
- 位置编码(Positional Encoding, PE):给词向量加位置信息。
- 周期性函数:sin、cos 函数。
- d_model:词向量维度。
- pos:当前词在序列中的位置。
- 2i:偶数维度。
- 2i+1:奇数维度。
3 模型与算法详解
为什么需要位置编码?
Transformer 的 Multi-Head Attention 每个词都能看到,但不知道词的顺序。
示例:
- "我爱你" 和 "你爱我"
- 处理"爱"这个字时,能看到"我"和"你"
- 但不知道"我"在前还是"你"在前
其他示例:
- "我欠你100元" 和 "你欠我100元"
- "小龙女来到了杨过生活过的地方,她说我也想过过过过过过的生活"
- "下雨天路滑,一把把把把住了"
- "明天校庆,校长说除了校徽别别别的"
位置编码原理
通过 sin/cos 周期性函数给每个位置贴独特的标签。
- 每个位置都有独特的标签
- 让模型区分词的顺序
- 类似军训排队:记住你在谁后面,就能排好队
编码器 vs 解码器
| 对比项 | 编码器 | 解码器 |
|---|---|---|
| Multi-Head Attention | 每个词都能看到 | 有掩码,看不到未来词 |
| 需要位置编码 | 是 | 是 |
4 数学原理与推导
位置编码公式
$$\text{PE}(pos, 2i) = \sin\left(\frac{pos}{10000^{2i/d_{model}}}\right)$$
$$\text{PE}(pos, 2i+1) = \cos\left(\frac{pos}{10000^{2i/d_{model}}}\right)$$
参数说明
| 参数 | 含义 |
|---|---|
| PE | 位置编码函数 |
| pos | 当前词在序列中的位置 |
| 2i | 偶数维度 |
| 2i+1 | 奇数维度 |
| d_model | 词向量维度 |
| 10000 | 常数 |
偶数维度和奇数维度
- 偶数维度(2i):用 sin 函数
- 奇数维度(2i+1):用 cos 函数
- 原因:2i 一定是偶数,能被 2 整除
最终输入
$$\text{input} = \text{embedded} + \text{PE}$$
词向量 + 位置编码 = 最终输入
5 代码示例
import torch
import math
def positional_encoding(pos, d_model):
"""
计算位置编码
:param pos: 当前词的位置
:param d_model: 词向量维度
:return: 位置编码向量
"""
pe = torch.zeros(d_model)
for i in range(d_model // 2):
# 偶数维度:sin
pe[2 * i] = math.sin(pos / (10000 ** (2 * i / d_model)))
# 奇数维度:cos
pe[2 * i + 1] = math.cos(pos / (10000 ** (2 * i / d_model)))
return pe
# 测试
d_model = 4 # 词向量维度
for pos in range(5):
pe = positional_encoding(pos, d_model)
print(f"位置 {pos} 的编码: {pe}")
输出示例
位置 0 的编码: [0, 1, 0, 1]
位置 1 的编码: [0.8415, 0.5403, 0.01, 0.9999]
位置 2 的编码: [0.9093, -0.4161, 0.02, 0.9998]
...
6 重难点与易错提醒
- ❗重点:位置编码通过 sin/cos 函数给每个词加位置信息。
- ❗重点:偶数维度用 sin,奇数维度用 cos。
- ⚠️易错:单独看公式会晕,需要结合图示理解。
- 💡深入理解:Transformer 本身不知道词的顺序,需要位置编码。
- 💡深入理解:类似军训排队,记住你在谁后面就能排好队。
7 课堂问答精选
Q1:为什么需要位置编码?
A:Transformer 的 Multi-Head Attention 每个词都能看到,但不知道词的顺序。例如"我爱你"和"你爱我"处理"爱"时能看到"我"和"你",但不知道谁在前。位置编码通过 sin/cos 函数给每个位置贴独特的标签,让模型区分词的顺序。
Q2:位置编码的公式是什么?
A:偶数维度:$\text{PE}(pos, 2i) = \sin\left(\frac{pos}{10000^{2i/d_{model}}}\right)$;奇数维度:$\text{PE}(pos, 2i+1) = \cos\left(\frac{pos}{10000^{2i/d_{model}}}\right)$。
Q3:为什么偶数维度用 sin,奇数维度用 cos?
A:因为 2i 一定是偶数,能被 2 整除。偶数维度用 sin,奇数维度用 cos,可以区分不同维度。
Q4:位置编码和词向量如何结合?
A:最终输入 = 词向量 + 位置编码,即 $\text{input} = \text{embedded} + \text{PE}$。
8 本课小结
- 位置编码:给词向量加位置信息。
- 公式:偶数维度用 sin,奇数维度用 cos。
- 原因:Transformer 不知道词的顺序。
- 类比:军训排队,记住你在谁后面。
- 最终输入 = 词向量 + 位置编码。
9 延伸思考
- 位置编码如何用代码实现?
- 位置编码的好处是什么?