關於transformer,面試官們都怎麼問

本文首發於微信公衆號:NewBeeNLP,歡迎關注獲取更多幹貨資源。

PS.全文較長,爲了方便大家閱讀,我整理了PDF版本,微信公衆號後臺回覆TS即可自取。
關於transformer,面試官們都怎麼問

模型總覽:

Transformer模型總覽

1.Transformer 的結構是什麼樣的?

Transformer 本身還是一個典型的 encoder-decoder 模型,如果從模型層面來看,Transformer 實際上就像一個 seq2seq with attention 的模型,下面大概說明一下 Transformer 的結構以及各個模塊的組成。

1.1 Encoder 端 & Decoder 端總覽

  • Encoder 端由 N(原論文中N=6)個相同的大模塊堆疊而成,其中每個大模塊又由兩個子模塊構成,這兩個子模塊分別爲多頭 self-attention 模塊,以及一個前饋神經網絡模塊;
    • 需要注意的是,Encoder 端每個大模塊接收的輸入是不一樣的,第一個大模塊(最底下的那個)接收的輸入是輸入序列的 embedding(embedding 可以通過 word2vec 預訓練得來),其餘大模塊接收的是其前一個大模塊的輸出,最後一個模塊的輸出作爲整個 Encoder 端的輸出。
  • Decoder 端同樣由 N(原論文中N=6)個相同的大模塊堆疊而成,其中每個大模塊則由三個子模塊構成,這三個子模塊分別爲多頭 self-attention 模塊,多頭 Encoder-Decoder attention 交互模塊,以及一個前饋神經網絡模塊;
    • 同樣需要注意的是,Decoder 端每個大模塊接收的輸入也是不一樣的,其中第一個大模塊(最底下的那個)訓練時和測試時的接收的輸入是不一樣的,並且每次訓練時接收的輸入也可能是不一樣的(也就是模型總覽圖示中的"shifted right",後續會解釋),其餘大模塊接收的是同樣是其前一個大模塊的輸出,最後一個模塊的輸出作爲整個 Decoder 端的輸出。
    • 對於第一個大模塊,簡而言之,其訓練及測試時接收的輸入爲:
      • 訓練的時候每次的輸入爲上次的輸入加上輸入序列向後移一位的 ground truth(例如每向後移一位就是一個新的單詞,那麼則加上其對應的 embedding),特別地,當 decoder 的 time step 爲 1 時(也就是第一次接收輸入),其輸入爲一個特殊的 token,可能是目標序列開始的 token(如),也可能是源序列結尾的 token(如),也可能是其它視任務而定的輸入等等,不同源碼中可能有微小的差異,其目標則是預測下一個位置的單詞(token)是什麼,對應到 time step 爲 1 時,則是預測目標序列的第一個單詞(token)是什麼,以此類推;
        • 這裏需要注意的是,在實際實現中可能不會這樣每次動態的輸入,而是一次性把目標序列的 embedding 通通輸入第一個大模塊中,然後在多頭 attention 模塊對序列進行 mask 即可
      • 而在測試的時候,是先生成第一個位置的輸出,然後有了這個之後,第二次預測時,再將其加入輸入序列,以此類推直至預測結束。

1.2 Encoder 端各個子模塊

1.2.1 多頭 self-attention 模塊

在介紹 self-attention 模塊之前,先介紹 self-attention 模塊,圖示如下:

self-attention

上述 attention 可以被描述爲將 query 和 key-value 鍵值對的一組集合映射到輸出,其中 query,keys,values 和輸出都是向量,其中 query 和 keys 的維度均爲dkd_{k},values 的維度爲dvd_{v}(論文中dk=dv=dmodel /h=64d_{k}=d_{v}=d_{\text {model }} / h=64),輸出被計算爲 values 的加權和,其中分配給每個 value 的權重由 query 與對應 key 的相似性函數計算得來。這種 attention 的形式被稱爲“Scaled Dot-Product Attention”,對應到公式的形式爲:

 Attention (Q,K,V)=softmax(QKTdk)V \text { Attention }(Q, K, V)=\operatorname{softmax}\left(\frac{Q K^{T}}{\sqrt{d_{k}}}\right) V

而多頭 self-attention 模塊,則是將Q,K,VQ,K,V通過參數矩陣映射後(給Q,K,VQ,K,V分別接一個全連接層),然後再做 self-attention,將這個過程重複hh(原論文中h=8h=8)次,最後再將所有的結果拼接起來,再送入一個全連接層即可,圖示如下:

multi-head attention

對應到公式的形式爲:
MultiHead(Q,K,V)=Concat(head1,,headh)WO MultiHead (Q, K, V)= Concat (head _{1}, \ldots, head _{\mathrm{h}} ) W^{O}
 where head i= Attention (QWiQ,KWiK,VWiV) \text { where head }_{\mathrm{i}}=\text { Attention }\left(Q W_{i}^{Q}, K W_{i}^{K}, V W_{i}^{V}\right)

其中WiQRdmodel ×dk,WiKRdmodel ×dk,WiVRdmodel ×dv,WORhdv×dmodel W_{i}^{Q} \in \mathbb{R}^{d_{\text {model }} \times d_{k}}, W_{i}^{K} \in \mathbb{R}^{d_{\text {model }} \times d_{k}}, W_{i}^{V} \in \mathbb{R}^{d_{\text {model }} \times d_{v}}, W^{O} \in \mathbb{R}^{h d_{v} \times d_{\text {model }}}

1.2.2 前饋神經網絡模塊

前饋神經網絡模塊(即圖示中的 Feed Forward)由兩個線性變換組成,中間有一個 ReLU 激活函數,對應到公式的形式爲:
FFN(x)=max(0,xW1+b1)W2+b2 \operatorname{FFN}(x)=\max \left(0, x W_{1}+b_{1}\right) W_{2}+b_{2}

論文中前饋神經網絡模塊輸入和輸出的維度均爲dmodel =512d_{\text {model }}=512,其內層的維度dff=2048d_{f f}=2048.

1.3 Decoder 端各個子模塊

1.3.1 多頭 self-attention 模塊

Decoder 端多頭 self-attention 模塊與 Encoder 端的一致,但是需要注意的是 Decoder 端的多頭 self-attention 需要做 mask,因爲它在預測時,是“看不到未來的序列的”,所以要將當前預測的單詞(token)及其之後的單詞(token)全部 mask 掉。

1.3.2 多頭 Encoder-Decoder attention 交互模塊

多頭 Encoder-Decoder attention 交互模塊的形式與多頭 self-attention 模塊一致,唯一不同的是其Q,K,VQ, K, V矩陣的來源,其QQ矩陣來源於下面子模塊的輸出(對應到圖中即爲 masked 多頭 self-attention 模塊經過 Add & Norm 後的輸出),而K,VK,V矩陣則來源於整個 Encoder 端的輸出,仔細想想其實可以發現,這裏的交互模塊就跟 seq2seq with attention 中的機制一樣,目的就在於讓 Decoder 端的單詞(token)給予 Encoder 端對應的單詞(token)“更多的關注(attention weight)”

1.3.3 前饋神經網絡模塊

該部分與 Encoder 端的一致

1.4 其他模塊

1.4.1 Add & Norm 模塊

Add & Norm 模塊接在 Encoder 端和 Decoder 端每個子模塊的後面,其中 Add 表示殘差連接,Norm 表示 LayerNorm,殘差連接來源於論文Deep Residual Learning for Image Recognition,LayerNorm 來源於論文Layer Normalization,因此 Encoder 端和 Decoder 端每個子模塊實際的輸出爲:LayerNorm (x+ Sublayer (x))(x+\text { Sublayer }(x)),其中Sublayer (x))(x))爲子模塊的輸出。

1.4.2Positional Encoding

Positional Encoding 添加到 Encoder 端和 Decoder 端最底部的輸入 embedding。Positional Encoding 具有與 embedding 相同的維度dmodeld_{model}\begin{aligned} P E_{(p o s, 2 i)} &=\sin \left(\operatorname{pos} / 10000^{2 i / d_{\text {model }}}\right) \ P E_{(p o s, 2 i+1)} &=\cos \left(\text { pos } / 10000^{2 i / d_{\text {model }}}\right) \end{aligned}PE(pos,2i)=sin(pos/100002i/dmodel )PE(pos,2i+1)=cos( pos /100002i/dmodel )\begin{aligned} P E_{(p o s, 2 i)} &=\sin \left(\operatorname{pos} / 10000^{2 i / d_{\text {model }}}\right) \\ P E_{(p o s, 2 i+1)} &=\cos \left(\text { pos } / 10000^{2 i / d_{\text {model }}}\right) \end{aligned},因此可以對兩者進行求和。

具體做法是使用不同頻率的正弦和餘弦函數,公式如下:
PE(pos,2i)=sin(pos/100002i/dmodel )PE(pos,2i+1)=cos( pos /100002i/dmodel ) \begin{aligned} P E_{(p o s, 2 i)} &=\sin \left(\operatorname{pos} / 10000^{2 i / d_{\text {model }}}\right) \\ P E_{(p o s, 2 i+1)} &=\cos \left(\text { pos } / 10000^{2 i / d_{\text {model }}}\right) \end{aligned}

其中pospos爲位置,ii爲維度,之所以選擇這個函數,是因爲任意位置PEpos+kP E_{p o s+k}可以表示爲PEposP E_{p o s}的線性函數,這個主要是三角函數的特性:

sin(α+β)=sin(α)cos(β)+cos(α)sin(β)cos(α+β)=cos(α)cos(β)sin(α)sin(β) \begin{array}{l} \sin (\alpha+\beta)=\sin (\alpha) \cos (\beta)+\cos (\alpha) \sin (\beta) \\ \cos (\alpha+\beta)=\cos (\alpha) \cos (\beta)-\sin (\alpha) \sin (\beta) \end{array}

需要注意的是,Transformer 中的 Positional Encoding 不是通過網絡學習得來的,而是直接通過上述公式計算而來的,論文中也實驗了利用網絡學習 Positional Encoding,發現結果與上述基本一致,但是論文中選擇了正弦和餘弦函數版本,因爲三角公式不受序列長度的限制,也就是可以對 比所遇到序列的更長的序列 進行表示。

2.Transformer Decoder 端的輸入具體是什麼?

見上述 Encoder 端 & Decoder 端總覽中,對 Decoder 端的輸入有詳細的分析

3.Transformer 中一直強調的 self-attention 是什麼?self-attention 的計算過程?爲什麼它能發揮如此大的作用?self-attention 爲什麼要使用 Q、K、V,僅僅使用 Q、V/K、V 或者 V 爲什麼不行?

3.1 self-attention是什麼?

self-attention,也叫 intra-attention,是一種通過自身和自身相關聯的 attention 機制,從而得到一個更好的 representation 來表達自身,self-attention 可以看成一般 attention 的一種特殊情況。在 self-attention 中,Q=K=VQ=K=V,序列中的每個單詞(token)和該序列中其餘單詞(token)進行 attention 計算。self-attention 的特點在於無視詞(token)之間的距離直接計算依賴關係,從而能夠學習到序列的內部結構,實現起來也比較簡單,值得注意的是,在後續一些論文中,self-attention 可以當成一個層和 RNN,CNN 等配合使用,並且成功應用到其他 NLP 任務。

3.2 關於 self-attention 的計算過程?

問題 1 中有詳細的解答

3.3 關於 self-attention 爲什麼它能發揮如此大的作用

在上述 self-attention 的介紹中實際上也有所提及,self-attention 是一種自身和自身相關聯的 attention 機制,這樣能夠得到一個更好的 representation 來表達自身,在多數情況下,自然會對下游任務有一定的促進作用,但是 Transformer 效果顯著及其強大的特徵抽取能力是否完全歸功於其 self-attention 模塊,還是存在一定爭議的,參見論文:How Much Attention Do You Need?A Granular Analysis of Neural Machine Translation Architectures,如下例子可以大概探知 self-attention 的效果:

圖 1 可視化 self-attention 實例

圖 2 可視化 self-attention 實例

從兩張圖(圖 1、圖 2)可以看出,self-attention 可以捕獲同一個句子中單詞之間的一些句法特徵(比如圖 1 展示的有一定距離的短語結構)或者語義特徵(比如圖 1 展示的 its 的指代對象 Law)。

很明顯,引入 Self Attention 後會更容易捕獲句子中長距離的相互依賴的特徵,因爲如果是 RNN 或者 LSTM,需要依次序序列計算,對於遠距離的相互依賴的特徵,要經過若干時間步步驟的信息累積才能將兩者聯繫起來,而距離越遠,有效捕獲的可能性越小。

但是 Self Attention 在計算過程中會直接將句子中任意兩個單詞的聯繫通過一個計算步驟直接聯繫起來,所以遠距離依賴特徵之間的距離被極大縮短,有利於有效地利用這些特徵。除此外,Self Attention 對於增加計算的並行性也有直接幫助作用。這是爲何 Self Attention 逐漸被廣泛使用的主要原因。

3.4 關於 self-attention 爲什麼要使用 Q、K、V,僅僅使用 Q、V/K、V 或者 V 爲什麼不行?

這個問題我覺得並不重要,self-attention 使用 Q、K、V,這樣三個參數獨立,模型的表達能力和靈活性顯然會比只用 Q、V 或者只用 V 要好些,當然主流 attention 的做法還有很多種,比如說 seq2seq with attention 也就只有 hidden state 來做相似性的計算,處理不同的任務,attention 的做法有細微的不同,但是主體思想還是一致的,不知道有沒有論文對這個問題有過細究,有空去查查~

其實還有個小細節,因爲 self-attention 的範圍是包括自身的(masked self-attention 也是一樣),因此至少是要採用 Q、V 或者 K、V 的形式,而這樣“詢問式”的 attention 方式,個人感覺 Q、K、V 顯然合理一些。

4.Transformer 爲什麼需要進行 Multi-head Attention?這樣做有什麼好處?Multi-head Attention 的計算過程?各方論文的觀點是什麼?

4.1 Why Multi-head Attention

原論文中說到進行 Multi-head Attention 的原因是將模型分爲多個頭,形成多個子空間,可以讓模型去關注不同方面的信息,最後再將各個方面的信息綜合起來。其實直觀上也可以想到,如果自己設計這樣的一個模型,必然也不會只做一次 attention,多次 attention 綜合的結果至少能夠起到增強模型的作用,也可以類比 CNN 中同時使用多個卷積核的作用,直觀上講,多頭的注意力有助於網絡捕捉到更豐富的特徵/信息

4.2 關於 Multi-head Attention 的計算過程

在 1 中也有詳細的介紹,但是需要注意的是,論文中並沒有對 Multi-head Attention 有很強的理論說明,因此後續有不少論文對 Multi-head Attention 機制都有一定的討論,一些相關工作的論文如下(還沒看,先攢着)

4.3 Multi-head Attention 機制相關的論文:

A Structured Self-attentive Sentence Embedding

Analyzing Multi-Head Self-Attention: Specialized Heads Do the Heavy Lifting, the Rest Can Be Pruned

Are Sixteen Heads Really Better than One?

What Does BERT Look At? An Analysis of BERT’s Attention

A Multiscale Visualization of Attention in the Transformer Model

Improving Deep Transformer with Depth-Scaled Initialization and Merged Attention

5.Transformer 相比於 RNN/LSTM,有什麼優勢?爲什麼?

5.1 RNN 系列的模型,並行計算能力很差

RNN 系列的模型TT時刻隱層狀態的計算,依賴兩個輸入,一個是TT時刻的句子輸入單詞XtX_{t},另一個是T1T-1時刻的隱層狀態的輸出St1\boldsymbol{S}_{t-1},這是最能體現 RNN 本質特徵的一點,RNN 的歷史信息是通過這個信息傳輸渠道往後傳輸的。而 RNN 並行計算的問題就出在這裏,因爲tt時刻的計算依賴t1t-1時刻的隱層計算結果,而t1t-1時刻的計算依賴t2t-2時刻的隱層計算結果,如此下去就形成了所謂的序列依賴關係。

5.2 Transformer 的特徵抽取能力比 RNN 系列的模型要好

上述結論是通過一些主流的實驗來說明的,並不是嚴格的理論證明,具體實驗對比可以參見:

放棄幻想,全面擁抱 Transformer:自然語言處理三大特徵抽取器(CNN/RNN/TF)比較

但是值得注意的是,並不是說 Transformer 就能夠完全替代 RNN 系列的模型了,任何模型都有其適用範圍,同樣的,RNN 系列模型在很多任務上還是首選,熟悉各種模型的內部原理,知其然且知其所以然,才能遇到新任務時,快速分析這時候該用什麼樣的模型,該怎麼做好。

6.Transformer 是如何訓練的?測試階段如何進行測試呢?

6.1 訓練

Transformer 訓練過程與 seq2seq 類似,首先 Encoder 端得到輸入的 encoding 表示,並將其輸入到 Decoder 端做交互式 attention,之後在 Decoder 端接收其相應的輸入(見 1 中有詳細分析),經過多頭 self-attention 模塊之後,結合 Encoder 端的輸出,再經過 FFN,得到 Decoder 端的輸出之後,最後經過一個線性全連接層,就可以通過 softmax 來預測下一個單詞(token),然後根據 softmax 多分類的損失函數,將 loss 反向傳播即可,所以從整體上來說,Transformer 訓練過程就相當於一個有監督的多分類問題。

  • 需要注意的是,Encoder 端可以並行計算,一次性將輸入序列全部 encoding 出來,但 Decoder 端不是一次性把所有單詞(token)預測出來的,而是像 seq2seq 一樣一個接着一個預測出來的。

6.2 測試

而對於測試階段,其與訓練階段唯一不同的是 Decoder 端最底層的輸入,詳細分析見問題 1。

7.Transformer 中的 Add & Norm 模塊,具體是怎麼做的?

見 1 其他模塊的敘述,對 Add & Norm 模塊有詳細的分析

8.爲什麼說 Transformer 可以代替 seq2seq?

這裏用代替這個詞略顯不妥當,seq2seq 雖已老,但始終還是有其用武之地,seq2seq 最大的問題在於將 Encoder 端的所有信息壓縮到一個固定長度的向量中,並將其作爲 Decoder 端首個隱藏狀態的輸入,來預測 Decoder 端第一個單詞(token)的隱藏狀態。在輸入序列比較長的時候,這樣做顯然會損失 Encoder 端的很多信息,而且這樣一股腦的把該固定向量送入 Decoder 端,Decoder 端不能夠關注到其想要關注的信息。

上述兩點都是 seq2seq 模型的缺點,後續論文對這兩點有所改進,如著名的Neural Machine Translation by Jointly Learning to Align and Translate,雖然確確實實對 seq2seq 模型有了實質性的改進,但是由於主體模型仍然爲 RNN(LSTM)系列的模型,因此模型的並行能力還是受限,而 transformer 不但對 seq2seq 模型這兩點缺點有了實質性的改進(多頭交互式 attention 模塊),而且還引入了 self-attention 模塊,讓源序列和目標序列首先“自關聯”起來,這樣的話,源序列和目標序列自身的 embedding 表示所蘊含的信息更加豐富,而且後續的 FFN 層也增強了模型的表達能力(ACL 2018 會議上有論文對 Self-Attention 和 FFN 等模塊都有實驗分析,見論文:How Much Attention Do You Need?A Granular Analysis of Neural Machine Translation Architectures),並且 Transformer 並行計算的能力是遠遠超過 seq2seq 系列的模型,因此我認爲這是 transformer 優於 seq2seq 模型的地方。

9.Transformer 中句子的 encoder 表示是什麼?如何加入詞序信息的?

Transformer Encoder 端得到的是整個輸入序列的 encoding 表示,其中最重要的是經過了 self-attention 模塊,讓輸入序列的表達更加豐富,而加入詞序信息是使用不同頻率的正弦和餘弦函數,具體見 1 中敘述。

10.Transformer 如何並行化的?

Transformer 的並行化我認爲主要體現在 self-attention 模塊,在 Encoder 端 Transformer 可以並行處理整個序列,並得到整個輸入序列經過 Encoder 端的輸出,在 self-attention 模塊,對於某個序列x1,x2,,xnx_{1}, x_{2}, \dots, x_{n},self-attention 模塊可以直接計算xi,xj\boldsymbol{x}_{i}, \boldsymbol{x}_{j}的點乘結果,而 RNN 系列的模型就必須按照順序從x1x_{1}計算到xnx_{n}

11.self-attention 公式中的歸一化有什麼作用?

首先說明做歸一化的原因,隨着dkd_{k}的增大,qkq \cdot k點積後的結果也隨之增大,這樣會將 softmax 函數推入梯度非常小的區域,使得收斂困難(可能出現梯度消失的情況)(爲了說明點積變大的原因,假設qqkk的分量是具有均值 0 和方差 1 的獨立隨機變量,那麼它們的點積qk=i=1dkqikiq \cdot k=\sum_{i=1}^{d_{k}} q_{i} k_{i}均值爲 0,方差爲dkd_{k}),因此爲了抵消這種影響,我們將點積縮放1dk\frac{1}{\sqrt{d_{k}}},對於更詳細的分析,參見(有空再來總結,哈哈~):transformer 中的 attention 爲什麼 scaled?

寫在後面

17 年提出的 Transformer 模型,在當時確實引起了很大的轟動,但是到現在事後看來,Transformer 模型也確實能力很強,但是我覺得並不像論文題目說的那樣《attention is all you need》,反而我覺得論文最大的貢獻在於它第一次做到了在自然語言處理任務中把網絡的深度堆疊上去還能取得很好的效果,而機器翻譯恰好也是一個目前數據量非常豐富且問題本身難度不大的一個任務了,這樣充分發揮了 Transformer 的優勢。另外,self-attention 其實並不是 Transformer 的全部,實際上從深度 CNN 網絡中借鑑而來的 FFN 可能更加重要。所以,理智看待 Transformer,面對不同的任務,選擇最合適自己任務的模型就好了~

參考

The Illustrated Transformer
The Annotated Transformer
BERT 大火卻不懂 Transformer?讀這一篇就夠了
放棄幻想,全面擁抱 Transformer:自然語言處理三大特徵抽取器(CNN/RNN/TF)比較
爲什麼 Transformer 需要進行 Multi-head Attention?
transformer 中的 attention 爲什麼 scaled?
【NLP】Transformer 詳解
transformer 和 LSTM 對比的設想?
目前主流的 attention 方法都有哪些?
谷歌論文《Attention is all you need》裏 Transformer 模型的一些疑問?
《Attention is All You Need》淺讀(簡介+代碼)

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章