一、Transformer
Transformer最開始用於機器翻譯任務,其架構是seq2seq的編碼器解碼器架構。其核心是自注意力機制: 每個輸入都可以看到全域性資訊,從而緩解RNN的長期依賴問題。
輸入: (待學習的)輸入詞嵌入 + 位置編碼(相對位置)
編碼器結構: 6層編碼器: 一層編碼器 = 多頭注意力+殘差(LN) + FFN+殘差(LN)
輸出:每一個位置上輸出預測機率分佈(K類類別分佈)
1.1 自注意力
分解式
縮放內積注意力
1. 自注意力的優勢
a. 計算開銷,計算可並行 (嵌入維度d,序列長度n,計算複雜度O(n^2d))
b. 建模長期依賴 (穩定訓練過程)
2. 自注意力縮放(內積過大,softmax飽和)
We suspect that for large values d_k, the dot products grow large in magnitude, pushing the softmax function into regions where it has extremely small gradients.To counteract this effect, we scale the dot products by sqrt(d_k)
如上為原文。作者懷疑,如果Q和K的維度特別大,會使得內積後的值也大。從而使softmax進入梯度極小的區域(類似於sigmoid的飽和區域)。 這樣容易導致梯度消失。
所以,他們將內積值除以sqrt(d_k),進行一個縮放,而又不破壞相對比例。
多頭注意力機制(multi-head attention)
Transformer 提出多頭注意力機制(不同頭結果拼起來,再做線性變換),增強了 attention 層的能力(引數量不變)。解釋:
- 它擴充套件了模型關注不同位置的能力。不同注意力頭,關注不同的位置。長距離依賴
- 多頭注意力機制賦予 attention 層多個“子表示空間(訓練之後,每組注意力可以看作是把輸入的向量對映到一個”子表示空間“)
torch.nn.MultiheadAttention(embed_dim, num_heads, dropout=0.0, bias=True, add_bias_kv=False, add_zero_attn=False, kdim=None, vdim=None)
引數說明如下:
- embed_dim:最終輸出的 K、Q、V 矩陣的維度,這個維度需要和詞向量的維度一樣
- num_heads:設定多頭注意力的數量。如果設定為 1,那麼只使用一組注意力。如果設定為其他數值,那麼 num_heads 的值需要能夠被 embed_dim 整除
- dropout:這個 dropout 加在 attention score 後面
定義 MultiheadAttention 的物件後,呼叫時傳入的引數如下。
forward(query, key, value, key_padding_mask=None, need_weights=True, attn_mask=None)
- query:對應於 Query 矩陣,形狀是 (L,N,E) 。其中 L 是輸出序列長度,N 是 batch size,E 是詞向量的維度
- key:對應於 Key 矩陣,形狀是 (S,N,E) 。其中 S 是輸入序列長度,N 是 batch size,E 是詞向量的維度
- value:對應於 Value 矩陣,形狀是 (S,N,E) 。其中 S 是輸入序列長度,N 是 batch size,E 是詞向量的維度
- key_padding_mask:如果提供了這個引數,那麼計算 attention score 時,忽略 Key 矩陣中某些 padding 元素,不參與計算 attention(序列長度不同)。形狀是 (N,S)。其中 N 是 batch size,S 是輸入序列長度。
- 如果 key_padding_mask 是 ByteTensor,那麼非 0 元素對應的位置會被忽略
- 如果 key_padding_mask 是 BoolTensor,那麼 True 對應的位置會被忽略
- attn_mask:計算輸出時,忽略某些位置。形狀可以是 2D (L,S),或者 3D (N∗numheads,L,S)。其中 L 是輸出序列長度,S 是輸入序列長度,N 是 batch size。
- 如果 attn_mask 是 ByteTensor,那麼非 0 元素對應的位置會被忽略
- 如果 attn_mask 是 BoolTensor,那麼 True 對應的位置會被忽略
在實際中,K、V 矩陣的長度一樣,而 Q 矩陣的序列長度可不一樣。這種情況發生在:在解碼器部分的encoder-decoder attention層中,Q 矩陣是來自解碼器下層,而 K、V 矩陣則是來自編碼器的輸出。
2. Encoder 和 Decoder
編碼器就是編碼器層(多頭注意力+(殘差+LN),FFN+(殘差+LN))的堆疊。
解碼器
Self-attention layers in the decoder allow each position in the decoder to attend to all positions in the decoder up to and including that position.We need to prevent leftward information flow in the decoder to preserve the auto-regressive property.We implement this inside of scaled dot-product attention by masking out (setting to −∞) all values in the input of the softmax which correspond to illegal connections.
為了保持自迴歸的性質,要保持從左往右的順序 (這種情況下,不能利用要預測的未來來推斷過去)。 這裡將當前token以後的進行mask (即將注意力得分加上-inf,將其變成無窮小,使其注意力係數極小接近於無) [exp(-inf) = 0]
GAT也是這樣做的,只不過mask的是非鄰居結點 (避免資訊洩露,從而讓模型學不好)。
# 把 mask 不為空,那麼就把 mask 為 0 的位置的 attention 分數設定為 -1e10(係數無窮小)
attention = torch.matmul(Q, K.permute(0, 1, 3, 2)) / self.scale if mask is not None: attention = attention.masked_fill(mask == 0, -1e10) attention = self.do(torch.softmax(attention, dim=-1)) x = torch.matmul(attention, V)
交叉注意力層(Decoder-Encoder Attention, Decoder到Encoder輸出的潛表示)
使用前一層的輸出來構造 Query 矩陣,而 Key 矩陣和 Value 矩陣來自於編碼器最終的輸出(seq2seq都是這樣的,預測當前輸出時,不僅看之前的輸出,同時也對輸入隱狀態進行關注)
預測
每一個位置有一個分類損失;總的損失就是每個位置損失之和。
訓練
讓我們假設輸出詞彙表只包含 6 個單詞(“a”, “am”, “i”, “thanks”, “student”, and “”(“”表示句子末尾))。
這種架構本就可以用來做語言模型,只不過這裡做了seq2seq的翻譯。
如果訓練資料中本身就有很多句子對,就可以直接透過語言模型實現翻譯,例如GPT架構。
學習筆記,配圖參考知乎-張賢同學、李宏毅機器學習。