本文主要是參考
https://yq.aliyun.com/articles/342508?utm_content=m_39938
將互相缺少的融合到一起,略微加了點其他東西。
一、簡介
對於Seq2Seq任務,均採用encoder-decoder+attention的模型,以往的encoder-decoder採用rnn或cnn,捕捉輸入輸出的全局信息,attention捕捉輸入和輸出之間的側重關係;而這篇google大作,採用的是attention做encoder-decoder;也就是說,模型中只有attention, 沒有rnn或者cnn。
二、模型整體架構
encoder由6個相同的層堆疊在一起,每一層又有兩個支層。第一個支層是一個多頭的自注意機制(Multi-head attention),第二個支層是一個簡單的全連接前饋網絡(position-wise FFN)。在兩個支層外面都添加了一個residual的連接,然後進行了layer nomalization的操作。模型所有的支層以及embedding層的輸出維度都是dmodel=512.
Stage1_out = Embedding512 + TokenPositionEncoding512
Stage2_out = layer_normalization(multihead_attention(Stage1_out) + Stage1_out)
Stage3_out = layer_normalization(FFN(Stage2_out) + Stage2_out)
out_enc = Stage3_out
decoder也是由6個相同的層堆疊在一起,不過每層除了編碼器中那兩個支層,還加入了第三個支層,即該層decoder和對應層encoder之間的多頭注意力機制,同樣也用了residual以及layer normalization,因爲decoder時只能用這個token之前的tokens,那麼做attention的時候需要添加一個mask將這個token及其之後的遮蓋住(是一種從左到右預測的味道)。
Stage1_out = OutputEmbedding512 + TokenPositionEncoding512
Stage2_Mask = masked_multihead_attention(Stage1_out)
Stage2_Norm1 = layer_normalization(Stage2_Mask + Stage1_out)
Stage2_Multi = multihead_attention(Stage2_Norm1 + out_enc) + Stage2_Norm1
Stage2_Norm2 = layer_normalization(Stage2_Multi) + Stage2_Multi
Stage3_FNN = FNN(Stage2_Norm2)
Stage3_Norm = layer_normalization(Stage3_FNN + Stage2_Norm2)
out_dec = Stage3_Norm
三、分塊解析
1. Scaled Dot-Product Attention
如果忽略激活函數 softmax 的話,那麼事實上它就是三個 的矩陣相乘,最後的結果就是一個的矩陣。於是我們可以認爲:這是一個 Attention 層,將的序列 Q 編碼成了一個新的 的序列。
那怎麼理解這種結構呢?我們不妨逐個向量來看。
其中 Z 是歸一化因子。事實上分別是 query,key,value 的簡寫, 是一一對應的,它們就像是 key-value 的關係,那麼上式的意思就是通過 這個 query,通過與各個 內積的並 softmax 的方式,來得到 與各個 的相似度,然後加權求和,得到一個 維的向量。其中因子起到調節作用,使得內積不至於太大(太大的話 softmax 後就非 0 即 1 了,不夠“soft”了),因爲文章假設數據符合標準正態分佈,爲了使點乘結果的方差爲1,所以使用了根號。
2. Multi-Head Attention
不過從形式上看,它其實就再簡單不過了,就是把 通過參數矩陣映射一下,然後再做 Attention,把這個過程重複做 h 次,結果拼接起來就行了,可謂“大道至簡”了。具體來說:
最後得到一個 的序列。所謂“多頭”(Multi-Head),就是隻多做幾次同樣的事情(參數不共享),然後把結果拼接。有點類似於cnn裏面的多kernel。
本文中,大部分的 Attention 都是 Self Attention,即“自注意力”,或者叫內部注意力,就是, 就是前面說的輸入序列。也就是說,在序列內部做 Attention,尋找序列內部的聯繫。decoder裏面和encoder的attention是
3. position-wise FFN
一個position對應一個詞,一個詞對應矩陣的一行,該函數爲對矩陣的每一行做兩個線性映射,中間加一個ReLU,每一行的線性映射參數一樣,相當於size爲1的kernel。不同layer的兩個線性映射參數不一致。記輸入矩陣的某行爲,則:
4. position encoding
但是這樣的模型並不能捕捉序列的順序。換句話說,如果將 按行打亂順序(相當於句子中的詞序打亂),那麼 Attention 的結果還是一樣的。所以,到目前爲止,Attention 模型頂多是一個非常精妙的“詞袋模型”而已。
但是對於時間序列來說,尤其是對於 NLP 中的任務來說,順序是很重要的信息,它代表着局部甚至是全局的結構,學習不到順序信息,那麼效果將會大打折扣(比如機器翻譯中,有可能只把每個詞都翻譯出來了,但是不能組織成合理的句子)。
於是 引入——Position Embedding,也就是“位置向量”,將每個位置編號,然後每個編號對應一個向量,通過結合位置向量和詞向量,就給每個詞都引入了一定的位置信息,這樣 Attention 就可以分辨出不同位置的詞了。
以前在 RNN、CNN 模型中其實都出現過 Position Embedding,但在那些模型中,Position Embedding 是錦上添花的輔助手段,也就是“有它會更好、沒它也就差一點點”的情況,因爲 RNN、CNN 本身就能捕捉到位置信息。但是在這個純 Attention 模型中,Position Embedding 是位置信息的唯一來源,因此它是模型的核心成分之一。
在以往的 Position Embedding 中,基本都是根據任務訓練出來的向量。而 Google 直接給出了一個構造 Position Embedding 的公式:
這裏的意思是將位置 映射爲一個 dpos 維的位置向量,這個向量的第 i 維的數值就是 PEi(p)。
Position Embedding 本身是一個絕對位置的信息,但在語言中,相對位置也很重要,由於我們有 以及 ,這表明位置 的向量可以表明位置 的向量的線性變換,這提供了表達相對位置信息的可能性。
結合位置向量和詞向量有幾個可選方案,可以把它們拼接起來作爲一個新向量,也可以把位置向量定義爲跟詞向量一樣大小,然後兩者加起來,本文選擇加起來。
四、優點
從三個方面去對比self-attention和遞歸結構、卷積結構的優劣性,首先是每一層的計算複雜度,其次是能夠被並行的計算量,最後是網絡中長期依賴的路徑長度。對比顯示,self-attention表現最好。
Attention 層的好處是能夠一步到位捕捉到全局的聯繫,因爲它直接把序列兩兩比較(代價是計算量變爲 ,當然由於是純矩陣運算,這個計算量相當也不是很嚴重)。相比之下,RNN 需要一步步遞推才能捕捉到,而 CNN 則需要通過層疊來擴大感受野,這是 Attention 層的明顯優勢。