1 概述
在介紹Transformer模型之前,先來回顧Encoder-Decoder中的Attention。其實質上就是Encoder中隱層輸出的加權和,公式如下:
將Attention機制從Encoder-Decoder框架中抽出,進一步抽象化,其本質上如下圖 (圖片來源:張俊林博客):
以機器翻譯為例,我們可以將圖中的Key,Value看作是source中的數據,這里的Key和Value是對應的。將圖中的Query看作是target中的數據。計算Attention的整個流程大致如下:
1)計算Query和source中各個Key的相似性,得到每個Key對應的Value的權重系數。在這里我認為Key的值是source的的隱層輸出,Key是等於Value的,Query是target的word embedding(這種想法保留)。
2)利用計算出來的權重系數對各個Value的值加權求和,就得到了我們的Attention的結果。
具體的公式如下:
$ Attention(Query, source) = \sum_{i=1}^{L_x} Similarity(Query, Key_i) * Value_i $
其中 $L_x$ 代表source中句子的長度。
再詳細化將Attention的計算分為三個階段,如下圖(圖片來源:張俊林博客)
1)計算相似性,在這里計算相似性的方法有多種:點積,Cosine相似性,MLP網絡等。較常用的是點積和MLP網絡。
2)將計算出的相似性用softmax歸一化處理。
3)計算Value值的加權和。
在這里的Attention本質上是一種對齊的方法,也可以將Attention看作是一種軟尋址的方法,以權重值將target中的詞和source中的詞對齊。相對應軟尋址(soft-Attention),還有一種hard-Attention,顧名思義就是直接用權值最大的Value值作為Attention。
2 Transformer模型
Transformer模型來源於谷歌2017年的一篇文章(Attention is all you need)。在現有的Encoder-Decoder框架中,都是基於CNN或者RNN來實現的。而Transformer模型匯中拋棄了CNN和RNN,只使用了Attention來實現。因此Transformer是一個完全基於注意力機制的Encoder-Decoder模型。在Transformer模型中引入了self-Attention這一概念,Transformer的整個架構就是疊層的self-Attention和全連接層。具體的結構如下:
上面結構中的左半部分是Encoder,右半部分是Decoder。在詳細介紹結構之前,先來看幾個概念詞:
self-Attention
在一般的Attention中,source和target中的內容是不一樣的,也就是Query是不屬於Key的。而self-Attention是發生在單個句子內的,它的Query是屬於Key的,可以認為下面公式中
$ Attention(Query, source) = \sum_{i=1}^{L_x} Similarity(Query, Key_i) * Value_i $
上面公式中Query = Key = Value。也就是說在序列內部做Attention,尋找序列內部的聯系。
那么為什么要用self-Attention呢?它有什么優點:
1) 可以並行化處理,在計算self-Attention是不依賴於其他結果的。
2)計算復雜度低,self-Attention的計算復雜度是$n^2 d$,而RNN是$n d^2$,在這里$n$是指序列的長度,$d$是指詞向量的維度,一般來說$d$的值是大於$n$的。
3)self-Attention可以很好的捕獲全局信息,無論詞的位置在哪,詞之間的距離都是1,因為計算詞之間的關系時是不依賴於其他詞的。在大量的文獻中表明,self-Attention的長距離信息捕捉能力和RNN相當,遠遠超過CNN(CNN主要是捕捉局部信息,當然可以通過增加深度來增大感受野,但實驗表明即使感受野能涵蓋整個句子,也無法較好的捕捉長距離的信息)。
Scaled dot-product attention
Scaled dot-product attention 的公式如下:
在上面公式中Q和K中的向量維度都是 $d_k$ ,V的向量維度是 $d_v$ ,實際上在self-Attention中,$d_k = d_v = d_wordEmbedding / numHeads$,為了方便將Attention的計算轉化為矩陣運算,論文在這里采用了點積的形式求相似度。常見的計算方法除了點積還有MLP網絡,但是點積能轉化為矩陣運算,計算速度更快。然而點積的方法面臨一個問題,當 $d_k$ 太大時,點積計算得到的內積會太大,這樣會導致softmax的結果非0即1,因此引入了$\sqrt{d_k}$ 來對內積進行縮放。
Multi-Head Attention
這是本文中首次提出的概念,這里的用法有點玄妙,但理解起來也很簡單,其表達式如下:
表達式的計算如下:
1)假設現在頭數為$h$,首先按照每一時序上的向量長度(如果是詞向量的形式輸入,可以理解為embedding size的值)等分成$h$份。
2)然后將上面等分后的$h$份數據分別通過不同的權重($W_i^Q, W_i^K, W_i^V$)映射得到新的Q, K, W的值。
3)將上述映射后的$h$份數據計算相應的Attention的值。
4)按照之前分割的形式重新拼接起來,再映射到原始的向量維度。就得到Multi-Head Attention的值。
在這里每一次映射時的矩陣都不相同,因此映射之后再計算也就會得到不一樣的結果。其實認真來看Multi-Head Attention的機制有點類似與卷積中的多個卷積核,在卷積網絡中,我們認為不同的卷積核會捕獲不同的局部信息,在這里也是一樣,我們認為Multi-Head Attention主要有兩個作用:
1)增加了模型捕獲不同位置信息的能力,如果你直接用映射前的Q, K, V計算,只能得到一個固定的權重概率分布,而這個概率分布會重點關注一個位置或個幾個位置的信息,但是基於Multi-Head Attention的話,可以和更多的位置上的詞關聯起來。
2)因為在進行映射時不共享權值,因此映射后的子空間是不同的,認為不同的子空間涵蓋的信息是不一樣的,這樣最后拼接的向量涵蓋的信息會更廣。
有實驗證明,增加Mult-Head Attention的頭數,是可以提高模型的長距離信息捕捉能力的。
Feed Forward 層
Feed Forward 層采用了全連接層加Relu函數實現,用公式可以表示為:
$ FFN(x) = Relu(xW_1 + b_1) W_2 + b_2$
其實關於在這里並不一定要用全連接層,也可以使用卷積層來實現。
Dropout 層
我們還可以在每個subLayers后面加上一個10%的Dropout層,則subLayers的輸出可以寫成:
$ LayerNorm(x + Dropout(Sublayer(x)))$
介紹到這里可以來看下我們整體的模型結構了。
Encoder
Encoder 是有N=6個layers層組成的,每一層包含了兩個sub-layers。第一個sub-layer就是多頭注意力層(multi-head attention layer),第二個就是一個簡單的全連接層。在每個sub-layer層之間都用了殘差連接,根據resNet,我們知道殘差連接實際上是:
$H(x) = F(x) + x$
因此每個sub-layer的輸出都是:
$ LayerNorm(x + Sublayer(x)) $
在這里LayerNorm中每個樣本都有不同的均值和方差,不像BatchNormalization是整個batch共享均值和方差。
注意:每個Layer的輸入和輸出的維度是一致的。
Decoder
Decoder 同樣是N=6個layers層組成的,但是這里的layer和Encoder不一樣,這里的layer包含了三個sub-layers。第一個sub-layer就是多頭自注意力層,也是計算輸入的self-Attention,但是因為這是一個生成過程,因此在時刻 $t$ ,大於 $t$ 的時刻都沒有結果,只有小於 $t$ 的時刻有結果,因此需要做masking,masking的作用就是防止在訓練的時候使用未來的輸出的單詞。第二個sub-layer是對encoder的輸入進行attention計算的,從這里可以看出Decoder的每一層都會對Encoder的輸出做Multi Attention(這里的Attention就是普通的Attention,非self-Attention)。第三個sub-layer是全連接層。
從上面的分析來看Attention在模型中的應用有三個方面:
1)Encoder-Decoder Attention
在這里就和普通的Attention一樣運用,query來自Decoder,key和value來自Encoder。
2)Encoder Attention
這里是self-Attention,在這里query,key,value都是來自於同一個地方
3)Decoder Attention
這里也是self-Attention,在這里的query,key,value也都是來自於同一個地方。但是在這里會引入masking。
Embedding and Softmax
和其他的序列傳導模型一樣,在這里的source,target的輸入都會使用word embedding。也會用softmax來預測token
Positional Embedding
Positional Embedding 是一個很重要的東西,我們回過頭來看上面的self-Attention,我們發現self-Attention能提取詞與詞之間的依賴關系,但是卻不能提取詞的絕對位置或者相對位置關系。如果將K,V的順序打亂,獲得的Attention的結果還是一樣的。在NLP任務中詞之間的順序是很重要的,因此文章運用了Positional Embedding來保留詞的信息,將每個位置編號,然后每個編號對應這一向量,最后將該向量和詞向量相加,這樣就給每個詞引入了一定的位置信息。
在論文中使用不同頻率的正弦和余弦函數來生成位置向量,表達式如下:
位置向量的維度和word embedding的一致。上面公式中 $pos$ 表示序列中詞的位置,$i$ 表示位置向量中每個值的維度,也就是說$ i < d_{model}$。通過上面公式計算出每一個位置的位置向量。位置向量是可以被訓練的值,而且用上面的公式計算的位置向量並不是絕對的,你也可以用其他的方法求位置向量。
參考文獻:
深度學習中的注意力機制(2017版)
《Attention is All You Need》淺讀(簡介+代碼)