一、位置编码概述:为什么需要位置编码
大家好,我是你们的老朋友。今天咱们聊聊位置编码。
说实话,我刚接触Transformer那会儿,第一个困惑就是:为什么这玩意儿需要位置编码?
你看CNN,天然就有空间结构。像素在左边、右边,卷积核一滑就知道。RNN呢,按时间步一步步走,顺序天然存在。但Transformer不一样——它的核心是自注意力机制,说白了就是“全连接”。
什么意思?
我给你举个例子。假设输入是“我 爱 你”三个词。在Transformer的注意力计算里,“我”和“你”的距离,跟“我”和“爱”的距离,数学上是一样的。没有远近之分,没有先后之别。
这就有问题了。
核心矛盾:Transformer的并行计算能力,恰恰来自于它抛弃了序列的时序依赖。但自然语言本身,是强时序依赖的。
“我打你”和“你打我”,词一样,顺序不同,意思天差地别。没有位置信息,模型根本分不清。
所以,我们需要一种方式,把位置信息“塞”进模型里。这就是位置编码的由来。
我在项目中遇到过一件事:有个同学直接把位置编码去掉,发现模型训练loss死活降不下去。嗯,这就是典型的“知其然不知其所以然”。
二、Transformer中位置编码的角色
位置编码在Transformer里,到底扮演什么角色?
我个人习惯把它理解为“坐标系统”。
你想想看,模型拿到一个句子,就像拿到一堆散落的积木。位置编码就是给每块积木贴上坐标标签。这样模型才知道:哦,这块积木在位置1,那块在位置5。
具体来说,位置编码有两个核心作用:
- 区分顺序:让模型知道“我”在“爱”前面,“爱”在“你”前面
- 感知距离:让模型知道“我”和“你”隔了多远
在原始Transformer论文中,位置编码是加到词嵌入上的。公式很简单:
最终输入 = 词嵌入 + 位置编码
为什么是加法,不是拼接?
我记得当时读论文时也纠结过。后来在实践中发现:加法相当于在原始语义空间里,给每个词向量加了一个“偏移量”。这个偏移量只跟位置有关,不影响词本身的语义。而拼接会改变向量维度,增加参数量,效果也没更好。
小技巧:如果你自己实现Transformer,位置编码的维度一定要和词嵌入维度一致。否则加不上去。
三、绝对位置编码与相对位置编码
好,接下来是重点。位置编码分两大类:绝对位置编码和相对位置编码。
3.1 绝对位置编码
绝对位置编码,就是给每个位置分配一个唯一的、固定的编码向量。
比如位置1是[0.1, 0.2, 0.3],位置2是[0.4, 0.5, 0.6]……每个位置都有自己的“身份证”。
原始Transformer用的就是这种。它用正弦和余弦函数生成编码:
PE(pos, 2i) = sin(pos / 10000^(2i/d_model))
PE(pos, 2i+1) = cos(pos / 10000^(2i/d_model))
这个公式看着复杂,其实思想很简单:
- 不同维度用不同的频率
- 低频维度编码长距离信息
- 高频维度编码短距离信息
这样做的好处是:模型可以学到位置之间的相对关系。因为sin和cos函数有周期性,位置k和位置k+n的编码,存在线性变换关系。
但绝对位置编码有个硬伤:长度限制。
避坑指南:我曾经在一个长文本任务里,直接用原始Transformer的位置编码。结果序列长度超过训练时的最大长度,模型直接崩了。因为位置编码只定义到max_len,超出部分没有编码。
3.2 相对位置编码
相对位置编码的思路完全不同。
它不关心“你在第几个位置”,而是关心“你离我有多远”。
比如句子“我 爱 你”:
- “爱”相对于“我”的距离是+1
- “你”相对于“我”的距离是+2
- “我”相对于“你”的距离是-2
相对位置编码的核心思想是:在注意力计算中,引入位置差信息。
具体来说,标准注意力公式是:
Attention(Q, K, V) = softmax(Q * K^T / sqrt(d)) * V
相对位置编码会把它改成:
Attention(Q, K, V) = softmax(Q * K^T + Q * R^T / sqrt(d)) * V
其中R是相对位置编码矩阵。这样,Q和K的交互不仅包含内容信息,还包含位置关系。
我个人的经验是:相对位置编码在长序列任务上,明显优于绝对位置编码。因为它不受序列长度限制,而且更符合语言本身的特性——我们理解句子时,更关心词与词之间的相对关系,而不是绝对位置。
3.3 两者的对比
| 特性 | 绝对位置编码 | 相对位置编码 |
|---|---|---|
| 编码方式 | 每个位置固定编码 | 编码位置之间的差值 |
| 长度外推 | 差(受限于max_len) | 好(理论上无限) |
| 计算复杂度 | 低(O(n)) | 较高(O(n²)) |
| 代表模型 | 原始Transformer | T5, Transformer-XL |
| 适用场景 | 短序列、固定长度 | 长序列、可变长度 |
看到这里你可能要问:那有没有一种方法,既能享受相对位置编码的好处,又能保持绝对位置编码的简洁?
有。这就是我们下一章要讲的RoPE(旋转位置编码)。
不过别急,咱们先把基础打牢。位置编码这个坑,我当年踩了不少。你先把绝对和相对的概念吃透,后面学RoPE就轻松多了。
一句话总结:绝对位置编码给每个位置发“身份证”,相对位置编码只关心“距离”。两者各有优劣,但现代大模型更倾向于相对位置编码或其变体。
四、知识体系结构图
下面我用一张SVG图,把本章的知识体系串起来。这样你一眼就能看清位置编码的全貌。
这张图把位置编码的脉络理清了。从“为什么需要”到“怎么实现”,再到“两大流派”,一目了然。
好了,第一章就到这里。记住:位置编码不是锦上添花,而是Transformer的必需品。没有它,模型就是个“词袋”,根本理解不了语言顺序。
下一章我们深入RoPE,看看它为什么能成为大模型的首选。