核心要点
Transformer 无循环/卷积结构,需显式注入位置信息。
公式:PE(pos,2i)=sin(pos/10000^(2i/d)),PE(pos,2i+1)=cos(同一频率)。
不同维度对应不同波长(频率几何衰减),便于模型表达相对位置。
易错点:分母指数用 2i/d 且偶/奇维共享同一频率;用对数形式计算避免数值溢出。
标准回答
Transformer 本身对输入顺序不敏感,需要位置编码为每个位置注入唯一的位置信号,再与词嵌入相加。正弦位置编码对偶数维用 sin、奇数维用 cos,且同一对 (2i, 2i+1) 共享频率 1/10000^(2i/d);随着维度增大波长变长、频率几何衰减,使不同维度刻画从高频到低频的位置变化,模型可由此线性表达相对位置。计算分母时用 exp(−log(10000)·2i/d) 的对数形式更数值稳定。下面用 NumPy 实现:
python
import numpy as np
def positional_encoding(seq_len, d_model):
# 返回 (seq_len, d_model) 的正弦位置编码矩阵
pos = np.arange(seq_len)[:, None] # (L, 1)
i = np.arange(0, d_model, 2) # 偶数维索引 0,2,4,...
# 用对数-指数形式计算频率,数值更稳定
div = np.exp(-np.log(10000.0) * i / d_model) # 1/10000^(2i/d)
pe = np.zeros((seq_len, d_model))
pe[:, 0::2] = np.sin(pos * div) # 偶数维用 sin
pe[:, 1::2] = np.cos(pos * div) # 奇数维用 cos(同一频率)
return pe
if __name__ == '__main__':
pe = positional_encoding(seq_len=10, d_model=16)
print(pe.shape) # (10, 16)
print(pe[0, :4].round(3)) # pos=0: sin=0, cos=1 交替常见误区
⚠️ 常见踩坑
分母指数容易误写成 i/d(应为 2i/d,对应偶数维索引);偶/奇维须共用同一频率而非各算各的;直接对 10000^(2i/d) 取幂在大 d 下可能精度差,推荐对数形式。
延伸学习
与本题相关的知识库文章、术语、工具与行业资讯。