今天给大家带来一篇知乎好友@Whisper的文章,详细介绍长文本大模型中从ROPE到Yarn的的位置编码。
知乎:https://zhuanlan.zhihu.com/p/15311461897
从Qwen2.5到Deepseek V3, Yarn几乎已经是各家LLM做长文本外推的标配组件 (相比Pretrain微乎其微的资源消耗获得至少16倍的长度外推)。 然而我最近在和很多做LLM的朋友交流发现大家对长文本的认知还停留在ROPE的时代。本文尝试用一条通用公式,带你以最简洁的方式彻底理解ROPE及其演化的变种逻辑,梳理以下长文本外推的方法本质:
- ROPE
- Position Interpolation
- NTK-Aware Interpolation
- Dyanmic NTK Interpolation
- NTK-by-parts Interpolation
- Yarn
后续ROPE的各类变体会不断更新记录在本文,欢迎点赞关注追踪最新进展。
1.位置编码的通用公式
无论是ROPE还是它的所有变种,本质上都可以被以下公式所统一:
这里:
- 是输入向量。
- 是位置索引。
- 是频率参数。
- 和 是可调函数,分别描述位置和频率的变换逻辑。
在原始 Transformer Self-Attention 中,通用公式中的 表示将输入向量 和位置相关信息( 和 )结合后,进行的进一步变换。具体来说:
这里:
- : 输入向量。
- : 位置编码,具体由 和 构成,基于 和 计算:
- : 线性投影矩阵,用于变换向量。
因此, 具体对应的是将位置编码 加到输入向量 ,再通过投影矩阵 处理后, 输入self-attention经典公式前的部分。
这条公式背后隐藏的逻辑是:如何通过适配 和 来在固定上下文长度的限制下延展语言模型的能力。接下来,我们基于这条公式逐一拆解各个变种。
- ROPE:一切的起点
在Transformer模型中,位置编码是连接输入序列与模型结构的重要桥梁。Rotary Position Embedding (ROPE) 是一种基于旋转变换的相对位置编码方法,它以极其优雅的方式将位置索引转化为模型内部的旋转信息。其核心数学公式如下:
ROPE的定义可以直接映射到通用公式:
因此,ROPE的具体实现为(这里求简只考虑二维情况):
其中:
- 是输入向量。
- 是输入向量的位置索引。
- 是频率参数,定义为 。
- 是映射矩阵,将输入向量投影到高维空间。
2.1复数空间的直观解释
为了更直观地理解这个公式,ROPE的旋转可以被视为复数域上的变换:
其中, 是复数域中的旋转操作, 和 是将输入向量投影到查询(query)和键(key)空间的权重矩阵。
在这种表示方式下,两个位置 和 的点积形式为:
注意,点积中与位置 和 相关的部分仅依赖于它们的相对距离 。这意味着,ROPE天然具有对相对位置的敏感性,无需额外编码绝对位置。
2.2 数学推导中的频率参数
(注意这部分是理解后续各种ROPE变体的基础,所以在这里单独列了一个章节来讲述)
ROPE的核心亮点是每个隐藏维度的旋转频率由 决定。
定义为:
这里:
- 是一个固定的基数(通常取 )。
- 是隐藏层的维度数。
- 表示隐藏层的某一具体维度。
频率参数 决定了每个维度的旋转速度:
对于低维度(即 值较小的维度),
更接近于 1 。
对于高维度(即 值较大的维度),
会迅速衰减到接近 0 。
旋转角度 决定了频率,
- 当 接近 1 (低维度), 的变化较大,旋转更快 。
- 当 接近 0 (高维度), 的变化较小,旋转更慢 。
因此低维度具有更快的旋转(对应局部细节捕捉),高维度具有更慢的旋转(对应长距离依赖)。这种设计巧妙地结合了长距离和短距离的信息编码能力。
2.3 为什么ROPE直接外推在长文本外推中受限?
尽管ROPE在预训练窗口范围内表现优异,其主要限制在于:
- 频率不变性 : 在预训练时被固定,无法适应更长的上下文长度。
- 频率分布的刚性 :所有维度的频率分布固定,不支持动态调整,导致当序列长度超出预训练范围时,旋转编码出现混乱。
当上下文窗口从预训练的 扩展到 时,相对位置 的值可能远超预期范围。此时,旋转频率无法捕捉新的位置信息,导致模型性能显著下降。
- Position Interpolation (PI):均匀拉伸的位置插值,也叫线性内插
PI尝试通过重新定义 将位置索引拉伸到预训练窗口内:
- ,其中 是上下文扩展比例。
- ,保持频率参数不变。
这使得每个位置索引被均匀拉伸到预训练窗口内,公式变为:
优点 :简单有效,训练开销小。
缺点 :对所有维度频率统一缩放,导致高频信息丢失,影响局部关系建模。
- NTK-Aware Interpolation:非均匀频率缩放,介于直接外推和线性内插之间的平滑方法
NTK-Aware方法对 引入动态调整, 保持不变:
这里 时,,有没有 都不影响,因此也叫直接外推。
这里 时, ,变成了线性内插。
所以该方法可以理解为介于直接外推和线性内插之间的平滑方法。 它主要通过对低频维度更大幅度地插值,高频维度保持不变,保留了更多高频细节。
优点 :在未微调模型中显著提升长文本建模能力。
缺点 :部分频率超出预训练范围,可能引发性能不稳定。
- Dynamic Scaling:动态适配插值比例, NTK-Aware Interpolation升级版
Dynamic Scaling进一步动态调整 以适配不同上下文长度:
或者采用指数形式调整:
其中,参数 和 的取值决定了缩放函数的动态灵活性。且 a,b需要满足 ,且 的推荐范围为 ,公式 (2) 可有效提升上下文适配能力。
相比于传统线性内插方法,公式 (1) 和 (2) 差不多可以实现 1%-2% 的性能增益 ,其优点在于:通过 和 调整缩放范围,位置索引从 被映射到更合理的区间范围,避免传统方式中索引越大越不充分的问题。
6 NTK-by-parts Interpolation:基于波长局部分段插值
- 基于波长的维度分类 :“NTK-by-parts”方法着重考虑RoPE公式中定义的波长。对于每个隐藏维度,计算其波长(其中,)。根据波长与原始上下文大小的比值,将隐藏维度分为不同类别。
- 不同类别维度的插值策略 :
- 高频维度( ) :对于波长明显小于上下文大小的维度(即,实验发现对于Llama模型,效果较好, 同样也是Deepseek V3的setting),这些维度被认为包含较多高频信息,采用线性插值,且插值比例为尺度因子。这种方式类似于PI方法,但避免了对高频信息的过度拉伸,从而减少高频细节的丢失。
- 低频维度( ) :当波长大于等于上下文大小(,对于Llama模型,效果较好,,这里同样也是Deepseek V3的setting)时,认为这些维度对绝对位置信息更敏感,因此不对这些维度进行插值,以保持绝对位置信息的完整性,避免因插值导致的位置信息混淆。
- 中间维度 :对于介于上述两种情况之间的维度,采用一种混合策略,通过引入一个 ramp 函数来确定插值程度。具体而言,这些维度的插值是在原始频率和拉伸后的频率之间进行线性插值,插值程度由决定。
根据上述策略,“NTK-by-parts”方法对RoPE的修改可以用以下公式表示: 定义,保持位置索引不变; ,根据维度的不同类别对频率参数进行相应的变换。其中,ramp函数定义为:
核心优势: 与之前的PI和“NTK-aware”插值方法相比,“NTK-by-parts”方法在处理RoPE维度时有更强的针对性。PI方法对所有维度同等插值,容易丢失高频信息;“NTK-aware”方法虽然尝试通过改变频率缩放方式来缓解问题,但会导致某些维度的外推,产生“越界”值,影响模型性能。而“NTK-by-parts”方法通过根据波长区分维度并采用不同插值策略,能够更好地平衡高频信息保留和位置关系理解,实验中可以表现的更好。
- Yarn
YaRN是基于NTK-aware方法的进一步拓展,通过结合温度缩放和NTK-by-parts插值技术,全面提升长文本外推能力。它核心解决的问题是线性内插导致的self-attention 点积的值增大。由于线性内插会改变旋转向量转动的幅度,原来距离较远的q,k点积由于旋转幅度变小,他们的点积结果会增大,进而导致Softmax操作过于“锐化”,使得注意力分布集中于少数位置,削弱模型对全局上下文的关注能力。 Yarn在 NTK-by-parts 基础上,引入注意力温度因子 来调整注意力分布:
优点 :
- 超低训练成本(0.1%预训练数据)。
- 几乎兼容目前所有主流的Transformer实现。
- 性能优越,无论是否微调均能在128k上下文中表现出色。
8 实验
最后放几张Yarn中的实验结果感受一下, Yarn无论在资源利用率还是128K长度性能上都超过其他PI, NTK 类方法, 无怪Yarn成为目前Long Context LLM的标配。
PS:看到这里,如果觉得不错,可以来个点赞 、在看 、关注 。 给公众号添加【星标⭐️】不迷路!您的支持是我坚持的最大动力!
欢迎多多关注公众号「NLP工作站」,加入交流群,交个朋友吧,一起学习,一起进步!