Transformer 看這一篇就夠了

知了愛啃程式碼發表於2020-12-03

之前我在這篇語言模型(五)—— Seq2Seq、Attention、Transformer學習筆記中說過要對Transformer來一個摳細節的筆記,今天它來了。由於大部分內容在上文中已有過系統地介紹,本篇筆記將側重點放在各個環節中一些重要的細節中,當然也會盡量按照主線流程來展開。歡迎食用。


全域性視角

語言模型(五)—— Seq2Seq、Attention、Transformer學習筆記中,我們已經看到過這樣的全域性視角,這裡引述一小段過來,以便在接下來的探索中不迷失:

在Transformer中,我們仍然能夠看見他其實也是由傳統的Encoder-Decoder演化而來,還是以機器翻譯為例,大致的結構圖還是與之前一樣,其中Encoders和Decoders 部分都是由6層Encoder或Decoder堆疊而成(也可以改的更多層):

image-20200724081154057image-20200724081517511

基礎版 Encoder = Self-Attention + FFN

每一個Encoder結構我們稱之為一個Encoder Block。它的內部結構如下:

image-20201202111627553

語言模型(五)—— Seq2Seq、Attention、Transformer學習筆記中所講,Encoder Block由Self-Attention和一個FFN組成。這裡需要再次強調一下Self-Attention與傳統Sequence to Sequence 中Attention(稱之為Encoder-Decoder Attention)的不同:

Encoder-Decoder Attention中是由Decoder作為Query來Attention Encoder中的隱藏態,是一個序列對另一個序列的Attention;而Self-Attention則是在一個序列樣本的上下文詞之間相互的Attention。

比如說機器翻譯中的指代問題,翻譯以下句子時“it” 能Self-Attention到"animal" 。而原先,可能只是”動物“Attention到"animal" 。這便是最大的區別。

The animal didn't cross the street because it was too tired

那下面我們具體來看Self-Attention的細節,還是那張圖,這次我們標記出部分向量的維度和運算過程:

image-20201202121945636

從圖中一點點往下看,第一個細節:

**Embedding的物件不一樣了。**對於中文來講,之前我們Embedding的物件是詞級別,比如說對於“中國歡迎您”這句話,在seq2seq中,我們一般會分詞”中國/歡迎/您“,但是在這裡我們一般會將一句話切分成所謂的token級別,也就是一個字元一個字元的”中/國/歡/迎/您“。那為什麼可以這樣呢?因為當我們分詞成”歡迎“的時候,其實就是預先提供了一定的語義特徵,而現在模型學習能力更強了,我們認為”歡/迎“能學習到”歡迎“在上下文中的意思了,所以Embedding的物件也就可以不一樣了。

第二個細節:

輸入的Embedding加入了位置資訊。為了讓模型能夠學習到詞語在語句中不同位置時可能的不同含義,Self-Attention中的Embedding在傳統的Embedding基礎上加入了位置編碼Position Encoding。這是個什麼意思呢?它其實就是給了相鄰的token以不同的初始化位置資訊。為了方便計算,這樣的位置資訊往往又是有周期性的。不要懵。看到下面的公式可能更懵:

image-20201202211652930

但不要被這個公式迷惑,重點是要理解這個位置編碼是要幹嘛以及簡單的實現原理:偶位置按照正弦函式編碼、奇位置按餘弦函式編碼。這樣當你在座標軸上畫出正餘弦函式影像的時候你會發現,相鄰位置的token一個在正弦函式上一個在餘弦函式上,每個token都有他自己獨特的位置,即:各token初始化位置按sin/cos週期分佈

還有一個問題,不用這種正餘弦函式進行位置編碼可不可以?當然可以,你也可以給一串token進行0-99的位置編碼,99號用完下一個再編號0。

繼續看下圖,我們回到Self-Attention的主流程上來:

image-20201202221610453
  1. 單詞Thinking對應的embedding維度是512維,乘上神經網路引數W_Q(512x64),得到對應的Query:q1(64維),同理得到k1。

  2. q、k點乘得到Score,這一步我們已經在Seq2Seq中說過,含義其實是求了一個相似度。

  3. Score除以根號d_k。再將得到的值通過softmax進行歸一化,得到Attention Weight。

    那麼細節又來了,為什麼要縮放?又為什麼是根號d_k?

    需要收縮的原因在於:使資料分佈更平滑,防止梯度消失。解釋:(如下圖softmax的影像)由於需要做softmax,資料分佈太不集中可能會導致某些分佈點的資料在反向求導的時候沒有梯度。我們需要通過縮放將資料分佈拉回到一個正常的分佈區間裡來。那為什麼是除以根號d_k呢,因為我們期望的是資料分佈要服從(0,1)標準正態分佈,但不縮放的時候資料分佈是服從均值為0,方差為根號d_k的正態分佈,所以要除以根號d_k,將方差拉回到1。

    image-20201202214709682

  4. 加權求和得結果z(對應Encoder-Decoder Attention中的context vector)。

回顧上面的四步,對照Encoder-Decoder Attention中的整個計算流程,不難發現一個細節:q對應Encoder-Decoder Attention中Decoder 輸出的上一時刻的隱藏層輸出h_t-1,k、v對應的Encoder-Decoder Attention中Encoder的隱藏層輸出h_s。如果有點迷糊,可以回去看一眼:Attention機制全流程詳解與細節學習筆記

得到z向量之後,按照Encoder Block的結構圖,下面將各個z傳入FFN,這樣便完成了一個Encoder Block的工作。好,暫停一下,我們來看一看這個FFN。

細節:

這裡的FFN有兩層全連線層:W2(Relu(W1x+b1))+b2,為什麼要加這個FFN?因為裡邊的啟用函式Relu為整個網路提供了非線性的學習能力,不然拿一個線性的網路去學習這個複雜的世界,那些重要的非線性特徵都沒法被髮掘出來。

升級版Encoder = Multi-Head Attention + Add&Norm +FFN

先來一張表,看看這個transformer中真正發育完全的升級版是長啥樣,再看看它和基礎版的差異。

注:”基礎版“和”升級版“是我自己起的名字(原論文作者勿怪),實際上”升級版“是真正的Transformer,為了理解上的方便,我在這裡給起了名字進行區分,也可以理解成基礎版就是沒有多頭注意力機制、沒有Add&Norm的原始版本。

基礎版升級版
整體結構image-20201203000546541image-20201203000405155
Encoder Blockimage-20201202111627553image-20200724160802104
Self-Attention的形態Transformer 看這一篇就夠了image-20200724153123975

當你看完這個表,你會發現,升級版的升級點主要在兩點:

  • Self-Attention的形態由單頭變為多頭,原先是一個Scaled Dot-Product Attention,現在變成了多個Scaled Dot-Product Attention並行。
  • Self-Attention和FFN之後都多了一步Add&Norm 的處理。

來吧,我們一個個來。先說Multi-Head Attention,為什麼要搞這麼一個東西出來?兩點原因:

  1. 增強了模型輸入處理的並行性
  2. 同時它對輸入的 Q,K,V 進行多次不同的對映,相當於把句子投影到不同的子空間中,提高其表達能力。(原文中8個頭,其實就有八組QKV,可以理解成每一組學習的角度不一樣,學到的東西也不一樣)

那這個多頭注意力機制又是怎麼實現的呢?直接看圖:

image-20201203004455584

整個Multi-Head Attention出來之後就來到了Add&Norm層,這裡邊主要包含兩部分:加入殘差(Add)和Layer Normalization(Norm)。

即:Layer Norm(X + Z)

那麼靈魂三問來了:

為什麼要加入殘差結構?

答:為了解決網路層數過深帶來的梯度消失問題。

Layer Normalization是什麼?

層級的Normalization。LN與BN作用一樣:防止梯度消失,加快收斂速度。

為什麼不用BN而用LN?

因為在這裡我們資料規範化的物件的維度一般都是(batch_size, seq_lenth, 512),如果是BN,歸一化的物件是整個一批資料(可以理解為是對batch_size這一維度)進行歸一化,因為每一條資料裡都可能會有padding補充的0元素,導致一個BN下來,整個資料的均值會降低,資料分佈也就改變了。如果是LN。它是針對於每一條資料的(可以看作是seq_lenth這一維度),一行行的歸一化不會包含padding進來的0,這樣資料的分佈也就能不被改變。

以圖說明如下:

image-20201203012722816

而為什麼在影像處理中,可以用BN,因為影像的每一個畫素點都有值,沒有padding 0帶來的問題。所以可以用BN。

延申:介於LN和BN之間還有一個Group Normalization,可以另行學習。

到這裡我們就看完了Encoder部分的所有東西,那麼問題又來了:

Transformer中只要Encoder可以嗎?

當然可以,事實上,整個Encoder就像一個RNN,它就是一個特徵提取器,它生成的特徵向量可以去做很多事情,比如加一個FC做分類任務、甚至可以把它當詞向量、句向量等等。

只有在生成式任務中我們才需要用到Decoder部分,其他任務Encoder就足以勝任。

image-20201203013648308

再繼續,我們來看看Decoder部分到底有啥?

Decoder = Masked Self-Attention + Encoder_Decoder Attention

還是先看基礎版的Decoder:

image-20201203020147940

重點都在圖上標註了:

Decoder中第一部分的Self-Attention與Encoder中的Self-Attention基本一致,Q、K、V都來源於自己對輸入y的學習。只不過多加了一個mask操作,這個mask操作是幹嘛的呢?

因為在Decoder時(比如預測句子的時候),當前時刻是不能提前獲取到未來時刻的資訊,即得把後面的答案遮住,不能提前把答案包進去學習了。遮住後面的答案,這就是mask操作。

第二部分,有一個Encoder-Decoder Attention,這就跟Seq2Seq中講的Attention是一樣的了,需要拿Encoder的輸出和Decoder的隱態來計算Attention Weight。這裡邊的Q是自己第一部分學習到的,K和V都是Encoder輸出過來的。這點需要注意。

說完了基礎版的Decoder , 升級版自然就是多頭並行了,原理和Encoder一樣,便不再贅述。

回顧

還是這張圖,在語言模型(五)—— Seq2Seq、Attention、Transformer學習筆記的回顧環節,也是這張圖,現在當你再看到這張圖,你會發現整個Transformer的流程和一些細節應該都藏在這張圖裡了。不信你品,你仔細品。

image-20200724154423110

最後有一個小小的劇透,左邊的Encoder將會是BERT的基礎,而右邊的Decoder卻又是GPT的基礎。

小結

一篇長文,花了將近五個小時來寫,但卻覺得很是值得。現在又到了凌晨兩點半,準備洗洗睡。諸位看官,看到這裡如果覺得還不錯請給一個贊|收藏|關注,一鍵三連對我來說便是最好的鼓勵了。

不積跬步,無以至千里。加油!

兩篇神文繼續貼在這:

Attention Is All You Need

The Illustrated Transformer

相關文章