官术网_书友最值得收藏!

1.2.1 位置編碼

在Transformer模型中,直接將詞元通過嵌入層后的向量輸入到編碼器中會有一些問題。我們需要知道的是,Transformer模型內(nèi)計算注意力權(quán)重的操作是并行的,沒有類似RNN的循環(huán)結(jié)構(gòu),因此并沒有捕捉順序序列的能力。也就是說,無論句子中單詞的順序怎么安排,Transformer模型最終都會得到類似的結(jié)果。為了解決這個問題,Transformer在處理輸入序列時引入了位置嵌入(Position Embedding,也稱為位置編碼)來提供單詞之間的順序信息,這是一種將單詞的位置信息嵌入輸入詞向量中的方法。它使用一系列額外的向量來表示單詞之間的距離,從而提供了順序信息。如圖1-9所示,在Transformer模型中,位置編碼的向量會與輸入的詞向量相加,從而可以綜合考慮單詞的語義信息和位置信息。

圖1-9 Transformer模型中的位置編碼與詞向量融合示意

位置編碼的設(shè)計十分講究,暫時拋開Transformer模型不談,單單就位置編碼方式來說,大體有兩種選擇:絕對位置編碼和相對位置編碼。

1.絕對位置編碼

絕對位置編碼相對來說比較簡單:對于第k個輸入向量xk,直接與位置向量pk拼接成xk+pk,其中pk是只依賴于索引k的。即便絕對位置編碼比較簡單,也出現(xiàn)了很多變種。

(1)訓(xùn)練位置編碼

訓(xùn)練位置編碼是一種最簡單的位置編碼方式,就是完全不定義任何規(guī)則,直接定義一個位置編碼向量,然后在模型訓(xùn)練的過程中進(jìn)行學(xué)習(xí),也就是說,直接將這個位置編碼當(dāng)作一個可以學(xué)習(xí)的參數(shù)。BERT和GPT等模型所采用的就是這種位置編碼方式。假如輸入文本的最大長度是512,而編碼的特征維度是768,那么就可以創(chuàng)建一個512×768的矩陣作為位置向量,然后讓它隨著訓(xùn)練過程逐漸更新。

python

self.pos_embedding=nn.Parameter(torch.randn(512, 768))

這種訓(xùn)練式的絕對位置編碼的缺點就是沒有外推性,也就是說,如果在訓(xùn)練的時候定義的最大句子長度是512,那么模型在推理時最多只能處理長度為512的句子,更長就處理不了了。

(2)三角函數(shù)位置編碼

Transformer模型中所采用的是三角函數(shù)式的絕對位置編碼,也稱為Sinusoidal位置編碼。假設(shè)輸入序列的長度為N,編碼向量的特征維度是dmodel,也就是說一句話對應(yīng)的特征向量矩陣的維度是(Ndmodel)。接下來我們將矩陣按列分別進(jìn)行編碼,偶數(shù)列采用正弦函數(shù)編碼,奇數(shù)列采用余弦函數(shù)編碼。然后定義兩個編碼函數(shù)為

其中pos是詞元的位置數(shù),i的取值范圍則是從0到

之所以采用三角函數(shù)進(jìn)行位置編碼,是因為它具有明顯的規(guī)律性,以此期望它具有一定的外推能力,還有一個原因是三角函數(shù)的兩角和公式為

這說明α+β位置的向量可以表示成α位置的向量和β位置的向量的組合,也就是說后面的編碼向量可以由前面的編碼向量線性表示,這其實從側(cè)面提供了模型單詞之間的絕對位置。

相應(yīng)的Python代碼如下。

python

def get_position_angle_vector(position):

  return [position/np.power(10000, 2 * (hid_j//2)/d_hid) for hid_j in range(d_hid)]


sinusoidal_table=np.array([get_position_angle_vector(i) for i in range(n_position)])

sinusoidal_table[:, 0::2]=np.sin(sinusoidal_table[:, 0::2]) #偶數(shù)列進(jìn)行sin操作

sinusoidal_table[:, 1::2]=np.cos(sinusoidal_table[:, 1::2]) #奇數(shù)列進(jìn)行cos操作

(3)遞歸位置編碼

從理論上來說,RNN模型本身就具備學(xué)習(xí)位置信息的能力,因此可以通過遞歸結(jié)構(gòu)訓(xùn)練一個可以捕捉序列位置關(guān)系的模型。如果在詞向量輸入之后先添加一個RNN層,隨后使用Transformer模型,理論上就不需要再添加位置編碼了。同樣,我們也可以利用RNN模型來學(xué)習(xí)絕對位置編碼,從初始向量p0開始,通過遞歸方式來生成各個位置的編碼向量。

理論上說,基于遞歸模型的位置編碼具備較好的外推能力,并且靈活性比三角函數(shù)式的位置編碼更好。然而,遞歸位置編碼的并行性不好,可能會導(dǎo)致模型訓(xùn)練變慢。

2.相對位置編碼

注意力機(jī)制在計算時,實際上只需要考慮當(dāng)前位置元素與被計算注意力分?jǐn)?shù)的位置元素的相對距離,而不需要嚴(yán)格知道當(dāng)前元素在輸入序列中的絕對位置,因此相對位置編碼的靈活性更大,可擴(kuò)展性也更好。

(1)經(jīng)典相對位置編碼

因為是在計算注意力分?jǐn)?shù)時丟失的位置信息,所以最直接的想法就是在這一層再加回來。于是,提出Transformer模型的原班人馬發(fā)表了“Self-Attention with Relative Position Representations”(https://arxiv.org/abs/1803.02155),在計算注意力分?jǐn)?shù)和加權(quán)平均時各加入了一個可學(xué)習(xí)的參數(shù),用來表示元素之間的相對位置,并且這個相對位置編碼參數(shù)可以在多頭之間共享。

在計算注意力分?jǐn)?shù)時,首先要計算:

其中xixj分別表示兩個位置的特征向量,pipj則表示兩個位置的編碼向量,接下來要計算注意力分?jǐn)?shù),即

在這一步,將第一項的位置編碼,pi去掉,然后將展開式中第二項的位置編碼替換為二元位置向量,變成

最后進(jìn)行加權(quán)平均,即

同樣將pjWV替換為二元位置向量,變成

如果要用來表示和的相對位置,那么它們應(yīng)該只與ij之間的差值k有關(guān),因此定義

通過這種方式,即使只有固定長度的位置編碼向量,也能夠表達(dá)出任意長度的相對位置關(guān)系。

(2)T5相對位置編碼

T5是一個通用的文本到文本的模型,適用于大多數(shù)NLP任務(wù),它用了一種比較簡單的相對位置編碼方法。對計算注意力分?jǐn)?shù)的式子進(jìn)行全展開,得

因為x表示的是輸入向量,p表示的是位置向量,所以上式可以分別理解為“輸入-輸入”“輸入-位置”“位置-輸入”“位置-位置”4項注意力分?jǐn)?shù)。但是,輸入向量與位置向量理論上應(yīng)該是相互獨(dú)立的,不應(yīng)該計算注意力分?jǐn)?shù),因此可以刪除中間兩項。而對于最后一項,我們認(rèn)為它只是一個用來表示相對位置的標(biāo)量,只依賴(ij),那就可以通過一個標(biāo)量直接將其表示出來,這樣注意力分?jǐn)?shù)就可以簡化為

在代碼層面,只要在簡化的注意力矩陣上加入一個偏置項即可。

還有一點是,對于T5相對位置編碼對(i,j),先對相對位置i-j做了分桶處理,然后才做截斷處理,如表1-6所示,將i-j相對位置映射到f(i-j)。

表1-6 T5相對位置編碼映射關(guān)系

3.融合位置編碼

絕對位置編碼以其實現(xiàn)簡單、計算速度快的優(yōu)點受到歡迎,而相對位置編碼則因為直觀地體現(xiàn)了相對位置信號,往往能帶來更好的實際性能。不過,如果我們能以絕對位置編碼的方式實現(xiàn)相對位置編碼,即采用融合位置編碼,就能在保持簡單和快速的同時享受更好的性能。旋轉(zhuǎn)位置編碼(Rotary Position Embedding,RoPE)就是為了實現(xiàn)這個目標(biāo)而提出的一種融合位置編碼方式,它將相對位置信息集成到了線性注意力層中,雖然按照定義應(yīng)該屬于相對位置編碼,但是在性能上超越了絕對位置編碼和經(jīng)典的相對位置編碼,并且它其實是以絕對位置編碼的方式實現(xiàn)了相對位置編碼。RoPE由蘇劍林最早應(yīng)用于自研的RoFormer模型,發(fā)表于論文“RoFormer: Enhanced Transformer with Rotary Position Embedding”(https://arxiv.org/abs/2104.09864)中。

RoPE主要是對注意力層中的查詢(query, q)向量和鍵(key, k)向量注入了絕對位置信息,然后用更新后的兩個向量做內(nèi)積,由此引入相對位置信息。其中,qk的形狀都是(L,E),L是序列長度,E是嵌入維度。在計算注意力分?jǐn)?shù)時,需要先計算qk的內(nèi)積,在這一步,RoPE設(shè)計了兩個函數(shù),用于給qk添加絕對位置信息,即假設(shè)運(yùn)算會給qk添加絕對位置信息。注意力機(jī)制的核心運(yùn)算就是內(nèi)積,所以我們希望內(nèi)積的結(jié)果帶有相對位置信息,而query向量qm和key向量kn之間的內(nèi)積運(yùn)算可以用一個函數(shù)g表示,g的輸入是單詞嵌入qk和它們之間的相對位置m-n,即

那么,我們要做的就是求出該恒等式的一個盡可能簡單的解。所以,RoPE編碼簡單講就是先通過函數(shù)f進(jìn)行了絕對位置編碼,又通過注意力機(jī)制的內(nèi)積運(yùn)算引入了相對位置編碼。

在這里補(bǔ)充一點,RoPE的工作是建立在復(fù)數(shù)理論之上的,因此我們需要先介紹一些復(fù)數(shù)的相關(guān)知識。復(fù)數(shù)的本質(zhì)其實就是旋轉(zhuǎn),如圖1-10所示,試想在一個數(shù)軸上,1×(-1)其實表示的就是將(1,0)向量逆時針旋轉(zhuǎn)180°。那么,有沒有一個數(shù)能讓1×i×i=-1呢,也就是將向量逆時針旋轉(zhuǎn)兩次90°?這就是對虛數(shù)單位i的直觀理解。更進(jìn)一步,歐拉恒等式其實表示的是將一個數(shù)持續(xù)旋轉(zhuǎn)弧度,而它將指向相反的方向。

圖1-10 復(fù)數(shù)表示旋轉(zhuǎn)的直觀理解

復(fù)數(shù)可以用極坐標(biāo)來表示,其中有兩個參數(shù):模和角度。模表示復(fù)數(shù)在復(fù)平面上的距離,而角度表示與正實軸之間的夾角。如果將二維向量看作復(fù)數(shù)的話,那么復(fù)數(shù)ab就可以表示成,而它們的內(nèi)積公式為

其中|a|與ra、|b|與rb分別是復(fù)數(shù)ab的模,θaθb分別是復(fù)數(shù)ab的角度,表示兩個向量的夾角的余弦值。

那么,在計算注意力分?jǐn)?shù)時,我們可以先假設(shè)詞嵌入向量的維度是二維,即E=2,而二維向量又可以寫成極坐標(biāo)的形式,這樣就可以利用二維平面上向量的幾何性質(zhì)提出一個滿足前面關(guān)系的函數(shù):

其中和分別表示模和角度。根據(jù)式(1-1)和內(nèi)積公式,可以推導(dǎo)出

我們的目標(biāo)是找到函數(shù)f的一個可行解,因此可以給f添加一些初始條件,簡化求解過程,可以設(shè)。那么當(dāng)m=n時,由式(1-2)可以得到

由于計算內(nèi)積g時實部只和m-n的相對值有關(guān),所以

因此,我們可以進(jìn)一步簡單假設(shè):

同理,當(dāng)m=n時,由式(1-3)可以得到

整理得

所以是一個只與m相關(guān)而與q無關(guān)的函數(shù),定義為φ(m),即

可以發(fā)現(xiàn)

也就是說,φ(m)-φ(m-1)的值也只與m相關(guān)而與q無關(guān),這說明φ(m)是一個關(guān)于m的等差數(shù)列,那么可以進(jìn)一步簡單假設(shè)φ(m)=,這里的θ是一個非0常數(shù)。根據(jù)式(1-4),我們可以得到

綜上所述,有

也就是說,我們找到了一個f的可行解。前面我們提到過,復(fù)數(shù)的本質(zhì)其實是旋轉(zhuǎn),因此RoPE才被稱為旋轉(zhuǎn)位置編碼。既然是旋轉(zhuǎn),那還可以將其寫成矩陣的形式:

當(dāng)然這還是在嵌入維度E=0的情況。當(dāng)E>2時,一般來說嵌入維度會是一個偶數(shù),那么可以直接將二維矩陣進(jìn)行拼接,即

到此為止,RoPE位置編碼的原理我們介紹完了,它巧妙地借助復(fù)數(shù)的表達(dá)形式,在注意力機(jī)制之前加入了絕對位置信息,而在注意力計算的過程中,又引入了相對位置信息。另外,RoPE相對于絕對位置編碼和經(jīng)典的相對位置編碼來說還具有外推性。若外推性不好,則當(dāng)大模型在訓(xùn)練和預(yù)測的輸入長度不一致時,模型的泛化能力可能會下降。例如,一個模型在訓(xùn)練時只處理長度為512個token的位置向量,那么在預(yù)測時,如果輸入文本超過512個token,模型可能會處理不好,從而影響其處理長文本或多輪對話等任務(wù)的效果。RoPE良好的外推性也使得它成為目前在大模型位置編碼中應(yīng)用最廣的方式之一,已經(jīng)被廣泛應(yīng)用在我們后面會介紹的Llama和GLM等模型中。

主站蜘蛛池模板: 达州市| 乐陵市| 冕宁县| 营山县| 庄浪县| 海林市| 普安县| 焉耆| 饶河县| 嘉鱼县| 灌阳县| 清丰县| 秦安县| 大英县| 长白| 轮台县| 蓬安县| 德令哈市| 锦屏县| 团风县| 临清市| 东源县| 磴口县| 元阳县| 河池市| 唐河县| 达拉特旗| 山阳县| 淮滨县| 阿拉善左旗| 独山县| 宝丰县| 金山区| 临夏县| 芦山县| 庆城县| 于都县| 襄垣县| 灵宝市| 蓝山县| 抚松县|