[閱讀筆記]Attention Is All You Need - Transformer結構
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. 因此每個子層的最終輸出為:
\[LayerNorm(x + Sublayer(x))\]
此外, 論文中限定了Embeding層的輸出和兩個子層的輸入輸出的維度都是\(d_{model}=512\).
Decoder
Decoder也是由\(N=6\)個獨立的層堆疊而成的, 除了與Encoder層中的兩個完全相同的子層外, 在兩層之間又加入了一個multi-head attention, 這裏是對Encoder的輸出做attention處理.
與Encoder相同, 每個子層也引入了residual connection, 並且相加之後使用layer normalization得到每個子層最後的輸出.
此外, 為了防止序列中元素的位置主導輸出結果, 對Decoder層的multi-head self-attention
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對應的計算公式為:
\[\text{Attention}(Q,K,V)=\text{softmax}(\frac{QK^T}{\sqrt{d_k}})V\]
需要註意的點是: \(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}\)維度的向量.
公式表示為:
\[\text{MultiHead}(Q,K,V)=\text{Concat}(\text{head}_1, \cdots, \text{head}_h)W^O\]
其中:
\[\text{head}_i=\text{Attention}(QW_i^Q,KW_i^K,VW_i^V)\]
\(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激活:
\[FFN(x) = \max(0, xW_1 + b_1)W_2 + b_2\]
對於不同位置的線性變換是完全一樣的, 即使用相同的參數.
這一層的輸入輸出都是\(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\)函數:
\[PE_{pos,2i} = \sin(pos/10000^{2i/d_model})\]
\[PE_{pos,2i+i} = \cos(pos/10000^{2i/d_model})\]
其中\(pos\)代表位置, \(i\)代表第\(i\)維. 每個維度對應於不同頻率不同的正弦函數. 使用這種方法, 我們認為能夠反應相對位置中包含的信息, 這是因為: 對於一個固定的偏移量\(k\), \(PE_{pos+k}\)能表示成\(PE_{pos}\)的線性函數.
Why Self-Attention
之所以使用Self-Attention而沒有使用循環或卷積的結構, 主要出於以下三點的考慮:
- 每層的計算復雜度
- 計算可以並行的程度
- 對於序列問題, 長序列是一個難點. Self-Attention方法對於長短序列都有較好的表現. 這是由於我們認為在模型中, 前向和後向傳播的路徑越短, 就更容易學習到其中的關系. 對於循環和卷積, 距離當前較遠的位置, 在傳播過程中都要經過較長的距離. 但對於Self-Attention結構, 無論兩個元素在序列中的相對距離如何, 傳播的距離總是相等的.
參考資料
- Attention Is All You Need
- Kyubyong/transformer
[閱讀筆記]Attention Is All You Need - Transformer結構