为什么需要位置编码
Transformer 并行处理整个序列,不像 RNN 那样逐步读取。这种并行性带来了效率,但也丢失了序列的顺序信息。位置编码正是为了解决这个问题。
Sinusoidal Position Encoding
原始 Transformer 使用正弦和余弦函数:
优点
- 可以外推到训练时未见过的序列长度
- 不需要额外学习参数
- 相对位置关系可通过三角函数推导
代码实现
def sinusoidal_encoding(max_len, d_model):
pe = torch.zeros(max_len, d_model)
position = torch.arange(0, max_len).unsqueeze(1).float()
div_term = torch.exp(torch.arange(0, d_model, 2).float() *
-(math.log(10000.0) / d_model))
pe[:, 0::2] = torch.sin(position * div_term)
pe[:, 1::2] = torch.cos(position * div_term)
return pe
Learned Position Embedding
GPT 系列使用的是可学习的位置嵌入。直接将位置索引映射到一个 Embedding 层,让模型自行学习最佳的位置表示。
选择 Sinusoidal 还是 Learned?如果需要在推理时使用比训练更长的序列,Sinusoidal 是更安全的选择。
更多背景可参考 Transformer 架构详解 和 注意力机制深入理解。