核心要点
Transformer 无循环/卷积结构,需显式注入位置信息。
公式:PE(pos,2i)=sin(pos/10000^(2i/d)),PE(pos,2i+1)=cos(同一频率)。
不同维度对应不同波长(频率几何衰减),便于模型表达相对位置。
易错点:分母指数用 2i/d 且偶/奇维共享同一频率;用对数形式计算避免数值溢出。
标准回答
一、先把结论讲清楚
可以先说为什么需要它:Transformer 没有 RNN 或 CNN 那种天然顺序结构,所以要显式注入位置信息。
一、正弦位置编码怎么定义?
对位置 pos 和维度 i,偶数维用 sin,奇数维用 cos:PE(pos, 2i)=sin(pos / 10000^(2i/d)),PE(pos, 2i+1)=cos(pos / 10000^(2i/d))。
二、拆开机制和判断点
同一对偶/奇维共享同一个频率。
二、为什么用很多频率?
低维变化快,高维变化慢,等于用一组不同波长描述位置。这样模型既能感知短距离变化,也能表达较长距离关系。
三、实现时注意什么?
偶数维和奇数维要配对;分母指数是 2i/d_model;
三、补上例子、边界和取舍
工程里常用 exp(-log(10000) * i / d_model) 来算频率,更稳定。下面用 NumPy 实现:
面试里可以补一句:手撕代码:实现正弦位置编码Positional Enco 在大模型场景下通常要同时权衡效果、延迟、成本和安全边界。回答时最好带一个例子,比如上下文过长、幻觉、缓存命中或工具调用失败时,系统应该如何降级和观测。
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 交替常见误区
⚠️ 常见踩坑
误区一:偶数维和奇数维频率没配对。 sin/cos 应该共享同一个频率。
误区二:指数写错。 公式里是 2i/d_model,对应实现时的偶数维索引。
🔗 相似问题
同一考点的不同问法,换着练更稳
延伸学习
按主题分类的相关资源,便于系统复习
