[Notes] Attention Is All You Need (Transformer)

Haren Lin
16 min readJun 11, 2021
image source: https://syncedreview.com/2020/01/05/google-uc-berkeley-reformer-runs-64k-sequences-on-one-gpu/

論文連結 Paper Link

https://arxiv.org/pdf/1706.03762.pdf

論文地位 Position

Google Brain在2017年提出了這個Transformer架構,是目前在自然語言處理上最強勁、效果最佳的一個模型。很多新一代的模型都是基於這個架構去改造,例如:BERT,RoBERTa,GPT等等。

摘要 Abstract

現今幾乎所有主流的翻譯模型都是建立在複雜的RNN或CNN的seq2seq架構為基礎,而其中表現最好的模型是基於注意力機制(Attention Mechanism)實現的。本論文提出了一種新的神經網路架構,Transformer,僅依賴於DNN搭配注意力機制,捨棄過往的CNN與RNN架構。在兩個機器翻譯任務上的實驗表明,本模型在效能上更勝一籌,同時可平行化並且減少的訓練時間。

介紹 Introduction

RNN-Based Seq2Seq 缺點:

  1. 因為Auto Regressive,無法進行平行計算
  2. Gradient Vanishing 梯度消失
  3. Uni-directional Representation 僅使用到單方向的表示
  4. Decoder只使用到Encoder最後一個時間點的hidden state
  5. Lower performance on longer sentences 序列越長,效果越差

本文提出的Transformer可以解決大部分上述問題(except #1),完全依靠注意力機制來繪製輸入和輸出之間的全局依賴關係。

[To Learn More] 李鴻毅老師課程補充

有一種方法是Non-AutoRegressive的Sequence Generation:

方法 Methodology

Transformer Model Architecture
Encoder Decoder architecture of Transformers (image source: http://jalammar.github.io/illustrated-transformer/)

Part1. Encoder’s Input

假設我們現在有一句輸入的句子X,經過斷詞之後且通過 Embedding Layer,得到 X = [x1, x2, …, xn],每個xi都是d維向量,所以整個句子是一個n*d的矩陣。在這邊有個東西要注意的是,RNN 會在 t=i 時間點讀進 xi ,但 Transformer 的操作是一口氣讀進來整個完整的X,然而,這樣就失去了文字之間的先後關係,所以加入了 Positional Encoding,P = [p1, p2, …, pn]。這個 Positional Encoding 的長度與輸入 X 長度一樣,每個 pi 都是 d 維向量,所以整個 P 也是一個 n*d 的矩陣。而 pi 的計算方法如下:

計算方法會產生一些奇特的效果。舉例來說,假設把 p5 與周圍的 pi 進行內積運算,得到 e = [e15, e25, e35, e45, e55, …, en5],我們可以發現越靠近自己的位置,ei 的數值會越大,他能夠顯現出文字之間彼此關係的強弱。

最後,我們將 Input Sequence Embedding, X 與 Position Embedding, P 進行相加,形成 E (E = X + P),傳入我們的Encoder,作為輸入使用。

Part2. Encoder

針對 Encoder 的部分,我們可以切割成每個 Encoder Layer 來探討。在每個Encoder Layer中,有兩個 sub-layers,由 Multi-Head 的注意力機制,以及 FCN 全連接層構成。

將 Encoder 的輸入 E,先經過三個矩陣變換:WQi, WKi, WVi (i = [0,7]),形成 Qi (query), Ki (key), Vi (value),都是 n*(d/8) 的矩陣。經過 Multi-Head 之後,他會再把每個 Head 結果 Concat 起來,得到 Q = [q1, q2, …, q8]、K = [k1, k2, …, k8]、V = [v1, v2, …, v8],每個 qi, ki, vi 都是 n*(d/8) 的矩陣,使得 Q, K, V 最後都是 n*d。

Q, K, V Transformation (image source: http://jalammar.github.io/illustrated-transformer/)
Multi-Head Attention (image source: http://jalammar.github.io/illustrated-transformer/)

為什麼要拆成多個Head進行計算?

1. 將原本維度很大的矩陣拆解開來,利於平行處理來加速其運算

2. 作者假設每個Head相互獨立,所學習到的注意力矩陣意義不相同

接著進行Self-Attention的運算,公式如下:

其中,Q 是 n*(d/8),KT = K 轉置矩陣是 (d/8)*n,兩者內積後得到 n*n 的矩陣。而事實上,內積的行為就是在算這兩個向量之間的相似度,所以 Q 與 K 內積的結果,就是他們的相似度分數。QKT(i,j) 代表 Q 的第 i 個字與 K 的第 j 個字的 Attention 大小。算完相似度分數後,還沒結束,記得要再除以根號 dk (dk = d/8)。接著再將計算結果傳入 Softmax,一樣得到 n*n 的矩陣。最後,將剛才的計算結果與 V(每個字的 Value Matrix)進行矩陣相乘,得到 n*(d/8) 的矩陣,並且把每個 Head 的計算結果 Concat 起來後,再乘上一個 W0 得到最後輸出結果 Multi-Head(Q,K,V)。

為什麼要除以根號dk?

這麼做的原因是要防止極端值只有 1與 0 的狀況出現。針對除以 dk 的部分,我們可以舉例來了解:假設現在出現了一組 Attention 數值是 [1000, 0.2, 0.5, …],他們如果經過 Softmax 後會變成 [1, 0, 0, …],極端值只有兩種可能,不是 1 就是 0 。但如果你除以了根號 dk 後再傳入 Softmax,你會得到一個比較不那麼Sparse的結果。

(image source: http://jalammar.github.io/illustrated-transformer/)

總結來說,Multi-Head 的每個 Head 輸入是 n*(d/8) 的矩陣,輸出也是 n*(d/8) 的矩陣。而對於整個 Attention Layer 來說,輸入是 n*d 的矩陣,輸出也是 n*d 的矩陣。我們把本層計算後的結果稱之為 Contextual Representation。

Workflow in Attention Layer (image source: http://jalammar.github.io/illustrated-transformer/)

再來,我們會將結果進行Add & Norm計算。其實就是進行 Residual Connection,為了避免梯度消失,具體上就是將傳入的 E 與經過 Multi-Head Self-Attention 計算出來得結果相加。然後傳入 Layer Normalization,為了穩定訓練過程與收斂速度。公式如下:E = LN( E + MHA(E) )。最後將這個算出來的 E 傳入 Dense/FCN,先放大到 n*4d,再縮回 n*d,並且重複 Add & Norm 計算:E = LN( E + FCN(E) )。

Residual Connection (image source: http://jalammar.github.io/illustrated-transformer/)

總結來說 Encoder Layer,輸入是 n*d,經過 MHA 與 FCN 計算,輸出也還是n*d。由於輸入輸出大小一樣,可以重複疊很多層。(本文N=6,Encoder 使用六層相同的 Encoder Layer。d = 512,dk = 512/8 = 64)

[To Learn More] 李鴻毅老師上課補充

(1) 其實有學者提出,先做Layer Norm再做Residual,效果上會有提升!
參考論文:On Layer Normalization in the Transformer Architecture

(2) 為什麼是Layer Norm,而不是Batch Norm呢?

參考論文:PowerNorm: Rethinking Batch Normalization in Transformers

Part3. Decoder’s Input

針對 Decoder 的 Input,與過往的Seq2Seq不太一樣。我們這邊的輸入是正確的答案 Sequence,不過值得注意的是要經過 shift right。什麼意思呢?一開始的正確解答為 Y = [y1, y2, …, ym],shift right 就是在最一開始的地方加入<BOS>這個token,目的就是為了 Auto-Regressive 的運作。

接著跟Encoder一樣,在得到 Target Sequence Embedding 後,加上 Positional Encoding,D = Y + P,傳入Decoder內。

Part4. Decoder‘s Masked Multi-Head Self-Attention

針對 Decoder 的部分,我們可以切割成每個 Decoder Layer 來探討。在每個Decoder Layer 中,有三個 sub-layers,由 Masked Multi-Head 的注意力機制,Multi-Head 的注意力機制,以及 FCN 全連接層構成。

與Encoder一樣,先將Decoder的輸入D,先經過三個矩陣變換:WQ, WK, WV,形成 Q (query), K (key), V (value),都是m*d的矩陣。每個Q, K, V經過Multi-Head之後,他會拆解成八等份,Q = {q1, q2, …, q8}、K = {k1, k2, …, k8}、V = {v1, v2, …, v8},每個 qi, ki, vi 都是 m*(d/8) 的矩陣。

接著進行 Self-Attention 的運算,算法與 Encoder 的 Attention 計算相同,唯一不同的地方就是 Masked。

為什麼要使用Masked?

因為在計算真實答案的 Attention Score 時,假設我們現在預測第 i 個位置,而 i+1 到 m 位置的文字其實我們還沒看到/還沒預測到,所以沒辦法計算Attention,因此我們要把現在當前這個字與後面的字的相似度關係遮蔽起來,不讓我們的模型架構知道,才不會造成有作弊,先看到答案的情形。

具體上 Masked MHA 在做的事情就是,預測第 1 個字的時候,把後面的字全部 Masked掉。預測第 2 個字的時候,把後面的字全部 Masked 掉。而這個Masked 過後的 QKT,他會形成一個維度為 m*m 的矩陣,且上三角都被Masked 掉,乘上一個很小的數,使他經過 Softmax 後會形成零。再將其除以根號 dk 並經過 Softmax 的結果乘上 V,得到 m*d 的 Attention Matrix。

最後,一樣透過 Add & Norm,D = LN( D + Masked MHA(D) ),形成一個m*d 的矩陣。

Part5. Decoder‘s Multi-Head Attention & FCN

這部分的 Multi-Head Attention Layer,又稱為 Cross Attention,是 Encoder 與 Decoder 之間的橋樑。

把上一階段在 Decoder 部份做好的 D,傳入到這一階段的 Multi-Head Attention Layer,作為 input query (Q),如圖中最右邊的線。此外,左半邊的兩條線分別代表K, Q,由 Encoder 的輸出導入。

所以簡單來說,這邊計算的 Attention Score,就是在了解來自輸出句子的 Q,大小為 m*d,與來自輸入句子的 K,大小為 n*d,兩者之間的關係。而QKT 的計算就是將 m*d 的矩陣與 d*n 的矩陣相乘,得到 m*n 的矩陣。(輸入語言與輸出語言的相似度矩陣)

再將這個相似度關係,與V相乘進行計算,得到 m*n * n*d = m*d 的矩陣。一樣經過 Add & Norm,D = LN( D + MHA(D) )。並且傳入Dense/FCN,重複 Add & Norm 計算:D = LN( D + FCN(D) )。

總結來說 Decoder Layer,輸入是 m*d,經過 MHA 與 FCN 計算,輸出也還是m*d。由於輸入輸出大小一樣,可以重複疊很多層。(本文N=6,Encoder使用六層相同的Decoder Layer。d = 512,dk = 512/8 = 64)

[To Learn More] 李鴻毅老師課程補充

Cross Attention Layer的架構有很多種,不是只有本篇論文的樣子。

參考論文:Layer-Wise Multi-View Decoding for Natural Language Generation

Source: https://arxiv.org/pdf/2005.08081.pdf

Part6. Linear & Softmax

最後把 Decoder 的產出,經過一個 Linear Transform,把維度改成輸出語言的 Vocabulary Size,並將矩陣傳入 Softmax 計算機率值,取出機率最大值作為輸出字預測結果。

(image source: http://jalammar.github.io/illustrated-transformer/)

模型訓練與測試 Model Training & Testing

訓練部分:我們希望輸出結果的 Dist.跟 Ground Truth 的 Dist.差距越小越好,Minimize Cross Entropy。其中要注意的是,他會使用 Teacher Forcing 的方法,避免模型一步錯步步錯。

測試部分:因為訓練是使用 Teacher Forcing,永遠會拿到正確的字作為輸入,但是在測試時,我們會拿上一個時間點產生的字作為當前時間點的輸入,這時候我們很難避免我們拿到的輸入是錯誤的。這樣形成了訓練與測試之間的 Mismatch,我們稱之為 Exposure Bias。那我們應該如何解決這樣的問題呢?加一些錯誤的東西到我們的訓練資料,簡單講就是製造 Noise,也就是 Schedule Sampling。不過要注意的是,原始版本的 Schedule Sampling 會傷害到 Transformer 的平行運算,所以有衍生岀 Transformer專用的 Schedule Sampling Algorithm。

(a) Original Schedule Sampling: https://arxiv.org/abs/1506.03099
(b) Schedule Sampling for Transformer: https://arxiv.org/abs/1906.07651
(c) Parallel Scheduled Sampling: https://arxiv.org/abs/1906.04331

[Tips] Pointer Network / Guided Attention (Monotonic Attention, Location-Aware Attention) / Beam Search

結論 Conclusion

Transformer’s Contribution:

  1. 不使用CNN與RNN,而是單純用DNN
  2. 使用內積 Dot Product 來進行 Self-Attention
  3. Multi-Head的每個Head獨立,利於平行化的運算
  4. 運用Positional Encoding來得知上下文資訊

Transformer’s Drawback:

  1. 計算成本隨著輸入輸出指數成長
  2. Auto-Regressive Inference

參考資料 Reference

  1. 科普學AI論文導讀
  2. 李鴻毅老師課程影片(上)

3. 李鴻毅老師課程影片(下)

4. 李鴻毅老師課程投影片
5. 他人論文筆記
6. Illustrated Transformer ( → highly recommended article to understand Transformer in detail)

延伸閱讀 Extra Reading

由於我這篇 Medium 文章只是個人筆記,如果想看更多 Transformer 的細節,且以中文解釋的,請參考這篇文章:A Brief Overview: Vanilla Transformer v.s. Universal Transformer。英文版本圖解 Transformer 請參考:The Illustrated Transformer

Medium 上,有人分享手刻 Tensorflow 版本的 Transforer:

This article will be updated at any time! Thanks for your reading. If you like the content, please click the “clap” button. You can also press the follow button to track new articles. Feel free to connect with me via LinkedIn or email.

--

--

Haren Lin

MSWE @ UC Irvine | MSCS @ NTU GINM | B.S. @ NCCU CS x B.A. @ NCCU ECON | ex-SWE intern @ TrendMicro