1. 程式人生 > >【NLP】Transformer詳解

【NLP】Transformer詳解

傳送門:【NLP】Attention原理和原始碼解析

自Attention機制提出後,加入attention的Seq2seq模型在各個任務上都有了提升,所以現在的seq2seq模型指的都是結合rnn和attention的模型,具體原理可以參考傳送門的文章。之後google又提出瞭解決sequence to sequence問題的transformer模型,用全attention的結構代替了lstm,在翻譯任務上取得了更好的成績。本文主要介紹《Attention is all you need》這篇文章,自己在最初閱讀的時候還是有些不懂,希望可以在自己的解讀下讓大家更快地理解這個模型^ ^

1. 模型結構

模型結構如下圖:

和大多數seq2seq模型一樣,transformer的結構也是由encoder和decoder組成。

1.1 Encoder

Encoder由N=6個相同的layer組成,layer指的就是上圖左側的單元,最左邊有個“Nx”,這裡是x6個。每個Layer由兩個sub-layer組成,分別是multi-head self-attention mechanism和fully connected feed-forward network。其中每個sub-layer都加了residual connection和normalisation,因此可以將sub-layer的輸出表示為:

sub\_layer\_output = LayerNorm(x+(SubLayer(x))) \\

接下來按順序解釋一下這兩個sub-layer:

  • Multi-head self-attention

熟悉attention原理的童鞋都知道,attention可由以下形式表示:

attention\_output = Attention(Q, K, V) \\

multi-head attention則是通過h個不同的線性變換對Q,K,V進行投影,最後將不同的attention結果拼接起來:

MultiHead(Q, K, V) = Concat(head_1, ..., head_h)W^O \\

head_i = Attention(QW_i^Q, KW_i^K, VW_i^V) \\

self-attention則是取Q,K,V相同。

另外,文章中attention的計算採用了scaled dot-product,即:

Attention(Q, K, V) = softmax(\frac{QK^T}{\sqrt{d_k}})V \\

作者同樣提到了另一種複雜度相似但計算方法additive attention,在 d_k 很小的時候和dot-product結果相似,d_k

大的時候,如果不進行縮放則表現更好,但dot-product的計算速度更快,進行縮放後可減少影響(由於softmax使梯度過小,具體可見論文中的引用)。

  • Position-wise feed-forward networks

第二個sub-layer是個全連線層,之所以是position-wise是因為處理的attention輸出是某一個位置i的attention輸出。

1.2 Decoder

Decoder和Encoder的結構差不多,但是多了一個attention的sub-layer,這裡先明確一下decoder的輸入輸出和解碼過程:

  • 輸出:對應i位置的輸出詞的概率分佈
  • 輸入:encoder的輸出 & 對應i-1位置decoder的輸出。所以中間的attention不是self-attention,它的K,V來自encoder,Q來自上一位置decoder的輸出
  • 解碼:這裡要特別注意一下,編碼可以平行計算,一次性全部encoding出來,但解碼不是一次把所有序列解出來的,而是像rnn一樣一個一個解出來的,因為要用上一個位置的輸入當作attention的query

明確瞭解碼過程之後最上面的圖就很好懂了,這裡主要的不同就是新加的另外要說一下新加的attention多加了一個mask,因為訓練時的output都是ground truth,這樣可以確保預測第i個位置時不會接觸到未來的資訊。

加了mask的attention原理如圖(另附multi-head attention):

1.3 Positional Encoding

除了主要的Encoder和Decoder,還有資料預處理的部分。Transformer拋棄了RNN,而RNN最大的優點就是在時間序列上對資料的抽象,所以文章中作者提出兩種Positional Encoding的方法,將encoding後的資料與embedding資料求和,加入了相對位置資訊。

這裡作者提到了兩種方法:

  1. 用不同頻率的sine和cosine函式直接計算
  2. 學習出一份positional embedding(參考文獻

經過實驗發現兩者的結果一樣,所以最後選擇了第一種方法,公式如下:

PE_{(pos, 2i)} = sin(pos/10000^{2i/d_{model}}) \\

PE_{(pos, 2i+1)} = cos(pos/10000^{2i/d_{model}}) \\

作者提到,方法1的好處有兩點:

  1. 任意位置的 PE_{pos+k} 都可以被 PE_{pos} 的線性函式表示,三角函式特性複習下:

cos(\alpha+\beta) = cos(\alpha)cos(\beta)-sin(\alpha)sin(\beta) \\

sin(\alpha+\beta) = sin(\alpha)cos(\beta) + cos(\alpha)sins(\beta) \\

2. 如果是學習到的positional embedding,(個人認為,沒看論文)會像詞向量一樣受限於詞典大小。也就是隻能學習到“位置2對應的向量是(1,1,1,2)”這樣的表示。所以用三角公式明顯不受序列長度的限制,也就是可以對 比所遇到序列的更長的序列 進行表示。


2. 優點

作者主要講了以下三點:

  1. Total computational complexity per layer (每層計算複雜度)

2. Amount of computation that can be parallelized, as mesured by the minimum number of sequential operations required

作者用最小的序列化運算來測量可以被並行化的計算。也就是說對於某個序列x_1, x_2, ..., x_n ,self-attention可以直接計算 x_i, x_j 的點乘結果,而rnn就必須按照順序從 x_1 計算到 x_n

3. Path length between long-range dependencies in the network

這裡Path length指的是要計算一個序列長度為n的資訊要經過的路徑長度。cnn需要增加捲積層數來擴大視野,rnn需要從1到n逐個進行計算,而self-attention只需要一步矩陣計算就可以。所以也可以看出,self-attention可以比rnn更好地解決長時依賴問題。當然如果計算量太大,比如序列長度n>序列維度d這種情況,也可以用視窗限制self-attention的計算數量

4. 另外,從作者在附錄中給出的栗子可以看出,self-attention模型更可解釋,attention結果的分佈表明了該模型學習到了一些語法和語義資訊

3. 缺點

缺點在原文中沒有提到,是後來在Universal Transformers中指出的,在這裡加一下吧,主要是兩點:

  1. 實踐上:有些rnn輕易可以解決的問題transformer沒做到,比如複製string,尤其是碰到比訓練時的sequence更長的時
  2. 理論上:transformers非computationally universal(圖靈完備),(我認為)因為無法實現“while”迴圈

4. 總結

Transformer是第一個用純attention搭建的模型,不僅計算速度更快,在翻譯任務上也獲得了更好的結果。Google現在的翻譯應該是在此基礎上做的,但是請教了一兩個朋友,得到的答案是主要看資料量,資料量大可能用transformer好一些,小的話還是繼續用rnn-based model

以上。


【參考資料】:

  1. Attention is all you need
  2. 知乎:谷歌論文《Attention is all you need》裡Transformer模型的一些疑問?
  3. Stackoverflow: positional embedding