文章目錄
- 前言
- 介紹
- 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結構
![](https://img.laitimes.com/img/9ZDMuAjOiMmIsIjOiQnIsIyZuBnL3QGM0MGO0kjZzYTZwYWOidTN4QDN3Y2MkFmZygzMhN2Lc52YucWbp5GZzNmLn9Gbi1yZtl2Lc9CX6MHc0RHaiojIsJye.png)
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 隻需要做矩陣乘法,計算更簡單,是以論文使用第二種。
上面的圖就是 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)的。
從圖中可以看出,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
從上面的自注意力機制介紹中可以看到,序列是全部一起輸入的,并沒有考慮到序列的順序。是以加了一個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
公式表示就是: 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本身的性質:它是處理語句的。
下面一張圖就可以說清楚它們的差別:
(圖來源: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
論文分析了問什麼使用自注意力機制比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。