Transformer
本文介紹了Transformer結構, 是一種encoder-decoder, 用來處理序列問題, 常用在NLP相關問題中. 與傳統的專門處理序列問題的encoder-decoder相比, 有以下的特點:
- 結構完全不依賴於CNN和RNN
- 完全依賴於self-attention機制, 是一種堆疊的self-attention
- 使用全連接層
- 逐點point-wise計算的
整個Transformer的結構圖如下所示:
Encoder and Decoder Stacks
如上所說, Transformer是基於stacked self-attention的, stack方式具體為:
Encoder
Encoder是由\(N=6\)個獨立的層堆疊而成的, 每層有兩個子層:
- 第一個層為multi-head self-attention結構
- 第二層為simple, position-wise fully connected feed-forward network, 即基於位置的簡單全連接反饋網絡
在每個子層又引入了residual connection, 具體的做法為每個子層的輸入與輸出相加, 這就要求每個子層的輸入與輸出的維度是完全相等的. 然后再使用layer normalization. 因此每個子層的最終輸出為:
此外, 論文中限定了Embeding層的輸出和兩個子層的輸入輸出的維度都是\(d_{model}=512\).
Decoder
Decoder也是由\(N=6\)個獨立的層堆疊而成的, 除了與Encoder層中的兩個完全相同的子層外, 在兩層之間又加入了一個multi-head attention, 這里是對Encoder的輸出做attention處理.
與Encoder相同, 每個子層也引入了residual connection, 並且相加之后使用layer normalization得到每個子層最后的輸出.
此外, 為了防止序列中元素的位置主導輸出結果, 對Decoder層的multi-head self-attention層增加了mask操作, 並且結合對output embedding結果進行右移一位的操作, 保證了每個位置\(i\)的輸出, 只會依賴於\(i\)位之前(不包括\(i\)位, 因為右移一位和mask).
Attention
論文中將常用的Attention結構從新的一種角度進行了描述:
Attention作為一種函數, 接受的輸入為:
- 一個query
- 一組key-value pairs
即包含三部分, query, keys和values. 三者都是向量.
輸出就是對組中所有values的加權之和, 其中的權值是使用compatibility function(如內積), 對組內的每一個keys和query計算得到的.
例如, 對於常見的self-attention來說, 這里值的就是對於序列中的某一個元素對應的向量, 求得經過self-attention之后對應的向量. query指的是這個元素對應的向量(如NLP任務中句子序列中某一個單詞對應的embedding向量), key-value pairs就是這個序列的所有元素, 其中的每個元素對應的key和value是完全相同的向量, 對於要比較的那個元素, 與query也是完全相同的. 然后使用當前向量和所有向量做內積得到權值, 最后的數據就是這個權值和對應向量的加權和.
論文中使用了兩種Attention方法, 分別為Scaled Dot-Product Attention和Multi-Head Attention
Instead.
Scaled Dot-Product Attention
我們假設query
和key
這兩個用來比較的向量, 長度都為\(d_k\); value
向量的長度為\(d_v\). 對query
和所有keys
進行點積得到值, 再對這里得到的每個點積結果除以\(\sqrt{d_k}\), 完成scale, 最后應用一個softmax function獲得每個value
對應的權值, 加權求得最后的輸出向量.
這是對於一個query
的情況. 實際中是直接對一個序列對應的所有querys
直接進行計算, 將所有querys
拼接成一個大的\(Q\)矩陣, 對應的keys
和values
也拼接成\(K\)和\(V\)矩陣, 則Scaled Dot-Product Attention對應的計算公式為:
需要注意的點是: \(d_k\)較大時, 向量之間的點積結果可能就會非常大, 這回造成softmax函數陷入到梯度很小的區域. 為了應對這種情況, 適應了縮放因子\(\sqrt{d_k}\), 將點積結果盡量縮小到梯度敏感的區域內.
Multi-Head Attention
之前的方法都是對\(d_{model}\)維度的querys
, keys
和values
直接使用一個Attention函數, 得到結果, 在Multi-Head Attention方法中, 我們如下操作:
-
對
querys
,keys
和values
都分別進行\(h\)次的線性映射(類似於SVM中的線性核), 得到\(h\)組維度為分別為\(d_k\), \(d_k\), \(d_v\)的三種向量.需要注意的是, 這\(h\)次映射都是不同的映射, 每次線性映射使用的參數是不相同的, 而且這個映射是可學習的, 相當於得到了\(h\)個不同空間(雖然這些空間的維數是相等的)中的表征.
-
然后並行的對這\(h\)組維度為分別為\(d_k\), \(d_k\), \(d_v\)的
querys
,keys
和values
向量執行Attention函數, 每組都產生一個\(d_v\)維的輸出結果. -
最后將這\(h\)個維度為\(d_k\)向量拼接起來.
-
通過線性轉換還原成\(d_{model}\)維度的向量.
公式表示為:
其中:
\(W_i^Q \in \mathbb{R}^{d_{model} \times d_k}\), \(W_i^K \in \mathbb{R}^{d_{model} \times d_k}\), \(W_i^V \in \mathbb{R}^{d_{model} \times d_v}\), 以及\(W_i^O \in \mathbb{R}^{hd_v \times d_{model}}\)都是可學習的線性映射參數. 在論文中超參數的選擇為\(h=8\), 又由於\(d_{model}=512\), 因此\(d_k=d_v=d_{model}/h=64\).
因為中間計算的降維, 總體計算的消耗與直接使用Attention函數的消耗相近.
Transformer模型中Attention使用的特殊點
對於Multi-Head Attention, 在Transformer模型中有三個不同點:
-
在encoder-decoder attention層中, 即Encoder和Decoder兩者之間的Attention中(對應於Decoder結構中的中間子層部分),
queries
來自於Decoder結構中上一個子層的輸出. 這保證了對於Decoder中的每一個位置, 都能捕獲input sequence各個位置的信息. -
Encoder中對應的是self-attention, 對應一個位置上的
query
,key
,value
是完全相同的一個向量. 每個位置的輸出結果, 都會參考輸入的所有位置. -
相似的, Decoder中第一個子層也是self-attention. 因此對於某個位置的元素, 會獲取序列中所有序列的信息. 但為了防止leftward information flow(左側信息泄露), 即防止出現自回歸屬性, 我們對這種Scaled Dot-Product Attention通過mask進行了限制, 屏蔽從第一個元素到當前元素(包含), 然后再進行Attention操作.
Position-wise Feed-Forward Networks
Encoder和Decoder都含有一個fully connected feed-forward network, 特殊的是, 這個網絡分別對每個位置的attention層的輸出向量單獨地進行作用. 整個過程包含了兩次線性變換以及中間夾雜的一次ReLU激活:
對於不同位置的線性變換是完全一樣的, 即使用相同的參數.
這一層的輸入輸出都是\(d_{model}=512\), 中間隱層的維度為\(d_{ff}=2048\).
Embeddings and Softmax
使用已經訓練好的embeddings將input token和output token轉換成\(d_{model}\)維度的向量.
在最后Decoder的輸出時, 將Decoder的輸出通過一層線性變換層和一個softmax層, 轉換成預測下一個token的概率向量. 這兩個層中的參數也是提前訓練好的.
在模型中, 兩個embedding layers以及最后的softmax之前的線性變換, 這三者共享使用相同的矩陣權值.
對於embedding層, 里面的權值需要乘以\(\sqrt{d_{model}}\)之后再使用.
Positional Encoding
因為模型完全沒有使用循環(RNN)和卷積(CNN), 而又想使用序列中的順序信息, 就必須加入一些關於token
的相對位置和絕對位置的信息. 因此我們加入Positional Encoding, 作為Encoder和Decoder的輸入. 需要注意的是Positional Encoding產生的向量的維度為\(d_{model}\), 與原本的embedding向量維度相同, 從而兩者可以被相加使用.
對位置進行embedding的方法很多, 有訓練方法和指定方法, 本文中, 采用**頻率不同的\(\sin\)和\(\cos\)函數:
其中\(pos\)代表位置, \(i\)代表第\(i\)維. 每個維度對應於不同頻率不同的正弦函數. 使用這種方法, 我們認為能夠反應相對位置中包含的信息, 這是因為: 對於一個固定的偏移量\(k\), \(PE_{pos+k}\)能表示成\(PE_{pos}\)的線性函數.
Why Self-Attention
之所以使用Self-Attention而沒有使用循環或卷積的結構, 主要出於以下三點的考慮:
- 每層的計算復雜度
- 計算可以並行的程度
- 對於序列問題, 長序列是一個難點. Self-Attention方法對於長短序列都有較好的表現. 這是由於我們認為在模型中, 前向和后向傳播的路徑越短, 就更容易學習到其中的關系. 對於循環和卷積, 距離當前較遠的位置, 在傳播過程中都要經過較長的距離. 但對於Self-Attention結構, 無論兩個元素在序列中的相對距離如何, 傳播的距離總是相等的.