作者:王焱
链接:https://zhuanlan.zhihu.com/p/694825487
来源:知乎 (已授权)
0 背景
本篇文章是Long LLM系列的第二篇,内容是公开文章和团队三个月前的实验分析。(一些更多的内部实验信息,因为要奔着发论文去,所以就先不方便放出来)
核心想要探讨这么一个问题,RoPE出来也好几年了,但在LLM这块,仍没有强有力的竞争对手出现。
为什么?why RoPE?
会从四部分来做一个探讨。
第一,LM位置编码的发展历程
第二,long context的挑战是什么?
第三,我们观察到了什么现象?
第四,基于这些现象,我们来探讨,RoPE的优点是什么?或者说,好的位置编码应该具有那些要素?
1 LM位置编码的发展历程——从绝对到相对
从BERT开始,主流LM基本都以transformer为基础。
transformer核心是self-attention,捕捉token之间的依赖关系,效果很好。
代价是self-attention本身不带有位置信息,所以大家折腾了一堆位置编码来解决这个问题。
但前几年,搜广推主导市场,主流nlp任务怼着搜索query优化,百来字不到。很多长文本任务,也就几千字,上万字都罕见。
位置编码,当时偏学术探索多一些,整体发展流程是从绝对位置编码,到相对位置编码。
1.1 绝对位置编码
核心思路,对于位置i,找个pos(i)函数,跟位置i的向量V(i)做一个相加。
1.1.1 训练式
无脑把位置转成向量跟着训,大力出奇迹,跟V(i)相加,Bert的做法。
1.1.2 三角函数式
可以参考这个回答——三角函数做深了,会很自然的往相对位置去拓展。https://www.zhihu.com/question/347678607/answer/2301693596(本人四年前也写过一篇类似的,但有点老)
绝对位置编码一步步演化,是一个蛮有趣的过程。
第一步,用最简单的顺序数字做位置编码,但最大值过于影响结果,于是做归一化。
第二步,归一化后,发现同样的差两个字,长文本,短文本的差值不同,于是引入周期函数。
第三步,周期函数,如sin(x)就可以解决这个问题,但频率如何选择是个蛮麻烦的问题。
第四步,transformer为了解决这个问题,人工增加了多样性,不同维度不同波长,且sin,cos轮着来。
第五步,有人觉得第四步没有方向,又魔改了三角函数,加上了方向信息。
三角函数挖掘空间蛮大的,苏剑林也问了一个很有趣的问题,为什么这种方式没有发扬光大?
https://kexue.fm/archives/8231(苏剑林在这篇文章中,2021年,也早早的提出衰减)
1.2 相对位置编码
把绝对位置函数pos(i),改成pos(i,j),跟相对位置有关。
大家从不同的方向,都做了一些很有趣的探索,这里只挑几个代表快速讲一下。
1.2.1 基本款
Self-Attention with Relative Position Representations。
原版论文公式没有苏剑林这篇讲的清楚——https://spaces.ac.cn/archives/8130
这篇文章当时得出的一个好玩结论,绝对+相对位置都用上,不会带来效果的提升。
1.2.2 XLNet——moonshot老板做的
建议参看俊林的文章,比原始论文写的更清晰一些 https://zhuanlan.zhihu.com/p/70257427
不过这篇文章的相对位置编码的设计,是因为他预训练为了更长的长度,但资源是有限的,所以reuse the hidden status,在attention这里做了魔改。
会导致位置信息丢失,所以专门设计了一种位置编码来解决这个问题。
思路已经接近现在的版本答案了。
位置编码应该是服务于预训练的长度扩充,而不是说有了位置编码长度就能无限长。
1.2.3 Alibi
https://arxiv.org/pdf/2108.12409.pdf
通过矩阵来表达相对距离,简单明了,直接作用在softmax的偏置上。
论文自己评估起来比RoPE要好。(小transformer是的,但在LLM上不是
1.3 RoPE
这里有一个很有趣的事情,小transformer上,RoPE效果并没有想象中那么好(也就是Alibi实验结论,包括一些别的report,但LLM上,RoPE就特别work。
1.3.1 基本原理
如何把位置函数pos(i),改成pos(i,j),跟相对位置相关?
attention中,query跟序列key会挨个计算score,RoPE改的就是这里。
他的目标是找到一个公式满足如下等式。
query和key分别走位置函数f(x),得到新的向量的内积。等价于函数g(x),g(x)的输入是query和key的向量和相对位置信息。
二维条件下,满足上面条件的公式是这个(满足这个条件的公式肯定不止这一个,你有兴趣也可以自己找一个)
llama2的代码实现方式如下
query和key分别走了下位置函数f(x),后面他们内积算attention score的时候,就相当于有了相对位置信息的计算。
1.3.2 RoPE的rotate在哪里?
https://zhuanlan.zhihu.com/p/642884818
这篇文章的公式的推导比较清晰。
RoPE核心有那么几点,你会发现都是旋转
a 虚数的使用
https://www.ruanyifeng.com/blog/2012/09/imaginary\_number.html
用比较容易理解的话,虚数是一个旋转量的定义,非常方便的支持了旋转的计算。
b 欧拉公式
也算是某种旋转
c 棣莫弗公式
两个复数相乘,等于其旋转半径相乘, 旋转角度相加
复数相乘,转成极坐标表达的复数相乘,再变成角度的相加。
本身就类似于,一开始只有绝对位置信息,做了转换后,两个角度相加,相对位置信息就做了交互。
这个交互过程是通过旋转来实现的。
d 旋转矩阵
https://zhuanlan.zhihu.com/p/433389563
旋转矩阵就是,别的向量乘以它,就可以改变向量的方向,但不改变大小和手性。
e 三角函数
也是旋转
但吊诡的是,后面的实验分析,旋转好像并不是RoPE能work的核心要素。
1.3.3 二维拓展到N维
RoPE的公式成立仅限于二维,怎么拓展到N维呢?
因为query和key做的是内积,把向量两两分组,分别旋转,在做内积,彼此完全不影响。
这里为了做区分,每个位置旋转的角度不一样。
这留下来了极大的自定义空间。
1.3.4 RoPE为何成了经典款?
Bert时代,attention,位置编码,无监督学习,这三个对最后效果的贡献。
位置编码的收益,从上面的实验来看,提升不是特别大。
事实上也是如此,当年attention,无监督学习这俩组合出来的bert,改变的是整个生态。
位置编码的一系列优化,带来的提升并没有想象中那么大,所以这块大家这块很多时候也都是各自尝试,并没有一个经典款出来。
为什么,在LLM时代,RoPE成为了经典款呢?
个人认为, 跟long context的需求和挑战紧密相关。
2 long context的挑战是什么?
2.1 成本非线性增长
long context现在已经卷到了256k是标配。
7B 100K,硬train,几十张卡可能够,但70B 100K,显卡乘以10,真的不一定够。
显卡需求不是一个线性增长,300B,1000B的模型也都不断的在冒出来。
保证效果的前提下,用尽可能低的成本来扩充长度,是long context的挑战。
现在主流做法是泛化和优化组合,来一点点的把长度提升,也是下一篇笔记的内容了。
2.2 泛化(zero-shot/外推)
a)是什么
训练模型4k,但我推理的时候,能不能在20k,甚至50k上效果依然很好。
b)优化点
大部分操作都是基于位置编码做改动的,slide windows,甚至还有最近的nope。
2.3 优化(pretrain or finetuing)
a)是什么
泛化是有上限的,我们不得不在pretrain和finetuing的时候就把长度给变长。
b)优化点
但刚刚也提到了,硬train的成本不低。如何用相对低的成本,就能硬train一个比较长的长度?
2.4 泛化(外推)的局限性
我这里犯过一个错误。
attention因为其特性,天然是不带位置信息的,这个是不是导致attention外推效果不好的根源?
再进一步,如果我们把位置编码给搞好了,是不是就能外推到一个很不错的长度了?
再极端一点,像RNN这种天然带位置信息的,如RMKV,mamba,外推是不是更轻松了?
答案是否定的,ROPE和RNN的外推都比较有限。
为什么?
回答好这个问题,也就能明白,为什么ROPE能成为经典款了。
现在搞机器学习,有点像当年搞物理学的样子了。
我先观察到现象,然后找解释原因,这里也一样。
下面四点,是我们小团队,前段时间,自己做实验,看论文,观察到的一些现象。
3 我们观察到了什么?
注意,观察到的现象,类似于牛顿观察到苹果树上的苹果会往下掉落,而不是往上掉,这是客观存在的,不是我们假设的。
3.1 现象1——远程衰减
远程衰减基于一个很朴素的假设。
相对位置编码引入后,相对距离越远,相关性就越弱。
团队殷超专门针对衰减做了一些实验,具体参看这个实验链接
https://harmless-riverbed-d76.notion.site/Rope-0c872dcda68a4fc8bba96b8de8e55f5e
(相对位置虚数夹角的定义很重要,如果困惑了,建议看懂定义,再往后看)
得出了这么几个结论
3.1.1 embedding维度
维度和衰减曲线的平滑程度成正相关,维度越高,衰减曲线越平滑。
而llama2除以head后的维度就是128,从实验的图来看,波动还是相对较大。
所以,现在业内的通用head的维度并不是衰减平滑友好的。
3.1.2 base越大,衰减越慢
这也是为什么训练更长的窗口,要把base改大的原因。
3.1.3 query和key的相对位置虚数夹角
只要任意的query和key通过RoPE的引入的相对位置的复数夹角,保证在0-90度,那么就能始终保持不错的远程衰减。
而这些稳定的夹角往往是出现在充分训练的位置上。
没有充分训练的夹角往往不稳定,错误累计,就会导致整个ppl崩掉。
3.1.4 训练不充分的bad夹角会逐层累计
未充分训练过的query和key相对位置的虚数夹角,90-180度,transformer第一层有一些,但没那么多。
很快,随着层数的累计,这个占比就开始不断提升。
也就导致最后ppl直接崩掉。
3.1.5 NTK为何有效?
RoPE是向量每两个为一组,给不同的频率的角度,公式如下。
这个公式是单调递减的,随着j的增加,频率也就是递减的过程。
外推——可以理解为不做操作。
内插——即对目标位置等比例放缩到模型支持的位置处。比如模型最大支持 1000,现在需适配最大长度 10000 的输入,那么就将 10000 映射到 1000, 1000 映射到 100,位置 k 映射到 k/10
其实,内插有效也是理所当然的,刚刚的分析发现,没有充分训练过的地方,虚数夹角是不稳定的,很容易崩。
ntk的另外一个解释方式。
ntk是调整的是RoPE中的base,长度大于一定长度的时候,base增大。
也就是qwen代码做的事情。
而我们也发现了,base越大衰减越慢,所以现在业界的主流做法都是窗口边长后,base也要跟着变大做适配。
所以,未充分训练过的窗口,强行衰减变慢,本身也是降低崩的概率的一种方式。
3.1.6 最后一层位置信息的消失
实验发现,最后一层位置信息已经丢失,对于模型来讲已经没有位置信息这个东西了。
类似于人类学习一本书,理解到最后,只剩下知识点。
3.1.7 远程衰减的遗留问题
a) 衰减曲线过于平滑是合理的么?
衰减曲线波动过高肯定不好,但衰减曲线过于平滑呢?
对于论文来讲,开头的abstract和尾部的summary往往也是强相关的,小说的第一章跟第一百章也是有可能相关的。
b) 衰减速度多少比较合理?
衰减的越缓慢越好,特别是窗口特别长的话
衰减的越慢,代表了学习起来越难
所以,从这个角度来看,我们的窗口能无止尽的拓展长度么?
c) 支持衰减的函数有很多,什么样的函数是好的呢?
3.2 现象2——attention的分层化
别人实验的观察,我们自己实验的观察。(我们做的实验有一些敏感,预计晚点会放出来)
其实都不约而同的指向了一个结论,transformer不同层是不同的特征抽取层,越往上层抽取的特征就更加抽象,越底层抽取的特征就更加原始。
有点类似当年cnn做人脸识别,底层抽取的是线条,最后几层就变成了眼睛,眉毛这些。
以及,前面层和最后几层都很重要。
前段时间在LLaMafia群讨论的小总结——https://zhuanlan.zhihu.com/p/689015698
3.3 现象3——attention的集中化
如果移除intial tokens的KV,会导致整个句子崩掉,有很多种解释。
其中一种解释,垃圾桶解释说,initial tokens对全局可见,所以一些杂七杂八的信息都往这里放。
基于此,田渊栋推出了streaming LLM。
这种扩充长度的做法,大概率效果是比不过正规扩充长度的套路。
不过,我当时曾经想过,对于一些角色扮演类的对话,好像这种做法还蛮合适的,但业务gap很远,就没有去做一些常识。
这是一个很有趣的现象。
3.4 现象4——self-similarity
Fractal Patterns May Unravel the Intelligence in Next-Token Prediction
以及更加根源的一篇论文——a general theory of self-similarity(很遗憾,这篇纯数学论文,一开头就是狄金森分割,实分析,后面是拓扑理论,我们团队没有搞纯数学的,只能局限于此)
科研小团队招募——如果你的数学能力很强,上面的数学对你来讲很简单,想做点好玩的跟大模型相关的数学论文。如大模型的learning theory,为什么大模型能够work,请私信我,很缺这方向的人。
Self-Similarity,指的是一个对象或模式在不同的尺度或大小上都表现出相似的特性。换句话说,无论你如何放大或缩小这个对象,你都能看到相似的结构或模式。
而这篇论文从数学角度证明了,自然语言也是Self-Similarity的。
也验证了我去年的一个猜想。
2000字和5w字的论文,它们的结构是不是相似的?再进一步,人类的文本结构,是不是就那么几类?
语言模型如果学到了这几类结构,哪怕训练长度只有4k。
但对于10k,100k的文本,因为已经学到了此类结构,那么扩展起来也是相对轻松的。
即语言模型哪怕训练的只有4k,但基于语言的self-similarity特性,应该是已具有long-context能力。
进一步我们可以做一个猜测。
是不是transformer这种每次都是见全局的学习方式,天然能更好的学习文本结构知识。
而RNN反而因为是序列的,学不好这类的结构知识。
进一步的假设,transformer的外推比RNN的外推成本更低,更友好。
可以看到不同domain数据的Fractal Patterns信息是不同的,所以大家现在模型训练这样的数据划分方式也是有合理性的。
大家之前都是靠直觉来划分,这里直接给出了数学证明。
3.5 现象5——衰减的震荡
RoPE的远程衰减,只是衰减到零,不是衰减到负无穷,结果是在零附近震荡。
这个可能也是关键?但缺乏一个消融实验和更加合理的理论验证,后面有更完善的实验的话,会补充进来的。
这块感谢@苏剑林的提醒
4 why RoPE ? beyond RoPE ?
从观察到的现象,我们尝试做一些推理。
4.1 LLM大概率已有长文本能力
4.1.1 衰减的角度
崩的原因是因为没训练过的地方虚数夹角不稳定。
ntk这种做法把夹角压到稳定范围后,就开始有不错的外推能力了。
这说明模型大概率对长文本本身就有不错的认知了,只不过OOD了。
4.1.2 self-similarity的角度
数学上已经证明,自然语言是self-similarity
那么只要论证了LLM很好的学到了这种结构化信息,那长短文本对于LLM是没区别的。
所以,我们需要关注的是如何把已有的长文本能力给激活出来。
4.1.3 检索头
来自于最近挂出来的论文,https://arxiv.org/abs/2404.15574。
其中就发现检索头是天然存在于基础模型中,基于上下文激活不同的头部。这个跟self-similar的结论是非常类似的。
我们在做实验的时候,也观察到了类似的现象。
4.2 slide window的局限性
slide window的吸引力是很大的,slide window代表了训练和推理的成本有着巨大的压缩空间。
但从上面的现象,我们会发现单纯的slide window是有着巨大的问题的,所以大家加了一堆补丁来解决。
4.2.1 LLM本身已有长文本能力
slide window会把语义切割,而LLM本身已经学到了文本的结构信息,这种分割反而会导致语义信息的丢失。
苏剑林提出一个解决方案,就是前几层做window attention,最后一层做full attention。
https://zhuanlan.zhihu.com/p/630464155
这篇文章也给出了类似结论,全部都是slide window attention肯定是不行的。
4.2.2 衰减会丢失
衰减应该是连贯的,持续的。用slide window做切割,难道每个window一个衰减,不同的window之间的衰减怎么算?
分层+full attention看起来也能对这个有一些缓解。
4.2.3 attention的集中化
前几个token那么重要,一旦丢失,整个句子就会崩掉。slide window把最重要的token跟后面的tokens分割开了。
一种解决办法是,把初始化tokens,加到每个slide window里面。
从上面三点来看,slide window问题其实不少,需要不停的打补丁来解决这些问题。这会导致训练框架没法像transformer那样叠积木来快速出效果,对scaling law实在是太不友好了。
但Attention框架在long context的推理成本,kv cache压力实在是太大了,训练成本也是。
这个方向依然有巨大的吸引力。
4.3 RNN能work么?
mamba被reject的一个reason就是long context的评估不够好,号称1 million tokens,但审稿人觉得评估的不完善。
近期有人专门做了mamba的外推,https://github.com/jzhang38/LongMamba
评估发现,mamba的外推的确不尽如意,跟rmkv是差不多的。最后用内插的方式把mamba的长度推长了。
4.3.1 self-similar在RNN上能学好么?
self-similar的成立是低成本外推的关键,但RNN这种序列框架是不是在学习这个特性上,天然要比transformer差一些?
4.3.2 full-attention很重要
slide window也需要一个full attention,不然long context的依赖就是学不好。
检索头这篇论文也论证了这么一点。
从一些吐槽来看,RNN对关系建模的效果也的确是比不过transformer的。
4.3.3 select能替换衰减么?
mamba的外推能力也一般,这是不是也代表的确无法很好的替换?
所以,我们发现RNN,无损外推效果一般,关系建模效果一般,训练成本也不低。
最大的优点就是没有kv cache的限制,但正如上文所说,这个实在是太吸引人了。
但针对KV cache,硬件上有Groke这种硬件优化方案,KV cache的压缩也有人在努力做各种尝试。
感觉RNN需要加把劲了,如果业界把KV cache很快解决了,这个方向的吸引力会降低不少。
4.4 位置编码四要素
基于以上信息,我们可以推理出,好的位置编码应该满足四个要素。
4.4.1 衰减
带有相对位置信息,有衰减性
4.4.2 没有参数跟着更新
事实上,只要资源管够,完全可以像Bert,每个位置一个位置embedding,大力出奇迹。但之前也不停的在强调,成本,成本,成本。
而LLM大概率已经有长文本的能力了,只不过因为OOD等原因,没有被合适的激活而已。
一个不用更新参数的位置编码,代表我们可以用更低的成本来扩充长度,激活Long context能力。
4.4.3 高度可定制化
在LLM本身有长文本能力的情况下,会有各种各样的操作来激活这个能力,也是下一篇笔记要讲的事情。
而这个可定制化,就变得很重要了。
举个例子。
alibi不太比得过RoPE的一个原因,它的衰减太快了。RoPE其实在低base下,衰减也很快,但它能调啊。
以及,RoPE为了保证公式成立,是从二维推广到多维,也留下了不少可定制化空间。
4.4.4 信息含量高
我一直在想RoPE的虚数,欧拉等这些公式的使用。包含的信息量,是不是给位置编码带来一定的鲁棒性和可拓展性?
单纯的三角函数比不过RoPE的原因,是不是因为这个?
但这个就是直觉上的猜测了。
如果你能找到一个相对复杂的公式,能满足以上四要素。
会不会,有可能超过RoPE?
以及,RoPE在小的transformer上效果一般,但就是在LLM上很work。
假如RNN,slide window这两种方案真的搞出了transformer的替代品,那么这四要素可能也就变了。
蛮期待两年后这个方向的进展
