現(xiàn)在,眾多大型模型已開始支持長(zhǎng)文本的推理,如最新的 GPT4 Turbo 能處理超過 128k 的內(nèi)容,而 Baichuan2 也可應(yīng)對(duì)最長(zhǎng)為 192K 的文本。但受顯存資源約束,這些模型在訓(xùn)練時(shí)并不一定會(huì)處理如此長(zhǎng)的文本,其預(yù)訓(xùn)練階段通常僅涉及約 4k 的內(nèi)容。 ? 因此,如何在推理階段確保模型能處理遠(yuǎn)超預(yù)訓(xùn)練時(shí)的文本長(zhǎng)度,已成為當(dāng)前大型模型面臨的核心問題之一,我們將此問題視為大模型的外推性挑戰(zhàn)。 ? 而為了應(yīng)對(duì)這個(gè)挑戰(zhàn),最關(guān)鍵的地方就是如何優(yōu)化大模型的位置編碼。在之前的文章十分鐘讀懂旋轉(zhuǎn)編碼(RoPE)中,我們已經(jīng)介紹了目前應(yīng)用最廣的旋轉(zhuǎn)位置編碼 RoPE。 ?
然而,那篇文章并未涉及 RoPE 在外推性方面的表現(xiàn)以及如何優(yōu)化其外推性。恰好最近,我們組的同事在論文分享中進(jìn)一步探討了大模型位置編碼的相關(guān)內(nèi)容,其中包含一些我之前未曾接觸的新觀點(diǎn)。因此,本文旨在更全面地介紹位置編碼及其與外推性的關(guān)系。 ? 我們主要圍繞以下兩個(gè)問題展開: ? 1. RoPE 是如何實(shí)現(xiàn)相對(duì)位置編碼的?(如何想到的?) ? 2.?如何通過調(diào)整旋轉(zhuǎn)角(旋轉(zhuǎn)角 ),提升外推效果。
? 本文主要有以下幾個(gè)結(jié)論: ? 1. 雖然 RoPE 理論上可以編碼任意長(zhǎng)度的絕對(duì)位置信息,但是實(shí)驗(yàn)發(fā)現(xiàn) RoPE 仍然存在外推問題,即測(cè)試長(zhǎng)度超過訓(xùn)練長(zhǎng)度之后,模型的效果會(huì)有顯著的崩壞,具體表現(xiàn)為困惑度(Perplexity,PPL)等指標(biāo)顯著上升。 ? 2. RoPE 做了線性內(nèi)插(縮放位置索引,將位置 m 修改為 m/k)修改后,通常都需要微調(diào)訓(xùn)練。 ? 3. 雖然外推方案也可以微調(diào),但是內(nèi)插方案微調(diào)所需要的步數(shù)要少得多。 ? 4. NTK-Aware Scaled RoPE 非線性內(nèi)插,是對(duì) base 進(jìn)行修改(base 變成 )。 ?
5. NTK-Aware Scaled RoPE 在不微調(diào)的情況下,就能取得不錯(cuò)的外推效果。(訓(xùn)練 2048 長(zhǎng)度的文本,就能在較低 PPL 情況下,外推 8k 左右的長(zhǎng)文本) ? 6. RoPE 的構(gòu)造可以視為一種 進(jìn)制編碼,在這個(gè)視角之下,NTK-aware Scaled RoPE 可以理解為對(duì)進(jìn)制編碼的不同擴(kuò)增方式(擴(kuò)大 k 倍表示范圍 L->k*L,那么原本 RoPE 的 β 進(jìn)制至少要擴(kuò)大成 進(jìn)制)。
絕對(duì)位置編碼
我們先來回顧一下絕對(duì)位置編碼的問題。絕對(duì)位置編碼通過可學(xué)習(xí)的 Positional Embedding 來編碼位置信息,這種方案直接對(duì)不同的位置隨機(jī)初始化一個(gè) postion embedding,然后與 word embedding 相加后輸入模型。postion embedding 作為模型參數(shù)的一部分,在訓(xùn)練過程中進(jìn)行更新。比如下面是絕對(duì)位置編碼的實(shí)現(xiàn):
#?初始化
self.position_embeddings?=?nn.Embedding(config.max_position_embeddings,?config.hidden_size)
#?計(jì)算
position_embeddings?=?self.position_embeddings(position_ids)
embeddings?+=?position_embeddings
對(duì)絕對(duì)位置編碼進(jìn)行可視化,如下圖所示:
▲ 圖1-1 絕對(duì)位置編碼可視化 ? 可以看到每個(gè)位置都會(huì)被區(qū)分開,并且相鄰的位置比較接近。這個(gè)方案的問題也非常明顯,不具備外推的性質(zhì)。長(zhǎng)度在預(yù)設(shè)定好之后就被固定了。 ? ? ?
正弦編碼(Sinusoidal)
基于 Sinusoidal 的位置編碼最初是由谷歌在論文 Attention is All You Need 中提出的方案,用于 Transformer 的位置編碼。具體計(jì)算方式如下所示: 其中 pos 是位置,i 表示維度。 ? 看起來是通過 sin 和cos函數(shù)將位置編碼的取值固定在了 [-1, 1] 之前,但是為什么不用線性函數(shù)?而且這里面的10000是怎么想到的? ? 谷歌在論文里面給出了解釋: ?
具有相對(duì)位置表達(dá)能力:Sinusoidal 可以學(xué)習(xí)到相對(duì)位置,對(duì)于固定位置距離的 k,PE(i+k) 可以表示成 PE(i) 的線性函數(shù)。
兩個(gè)位置向量的內(nèi)積只和相對(duì)位置 k 有關(guān)。
Sinusoidal 編碼具有對(duì)稱性。
隨著 k 的增加,內(nèi)積的結(jié)果會(huì)直接減少,即會(huì)存在遠(yuǎn)程衰減。
下面我們來分析一下為什么會(huì)有上面四點(diǎn)結(jié)論。
2.1 相對(duì)位置表達(dá)能力
Sinusoidal 可以學(xué)習(xí)到相對(duì)位置,對(duì)于固定位置距離的 k,PE(i+k) 可以表示成 PE(i) 的線性函數(shù)。證明如下:
其中 u, v 為關(guān)于 k 的常數(shù),所以可以證明 PE(i+k) 可以由 PE(i) 線性表示。?
2.2 內(nèi)積只和相對(duì)位置k有關(guān)
Attention 中的重要操作就是內(nèi)積。計(jì)算兩個(gè)位置的內(nèi)積 PE(t+k)PE(t) 如下所示:
可以看到,最終的結(jié)果是關(guān)于 k 的一個(gè)常數(shù)。這表明兩個(gè)位置向量的內(nèi)積只和相對(duì)位置 k 有關(guān)。 ? 通過計(jì)算,很容易得到 PE(t+k)PE(t) = PE(t)PE(t-k),這表明 Sinusoidal 編碼具有對(duì)稱性。
2.3 遠(yuǎn)程衰減
可以發(fā)現(xiàn),隨著 k 的增加,位置向量的內(nèi)積結(jié)果會(huì)逐漸降低,即會(huì)存在遠(yuǎn)程衰減。如下圖所示:
▲ 圖2-1 隨著相對(duì)距離 k 的增加,位置向量?jī)?nèi)積 PE(t)PE(t+k) 逐漸降低
2.4 為什么選擇參數(shù)base=10000
選擇 sin,cos 是因?yàn)榭梢员磉_(dá)相對(duì)位置,以及具備遠(yuǎn)程衰減。但是 sin/cos 里面的參數(shù) 10000 是如何來的? ? 這里可以從 sin/cos 的周期性角度進(jìn)行分析。分析周期可以發(fā)現(xiàn),維度i的周期為 ,其中 0<=i
▲ 圖2-2 不同 base 下的 position embedding 取值 ? 可以看到隨著 base 的變大,周期會(huì)明顯變長(zhǎng)。Transformer 選擇比較大的 base=10000,可能是為了能更好的區(qū)分開每個(gè)位置。 ? 備注:解釋下為什么周期大能更好區(qū)分位置 ? 從圖 2-2 可以看出,base 越大,周期越大。而周期越大,在 position 從 0~100 范圍內(nèi),只覆蓋了不到半個(gè)周期,這使得重復(fù)值少;而周期小的,覆蓋了多個(gè)周期,就導(dǎo)致不同位置有大量重復(fù)的值。
2.5 正弦編碼是否真的具備外推性?
在前面的圖 2-1 中,似乎 Sinusoidal 只和相對(duì)位置有關(guān)。但是實(shí)際的 Attention 計(jì)算中還需要與 attention 的權(quán)重 W 相乘,即 ,這時(shí)候內(nèi)積的結(jié)果就不能反映相對(duì)距離,如下圖所示:
▲ 圖2-3 真實(shí)的 q,k 向量?jī)?nèi)積和相對(duì)距離之間,沒有遠(yuǎn)程衰減性
旋轉(zhuǎn)位置編碼(RoPE)
3.1 什么是好的位置編碼
既然前面的絕對(duì)位置編碼和 Sinusoidal 編碼都不是好的位置編碼,那么什么才是好的位置編碼? ? 理想情況下,一個(gè)好的位置編碼應(yīng)該滿足以下條件: ?
每個(gè)位置輸出一個(gè)唯一的編碼
具備良好的外推性
任何位置之間的相對(duì)距離在不同長(zhǎng)度的句子中應(yīng)該是一致的
這兩條比較好理解,最后一條是指如果兩個(gè) token 在句子 1 中的相對(duì)距離為 k,在句子 2 中的相對(duì)距離也是 k,那么這兩個(gè)句子中,兩個(gè) token 之間的相關(guān)性應(yīng)該是一致的,也就是 attention_sample1 (token1, token2) = attention_sample2 (token1, token2)。
▲ 圖3-1 平移性 ? 而 RoPE 正是為了解決上面三個(gè)問題而提出的。
3.2 RoPE如何解決內(nèi)積只和相對(duì)位置有關(guān)
RoPE 旋轉(zhuǎn)位置編碼是蘇神在論文 RoFormer 中提出的,也是目前大模型廣泛采用的一種位置編碼方式。這種編碼不是作用在 embedding 的輸入層,而是作用在與 Attention 的計(jì)算中。 ? 假設(shè)位置 m 的位置編碼為 ,位置 n 的位置編碼為 ,如果使用之前的絕對(duì)位置編碼方式,那么兩個(gè)位置之間的 attention 可以表示為: 后面的三項(xiàng)都是和絕對(duì)位置位置 m,n 有關(guān),無法表示成 m-n 的形式。 ? 因此,我們需要找到一種位置編碼,使得公式(6)表示為如下的形式: 接下來的目標(biāo)就是找到一個(gè)等價(jià)的位置編碼方式,從而使得上述關(guān)系成立。 ? 假定現(xiàn)在詞嵌入向量的維度是兩維 d=2,這樣就可以利用上 2 維度平面上的向量的幾何性質(zhì),然后論文中提出了一個(gè)滿足上述關(guān)系的 f 和 g 的形式如下: 這里面 Re 表示復(fù)數(shù)的實(shí)部。 ? 進(jìn)一步地, 可以表示成下面的式子:
其中 表示位置 m 的旋轉(zhuǎn)矩陣。 ? 將 d=2 擴(kuò)展到多維,旋轉(zhuǎn)矩陣表示如下: 總結(jié)來說,RoPE 的 self-attention 操作的流程是:對(duì)于 token 序列中的每個(gè)詞嵌入向量,首先計(jì)算其對(duì)應(yīng)的 query 和 key 向量,然后對(duì)每個(gè) token 位置都計(jì)算對(duì)應(yīng)的旋轉(zhuǎn)位置編碼,接著對(duì)每個(gè) token 位置的 query 和 key 向量的元素按照兩兩一組應(yīng)用旋轉(zhuǎn)變換,最后再計(jì)算 query 和 key 之間的內(nèi)積得到 self-attention 的計(jì)算結(jié)果。 ? RoPE 為什么會(huì)想到用 進(jìn)行位置編碼?來看一下蘇神現(xiàn)身說法(相乘后可以表達(dá)成差的形式,所以可能可以實(shí)現(xiàn)相對(duì)位置編碼):
▲ 圖3-2 為什么 RoPE?選擇 方式進(jìn)行位置編碼
3.3 RoPE的遠(yuǎn)程衰減
▲ 圖3-3 RoPE 的遠(yuǎn)程衰減 ? 從圖中我們可以看到隨著相對(duì)距離的變大,內(nèi)積結(jié)果有衰減趨勢(shì)的出現(xiàn)。因此,選擇 ,確實(shí)能帶來一定的遠(yuǎn)程衰減性。論文中還試過以 為初始化,將 視為可訓(xùn)練參數(shù),然后訓(xùn)練一段時(shí)間后發(fā)現(xiàn) 并沒有顯著更新,因此干脆就直接固定 了。 ? ? ?
調(diào)整旋轉(zhuǎn)角提升外推效果
雖然 RoPE 理論上可以編碼任意長(zhǎng)度的絕對(duì)位置信息,并且 sin/cos 計(jì)算就能將任意長(zhǎng)度的相對(duì)位置信息表達(dá)出來,但是實(shí)驗(yàn)發(fā)現(xiàn) RoPE 仍然存在外推問題,即測(cè)試長(zhǎng)度超過訓(xùn)練長(zhǎng)度之后,模型的效果會(huì)有顯著的崩壞,具體表現(xiàn)為困惑度(Perplexity,PPL)等指標(biāo)顯著上升。 ? 對(duì)此,就有很多人提出了如何擴(kuò)展 LLM 的 Context 長(zhǎng)度,比如有人實(shí)驗(yàn)了“位置線性內(nèi)插”的方案,顯示通過非常少的長(zhǎng)文本微調(diào),就可以讓已有的 LLM 處理長(zhǎng)文本。 ? 幾乎同時(shí),Meta 也提出了同樣的思路,在論文 Extending Context Window of Large Language Models via Positional Interpolation 中提出了位置線性內(nèi)插(Position Interpolation,PI)。 ? 隨后,又有人提出了 NTK-aware Scaled RoPE,實(shí)現(xiàn)了不用微調(diào)就可以擴(kuò)展 Context 長(zhǎng)度的效果。 ? 從 Sinusoidal 編碼到旋轉(zhuǎn)位置編碼 RoPE, 的取值一直都是 ,也就是base = 10000。而最新的位置線性內(nèi)插和 NTK 都打破了這一傳統(tǒng)。
4.1 位置線性內(nèi)插(Position Interpolation,PI)
傳統(tǒng)的 RoPE 算法在超出最大距離后,PPL 就會(huì)爆炸,因此直接推廣的效果一定是很差的,因此 Position Interpolation 繞過了推廣的限制,通過內(nèi)插的方法,如下圖所示。
▲ 圖4-1 RoPE 位置線性內(nèi)插(base 和位置線性內(nèi)插的效果對(duì)比)
圖 4-1 是關(guān)于“位置線性內(nèi)插(Position Interpolation)”方法的圖示說明。對(duì)于預(yù)訓(xùn)練 2048 長(zhǎng)度,外推 4096 長(zhǎng)度: ? 左上角圖示:
這部分是 LLM 預(yù)訓(xùn)練的長(zhǎng)度。
藍(lán)色點(diǎn)代表輸入的位置索引,它們都在 0 到 2048 的范圍內(nèi),即預(yù)訓(xùn)練范圍內(nèi)。
這意味著給模型提供的輸入序列長(zhǎng)度沒有超過它預(yù)訓(xùn)練時(shí)的最大長(zhǎng)度。
右上角圖示:
這部分展示了所謂的“長(zhǎng)度外推”(Extrapolation)情況。
在這種情況下,模型被要求處理位置索引超出 2048 的情況,直到 4096(由紅色點(diǎn)表示)。
這些位置對(duì)于模型來說是“未見過的”,因?yàn)樵陬A(yù)訓(xùn)練時(shí)它們并沒有涉及。
當(dāng)模型遇到這種更長(zhǎng)的輸入序列時(shí),其性能可能會(huì)受到影響,因?yàn)樗鼪]有被優(yōu)化來處理這種情況。
左下角圖示:
這部分展示了“位置線性內(nèi)插”方法的應(yīng)用。
為了解決模型處理更長(zhǎng)序列時(shí)的問題,研究者們提出了一個(gè)策略:將位置索引本身進(jìn)行下采樣或縮放。
具體來說,他們將原本在 [0, 4096] 范圍內(nèi)索引(由藍(lán)色和綠色點(diǎn)表示)縮放到 [0, 2048] 的范圍內(nèi)。
通過這種方式,所有的位置索引都被映射回了模型預(yù)訓(xùn)練時(shí)的范圍內(nèi),從而幫助模型更好地處理這些原本超出其處理能力的輸入序列。
我們?cè)倥e一個(gè)例子,base=10000,d=2048,對(duì)于 token embedding 第 2000 維,RoPE 為:
base?=?10000
▲ 圖4-2 RoPE位置編碼 ? 從圖 4-2 可以看出,在外推(Extrapolation)時(shí),紅色點(diǎn)超出了預(yù)訓(xùn)練時(shí)的位置編碼。 ? 為了解決這個(gè)問題,位置線性內(nèi)插的核心思想是通過縮放位置索引,使得模型能夠處理比預(yù)訓(xùn)練時(shí)更長(zhǎng)的序列,而不損失太多性能。 其中 x 是 token embedding,m 是位置。對(duì)于一個(gè)超過之前最大長(zhǎng)度 L 的樣本(長(zhǎng)度為 L’),通過縮放將所有位置映射回 L 區(qū)間,每個(gè)位置都不再是整數(shù)。通過這種方式在長(zhǎng)樣本區(qū)間訓(xùn)練 1000 步,就能很好的應(yīng)用到長(zhǎng)樣本上。 ? 我們看一下新的位置編碼后,設(shè)?,內(nèi)積可以表示為: 其中 可以表示為 , 中的“*”表示共軛,可以表示為 。這里面 可以改寫為:
由于 ,因此相當(dāng)于是擴(kuò)大了 base,縮小了 。 從小到大對(duì)應(yīng)低頻到高頻的不同特征(周期 ,頻率 )。 ? 下面是實(shí)驗(yàn)結(jié)果:
▲ 圖4-3 微調(diào)少量長(zhǎng)文本,位置線性內(nèi)插就能推理長(zhǎng)文本 ? 從圖 4-2 可以看出,使用 10000 條樣本,直接進(jìn)行微調(diào)長(zhǎng)度為 8192 的文本,外推長(zhǎng)度只能到 2560;而只用 1000 條樣本,在微調(diào)中使用位置線性內(nèi)插,外推長(zhǎng)度就可以達(dá)到 8192。
4.2 NTK-Aware Scaled RoPE
位置線性內(nèi)插雖然效果不錯(cuò),但是插值方法是線性的,這種方法在處理相近的 token 時(shí)可能無法準(zhǔn)確區(qū)分它們的順序和位置。因此,研究者提出了一種非線性的插值方案,它改變 RoPE 的 base 而不是比例,從而改變每個(gè) RoPE 維度向量與下一個(gè)向量的“旋轉(zhuǎn)”速度。 ? 由于它不直接縮放傅里葉特征,因此即使在極端情況下(例如拉伸 100 萬倍,相當(dāng)于 20 億的上下文大?。?,所有位置都可以完美區(qū)分。 ? 新的方法被稱為 “NTK-Aware Scaled RoPE”,它允許 LLaMA 模型在無需任何微調(diào)且困惑度降低到最小的情況下擴(kuò)展上下文長(zhǎng)度。這種方法基于 Neural Tangent Kernel(NTK)理論和 RoPE 插值進(jìn)行改進(jìn)。 ? NTK-Aware Scaled RoPE 在 LLaMA 7B(Context 大小為 2048)模型上進(jìn)行了實(shí)驗(yàn)驗(yàn)證,結(jié)果表明在不需要對(duì) 4096 Context 進(jìn)行微調(diào)的情況下,困惑度可以降低到非常小。 ? NTK-Aware Scaled RoPE 的計(jì)算非常簡(jiǎn)單,如下所示:
可以看到,公式(15)只是對(duì) base 進(jìn)行了放大,但是實(shí)驗(yàn)效果卻非常好。為什么會(huì)取得這樣的效果? ? 為了解開這個(gè)謎底,我們需要理解 RoPE 的構(gòu)造可以視為一種 進(jìn)制編碼,在這個(gè)視角之下,NTK-aware Scaled RoPE 可以理解為對(duì)進(jìn)制編碼的不同擴(kuò)增方式。
4.2.1 進(jìn)制表示 假設(shè)我們有一個(gè) 1000 以內(nèi)(不包含 1000)的整數(shù) n 要作為條件輸入到模型中,那么要以哪種方式比較好呢? ? 最樸素的想法是直接作為一維浮點(diǎn)向量輸入,然而 0~999 這涉及到近千的跨度,對(duì)基于梯度的優(yōu)化器來說并不容易優(yōu)化得動(dòng)。那縮放到 0~1 之間呢?也不大好,因?yàn)榇藭r(shí)相鄰的差距從 1 變成了 0.001,模型和優(yōu)化器都不容易分辨相鄰的數(shù)字。總的來說,基于梯度的優(yōu)化器只能處理好不大不小的輸入,太大太小都容易出問題。 ? 所以,為了避免這個(gè)問題,我們還需要繼續(xù)構(gòu)思新的輸入方式。在不知道如何讓機(jī)器來處理時(shí),我們不妨想想人是怎么處理呢。對(duì)于一個(gè)整數(shù),比如 759,這是一個(gè) 10 進(jìn)制的三位數(shù),每位數(shù)字是 0~9。 ? 既然我們自己都是用 10 進(jìn)制來表示數(shù)字的,為什么不直接將 10 進(jìn)制表示直接輸入模型呢?也就是說,我們將整數(shù)n以一個(gè)三維向量 [a,b,c] 來輸入,a,b,c 分別是n的百位、十位、個(gè)位。這樣,我們既縮小了數(shù)字的跨度,又沒有縮小相鄰數(shù)字的差距,代價(jià)是增加了輸入的維度——?jiǎng)偤茫?a href="http://wenjunhu.com/tags/神經(jīng)網(wǎng)絡(luò)/" target="_blank">神經(jīng)網(wǎng)絡(luò)擅長(zhǎng)處理高維數(shù)據(jù)。 ? 如果想要進(jìn)一步縮小數(shù)字的跨度,我們還可以進(jìn)一步縮小進(jìn)制的基數(shù),如使用 8 進(jìn)制、6 進(jìn)制甚至 2 進(jìn)制,代價(jià)是進(jìn)一步增加輸入的維度。
4.2.2 直接外推 假設(shè)我們還是用三維 10 進(jìn)制表示訓(xùn)練了模型,模型效果還不錯(cuò)。然后突然來了個(gè)新需求,將 n 上限增加到 2000 以內(nèi),那么該如何處理呢? ? 如果還是用 10 進(jìn)制表示的向量輸入到模型,那么此時(shí)的輸入就是一個(gè)四維向量了。然而,原本的模型是針對(duì)三維向量設(shè)計(jì)和訓(xùn)練的,所以新增一個(gè)維度后,模型就無法處理了。有一種方法是提前預(yù)留好足夠多的維度,訓(xùn)練階段設(shè)為 0,推理階段直接改為其他數(shù)字,這就是外推(Extrapolation)。 ▲ 圖4-4 直接外推 ? 然而,訓(xùn)練階段預(yù)留的維度一直是 0,如果推理階段改為其他數(shù)字,效果不見得會(huì)好,因?yàn)槟P蛯?duì)沒被訓(xùn)練過的情況不一定具有適應(yīng)能力。也就是說,由于某些維度的訓(xùn)練數(shù)據(jù)不充分,所以直接進(jìn)行外推通常會(huì)導(dǎo)致模型的性能嚴(yán)重下降。 4.2.3 線性內(nèi)插 于是,有人想到了將外推改為內(nèi)插(Interpolation),簡(jiǎn)單來說就是將 2000 以內(nèi)壓縮到 1000 以內(nèi),比如通過除以 2,1749 就變成了 874.5,然后轉(zhuǎn)為三維向量 [8,7,4.5] 輸入到原來的模型中。從絕對(duì)數(shù)值來看,新的 [7,4,9] 實(shí)際上對(duì)應(yīng)的是1498,是原本對(duì)應(yīng)的 2 倍,映射方式不一致;從相對(duì)數(shù)值來看,原本相鄰數(shù)字的差距為 1,現(xiàn)在是 0.5,最后一個(gè)維度更加“擁擠”。 ? 所以,做了內(nèi)插修改后,通常都需要微調(diào)訓(xùn)練,以便模型重新適應(yīng)擁擠的映射關(guān)系。
▲ 位置線性內(nèi)插 ? 當(dāng)然,外推方案也可以微調(diào),但是內(nèi)插方案微調(diào)所需要的步數(shù)要少得多,因?yàn)楹芏鄨?chǎng)景(比如位置編碼)下,相對(duì)大小(或許說序信息)更加重要,換句話說模型只需要知道 874.5 比 874 大就行了,不需要知道它實(shí)際代表什么多大的數(shù)字。而原本模型已經(jīng)學(xué)會(huì)了 875 比 874 大,加之模型本身有一定的泛化能力,所以再多學(xué)一個(gè) 874.5 比 874 大不會(huì)太難。 ? 不過,內(nèi)插方案也不盡完美,當(dāng)處理范圍進(jìn)一步增大時(shí),相鄰差異則更小,并且這個(gè)相鄰差異變小集中在個(gè)位數(shù),剩下的百位、十位,還是保留了相鄰差異為 1。換句話說,內(nèi)插方法使得不同維度的分布情況不一樣,每個(gè)維度變得不對(duì)等起來,模型進(jìn)一步學(xué)習(xí)難度也更大。 4.2.4 進(jìn)制轉(zhuǎn)換 有沒有不用新增維度,又能保持相鄰差距的方案呢? ? 有,就是進(jìn)制轉(zhuǎn)換。三個(gè)數(shù)字的 10 進(jìn)制編碼可以表示 0~999,如果是 16 進(jìn)制呢?它最大可以表示 。所以,只需要轉(zhuǎn)到 16 進(jìn)制,如 1749 變?yōu)?[6,13,5],那么三維向量就可以覆蓋目標(biāo)范圍,代價(jià)是每個(gè)維度的數(shù)字從 0~9 變?yōu)?0~15。
▲ 圖4-5 進(jìn)制轉(zhuǎn)換 ? ? 剛才說到,我們關(guān)心的場(chǎng)景主要利用序信息,原來訓(xùn)練好的模型已經(jīng)學(xué)會(huì)了 875 > 874,而在 16 進(jìn)制下同樣有 875 > 874,比較規(guī)則是一模一樣的(模型根本不知道你輸入的是多少進(jìn)制)。 ? 唯一擔(dān)心的是每個(gè)維度超過 9 之后(10~15)模型還能不能正常比較,但事實(shí)上一般模型也有一定的泛化能力,所以每個(gè)維度稍微往外推一些是沒問題的。所以,這個(gè)轉(zhuǎn)換進(jìn)制的思路,甚至可能不微調(diào)原來模型也有效!另外,為了進(jìn)一步縮窄外推范圍,我們還可以換用更小的 進(jìn)制而不是 16 進(jìn)制。 ? 接下來我們將會(huì)看到,這個(gè)進(jìn)制轉(zhuǎn)換的思想,實(shí)際上就對(duì)應(yīng)著前面的 NTK-aware scaled RoPE。 4.2.5 位置編碼 為了建立起它們的聯(lián)系,我們先要建立如下結(jié)果: ? ?
位置 n 的旋轉(zhuǎn)位置編碼(RoPE),本質(zhì)上就是數(shù)字 n 的 β 進(jìn)制編碼
看上去可能讓人意外,因?yàn)閮烧弑砻嫔襄娜徊煌?。但事?shí)上,兩者的運(yùn)算有著相同的關(guān)鍵性質(zhì)。為了理解這一點(diǎn),我們首先回憶一個(gè) 10 進(jìn)制的數(shù)字 n,我們想要求它的 β 進(jìn)制表示的(從右往左數(shù))第 m 位數(shù)字,方法是: 也就是先除以 次方,然后求模(余數(shù))。然后再來回憶 RoPE,它的構(gòu)造基礎(chǔ)是 Sinusoidal 位置編碼,可以改寫為:
對(duì)比公式(16)和(17),兩者都有相同的 ,并且 mod,cos,sin 都是周期函數(shù)。所以,除掉取整函數(shù)這個(gè)無關(guān)緊要的差異外,RoPE/Sinusoidal 位置編碼類比為位置 n 的 進(jìn)制編碼。 ? 建立起這個(gè)聯(lián)系后,直接外推方案就是啥也不改,位置線性內(nèi)插就是將 n 換成 n/k,其中 k 是要擴(kuò)大的倍數(shù),這就是 Meta 的論文所實(shí)驗(yàn)的 Positional Interpolation,里邊的實(shí)驗(yàn)結(jié)果也證明了外推比內(nèi)插確實(shí)需要更多的微調(diào)步數(shù)。 ? 至于進(jìn)制轉(zhuǎn)換,就是要擴(kuò)大 k 倍表示范圍,那么原本的 β 進(jìn)制至少要擴(kuò)大成 進(jìn)制(公式(17)雖然是 d 維向量,但 cos,sin 是成對(duì)出現(xiàn)的,所以相當(dāng)于 d/2 位 進(jìn)制表示,因此要開 d/2 次方而不是 d 次方),或者等價(jià)地原來的底數(shù) 10000 換成 10000k,這基本上就是 NTK-aware Scaled RoPE。 ? 跟前面討論的一樣,由于位置編碼更依賴于序信息,而進(jìn)制轉(zhuǎn)換基本不改變序的比較規(guī)則,所以 NTK-aware Scaled RoPE 在不微調(diào)的情況下,也能在更長(zhǎng) Context 上取得不錯(cuò)的效果。 4.2.6 NTK-Aware Scaled RoPE和RoPE β進(jìn)制的關(guān)系 所以,這跟 NTK 有什么關(guān)系呢?NTK 全稱是 “Neural Tangent Kernel”,具體原理可以參考《從動(dòng)力學(xué)角度看優(yōu)化算法:SGD ≈ SVM?》。 ? 要說上述結(jié)果跟 NTK 的關(guān)系,更多的是提出者的學(xué)術(shù)背景緣故,提出者對(duì)《Fourier Features Let Networks Learn High Frequency Functions in Low Dimensional Domains》等結(jié)果比較熟悉,里邊利用 NTK 相關(guān)結(jié)果證明了神經(jīng)網(wǎng)絡(luò)無法直接學(xué)習(xí)高頻信號(hào),解決辦法是要將它轉(zhuǎn)化為 Fourier 特征——其形式就跟公式(17)的 Sinusoidal 位置編碼差不多。 ? 所以,提出者基于 NTK 相關(guān)結(jié)果的直覺,推導(dǎo)了 NTK-aware Scaled RoPE。假設(shè)要擴(kuò)大 k 倍范圍表示,根據(jù) NTK-Aware Scaled RoPE,高頻外推、低頻內(nèi)插。具體來說,公式(17)最低頻是 ,引入?yún)?shù) 變?yōu)?,讓他與內(nèi)插一致,即: 那么得到 。至于最高頻是 項(xiàng),引入 變?yōu)?,由于 d 很大,,所以它還是接近于初始值 ,等價(jià)于外推。 ? 所以這樣的方案簡(jiǎn)單巧妙地將外推和內(nèi)插結(jié)合了起來。另外,由于 d 比較大,因此 跟 差別不大,所以它跟前面基于進(jìn)制思想提出的解 是基本一致的。還有,從提出者這個(gè)思想來看,任意能實(shí)現(xiàn)“高頻外推、低頻內(nèi)插”的方案都是可以的,并非只有上述引入 的方案。 ? 如果從前面的進(jìn)制轉(zhuǎn)換的角度分析,直接外推會(huì)將外推壓力集中在“高位(m 較大)”上,而位置內(nèi)插則會(huì)將“低位(m 較小)”的表示變得更加稠密,不利于區(qū)分相對(duì)距離。而 NTK-aware Scaled RoPE 其實(shí)就是進(jìn)制轉(zhuǎn)換,它將外推壓力平攤到每一位上,并且保持相鄰間隔不變,這些特性對(duì)明顯更傾向于依賴相對(duì)位置的 LLM 來說是非常友好和關(guān)鍵的,所以它可以不微調(diào)也能實(shí)現(xiàn)一定的效果。 ? 從公式(17)可以看出,cos,sin 事實(shí)上是一個(gè)整體,所以它實(shí)際只有 d/2 位,也就是說它相當(dāng)于位置 n 的 d/2 位 進(jìn)制。如果我們要擴(kuò)展到 k 倍 Context,就需要將 進(jìn)制轉(zhuǎn)換為 進(jìn)制,那么 應(yīng)該滿足: 所以可以取 。 ? 于是新的 RoPE 變?yōu)椋? 這樣就從 進(jìn)制的思路解釋了 NTK-RoPE 的原理。 ? 下面我們看一下位置插值和 NTK-Aware Scaled RoPE 的實(shí)驗(yàn)效果:
▲ 圖4-6 不同插值方法的效果(這里的 scale 是指位置插值中擴(kuò)大的倍數(shù) k,alpha 是指 NTK 中的 lambda 參數(shù)或者是公式(15)中的 alpha 參數(shù))
從圖中可以看出在 時(shí),NTK 可以在比較小的 PPL 情況下,外推 8k 左右的長(zhǎng)文本。 ? 再看一下蘇神的實(shí)驗(yàn)結(jié)論(表中的數(shù)據(jù)表示準(zhǔn)確率),當(dāng) k=8 時(shí),結(jié)論如下:
上面的結(jié)論是沒有經(jīng)過長(zhǎng)文本微調(diào)的結(jié)果,其中 Baseline 就是外推,PI(Positional Interpolation)就是 Baseline 基礎(chǔ)上改內(nèi)插,NTK-RoPE 就是 Baseline 基礎(chǔ)上改 NTK-aware Scaled RoPE。 ? 從表中我們得出以下結(jié)論: ?
1、直接外推的效果不大行
2、內(nèi)插如果不微調(diào),效果也很差
3、NTK-RoPE 不微調(diào)就取得了不錯(cuò)的外推結(jié)果 ? ? ?
總結(jié)
目前大模型處理長(zhǎng)文本的能力成為研究的熱點(diǎn),由于收集長(zhǎng)文本的語料非常的困難,因此如何不用微調(diào)或者少量微調(diào),就能外推 k 倍的長(zhǎng)文本,成為大家的關(guān)注的焦點(diǎn)。 ? 本文詳細(xì)介紹了 Meta 的位置線性內(nèi)插和 NTK 兩種優(yōu)化外推的方法,結(jié)合蘇神對(duì) RoPE 解釋為一種 進(jìn)制編碼,那么位置線性內(nèi)插和 NTK 都可以理解為對(duì)進(jìn)制編碼的不同擴(kuò)增方式。 ?
審核編輯:黃飛
?
i?=?2000
d?=?4096
pos?=?list(range(1,?2049))
w?=?math.pow(base,?-i/d)
v?=?np.array([math.cos(p?*?w)?for?p?in?pos])
index?=?sorted(random.sample(pos,?15))
#?繪制曲線??
plt.figure(figsize=(10,?4))??#?創(chuàng)建一個(gè)新的圖形??
plt.scatter([pos[-1]],?[v[-1]])
index_to_highlight?=?-1????
#?添加注釋顯示坐標(biāo)值??
plt.annotate(f'({pos[index_to_highlight]},?{v[index_to_highlight]:.2f})',??
?????????????xy=(pos[index_to_highlight],?v[index_to_highlight]),???
?????????????xytext=(10,?-10),??#?文本位置相對(duì)于注釋點(diǎn)的偏移量??
?????????????textcoords="offset?points",??#?文本坐標(biāo)的參照系(基于點(diǎn)的偏移)??
#??????????????arrowprops=dict(arrowstyle="-|>",?connectionstyle="arc3,rad=0.2")
????????????)??#?箭頭樣式和連接樣式??
plt.plot(pos,?v,?'-')??#?繪制第一條曲線?
plt.scatter(index,?v[index],?color='blue',?s=20,?label='pre-trained?RoPE')??#?繪制第一條曲線?
pos?=?list(range(2048,?4097))
w?=?math.pow(base,?-i/d)
v?=?np.array([math.cos(p?*?w)?for?p?in?pos])
index?=?sorted(random.sample(pos,?15))
v_?=?np.array([math.cos(p?*?w)?for?p?in?index])
plt.plot(pos,?v,?'green')??#?繪制第一條曲線?
plt.scatter(index,?v_,?color='r',?s=20,?label='Extrapolation?RoPE')??#?繪制第一條曲線?
plt.annotate(f'({pos[index_to_highlight]},?{v[index_to_highlight]:.2f})',????
?????????????xy=(pos[index_to_highlight],?v[index_to_highlight]),???
?????????????xytext=(10,?-10),??#?文本位置相對(duì)于注釋點(diǎn)的偏移量??
?????????????textcoords="offset?points",??#?文本坐標(biāo)的參照系(基于點(diǎn)的偏移)??
#??????????????arrowprops=dict(arrowstyle="-|>",?connectionstyle="arc3,rad=0.2")
????????????)??#?箭頭樣式和連接樣式?
plt.grid(axis='y')
#?添加圖例??
plt.legend()??
#?顯示圖形??
plt.show()
評(píng)論
查看更多