[筆記] Attention 及 Transformer 架構理解

Min
8 min readJan 20, 2021

--

Attention 和 Transformer 來自 Google 2017 發的論文 “ Attention Is All You Need ” 中,其中 Attention 架構結合了 CNN 及 RNN 的優點,並且能改善RNN不能平行運算的缺點。 Transformer 則是基於 Attention 架構的 Encoder 和 Decoder ,接下來將分別講述對於這兩個架構的理解。

Attention

Attention 乍看之下很新潮,但其實只要 input 2 個 vector,output 一個 value,最後 output 會根據這個 value 去加權原本的 input,得到一個新的 context vector,這樣的過程就可以稱為 Attention,至於如何去計算那個 value 就有很多選擇,可以是內積、NN等,這裡紀錄原論文使用的Scaled Dot-Product Attention。

Scaled Dot-Product Attention

對於一個input vector x (本篇 paper 的 x 是 word embedding), 透過三個矩陣W_Q、W_K、W_V 去計算 query vector (q)、key vector (k)、value vector (v)。

這時候每個 x 都能有三個 vector。接下來拿其中一個 x_i 的 query vector,去和其他所有 x_j 的 key vector 做內積,為了要減少維度造成的影響,再來會除以 vector 維度 (d_k) 的開根號。計算出來的值就是 attention weight,也就是下面公式的 alpha,它反應其他 x_j 對應的 v_j 要貢獻多少比例到 output vector。最後的 output vector b_i , 就是所有 v 透過 attention weight 加權的總和。

自己對於這個機制直觀上的理解是: x_i encode 成 query vector(此 query vector 可根據不同情況有不同解釋),key vector 表示 output b_i 需要的 query vector 模樣,那麼這兩個 vector 越相近的話,就是內積的結果越高,表示 x_j 對於 b_i 應該越重要、在計算時要貢獻越高的權重。

最後把所有 q、k、v 寫成一個矩陣的形式就是:

Multi-head Self-attention

相當於是W_Q、W_K、W_V有多個(很像CNN的多層filter概念),最後產生的output會concat起來再降維。在原paper有展示不同的 head 可能會 attend 在不同的東西上,例如長時間的資訊 vs 短時間的資訊。

Scaled Dot-Product Attention & Multi-Head Attention

Position Encoding

看完以上的機制可以發現,這個架構並未考慮 x_i 位置的資訊。所以在實作時會先在 x_i 加上 position embedding 後,再去做 Attention 需要的計算。原 paper 的 position embedding 是固定的,並非可以 train 的參數。

Transformer

Transformer 有 Encoder 和 Decoder ,Encoder 是下圖左方的部分,Decoder 是下圖右方的部分。

Transformer

Encoder

input x_i 加上 position embedding 後,依序經過以下步驟:

  1. Multi-head attention
  2. Add & Norm:Add 即是把 1. 得到的Attention 的 output 各自加上原本對應的 input,後面的 Add 也都是和這裡相同:把 input 和 output 加起來。Norm 指的是 Layer Normalization:將 vector 內的 element 變成 mean = 0,variance = 1。
  3. Feed forward layer、Add & Norm

以上的 Block 有 N 層,一層的 output 會成為下一層的 input,最後的 ouput 再傳到 Decoder。

Decoder

Decoder 的 input 是上一個 timestamp 的 output。一樣加上 position embedding 後,依序經過:

  1. Masked multi-head attention:Masked 的意思是只會 attend 在已經產生的 sequence。
  2. Add & Norm
  3. Multi-head attention、Add & Norm:這裡的 Attention 會 attend 到 encoder 的輸出。也就是把 2. 的輸出拿去算 query vector。key vector 和 value vector 則用 encoder 的輸出來計算。
  4. Feed forward layer、Add & Norm

以上 Block 一樣也有 N 層,最後的 output 再根據 task 進行不同的操作。

Code

以下是簡單的 code 幫助理解:

def vanilla_transformer(enc_inp, dec_inp):
"""Transformer variant known as the "vanilla" transformer."""
x = embedding(enc_inp) * sqrt(d_m)
x = x + pos_encoding(x)
x = dropout(x)
for _ in range(n_enc_layers):
attn = multi_head_attention(x, x, x, None)
attn = dropout(attn)
attn = layer_normalization(x + attn)

x = pointwise_ff(attn) # GELU activation(affine map(attn))
x = layer_normalization(x + attn)

# x is at this point the output of the encoder
enc_out = x

x = embedding(dec_inp) * sqrt(d_m)
x = x + pos_encoding(x)
x = dropout(x)
mask = causal_mask(x)
for _ in range(n_dec_layers):
attn1 = multi_head_attention(x, x, x, mask)
attn1 = layer_normalization(attn1 + x)

attn2 = multi_head_attention(attn1, enc_out, enc_out, None)
attn2 = dropout(attn2)
attn2 = layer_normalization(attn1 + attn2)

x = pointwise_ff(attn2)
x = layer_normalization(attn2 + x)
return dense(x)

Application: BERT

BERT這個 pretrained model 的架構即是來自上面 Transformer 的 Encoder 的灰底區塊。

後續許多 pretrained model 也是沿用 Encoder 灰底區塊的架構,並且在 paper 內會直接稱之為 transformer,和本篇所寫的 Encoder + Decoder 不同。

BERT 做了以下兩個 task 來訓練參數:

  1. Masked LM:mask 掉一些 input 的字詞,在那些 mask 的位置的 output 後面接一個 Linear classifier去預測結果(因為是 Transformer 的 Encoder,所以每個字詞都有對應的一個 output)。
  2. Next Sentence Prediction:把兩個句子用[SEP]的符號接起來,在句子最前面接上[CLS],在[CLS]的output vector後面接上 Linear classifier。

由於以上兩件事都是不需要去 label data ,只要有大量的 document 就可以訓練,但也並不是沒有 target ,而是 target 就在句子本身,所以又有人稱為 self-supervised。

--

--

Min
Min

Written by Min

隨手記一些東西,應該會是和論文閱讀以及實作相關的吧。

No responses yet