NLP model — Transformer ( All Attention you need )

陳明佐
我就問一句,怎麼寫?
9 min readJul 22, 2019

自Attention mechanism 提出後,加入attention的Seq2seq模型在各個任務上都有了提升

所以現在的seq2seq模型指的都是結合RNN和attention的模型

之後google又提出了解決sequence to sequence問題的transformer模型

用全attention的結構代替了LSTM,在翻譯任務上取得了更好的成績,本文主要介紹《Attention is all you need》

Encoder

Encoder由N=6個相同的layer組成,layer指的就是上圖左側的單元,最左邊有個“Nx”,這裡是6個

每個Layer由兩個sub-layer組成,分別是multi-head self-attention mechanism和fully connected feed-forward network

其中每個sub-layer都加了residual connection和normalization,因此可以將sub-layer的輸出表示為:

Multi-head self-attention

Attention可由以下形式表示:

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

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

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

作者同樣提到了另一種複雜度相似但計算方法additive attention

在dk很小的時候和dot-product結果相似,dk大的時候,如果不進行縮放則表現更好

但dot-product的計算速度更快,進行縮放後可減少影響(由於softmax使梯度過小,具體可見論文中的引用)

Position-wise feed-forward networks

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

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):

Positional Encoding

除了主要的Encoder和Decoder,還有數據預處理的部分

Transformer拋棄了RNN,而RNN最大的優點就是在時間序列上對數據的抽象

所以文章中作者提出兩種Positional Encoding的方法,將encoding後的數據與embedding數據求和,加入了相對位置信息

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

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

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

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

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

2. 如果是學習到的positional embedding,(個人認為,沒看論文)會像詞向量一樣受限於詞典大小

也就是只能學習到“位置2對應的向量是(1,1,1,2)”這樣的表示

所以用三角公式明顯不受序列長度的限制,也就是可以對比所遇到序列的更長的序列進行表示

實際操作狀況 Encoder — Multi-Head

Multi-Head Attention結構,這個結構是算法單元中最重要的部分

之後是做了一個shortcut的處理,就是把輸入和輸出按照對應位置加起來

如果了解殘差網絡(ResNet)會對這個結構比較熟悉,這個操作有利於加速訓練,然後經過一個歸一化normalization的操作

接著經過一個兩層的全連接網絡,最後同樣是shortcut和normalization的操作

這裡需要注意的是,每個小模塊的輸入和輸出向量,維度都是相等的

比如,Multi-Head Attention的輸入和輸出向量維度是相等的,否則無法進行shortcut的操作

Feed Forward的輸入和輸出向量維度也是相等的;最終的輸出和輸入向量維度也是相等的

但是Multi-Head Attention和Feed Forward內部,向量維度會發生變化

從上圖的左側Encoder橙色方塊可以看到,embedding在進入到Attention之前,有3個分叉

那表示說從1個向量,變成了3個向量

具體來說,算法是定義一個WQ矩陣(這個矩陣隨機初始化,通過訓練得到),將embedding和WQ矩陣做乘法

得到查詢向量q,假設輸入embedding是512維,下圖中我們用4個小方格表示,輸出的查詢向量是64維,下圖中用3個小方格以示不同

然後類似地,定義WK和WV矩陣,將embedding和WK做矩陣乘法,得到鍵向量k;將embeding和WV做矩陣乘法,得到值向量v

對每一個embedding做同樣的操作,那麼每個輸入就得到了3個向量,查詢向量,鍵向量和值向量

需要注意的是,查詢向量和鍵向量要有相同的維度,值向量的維度可以相同,也可以不同,但一般也是相同的

接下來我們計算每一個embedding的輸出,以第一個詞Thinking為例:

用查詢向量q1跟鍵向量k1和k2分別做點積,得到112和96兩個數值

這也是為什麼前文提到查詢向量和鍵向量的維度必須要一致,否則無法做點積

然後除以常數8,得到14和12兩個數值

這個常數8是鍵向量的維度的開方,鍵向量和查詢向量的維度都是64,開方後是8

做這個尺度上的調整目的是為了易於訓練,然後把14和12丟到softmax函數中

得到一組加和為1的係數權重,算出來是大約是0.88和0.12

將0.88和0.12對兩個值向量v1和v2做加權求和,就得到了Thinking的輸出向量z1

類似的,可以算出Machines的輸出z2。如果一句話中包含更多的詞,也是相同的計算方法

每個詞的輸出向量z都包含了其他詞的信息,每個詞都不再是孤立的了

而且每個位置中,詞與詞的相關程度,可以通過softmax輸出的權重進行分析

Multi-Head,對於同一組輸入embedding,我們可以並行做若干組上面的操作

例如:我們可以進行8組這樣的運算,每一組都有WQ,WK,WV矩陣,並且不同組的矩陣也不相同

這樣最終會計算出8組輸出,我們把8組的輸出連接起來,並且乘以矩陣WO做一次線性變換得到輸出

WO也是隨機初始化,通過訓練得到,計算過程如下面所示

這樣的好處,一是多個組可以並行計算,二是不同的組可以捕獲不同的子空間的信息

RNN的結構包含了序列的時序信息,而Transformer卻完全把時序信息給丟掉了

為了解決時序的問題,Transformer的作者用了一個絕妙的辦法,就是前面提到的位置編碼(Positional Encoding)

位置編碼是和word embedding同樣維度的向量,將位置embedding和詞embedding加在一起,作為輸入embedding

位置編碼可以通過學習得到,也可以通過設置一個跟位置或者時序相關的函數得到,比如設置一個正弦或者余弦函數

Reference

https://zhuanlan.zhihu.com/p/44121378

https://zhuanlan.zhihu.com/p/47510705

--

--