1. Transformer模型
在Attention機制被提出後的第3年,2017年又有一篇影響力巨大的論文由Google提出,它就是著名的Attention Is All You Need[1]。這篇論文中提出的Transformer模型,對自然語言處理領域帶來了巨大的影響,使得NLP任務的效能再次提升一個臺階。
Transformer是一個Seq2Seq架構的模型,所以它也由Encoder與Decoder這2部分組成。與原始Seq2Seq 模型不同的是:Transformer模型中沒有RNN,而是完全基於Attention(以及全連線層)。在大型資料集上,它的效果可以完全碾壓RNN模型(即使RNN中加入Attention機制)。現如今例如機器翻譯場景,已經看不到RNN的影子了,基本都是Transformer + Bert。
Transformer模型的架構如下圖所示:
Figure 1: The Transformer - model architecture[1]
在上圖中,左邊的是Encoder部分,右邊的是Decoder部分。它們旁邊均有個Nx,這個代表的是有N個這個的結構層進行堆疊,這裡N為6。假設左邊與右邊部分命名分別為Base_Encoder_Layer和Base_Decoder_layer(均拋開Input Embedding與Positional Encoding),則Encoder由Base_Encoder_Layer堆疊6次組成,Decoder是由Base_Decoder_layer堆疊6次組成。
由於Transformer也是Seq2Seq模型,所以它們的輸入輸出與流程基本一致。在Transformer中,輸入首先經過詞嵌入(Word Embedding)以及(Positional Encoding),然後輸入到6個堆疊的Base_Encoder_Layer中,得到隱藏層的向量表示h。然後在Decoder中,隱藏層向量h會輸入到每個Base_Decoder_Layer。Decoder的輸入經過6個堆疊的Base_Decoder_Layer後,得到Decoder的輸出。此過程如下圖所示(此圖是一個基本流程,省去了很多元件):
在對Transformer模型有了一個基本瞭解後,下面逐一介紹Transformer中的各個元件。
2. Input Embedding
與其他序列轉換模型一樣,Transformer使用了預訓練的詞嵌入,將輸入的單詞(Input Embedding層)以及輸出的單詞(Output Embedding層)轉為512維的詞嵌入。詞嵌入的介紹以及方法已經在前面(NLP與深度學習(一)NLP任務流程)已經介紹過,在此不再贅述。不過值得提到的一點是:如果訓練的資料非常大,那麼使用隨機初始化的詞向量與預訓練的詞向量(如word2vec、GloVe)的結果差別不會太大。但如果是參加各類比賽的話,則需要多嘗試各種方法。
2. Positional Encoding
前面提到,Transformer模型種沒有使用RNN,而是完全基於Attention。RNN的一個重要特點就是:對於輸入序列的單詞是有位置資訊的。例如“我愛中國“,第一個輸入字元是”我“,然後是”愛“,直到最後的”國“。所以RNN在處理序列過程種本身就包含了輸入字元的位置資訊。但是這種機制在Attention中是沒有的,所以Transformer在處理輸入序列時,需要對輸入序列的每個token進行位置編碼。
在原論文中,位置編碼的公式為:
首先解釋公式裡的3個引數:
- pos:序列中token(也就是單詞)的位置
- i:詞向量的維度範圍。例如假設詞向量維度為512,則i的範圍為[0, 511]
- dmodel:Embedding維度,論文中為512維
然後可以看到編碼公式一共有2個,分別定義了偶數位置(2i)與奇數位置(2i+1)的位置i的編碼方式。偶數位置i的值使用sin函式,奇數位置的i的值使用cos函式。
下面舉個例子說明編碼方式,以“我愛我的國家“序列為例。其中”愛“在序列中的位置為1(從0開始),維度為512(詞嵌入維度)。所以”愛“的位置編碼為:
PE(1, 2i) = sin(1/100002i/512)
PE(1, 2i+1) = cos(1/100002i/512)
將sin與cos方法抽象出來後,更具體的表現為:
愛 => 512維詞嵌入 [0, 1, 2, …, 511] => 對不同位置i的值進行處理 [sin, cos, sin, …, cos]
如下圖所示:
所以最終對單詞“愛“的位置編碼也為512維(與詞嵌入維度一致)。在得到一個單詞的位置編碼PEtoken後,直接與單詞的Embeddingtoken進行矩陣加法,即完成了對輸入單詞的編碼。
在原論文中,作者還提到了另一種位置編碼的方法:直接通過訓練學習得到位置編碼。並且從測試結果來看,兩者幾乎沒什麼差別。不過作者最終仍使用了正弦曲線(sin與cos)的方法,原因有2點:
- 因為它可以使得模型能夠適應更長的序列。舉個例子,假設訓練集中序列最長長度為100,但是在部署後遇到了長度為110的序列。正弦曲線的方法在這種情況下仍能很好的以預期的方式對序列進行位置編碼。
- 預期模型能夠很容易學習到相對位置的表示。因為任意位置的PEpos+k 都可以被PEpos 以線性函式的方式表示。這點基於的是2個公式:cos(a + b) = cos(a)cos(b) – sin(a)sin(b) 和 sin(a + b) = sin(a)cos(b) + cos(a)sin(b)
在輸入經過了詞嵌入與位置編碼後,下一步遍輸入Encoder進行處理。
3. Base_Encoder_Layer
前面提到Encoder是由6個Base_Encoder_Layer堆疊而來(這裡Base_Encoder_Layer是本文為了方便解釋而提出,並非原論文中的術語),其中每個Base_Encoder_Layer的結構都相同,如下圖所示:
在每個Base_Encoder_Layer中,都由2個Sublayer組成,分別為多頭自注意力機制(Multi-Head Self-Attention mechanism),以及一個前饋網路(Feed Forward)。而每個Sublayer都使用了殘差連線(residual connection)以及層標準化(Layer Normalization)。
使用公式來表示,每個Sublayer的輸出Sublayer_Output即可表示為:
Sublayer_Output = LayerNorm(x + Sublayer(x))
殘差連線與層標準化LN(Layer Normalization)均是用於在模型到一定深度後,為了解決梯度消失的問題而提出(相對於層標準化,還有批標準化BN(Batch Normalization),但是BN在NLP場景有侷限性)。這2部分不在本文的討論中,所以不在此進行贅述。
下面我們介紹Base_Encoder_Layer中最重要的部分——多頭自注意力機制。
4. Multi-Head Self-Attention
在介紹多頭自注意力(Multi-Head Self-Attention)機制前,我們先介紹Self-Attention。
4.1. Self-Attention
在上一章中,我們介紹了注意力(Attention)機制,它被應用於Seq2Seq模型中,解決長序列的表示問題。在每一個時間步t中,在計算Attention時,除了需要當前Decoder在時間步t的輸入外,還需要用到所有輸入序列的hidden states。這個是一般Attention的計算方法。但是在Self-Attention中,並不需要Decoder的輸入,而是僅用Encoder的輸入。
首先我們要明確一個概念:Self-Attention是輸入一個序列,輸出一個同等長度的序列。輸出序列中每個輸出token,都是看過了輸入序列中每個輸入token的資訊後生成 。如下圖所示:
Fig. 2. 李巨集毅. Transformer Model[2]
Self-Attention中涉及到3個可訓練的引數矩陣,分別為WK,WQ與WV。假設輸入的序列為x=[x1, x2, …, xm],使用512維的詞嵌入,則x向量的維度為[m, 512](在batch訓練時,維度應為[batch, m, 512])。在這個前提下,計算Self-Attention的具體步驟為:
- 對每個輸入token xi,分別與引數矩陣WK,WQ與WV 進行矩陣乘法。這3個引數矩陣的維度均為[dimEmbedding, d](其中d = dK = kQ = dV = 64),在原論文中是[512, 64]。得到3個向量分別為:
l Query向量Q=[q1, q2, …, qm],維度為[m, 64]
l Key向量K = [k1, k2, …, km],維度為[m, 64]
l Value向量V = [v1, v2, …, vm],維度為[m, 64]
以x1為例(維度為[1, 512]),分別與WK,WQ與WV做矩陣乘法得到的向量為q1,k1,v1,維度均為[1, 64]。如下圖所示:
Fig. 3. ShusenWang. Transformer Model[3]
- 然後計算權重向量a。對每個qi(維度為[1, 64])與K向量(維度為[m, 64])每一行進行點積(其實就是與每個ki做點積),也就是[qi * k1, qi * k2, …, qm * km]。得到向量a1(維度為[1, m]),並將ai送入Softmax後得到權重向量ai(維度為[1, m])。最終得到權重向量a = [a1, a2, …, am](維度為[m, m])。如下圖所示:
Fig. 4. ShusenWang. Transformer Model[3]
3. 對每個vi(維度為[1, 64]),與其對應的ai權重(維度為[1, m])進行加權平均(此時ai即為vi的權重),得到上下文向量ci,即ci =v1 * a1 + v2 * a2 +…+ vm * am(維度為[1, 64])。並最終得到Self-Attention的輸出,也就是上下文向量c=[c1, c2, …, c3],維度為[m, 64]。如下圖所示:
Fig. 5 ShusenWang. Transformer Model[3]
整個過程用公式表示很簡單:
Attention(Query, Key, Value) = softmax(Query x KeyT) x Value
但是在Transformer中,對Query x KeyT 進行了進一步縮放,使用的公式為:
其中dk = dv = dmodel/h = 64。這裡h表示的Multi-Head的個數,原模型中為8。前面提到過,dmodel為512。
所以在經過了1個Self-Attention層後,輸入由[m, 512] 轉變為了[m, 64]。且每個ci都包含了每個輸入xi的資訊。這篇文章中[4]也很清晰地展示了這個計算過程:
Fig.6. Jay Alammar. The Illustrated Transformer[4]
在瞭解了Self-Attention的計算方法後,下面我們繼續介紹Multi-Head Self-Attention。
4.2. Multi-Head Self-Attention
多頭自注意力機制(Mutli-Head Self-Attention)其實非常簡單,就是多個Self-Attention的輸出的拼接。如下圖所示:
例如,transformer中使用的是8頭(也就是圖中的h=8),那就有8個self-attention模組。這8個self-attention的WK,WQ,WV 引數均不共享。也就是說,會有8組不同的WK,WQ,WV 引數。
前面提到,在經過了1個Self-Attention層後,輸入由[m, 512] 轉變為了[m, 64]。那同時經過8-頭Self-Attention後,將所有Self-Attention的輸出進行拼接,輸出維度即為[m, 512](也就是 64 * 8 = 512)。
5. Encoder總結
前面提到,每個Base_Encoder 中都有2個Sublayer,1個為Multi-Head Attention,1個為前饋網路(Feed Forward Network,其實就是一個全連線層)。每個Sublayer的輸出Sublayer_Output即可表示為:
Sublayer_Output = LayerNorm(x + Sublayer(x))
在經過6個Base Encoder的堆疊後,便得到了Encoder的輸出u=[u1, u2, …, um],維度為[m, 512]。如下圖所示:
Fig. 7 ShusenWang. Transformer Model[3]
它會輸入到每個Base_Decoder_Layer中進行進一步處理。
6. Decoder
同樣,Decoder部分也是由6個Base_Decoder_Layer堆疊而來(這裡Base_ Decoder _Layer同樣也是本文為了方便解釋而提出,並非原論文中的術語),其中每個Base_ Decoder _Layer的結構都相同,如下圖所示(需要注意的是,Base_Decoder_Layer僅代表Nx的那部分,前後的輸入與輸出不包含在這個堆疊結構中):
6.1. Decoder 輸入
在Decoder中,首先來看輸入部分,可以看到這裡有個shifted right,這裡表示右移一位。是為了在給Decoder第一次輸入時,新增一個起始符。因為Decoder在第一次輸入時,需要一個起始符。以機器翻譯為例,將中文翻譯為英文。Encoder輸入是“我愛中國”。在對應Decoder輸出時,它需要一個起始的狀態,例如</start>,將其編碼後,輸入到Decoder中,而後模型應該輸出一個“I”。然後“love”再次作為Decoder的輸入,用於預測下一個單詞。所以正常的Decoder輸出序列應為:
0 – “I“
1 – “love”
2 – “China”
而在Decoder的輸入序列應為:
0 – “</start>”
1 – “I“
2 – “love”
3 – “China”
所以相當於輸出整體右移了1位。
然後便是與Encoder部分同樣結構的Embedding(這個Embedding層與Encoder中Embedding層共享同一組詞嵌入引數)以及Positional Embedding,在此不再贅述。
6.2. Base_Decoder_Layer
Base_Decoder_Layer的結構與Base_Encoder_Layer中sublayer的結構類似,裡面包含3個Sublayer。首先是一個Masked Multi-Head Self Attention層,它與前面提到的Multi-Head Self Attention稍微有點區別。
在Encoder 中,由於序列是一次性輸入的,所以在計算Multi-Head Self Attention時,可以獲取到所有的輸入資訊。但是在Decoder中,只能看到當前已經輸出的序列資訊。以機器翻譯為例,Encoder輸入是“我愛中國“。預期Decoder的輸入應為”I love China“。但是在時間步1時,Decoder輸入了”love“,所以此時Decoder在計算Multi-Head Self Attention時,僅能看到”I love“這2個單詞。所以此時便引入了Masked Multi-Head Self Attention。
Masked Multi-Head Self Attention 與 Multi-Head Self Attention的計算方法類似,也是使用了3個引數矩陣WK,WQ與WV。它們唯一的區別在於計算權重向量a那裡。例如,在第2個時間步t2時,由於Decoder僅能看到輸入的x1與x2,所以在計算權重向量a1時,只會使用到x1與x2,如下圖所示(需要注意的是,Decoder的輸出並非是一個序列,而是每次一個單詞,也就是說,這裡t2時間步的輸出此時只有c2):
在得到Masked Multi-Head Self Attention的輸出後(維度為[1, 512])。繼續進入到下一個
Multi-Head Self Attention。但是在這一層的Multi-Head Self-Attention中,Encoder的輸出也會加入進來,如下圖所示:
Encoder部分e的維度為[m, 512],Decoder輸入部分c1的維度為[1, 512],經過Multi-Head Self-Attention後,輸出為d1,維度為[1,512]。最後,d1會輸入到一個前饋網路。這樣,一個Base_Decoder_Layer便結束了。將6個Base_Decoder_Layer進行堆疊,得到的向量(維度為[1, 512])輸入到一個線性變化層(Linear,就是一個全連線神經網路),然後輸入到softmax後,即可進行根據softmax輸出的概率結果,對下一個單詞進行預測。
7. Transformer總結
Transformer模型的出現,對NLP領域產生了巨大的影響。當前仍非常熱門的預訓練模型如BERT(僅使用了Transformer的Encoder部分),GPT-2,GPT-3(GPT使用的是Decoder部分)等,都是基於Transformer模型而構建。對於小型企業或是各類比賽,這幾個預訓練模型(及其變種)仍然在被廣泛使用。下一章節我們會介紹BERT與GPT以及它們的應用。
References
[1] https://arxiv.org/pdf/1706.03762.pdf
[2] https://www.bilibili.com/video/BV1Wv411h7kN?p=35
[3] https://www.bilibili.com/video/BV1SK4y1d7Qh
[4] http://jalammar.github.io/illustrated-transformer/
[5] https://www.zhihu.com/question/337886108/answer/893002189