上一篇 | 下一篇 |
---|---|
注意力機制(2/4集) | 注意力機制(4/4集) |
位置編碼
R N N RNN RNN 和 L S T M LSTM LSTM 這些網絡都是串行執行的,在潛移默化中,就包含了順序關系,也就是詞序關系。而注意力機制是并行的,詞與詞之間不存在順序關系,比如說輸入 [ A , B , C ] [A, B, C] [A,B,C] 和 [ B , A , C ] [B, A, C] [B,A,C] 會被視為相似,那么這樣就會丟失詞序信息,所以需要在執行注意力機制之前,先進行位置編碼,這樣就包含了詞序關系。
①位置編碼向量添加方式
原本的自注意力機制的輸入,就是詞向量,但是對其位置編碼后,會在原來的詞向量上再加一個位置向量變成一個新的向量(對應元素相加),里面包含了當前詞向量和其他的詞向量之間的位置關系。并且位置向量的維度和詞向量的維度是一致的。
②位置編碼公式
編碼方式其實有多種,不過 T r a n s f o r m e r Transformer Transformer 中用的就是下方這種(效果不是最好的,只是當時正好想到了這種方式)。
T r a n s f o r m e r Transformer Transformer 論文中使用的 正弦-余弦位置編碼 是固定編碼(不可訓練),其公式如下:
P E ( p o s , 2 i ) = s i n ( p o s 1000 0 2 i d m o d e l ) P E ( p o s , 2 i + 1 ) = c o s ( p o s 1000 0 2 i d m o d e l ) \Large PE_{(pos,2i)}=sin(\frac{pos}{10000^{\frac{2i}{d_{model}}}})\\ \Large PE_{(pos,2i+1)}=cos(\frac{pos}{10000^{\frac{2i}{d_{model}}}}) PE(pos,2i)?=sin(10000dmodel?2i?pos?)PE(pos,2i+1)?=cos(10000dmodel?2i?pos?)
其中, p o s pos pos 表示元素在序列中的位置( 0 ≤ p o s ≤ 單詞個數 0 ≤ pos ≤ 單詞個數 0≤pos≤單詞個數)。 i i i 表示編碼向量的維度索引( 0 ≤ i < d m o d e l 2 0 ≤ i < \frac{d_{model}}{2} 0≤i<2dmodel??)。 d m o d e l d_{model} dmodel? 表示模型隱藏層維度(如 512 512 512 )。
上述公式表明:偶數位置的元素值使用 s i n sin sin 函數計算,奇數位置的元素值使用 c o s cos cos 函數計算(偶 s i n sin sin 奇 c o s cos cos )。
③舉例幫助理解
舉個例子幫助理解上述參數的含義:假設一句話中有 m m m 個單詞,則有 0 ≤ p o s ≤ m 0 ≤ pos ≤ m 0≤pos≤m ,每個單詞的位置編碼向量的維度為 d m o d e l d_{model} dmodel? (就是這個向量中的元素個數),比如說第 p o s pos pos 個單詞的位置編碼向量為 [ 0.841 , 0.540 , 0.860 , 0.509 , . . . ] [0.841, 0.540, 0.860, 0.509, ...] [0.841,0.540,0.860,0.509,...] 。
現在我們來更具體化這個例子:
令 m = 3 m=3 m=3 ,假設句子為 “ I l o v e y o u I~love~you I?love?you”,包含 3 3 3 個單詞(對應于位置 p o s = 0 , 1 , 2 pos=0,1,2 pos=0,1,2 ),模型維度 d m o d e l = 512 d_{model}=512 dmodel?=512。則第 p o s pos pos 個單詞的位置編碼向量中第 2 i 2i 2i 和第 2 i + 1 2i+1 2i+1 個元素的值應按照如下公式計算:
P E ( p o s , 2 i ) = s i n ( p o s 1000 0 2 i 512 ) P E ( p o s , 2 i + 1 ) = c o s ( p o s 1000 0 2 i 512 ) \Large PE_{(pos,2i)}=sin(\frac{pos}{10000^{\frac{2i}{512}}})\\ \Large PE_{(pos,2i+1)}=cos(\frac{pos}{10000^{\frac{2i}{512}}}) PE(pos,2i)?=sin(100005122i?pos?)PE(pos,2i+1)?=cos(100005122i?pos?)
則有:
單詞位置(pos) | 維度0 | 維度1 | 維度2 | 維度3 | …(共512維) |
---|---|---|---|---|---|
pos=0 (“I”) | 0.000 | 1.000 | 0.000 | 1.000 | … |
pos=1 (“love”) | 0.841 | 0.540 | 0.860 | 0.509 | … |
pos=2 (“deep”) | 0.909 | -0.416 | 0.876 | -0.481 | … |
- 高頻維度(如維度 512 的最后幾維)的值接近微小波動,但對模型仍攜帶位置信息。
- 單詞很多時,其中更遠的位置(例如
pos=100
)會因為頻率放大分母,使得大幅衰減為小值。
測試代碼:
import math
import numpy as npdef get_div_term(d_model):div_term = np.exp(np.arange(0, d_model, 2) * (-math.log(10000.0) / d_model))return div_term # 形狀: [256]if __name__ == '__main__':np.set_printoptions(suppress=True)# 更改下面的 0 為其他的 posprint(np.sin(0 / get_div_term(512))) # 輸出向量中偶數位置元素print(np.cos(0 / get_div_term(512))) # 輸出向量中奇數位置元素
④為什么位置編碼要這樣編碼
下面只做簡單解釋,詳細的原因可以問 d e e p s e e k deepseek deepseek
按順序推導,請耐心觀看。
(里面為什么是除以 1000 0 2 i / 512 10000^{2i/512} 100002i/512 不用管,知道宏觀公式的原因就行)
靈感來源:三角函數的和差化積公式:
s i n ( α + β ) = s i n α ? c o s β + c o s α ? s i n β c o s ( α + β ) = c o s α ? c o s β ? s i n α ? s i n β sin(\alpha+\beta)=sin\alpha·cos\beta+cos\alpha·sin\beta\\ cos(\alpha+\beta)=cos\alpha·cos\beta-sin\alpha·sin\beta sin(α+β)=sinα?cosβ+cosα?sinβcos(α+β)=cosα?cosβ?sinα?sinβ
則第 p o s + k pos+k pos+k 個位置的單詞的位置編碼向量 P E ( p o s + k ) PE_{(pos+k)} PE(pos+k)? 中的偶數和奇數位置的元素可被表示為:
偶數位: P E ( p o s + k , 2 i ) = sin ? ( p o s + k 1000 0 2 i 512 ) = sin ? ( p o s 1000 0 2 i 512 + k 1000 0 2 i 512 ) = sin ? ( p o s 1000 0 2 i 512 ) ? cos ? ( k 1000 0 2 i 512 ) + cos ? ( p o s 1000 0 2 i 512 ) ? sin ? ( k 1000 0 2 i 512 ) = P E ( p o s , 2 i ) ? P E ( k , 2 i + 1 ) + P E ( p o s , 2 i + 1 ) ? P E ( k , 2 i ) 奇數位: P E ( p o s + k , 2 i + 1 ) = cos ? ( p o s + k 1000 0 2 i 512 ) = cos ? ( p o s 1000 0 2 i 512 + k 1000 0 2 i 512 ) = cos ? ( p o s 1000 0 2 i 512 ) ? cos ? ( k 1000 0 2 i 512 ) ? sin ? ( p o s 1000 0 2 i 512 ) ? sin ? ( k 1000 0 2 i 512 ) = P E ( p o s , 2 i + 1 ) ? P E ( k , 2 i + 1 ) ? P E ( p o s , 2 i ) ? P E ( k , 2 i ) \begin{aligned} \text{偶數位:} & \\ PE_{(pos+k,2i)} &= \sin\left(\frac{pos+k}{10000^{\frac{2i}{512}}}\right) = \sin\left(\frac{pos}{10000^{\frac{2i}{512}}} + \frac{k}{10000^{\frac{2i}{512}}}\right) \\ &= \sin\left(\frac{pos}{10000^{\frac{2i}{512}}}\right) \cdot \cos\left(\frac{k}{10000^{\frac{2i}{512}}}\right) + \cos\left(\frac{pos}{10000^{\frac{2i}{512}}}\right) \cdot \sin\left(\frac{k}{10000^{\frac{2i}{512}}}\right) \\ &= PE_{(pos,2i)} \cdot PE_{(k,2i+1)} + PE_{(pos,2i+1)} \cdot PE_{(k,2i)} \\ \hline\\ \text{奇數位:} & \\ PE_{(pos+k,2i+1)} &= \cos\left(\frac{pos+k}{10000^{\frac{2i}{512}}}\right) = \cos\left(\frac{pos}{10000^{\frac{2i}{512}}} + \frac{k}{10000^{\frac{2i}{512}}}\right) \\ &= \cos\left(\frac{pos}{10000^{\frac{2i}{512}}}\right) \cdot \cos\left(\frac{k}{10000^{\frac{2i}{512}}}\right) - \sin\left(\frac{pos}{10000^{\frac{2i}{512}}}\right) \cdot \sin\left(\frac{k}{10000^{\frac{2i}{512}}}\right) \\ &= PE_{(pos,2i+1)} \cdot PE_{(k,2i+1)} - PE_{(pos,2i)} \cdot PE_{(k,2i)} \end{aligned} 偶數位:PE(pos+k,2i)?奇數位:PE(pos+k,2i+1)??=sin(100005122i?pos+k?)=sin(100005122i?pos?+100005122i?k?)=sin(100005122i?pos?)?cos(100005122i?k?)+cos(100005122i?pos?)?sin(100005122i?k?)=PE(pos,2i)??PE(k,2i+1)?+PE(pos,2i+1)??PE(k,2i)?=cos(100005122i?pos+k?)=cos(100005122i?pos?+100005122i?k?)=cos(100005122i?pos?)?cos(100005122i?k?)?sin(100005122i?pos?)?sin(100005122i?k?)=PE(pos,2i+1)??PE(k,2i+1)??PE(pos,2i)??PE(k,2i)???
可以看出,對于 p o s + k pos+k pos+k 位置的位置向量中的 2 i 2i 2i 或 2 i + 1 2i+1 2i+1 維而言,可以被表示為: p o s pos pos 位置與 k k k 位置的位置向量中的 2 i 2i 2i 與 2 i + 1 2i+1 2i+1 維的線性組合,這樣的線性組合意味著位置向量中蘊含了相對位置信息(也就是說:第 p o s + k pos+k pos+k 個單詞和第 p o s pos pos 、第 k k k 個單詞有關聯)。
將上述推導過程中的 P E ( k , 2 i ) PE_{(k,2i)} PE(k,2i)? 和 P E ( k , 2 i + 1 ) PE_{(k,2i+1)} PE(k,2i+1)? 看成是 W k W_k Wk? ,那么上述公式就可以理解成:模型可以通過權重 W k W_k Wk? 來掌握第 p o s pos pos 個單詞和距離它 k k k 個單位遠的單詞之間的關聯。
⑤這種編碼方式的優缺點
-
優點:
- 泛化性強:支持處理比訓練時更長的序列(外推能力)。
- 計算高效:無需額外訓練參數。
-
缺點:這是一種不可學習,即給出即固定的編碼方式,靈活性低。
后續的 GPT 等模型大部分都采用了可學習的編碼方式。