Attention和Transformer詳解
Transformer引入
來源於機器翻譯:
Transformer 分為兩個部分——編碼器(encoders )和解碼器(decoders):
encoders 和 decoders 分解,其中 6 個 encoder 的結構是相同的,但是 6 個 decoder 的引數會獨立訓練,也就是引數是不同的;decoder 同理:
Transformer 原論文中的圖:
Encoder 詳解
encoder 模型:
輸入部分
Embedding
12 個字對應512 維度的字向量:
位置嵌入
為什麼需要,RNN 中的每個 timestep (箭頭左端就是一個 timestep,右端是 3 個 timestep 的集合)共享一套引數 \(u、v、w\),天然的具有持續關係(句子中單詞的序列關係),由於後一個 timestep 輸入必須得等前一個 timestep 的輸出,不具有並行處理的能力,並且由於所有 timestep 共享一套引數,所以會出現梯度消失或梯度爆炸的問題;而對於 attention,具有並行處理的能力,但是並不具有位置資訊顯示的能力,下面講到 attention 時會講到:
位置編碼公式,其中 pos 表示位置、i 表示維度、 \(2i、2i+1\) 表示的是奇偶數(奇偶維度),下圖就是偶數位置使用 \(\sin\) 函式,奇數位置使用 \(\cos\) 函式:
位置編碼嵌入單詞編碼:
為什麼位置嵌入機制有用,我們不要去關心三角函式公式,可以看看 公式(3) 中的第一行,我們做如下的解釋,對於 “我愛德” 這一句話,有三個單詞,假設序號分別為 1、2、3,假設 \(pos=1=我、k=2=愛、pos+k=3=德\),也就是說 \(pos+k=3\) 位置的位置向量的某一維可以通過 \(pos=1\) 和 \(k=2\) 位置的位置向量的某一維線性組合加以線性表示,通過該線性表示可以得出 “德” 的位置編碼資訊蘊含了相對於前兩個字 “我” 和 “愛” 的位置編碼資訊:
注意力機制
人類的注意力機制
第一眼會注意什麼?紅色的地方首先會映入眼簾;其次,我們如果問一句:嬰兒在幹什麼?會怎麼觀察這幅圖:
Attention 計算
Q、K、V 三個矩陣:
理解上述公式,嬰兒和左上、左下…做點乘,點乘的結果是一個向量在另外一個向量上投影的長度,是一個標量,可以獲取二者的相似度,相似度越大,則表示二者越靠近,此處就是觀察嬰兒更關注左上、左下…哪個部分:
上述公式的更詳細解釋:
Transformer 中 Q、K、V 的獲取,其中 W 是一個隨機初始化的引數,在訓練過程中會被更新:
計算 attention 值,其中由於 \(QK^T\) 的值很大時,通過 softmax 的公式可以得知,softmax 的梯度會很小,則會造成梯度消失,有興趣想具體瞭解的可以看這個連結:transformer中的attention為什麼scaled?。因此有了 \(\frac{QK^T}{\sqrt{d_k}}\),分母為 \(\sqrt{d_k}\) 的原因是為了控制 \(QK^T\) 的方差為 1:
實際程式碼會使用矩陣的形式,方便平行計算:
多頭 Attention 計算
多頭 attention,使用多套引數,多套引數相當於把原始資訊放到了多個空間中,也就是捕捉了多個資訊,對於使用多頭 attention 的簡單回答就是,多頭保證了transformer可以注意到不同子空間的資訊,捕捉到更加豐富的特徵資訊。其實本質上是論文原作者發現這樣效果確實好:
多頭資訊輸出,由於多套引數得到了多個資訊,然而我們還是隻需要一個資訊,因此可以通過某種方法(例如矩陣相乘)把多個資訊彙總為一個資訊:
多套資訊合併為一個資訊:
殘差及其作用
encoder 詳解,其中 \(X+Z\) 為殘差的結果:
殘差網路,把輸入原封不動的和元網路處理的結果相加:
殘差的作用,沒有殘差,最後一行公式中括號內沒有 1,只有三個連乘項,而這三個連乘項如果很小的話,則可能結果會為 0,而有了殘差之後,即括號內有了 1,由此確保了梯度永遠不會為 0,則不會出現梯度消失的情況,進而網路深度可以增加:
BatchNorm 和 LayerNorm
為什麼 LayerNorm 單獨對一個樣本的所有單詞做縮放可以起到效果,9 個句子各 5 個單詞、1 個句子 20 個單詞,很明顯,由於樣本長度不一,使用 BN 的效果一定是大打折扣的,而 LN 可以針對每一句話做一個歸一化:
對於齊平的句子,BN 和 LN 的區別,BN由於是針對 batch 維度的歸一化,是對“我今”、“愛天”……做歸一化;LN 是對某一層神經元的輸入進行歸一化,“我愛中國xxx”和“今天天氣真不錯”做歸一化:
前饋神經網路
每一層經過attention之後,還會有一個FFN,這個FFN的作用就是空間變換。FFN包含了2層linear transformation層,中間的啟用函式是ReLu。
其實,FFN的加入引入了非線性(ReLu啟用函式),變換了attention output的空間, 從而增加了模型的表現能力。把FFN去掉模型也是可以用的,但是效果差了很多。
Decoder 詳解
decoder 模型架構:
mask 的作用,當預測 you 的時候,我們是看不到 you 後面單詞的資訊的,也就是 mask 掉 you 和 now:
encoder 和 decoder 互動方法:
encoder 的輸出會給所有的 decoder 提供一定的資訊:
encoder 和 decoder 互動時提供的資訊,encoder 生成的 K、V 矩陣,decoder 生成的是 Q 矩陣:
encoder 和 decoder 互動的整個過程:
Transformer 最終輸出
以上,就講完了Transformer編碼和解碼兩大模組,那麼我們迴歸最初的問題,將“機器學習”翻譯成“machine learing”,解碼器輸出本來是一個浮點型的向量,怎麼轉化成“machine learing”這兩個詞呢?
是個工作是最後的線性層接上一個softmax,其中線性層是一個簡單的全連線神經網路,它將解碼器產生的向量投影到一個更高維度的向量(logits)上,假設我們模型的詞彙表是10000個詞,那麼logits就有10000個維度,每個維度對應一個惟一的詞的得分。之後的softmax層將這些分數轉換為概率。選擇概率最大的維度,並對應地生成與之關聯的單詞作為此時間步的輸出就是最終的輸出啦!!
假設詞彙表維度是6,那麼輸出最大概率詞彙的過程如下:
TRM 面試題講解
RNN、LSTM、Transformer 三者的區別?
- RNN系列的模型時刻隱層狀態的計算,依賴兩個輸入,一個是 時刻的句子輸入單詞 ,另一個是 時刻的隱層狀態 的輸出,這是最能體現RNN本質特徵的一點,RNN的歷史資訊是通過這個資訊傳輸渠道往後傳輸的。而RNN平行計算的問題就出在這裡,因為 時刻的計算依賴 時刻的隱層計算結果,而 時刻的計算依賴 時刻的隱層計算結果,如此下去就形成了所謂的序列依賴關係。
- 很明顯,Transformer 中引入 Self Attention 後會更容易捕獲句子中長距離的相互依賴的特徵,因為如果是 RNN 或者 LSTM,需要依次序序列計算,對於遠距離的相互依賴的特徵,要經過若干時間步步驟的資訊累積才能將兩者聯絡起來,而距離越遠,有效捕獲的可能性越小。
- 但是Self Attention在計算過程中會直接將句子中任意兩個單詞的聯絡通過一個計算步驟直接聯絡起來,所以遠距離依賴特徵之間的距離被極大縮短,有利於有效地利用這些特徵。除此外,Self Attention對於增加計算的並行性也有直接幫助作用。這是為何Self Attention逐漸被廣泛使用的主要原因。
為什麼有縮放因子 ?attention為什麼scaled?
-
- 先一句話回答這個問題: 縮放因子的作用是歸一化。
- 假設 , 裡的元素的均值為0,方差為1,那麼 中元素的均值為0,方差為d. 當d變得很大時, 中的元素的方差也會變得很大,如果 中的元素方差很大,那麼 的分佈會趨於陡峭(分佈的方差大,分佈集中在絕對值大的區域)。總結一下就是的分佈會和d有關。因此 中每一個元素乘上 後,方差又變為1。這使得 的分佈“陡峭”程度與d解耦,從而使得訓練過程中梯度值保持穩定。
- 可以看到,數量級對softmax得到的分佈影響非常大。在數量級較大時,softmax將幾乎全部的概率分佈都分配給了最大值對應的標籤。如果某一維度的數量級較大,進而會導致 softmax 未來求梯度時會消失。
- Transformer 的並行化
- decoders 沒有並行化,6 個encoder 之間也沒有並行化,encoder 內部的兩個子模組也沒有並行化,但是 encoder 內部的兩個子模組自身是可以並行化的
Decoder端的Mask
Transformer模型屬於自迴歸模型(p.s. 非自迴歸的翻譯模型我會專門寫一篇文章來介紹),也就是說後面的token的推斷是基於前面的token的。Decoder端的Mask的功能是為了保證訓練階段和推理階段的一致性。
論文原文中關於這一點的段落如下:
We also modify the self-attention sub-layer in the decoder stack to prevent from attending to subsequent positions. This masking, combined with the fact that the output embeddings are offset by one position, ensures that the predictions for position i can depend only on the known outputs at positions less than i.
在推理階段,token是按照從左往右的順序推理的。也就是說,在推理timestep=T的token時,decoder只能“看到”timestep < T的 T-1 個Token, 不能和timestep大於它自身的token做attention(因為根本還不知道後面的token是什麼)。為了保證訓練時和推理時的一致性,所以,訓練時要同樣防止token與它之後的token去做attention。
比如我要翻譯出來的一句話為“我愛陳有德”的時候,如果沒有 mask,當我們在訓練階段,翻譯到“愛”的時候,由於沒有 mask,“陳有德”三個字對翻譯“愛”是有輸出貢獻的,也就是說訓練階段,模型是基於知道這個時刻後面的單詞進行的訓練,然而當我們在測試階段的時候,我們並不知道“愛”後面是什麼,也就是說訓練階段不 mask,那麼測試階段會受到一定的影響。(這裡要說明,訓練階段我們是知道 ground truth “我愛陳有德” 的,而 decoders 的第一個 output Embedding 就是真實的那個 ground truth “我愛陳有德”,也就是說訓練階段不 mask,那麼預測 “愛” 時,“陳有德” 就會有貢獻,而在測試階段,沒有 ground truth,decoders 的第一個 output Embedding 是隨機的,此時訓練階段和測試階段就會出現差別)
從下圖可以看出,預測是一步接著一步的,由於是序列生成過程,所以在時刻 i 的時候,大於 i 的時刻都沒有結果,只有小於 i 的時刻有結果,因此需要做Mask
如何 mask
其實就會組成一個word2word的attention map!(加了softmax之後就是一個合為1的權重了)。比如說你的輸入是一句話 "i have a dream" 總共4個單詞,這裡就會形成一張4x4的注意力機制的圖:
這樣一來,每一個單詞就對應每一個單詞有一個權重
注意encoder裡面是叫self-attention,decoder裡面是叫masked self-attention。
這裡的masked就是要在做language modelling(或者像翻譯)的時候,不給模型看到未來的資訊。
mask就是沿著對角線把灰色的區域用0覆蓋掉,不給模型看到未來的資訊。
詳細來說,i作為第一個單詞,只能有和i自己的attention。have作為第二個單詞,有和i, have 兩個attention。 a 作為第三個單詞,有和i,have,a 前面三個單詞的attention。到了最後一個單詞dream的時候,才有對整個句子4個單詞的attention。
做完softmax後就像這樣,橫軸合為1
Layer Normalization (歸一化)的作用
Layer Normalization是一個通用的技術,其本質是規範優化空間,加速收斂。當我們使用梯度下降法做優化時,隨著網路深度的增加,資料的分佈會不斷髮生變化,假設feature只有二維,那麼用示意圖來表示一下就是:
為了保證資料特徵分佈的穩定性(如左圖),我們加入Layer Normalization,這樣可以加速模型的優化速度。