天天看點

Transformer論文閱讀:Attention Is All You Need前言介紹Transformer結構why self-attention訓練

文章目錄

  • 前言
  • 介紹
  • Transformer結構
    • Encoder
      • 1. Multi-Head Attention
      • 2. Positional Encoding
      • 3. Add&Norm
      • 4. Position-wise Feed-Forward Networks
      • 5. Embeddings
    • Decoder
      • 1. masked multi-head attention
      • 2. 連接配接Encoder和Decoder的部分
      • 3. Linear transformation和softmax
  • why self-attention
  • 訓練
    • 正則化政策

前言

自己感覺不錯的入門方式:先看李宏毅的self-attention和transformer的視訊,了解好計算步驟;再自己去看論文更加深入地了解Transformer的架構;再看李沐的Transformer論文閱讀搞清楚自己沒有發現的一些點。

介紹

首先要了解seq2seq是什麼東西。seq2seq簡單來說就是:輸入是一個序列,輸出也是一個序列且輸出的長度是不确定的。之前的seq2seq model的結構基本是:基于RNN或CNN的一個encoder和一個decoder,以及通過 attention machanism 連接配接 encoder 和 decoder。

了解RNN的都知道,RNN的輸出需要上一個輸出作為輸入,也就是它不能做到并行處理;而且RNN無法考慮到太久以前的資訊(傳着傳着就沒了)。後來的LSTM可以處理更長的序列,但是它仍做不到并行處理。

CNN實際上算是注意力機制的一種特殊情況,它考慮的是固定範圍的輸入,對感受野内的值進行權重求和。

Attention mechanism(注意力機制)就像它的名字所說,它是用來計算模型輸出一個東西的時候應該更加注意哪些輸入。舉個例子:翻譯 “hello world”,輸出第一二個字“你好”時,注意力機制就要求模型更加關注 “hello” 這個詞。它可以在 不用考慮輸入與輸出的情況下 計算輸出和輸入的相關性,為并行化提供了條件。

但是之前的模型都是把注意力機制跟循環網絡一起用的,導緻無法并行化。是以 Transformer 抛棄了循環網絡,完全使用注意力機制,進而實作了并行化,且效果達到了最佳。

Transformer使用的是 self-attention(自注意力機制),就是用輸入計算權重,再對輸入進行權重求和(後面會講)。

Transformer結構

Transformer論文閱讀:Attention Is All You Need前言介紹Transformer結構why self-attention訓練

Transformer仍然使用 encoder-decoder 架構。圖中左邊為 encoder 的一個block,右邊為 decoder 的一個 block,一個 encoder/decoder 由N(N=6)個這樣的blocks組成。

Encoder

Encoder的一個block的結構:輸入進入embedding layer得到 input embedding,再加上一個 positional encoding 輸入 multi-head attention 中,經過 add&norm 後再輸入全連接配接的 feed forward,再輸入 add&norm。

下面一一介紹每一部分。

1. Multi-Head Attention

再介紹多頭注意力機制前,得先知道單頭自注意力機制是怎麼算的。

一、單頭注意力機制

常見的自注意力機制有兩種,一種是 addtive attention,一種是 dot-product attention(需要向量queries和keys次元相同)。它們的效果差不多,但是 dot-product attention 隻需要做矩陣乘法,計算更簡單,是以論文使用第二種。

Transformer論文閱讀:Attention Is All You Need前言介紹Transformer結構why self-attention訓練

上面的圖就是 scaled dot-product attention 的計算方式。那Q, K, V是什麼呢,接下來講。

矩陣Q, K, V分别表示query, key, value,它們都是用輸入的矩陣乘以矩陣 W Q , W K , W V W^Q, W^K, W^V WQ,WK,WV計算來的。從它們的意思直覺了解,queries就是想要問詢一個輸入與每個輸入有多大關系;keys就是每個輸入對應的關鍵資訊,用來給queries計算相關程度的;values就是queries計算完相關程度後,用來權重求和的值。

假設有n個輸入,那麼每個輸入會對應一個query vector q i q_i qi​、一個key vector k i k_i ki​、一個value vector v i v_i vi​,它們組成矩陣Q, K, V,次元分别為 n × d k n\times d_k n×dk​, n × d k n\times d_k n×dk​, n × d v n\times d_v n×dv​。

① 先用 q i q_i qi​ 和 k j k_j kj​ 做内積得到attention scores,也即 A = Q K T A = QK^T A=QKT;

② 再除以 d k \sqrt{d_k} dk​

​,做scaled;這裡要做scaled的原因是:當 d k d_k dk​較大時,dot-product attention的效果會變差。這是因為值太大時softmax的梯度會消失,是以要做scaled。

③ 做softmax: A ′ = s o f t m a x ( A d k ) A' = softmax(\frac{A}{\sqrt{d_k}}) A′=softmax(dk​

​A​),得到attention scores;

④ 最後做權重求和: A t t e n t i o n ( Q , K , V ) = A ′ V Attention(Q, K, V)=A'V Attention(Q,K,V)=A′V。輸出的次元為 n × d v n\times d_v n×dv​,每一行代表一個輸入。

二、多頭自注意力機制

單頭的隻能提取到一種相關性,為了提取多種相關性,就使用多頭(multi head)的。

Transformer論文閱讀:Attention Is All You Need前言介紹Transformer結構why self-attention訓練

從圖中可以看出,multi-head就是把Q, K, V分别做線性映射成h個矩陣,再對這些矩陣分别做h次single-head,最後再concat在一起後做線性映射。

用公式來表示就是:

h e a d i = A t t e n t i o n ( Q W i Q , K W i K , V W i V ) , i = 1 , 2 , . . . , h head_i=Attention(QW_i^Q, KW_i^K, VW_i^V), i=1, 2, ..., h headi​=Attention(QWiQ​,KWiK​,VWiV​),i=1,2,...,h

M u l t i H e a d ( Q , K , V ) = C o n c a t ( h e a d 1 , . . . , h e a d h ) W O MultiHead(Q, K, V)=Concat(head_1, ..., head_h)W^O MultiHead(Q,K,V)=Concat(head1​,...,headh​)WO

其中 Q , K , V Q, K, V Q,K,V次元都為 n × d m o d e l n\times d_{model} n×dmodel​, W i Q , W i K W_i^Q, W_i^K WiQ​,WiK​次元為 d m o d e l × d k d_{model}\times d_k dmodel​×dk​, W i V W_i^V WiV​次元為 d m o d e l × d v d_{model}\times d_v dmodel​×dv​, W O W^O WO次元為 h d v × d m o d e l hd_v\times d_{model} hdv​×dmodel​。最後輸出次元為 n × d m o d e l n\times d_{model} n×dmodel​。

因為multi-head要把Q, K, V分解成 h 個部分,那自然地認為 q i , k i , v i q_i, k_i, v_i qi​,ki​,vi​ 的特征次元應該增加 h 倍,是以論文取 d k = d v = d m o d e l / h = 64 d_k=d_v=d_{model}/h=64 dk​=dv​=dmodel​/h=64。

2. Positional Encoding

Transformer論文閱讀:Attention Is All You Need前言介紹Transformer結構why self-attention訓練

從上面的自注意力機制介紹中可以看到,序列是全部一起輸入的,并沒有考慮到序列的順序。是以加了一個positional encoding,讓輸入帶有位置的資訊。

這個東西既可以自己設定,也可以從網絡中學出來。兩個的效果差不多,而自己設定的可以不用在意序列長度。是以論文采用自己設定的正弦和餘弦函數:

P E ( p o s , 2 i ) = s i n ( p o s / 1000 0 2 i / d m o d e l ) PE_{(pos, 2i)}=sin(pos/10000^{2i/d_{model}}) PE(pos,2i)​=sin(pos/100002i/dmodel​)

P E ( p o s , 2 i + 1 ) = c o s ( p o s / 1000 0 2 i / d m o d e l ) PE_{(pos, 2i+1)}=cos(pos/10000^{2i/d_{model}}) PE(pos,2i+1)​=cos(pos/100002i/dmodel​)

其中pos表示位置,i表示第i個次元,postional encoding的次元也是 d m o d e l d_{model} dmodel​。

之是以用正弦餘弦函數,是因為論文認為它們可以讓模型很好地學到如何讓相關位置參與到 attention scores 的計算中(因為可以證明, P E p o s + k PE_{pos+k} PEpos+k​可以表示為 P E p o s PE_{pos} PEpos​的線性方程)。

3. Add&Norm

Transformer論文閱讀:Attention Is All You Need前言介紹Transformer結構why self-attention訓練

公式表示就是: L a y e r N o r m ( x + S u b l a y e r ( x ) ) LayerNorm(x+Sublayer(x)) LayerNorm(x+Sublayer(x))。

這裡的Add就是殘差連接配接(ResNet),為了防止梯度消失的。把self-attention的輸入加到它的輸出上。

Norm不是batch norm,而是用layer norm,主要是因為NLP本身的性質:它是處理語句的。

下面一張圖就可以說清楚它們的差別:

Transformer論文閱讀:Attention Is All You Need前言介紹Transformer結構why self-attention訓練

(圖來源:https://zhuanlan.zhihu.com/p/74516930)

每個句子的長度是不同的,如果對同一個位置的詞進行歸一化,明顯是不合理的。而layer norm是對一句話進行歸一化。

4. Position-wise Feed-Forward Networks

這是由兩個線性變換和一個ReLU組成的,寫作公式是: F F N ( x ) = m a x ( 0 , x W 1 + b 1 ) W 2 + b 2 FFN(x)=max(0, xW_1+b_1)W_2+b_2 FFN(x)=max(0,xW1​+b1​)W2​+b2​。輸入和輸出次元都是 d m o d e l = 512 d_{model}=512 dmodel​=512,中間層的次元是2048。

5. Embeddings

前面說了,Embeddings是把輸入的每個詞轉成次元為 d m o d e l d_{model} dmodel​的向量。

論文提到,這裡跟decoder的Embeddings、decoder最後的linear transformation共享同一個權重矩陣,不過兩個embedding layers的權重還要乘上 d m o d e l \sqrt{d_{model}} dmodel​

​。要乘上的原因是為了與後面加上的positional encoding(絕對值範圍是0到1)的大小相差的不多。

Decoder

接下來将Decoder的結構。

Decoder的一個block結構與encoder的差不多,就是多出了一塊連接配接decoder和encoder的部分,以及最開始的multi-head attention是masked的。

1. masked multi-head attention

Decoder的輸入并不是像Encoder一樣把整個句子一次性輸入的。它是auto-regressive(自回歸)的,舉個例子:翻譯,第一次先輸入 ‘[BEGIN]’,decoder輸出預測第一個詞 ‘機’;第二次把 ‘[BEGIN]’ ‘機’ 都作為輸入,decoder輸出預測的第二個詞 ‘器’… 知道decoder預測詞為 '[END]‘。

是以decoder隻能看到此時的time-step之前的單詞,也就是要把此時以及之後的單詞遮住(mask),權重求和的values隻使用此時time-step之前的詞對應的values。就是 softmax後的attention scores矩陣 A ′ A' A′的形式會是一個下三角矩陣:

( o 1 o 2 o 3 o 4 ) = ( α 1 , 1 ′ 0 0 0 α 2 , 1 ′ α 2 , 2 ′ 0 0 α 3 , 1 ′ α 3 , 2 ′ α 3 , 3 ′ 0 α 4 , 1 ′ α 4 , 2 ′ α 4 , 3 ′ α 4 , 4 ′ ) ( v 1 v 2 v 3 v 4 ) \begin{pmatrix} o^1\\ o^2\\ o^3\\ o^4 \end{pmatrix}= \begin{pmatrix} \alpha_{1,1}^{'} & 0&0&0\\ \alpha_{2,1}^{'} & \alpha_{2,2}^{'}&0&0\\ \alpha_{3,1}^{'} & \alpha_{3,2}^{'}&\alpha_{3,3}^{'}&0\\ \alpha_{4,1}^{'} & \alpha_{4,2}^{'}&\alpha_{4,3}^{'}&\alpha_{4,4}^{'}\\ \end{pmatrix} \begin{pmatrix} v^1\\ v^2\\ v^3\\ v^4 \end{pmatrix} ⎝⎜⎜⎛​o1o2o3o4​⎠⎟⎟⎞​=⎝⎜⎜⎜⎛​α1,1′​α2,1′​α3,1′​α4,1′​​0α2,2′​α3,2′​α4,2′​​00α3,3′​α4,3′​​000α4,4′​​⎠⎟⎟⎟⎞​⎝⎜⎜⎛​v1v2v3v4​⎠⎟⎟⎞​

那要使得softmax後的值變為0,就隻要在softmax前把attention scores矩陣 A A A對應位置的值設為 − ∞ -\infty −∞就好。

2. 連接配接Encoder和Decoder的部分

這部分的multi-head attention的輸入keys, values來自Encoder的輸出,queries來自decoder前面的輸出。計算方式跟前面是一樣的。

3. Linear transformation和softmax

最後一部分沒什麼好說的,就是權重矩陣是與兩個embedding layers共享的。輸出的是預測每個詞對應的機率,最後取機率最大的就得到預測的詞。

why self-attention

Transformer論文閱讀:Attention Is All You Need前言介紹Transformer結構why self-attention訓練

論文分析了問什麼使用自注意力機制比RNN、CNN好。

① 首先是每一層的計算複雜度。

設n為序列長度,d為representation的次元,k是kernel size,r是限制的self-attention的領域大小。

self-attention每一層就是矩陣與矩陣相乘,時間複雜度為 O ( n 2 ⋅ d ) O(n^2\cdot d) O(n2⋅d);RNN每一步計算時間複雜度為 O ( d 2 ) O(d^2) O(d2),共n步,總共是 O ( n ⋅ d 2 ) O(n\cdot d^2) O(n⋅d2);CNN做卷積計算複雜度為 ( k ⋅ n ⋅ d 2 ) (k\cdot n \cdot d^2) (k⋅n⋅d2);限制的self-attention計算複雜度為 O ( r ⋅ n ⋅ d ) O(r\cdot n\cdot d) O(r⋅n⋅d)。

大多數時候n比d小,是以self-attention每一層的計算會比RNN CNN快。

② 計算的并行度。

RNN計算完整個序列需要n步,其他都是一步到位。

③ the length of the paths forward and backward signals have to traverse in the network.

在别的地方看到一個很好的說法:叫做全局感受野所需網絡層數。這個名額就是衡量模型能不能很好地捕捉到很久以前的資訊。

self-attention輸入是一整個序列一起輸入的,看到整個序列隻需要一層;而RNN需要走n步才能看到完整的輸入資訊。

訓練

論文訓練使用的是Adam優化器,學習率的變化是在前 warmup_steps 逐漸上升,随後逐漸減小:

l r a t e = d m o d e l − 0.5 ⋅ m i n ( s t e p n u m − 0.5 , s t e p n u m ⋅ w a r m u p s t e p s − 1.5 ) lrate=d^{-0.5}_{model}\cdot min(stepnum^{-0.5}, stepnum\cdot warmupsteps^{-1.5}) lrate=dmodel−0.5​⋅min(stepnum−0.5,stepnum⋅warmupsteps−1.5)

這個學習率的變化挺關鍵的,不這樣設定訓練不出很好的模型。

正則化政策

在每個 add&norm 輸入之前都做一次dropout;還有在 embeddings 和 positional encodings 相加時也做dropout。

在softmax的時候使用label smoothing。

繼續閱讀