本篇文章的知識點順序是按照 Transformer 的架構,從下往上,從 encoders 到 decoders 的順序編寫的,可能不利於新手的理解,但是非常全面,可以參考其他的文章一起閱讀,效果更佳!
一、Transformer引入
來源於機器翻譯:
Transformer 分為兩個部分——編碼器(encoders )和解碼器(decoders):
encoders 和 decoders 分解,其中 6 個 encoder 的結構是相同的,但是 6 個 decoder 的參數會獨立訓練,也就是參數是不同的;decoder 同理:
Transformer 原論文中的圖:
二、Encoder 詳解
encoder 模型:
2.1 輸入部分
2.1.1 Embedding
12 個字對應512 維度的字向量:
2.1.2 位置嵌入
為什么需要,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\) 位置的位置向量的某一維線性組合加以線性表示,通過該線性表示可以得出 “德” 的位置編碼信息蘊含了相對於前兩個字 “我” 和 “愛” 的位置編碼信息:
2.2 注意力機制 Attention
2.2.1 人類的注意力機制
第一眼會注意什么?紅色的地方首先會映入眼簾;其次,我們如果問一句:嬰兒在干什么?會怎么觀察這幅圖:
2.2.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:
實際代碼會使用矩陣的形式,方便並行計算:
2.2.3 多頭 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 面試題講解
8.1 RNN、LSTM、Transformer 三者的區別?
- RNN系列的模型時刻隱層狀態的計算,依賴兩個輸入,一個是
時刻的句子輸入單詞
,另一個是
時刻的隱層狀態
的輸出,這是最能體現RNN本質特征的一點,RNN的歷史信息是通過這個信息傳輸渠道往后傳輸的。而RNN並行計算的問題就出在這里,因為
時刻的計算依賴
時刻的隱層計算結果,而
時刻的計算依賴
時刻的隱層計算結果,如此下去就形成了所謂的序列依賴關系。 
- 很明顯,Transformer 中引入 Self Attention 后會更容易捕獲句子中長距離的相互依賴的特征,因為如果是 RNN 或者 LSTM,需要依次序序列計算,對於遠距離的相互依賴的特征,要經過若干時間步步驟的信息累積才能將兩者聯系起來,而距離越遠,有效捕獲的可能性越小。
- 但是Self Attention在計算過程中會直接將句子中任意兩個單詞的聯系通過一個計算步驟直接聯系起來,所以遠距離依賴特征之間的距離被極大縮短,有利於有效地利用這些特征。除此外,Self Attention對於增加計算的並行性也有直接幫助作用。這是為何Self Attention逐漸被廣泛使用的主要原因。
8.2 為什么有縮放因子
?attention為什么scaled?
-
- 先一句話回答這個問題: 縮放因子的作用是歸一化。
- 假設
,
里的元素的均值為0,方差為1,那么
中元素的均值為0,方差為d. 當d變得很大時,
中的元素的方差也會變得很大,如果
中的元素方差很大,那么
的分布會趨於陡峭(分布的方差大,分布集中在絕對值大的區域)。總結一下就是
的分布會和d有關。因此
中每一個元素乘上
后,方差又變為1。這使得
的分布“陡峭”程度與d解耦,從而使得訓練過程中梯度值保持穩定。
- 可以看到,數量級對softmax得到的分布影響非常大。在數量級較大時,softmax將幾乎全部的概率分布都分配給了最大值對應的標簽。如果某一維度的數量級較大,進而會導致 softmax 未來求梯度時會消失。

- 可以看到,數量級對softmax得到的分布影響非常大。在數量級較大時,softmax將幾乎全部的概率分布都分配給了最大值對應的標簽。如果某一維度的數量級較大,進而會導致 softmax 未來求梯度時會消失。
- Transformer 的並行化
- decoders 沒有並行化,6 個encoder 之間也沒有並行化,encoder 內部的兩個子模塊也沒有並行化,但是 encoder 內部的兩個子模塊自身是可以並行化的
8.3 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

8.4 如何 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
8.5 Layer Normalization (歸一化)的作用
Layer Normalization是一個通用的技術,其本質是規范優化空間,加速收斂。當我們使用梯度下降法做優化時,隨着網絡深度的增加,數據的分布會不斷發生變化,假設feature只有二維,那么用示意圖來表示一下就是:

為了保證數據特征分布的穩定性(如左圖),我們加入Layer Normalization,這樣可以加速模型的優化速度。
