[TOC]
@author by xubing
0x00、先導(dǎo)知識
0.1 Seq2Seq
0.2 Attention
0x01.第一層境界
高屋建瓴,會當(dāng)凌絕頂
- 文章題目:《Attention is all you need》
- 發(fā)表時間:2017.06
- 作者:Google(幾位作者全部是一作)
- 傳統(tǒng)的編碼器解碼器一般使用RNN,這也是在機器翻譯中最經(jīng)典的模型。但RNN難以處理長序列的句子,無法實現(xiàn)并行,并且面臨對齊問題。
- Attention模型就是在Encoder和Decoder之間增加了Attention層,解決了長距離依賴的問題。
(長距離依賴信息”可以這么來理解:[1]一個詞其實是一個可以表達多樣性語義信息的符號(歧義問題)。[2]一個詞的語義確定,要依賴其所在的上下文環(huán)境。(根據(jù)上下文消岐)[3]有的詞可能需要一個范圍較小的上下文環(huán)境就能確定其語義(短距離依賴現(xiàn)象),有的詞可能需要一個范圍較大的上下文環(huán)境才能確定其語義(長距離依賴現(xiàn)象)。)
- 而本文提出的Transformer拋棄了傳統(tǒng)的CNN和RNN,只使用Attention 機制。
- 并且在Attention的基礎(chǔ)增加了位置向量,保留了單詞序列信息。
- 還提出了兩個新的Attention機制,Sacled Dot-Product Attention和Multi-head Attention。
- Attention是Seq2Seq的升級版,Transformer是Attention的升級版。
總結(jié)
- 本文的創(chuàng)新點:拋棄了之前傳統(tǒng)的Encoder-Decoder模型必須結(jié)合CNN或RNN的固有模式,只用了Attention。提出了兩個新的attention 機制,分別叫做Scaled Dot-Product Attention和Multi-head Attention。
- 與之前的模型的對比: 減少了計算量、提高了并行效率、任務(wù)效果提升。
- 模型的應(yīng)用:機器翻譯、文檔摘要、對話系統(tǒng)...
0x02、第二層境界
由淺入深,由表及里,漸入佳境
宏觀視角(A High-Level Look)
我們先把Transformer想象成一個黑盒子,在機器翻譯的領(lǐng)域中,這個黑盒子的功能就是輸入一種語言然后將它翻譯成其他語言。如下圖:
打開這個黑盒子,可以看到,這個黑盒子由兩個部分組成:Encoders和Decoders。(注意結(jié)尾加s)
再進行進一步的剖析,可以看到Encoders由6個Encoder組成,Decoders由6個Decoder組成。
打破砂鍋拆到底,每一個Encoder由兩部分組成,每一個Decoder由三部分組成。
還可以再細分嗎? - 可以,不過這里我們先解釋一下每個層的功能。
- 每個Encoder的輸入首先會通過一個self-attention層,通過self-attention層幫助Endcoder在編碼單詞的過程中查看輸入序列中的其他單詞。
- Self-attention的輸出會被傳入一個全連接的前饋神經(jīng)網(wǎng)絡(luò),每個encoder的前饋神經(jīng)網(wǎng)絡(luò)參數(shù)個數(shù)都是相同的,但是他們的作用是獨立的。
- 每個Decoder也同樣具有這樣的層級結(jié)構(gòu),但是在這之間有一個Attention層,幫助Decoder專注于與輸入句子中對應(yīng)的那個單詞(類似與seq2seq models的結(jié)構(gòu))
將張量引入圖片(Bringing The Tensors Into The Picture)
用一個具體的例子來解釋,觀察從輸入到輸出的過程中這些數(shù)據(jù)在各個網(wǎng)絡(luò)結(jié)構(gòu)中的流動。
首先,進行embedding
每個單詞被映射到一個512維的向量。詞嵌入(embedding)的過程只發(fā)生在最底層的一個Encoder。
在每個單詞進入Self-Attention層后都會有一個對應(yīng)的輸出。Self-Attention層中的輸入和輸出是存在依賴關(guān)系的,而前饋層則沒有依賴,所以在前饋層,我們可以用到并行化來提升速率。(重點:并行在前饋層)
開始“編碼”(Now We’re Encoding! )
如上圖所示,每個位置的單詞首先會經(jīng)過一個self attention層,然后每個單詞都通過一個獨立的前饋神經(jīng)網(wǎng)絡(luò)(這些神經(jīng)網(wǎng)絡(luò)結(jié)構(gòu)完全相同)。
從宏觀視角看自注意力機制(Self-Attention at a High Level)
Self Attention是本文提出的新的概念,假設(shè)下面的句子就是我們需要翻譯的輸入句:
The animal didn't cross the street because it was too tired.
- 這句話中的"it"指的是什么?它指的是“animal”還是“street”?對于人來說,這其實是一個很簡單的問題,但是對于一個算法來說,處理這個問題其實并不容易。self attention的出現(xiàn)就是為了解決這個問題,通過self attention,我們能將 “it” 與 “animal” 聯(lián)系起來。
- 當(dāng)模型處理單詞的時候,self attention層可以通過當(dāng)前單詞去查看其輸入序列中的其他單詞,以此來尋找編碼這個單詞更好的線索.
-
self-attention正是transformer中設(shè)計的一種通過其上下文來理解當(dāng)前詞的一種辦法。你會很容易發(fā)現(xiàn)...相較于RNNs,transformer具有更好的并行性。
image.png
如上圖,是我們第五層Encoder針對單詞'it'的圖示,可以發(fā)現(xiàn),我們的Encoder在編碼單詞‘it’時,部分注意力機制集中在了‘a(chǎn)niml’上,這部分的注意力會通過權(quán)值傳遞的方式影響到'it'的編碼。
從微觀視角看自注意力機制(Self-Attention in Detail)
計算self attention的第一步是從每個Encoder的輸入向量上創(chuàng)建3個向量(在這個情況下,對每個單詞做詞嵌入)。所以,對于每個單詞,我們創(chuàng)建一個Query向量,一個Key向量和一個Value向量。
如何產(chǎn)生QKV:這些向量是通過詞嵌入乘以我們訓(xùn)練過程中創(chuàng)建的3個訓(xùn)練矩陣而產(chǎn)生的。(矩陣最開始是隨機的)
以下是兩個詞的演示:
- 第1步:為每個單詞生成qkv
- 第2步:計算得分。將 query向量與每個key向量進行點乘,如下圖。
image.png - 第3步:將第二步的得分除以
,(論文中使用key向量的維度是64維,其平方根=8,這樣可以使得訓(xùn)練過程中具有更穩(wěn)定的梯度。這個并不是唯一值,經(jīng)驗所得)。
-
第4步:將得到的輸出通過softmax函數(shù)標準化,使得最后的列表和為1。
image.png
這個softmax的分數(shù)決定了當(dāng)前單詞在每個句子中每個單詞位置的表示程度。很明顯,當(dāng)前單詞對應(yīng)句子中此單詞所在位置的softmax的分數(shù)最高,但是,有時候attention機制也能關(guān)注到此單詞外的其他單詞,這很有用。
- 第5步:將每個Value向量乘以softmax后的得分。這里實際上的意義在于保存對當(dāng)前詞的關(guān)注度不變的情況下,降低對不相關(guān)詞的關(guān)注。
-
第6步:累加加權(quán)值的向量。 這會在此位置產(chǎn)生self-attention層的輸出(對于第一個單詞)。
image.png
總結(jié)self-attention的計算過程(單詞級別),就是得到一個我們可以放到前饋神經(jīng)網(wǎng)絡(luò)的矢量。 然而在實際的實現(xiàn)過程中,該計算會以矩陣的形式完成,以便更快地處理。下面我們來看看Self-Attention的矩陣計算方式。
通過矩陣運算實現(xiàn)自注意力機制(Matrix Calculation of Self-Attention)
第一步是去計算Query,Key和Value矩陣。我們將詞嵌入轉(zhuǎn)化成矩陣X中,并將其乘以我們訓(xùn)練的權(quán)值矩陣
X矩陣中的每一行對應(yīng)于輸入句子中的一個單詞。 我們看到的X每一行的方框數(shù)實際上是詞嵌入的維度,圖中所示的和論文中是有差距的。X(圖中的4個方框論文中為512個)和q / k / v向量(圖中的3個方框論文中為64個)
最后,由于我們正在處理矩陣,我們可以在一個公式中濃縮前面步驟2到6來計算self attention層的輸出。
“多頭怪”(The Beast With Many Heads)
本文通過使用“Multi-headed”的機制來進一步完善self attention層。“Multi-headed”主要通過下面兩種方式改善了attention層的性能:
1、它擴展了模型專注于不同位置的能力。在上面的例子中,雖然每個編碼都在
中有或多或少的體現(xiàn),但是它可能被實際的單詞本身所支配。如果我們翻譯一個句子,比如“The animal didn’t cross the street because it was too tired”,我們會想知道“it”指的是哪個詞,這時模型的“多頭”注意機制會起到作用。
2、它給出了注意力層的多個“表示子空間”(representation subspaces)。接下來我們將看到,對于“多頭”注意機制,我們有多個查詢/鍵/值權(quán)重矩陣集(Transformer使用八個注意力頭,因此我們對于每個編碼器/解碼器有八個矩陣集合)。這些集合中的每一個都是隨機初始化的,在訓(xùn)練之后,每個集合都被用來將輸入詞嵌入(或來自較低編碼器/解碼器的向量)投影到不同的表示子空間中。
通過multi-headed attention,我們?yōu)槊總€“header”都獨立維護一套Q/K/V的權(quán)值矩陣。然后我們還是如之前單詞級別的計算過程一樣處理這些數(shù)據(jù)。
如果對上面的例子做同樣的self attention計算,而因為我們有8頭attention,所以我們會在八個時間點去計算這些不同的權(quán)值矩陣,但最后結(jié)束時,我們會得到8個不同的矩陣。如下圖:
我們知道在self-attention后面緊跟著的是前饋神經(jīng)網(wǎng)絡(luò),而前饋神經(jīng)網(wǎng)絡(luò)接受的是單個矩陣向量,而不是8個矩陣。所以我們需要一種辦法,把這8個矩陣壓縮成一個矩陣。我們將這8個矩陣連接在一起然后再與一個矩陣相乘。步驟如下圖所示:
這樣multi-headed self attention的全部內(nèi)容就介紹完了。之前可能都是一些過程的圖解,現(xiàn)在我將這些過程連接在一起,用一個整體的框圖來表示一下計算的過程,希望可以加深理解。
現(xiàn)在我們已經(jīng)觸及了attention的header,讓我們重新審視我們之前的例子,看看例句中的“it”這個單詞在不同的attention header情況下會有怎樣不同的關(guān)注點。
如圖:當(dāng)我們對“it”這個詞進行編碼時,一個注意力的焦點主要集中在“animal”上,而另一個注意力集中在“tired”,如果我們將所有注意力添加到圖片中,那么事情可能更難理解:
使用位置編碼表示序列的順序( Representing The Order of The Sequence Using Positional Encoding)
考慮輸入序列中單詞順序。
- 為了解決這個問題,transformer為每個輸入單詞的詞嵌入上添加了一個新向量-位置向量。
-
變換器為每個輸入嵌入添加了一個向量。這些位置編碼向量有固定的生成方式,所以獲取他們是很方便的,但是這些信息確是很有用的,他們能捕捉到每個單詞的位置,或者序列中不同單詞之間的距離。將這些信息也添加到詞嵌入中,然后與Q/K/V向量進行點積,獲得的attention就有了距離的信息了。
image.png
為了讓模型捕捉到單詞的順序信息,我們添加位置編碼向量信息(POSITIONAL ENCODING)-位置編碼向量不需要訓(xùn)練,它有一個規(guī)則的產(chǎn)生方式。
如果我們的嵌入維度為4,那么實際上的位置編碼就如下圖所示:
那么生成位置向量需要遵循怎樣的規(guī)則呢?
觀察下面的圖形,每一行都代表著對一個矢量的位置編碼。因此第一行就是我們輸入序列中第一個字的嵌入向量,每行都包含512個值,每個值介于1和-1之間。我們用顏色來表示1,-1之間的值,這樣方便可視化的方式表現(xiàn)出來:
這是一個20個字(行)的(512)列位置編碼示例。你會發(fā)現(xiàn)它從中心位置被分為了2半,這是因為左半部分的值是一由一個正弦函數(shù)生成的,而右半部分是由另一個函數(shù)(余弦)生成。然后將它們連接起來形成每個位置編碼矢量。
位置編碼的公式在論文(3.5節(jié))中有描述。你也可以在中查看用于生成位置編碼的代碼
get_timing_signal_1d()
.這不是位置編碼的唯一可能方法。然而,它具有能夠擴展到看不見的序列長度的優(yōu)點(例如,如果我們訓(xùn)練的模型被要求翻譯的句子比我們訓(xùn)練集中的任何句子都長)。
殘差模塊 (The Residuals)
這一節(jié)介紹的是encoder過程中的每個self-attention層的左右連接情況,我們稱這個為:layer-normalization 步驟。如下圖所示:
再進一步探索其內(nèi)部的計算方式,可以得到下圖:
Decoder的子層也是同樣的,如果我們想做堆疊了2個Encoder和2個Decoder的Transformer,那么它可視化就會如下圖所示:
解碼側(cè)(The Decoder Side)
Decoder 和 Encoder基本上差不多,不過還是需要仔細探討一下Decoder的數(shù)據(jù)計算原理。
編碼器通過處理輸入序列開啟工作。頂端編碼器的輸出之后會變轉(zhuǎn)化為一個包含向量K(鍵向量)和V(值向量)的注意力向量集 。這些向量將被每個解碼器用于自身的“編碼-解碼注意力層”,而這些層可以幫助解碼器關(guān)注輸入序列哪些位置合適:
在完成編碼階段后,則開始解碼階段。解碼階段的每個步驟都會輸出一個輸出序列(在這個例子里,是英語翻譯的句子)的元素
接下來的步驟重復(fù)了這個過程,直到到達一個特殊的終止符號,它表示transformer的解碼器已經(jīng)完成了它的輸出。每個步驟的輸出在下一個時間步被提供給底端解碼器,并且就像編碼器之前做的那樣,這些解碼器會輸出它們的解碼結(jié)果 。另外,就像我們對編碼器的輸入所做的那樣,我們會嵌入并添加位置編碼給那些解碼器,來表示每個單詞的位置。
而那些解碼器中的自注意力層表現(xiàn)的模式與編碼器不同:在解碼器中,自注意力層只被允許處理輸出序列中更靠前的那些位置。在softmax步驟前,它會把后面的位置給隱去(把它們設(shè)為-inf)。
這個“編碼-解碼注意力層”工作方式基本就像多頭自注意力層一樣,只不過它是通過在它下面的層來創(chuàng)造查詢矩陣,并且從編碼器的輸出中取得鍵/值矩陣。
最終的線性變換和Softmax層(The Final Linear and Softmax Layer)
解碼組件最后會輸出一個實數(shù)向量。我們?nèi)绾伟迅↑c數(shù)變成一個單詞?這便是線性變換層要做的工作,它之后就是Softmax層。
線性變換層是一個簡單的全連接神經(jīng)網(wǎng)絡(luò),它可以把解碼組件產(chǎn)生的向量投射到一個比它大得多的、被稱作對數(shù)幾率(logits)的向量里。
不妨假設(shè)我們的模型從訓(xùn)練集中學(xué)習(xí)一萬個不同的英語單詞(我們模型的“輸出詞表”)。因此對數(shù)幾率向量為一萬個單元格長度的向量——每個單元格對應(yīng)某一個單詞的分數(shù)。
接下來的Softmax 層便會把那些分數(shù)變成概率(都為正數(shù)、上限1.0)。概率最高的單元格被選中,并且它對應(yīng)的單詞被作為這個時間步的輸出。
這張圖片從底部以解碼器組件產(chǎn)生的輸出向量開始。之后它會轉(zhuǎn)化出一個輸出單詞。
訓(xùn)練部分總結(jié)(Recap Of Training)
既然我們已經(jīng)過了一遍完整的transformer的前向傳播過程,那我們就可以直觀感受一下它的訓(xùn)練過程。
在訓(xùn)練過程中,一個未經(jīng)訓(xùn)練的模型會通過一個完全一樣的前向傳播。但因為我們用有標記的訓(xùn)練集來訓(xùn)練它,所以我們可以用它的輸出去與真實的輸出做比較。
為了把這個流程可視化,不妨假設(shè)我們的輸出詞匯僅僅包含六個單詞:“a”, “am”, “i”, “thanks”, “student”以及 “”(end of sentence的縮寫形式)。
我們模型的輸出詞表在我們訓(xùn)練之前的預(yù)處理流程中就被設(shè)定好。
一旦我們定義了我們的輸出詞表,我們可以使用一個相同寬度的向量來表示我們詞匯表中的每一個單詞。這也被認為是一個one-hot 編碼。所以,我們可以用下面這個向量來表示單詞“am”:
接下來我們討論模型的損失函數(shù)——這是我們用來在訓(xùn)練過程中優(yōu)化的標準。通過它可以訓(xùn)練得到一個結(jié)果盡量準確的模型。
損失函數(shù)(The Loss Function)
比如說我們正在訓(xùn)練模型,現(xiàn)在是第一步,一個簡單的例子——把“merci”翻譯為“thanks”。
這意味著我們想要一個表示單詞“thanks”概率分布的輸出。但是因為這個模型還沒被訓(xùn)練好,所以不太可能現(xiàn)在就出現(xiàn)這個結(jié)果。
為模型的參數(shù)(權(quán)重)都被隨機的生成,(未經(jīng)訓(xùn)練的)模型產(chǎn)生的概率分布在每個單元格/單詞里都賦予了隨機的數(shù)值。我們可以用真實的輸出來比較它,然后用反向傳播算法來略微調(diào)整所有模型的權(quán)重,生成更接近結(jié)果的輸出。
你會如何比較兩個概率分布呢?我們可以簡單地用其中一個減去另一個。更多細節(jié)請參考交叉熵和KL散度。
交叉熵:https://colah.github.io/posts/2015-09-Visual-Information/
KL散度:https://www.countbayesie.com/blog/2017/5/9/kullback-leibler-divergence-explained
但注意到這是一個過于簡化的例子。更現(xiàn)實的情況是處理一個句子。例如,輸入“je suis étudiant”并期望輸出是“i am a student”。那我們就希望我們的模型能夠成功地在這些情況下輸出概率分布:
每個概率分布被一個以詞表大小(我們的例子里是6,但現(xiàn)實情況通常是3000或10000)為寬度的向量所代表。
第一個概率分布在與“i”關(guān)聯(lián)的單元格有最高的概率
第二個概率分布在與“am”關(guān)聯(lián)的單元格有最高的概率
以此類推,第五個輸出的分布表示“”關(guān)聯(lián)的單元格有最高的概率
依據(jù)例子訓(xùn)練模型得到的目標概率分布
在一個足夠大的數(shù)據(jù)集上充分訓(xùn)練后,我們希望模型輸出的概率分布看起來像這個樣子:
我們期望訓(xùn)練過后,模型會輸出正確的翻譯。當(dāng)然如果這段話完全來自訓(xùn)練集,它并不是一個很好的評估指標(參考:交叉驗證,鏈接https://www.youtube.com/watch?v=TIgfjmp-4BA)。注意到每個位置(詞)都得到了一點概率,即使它不太可能成為那個時間步的輸出——這是softmax的一個很有用的性質(zhì),它可以幫助模型訓(xùn)練。
因為這個模型一次只產(chǎn)生一個輸出,不妨假設(shè)這個模型只選擇概率最高的單詞,并把剩下的詞拋棄。這是其中一種方法(叫貪心解碼)。另一個完成這個任務(wù)的方法是留住概率最靠高的兩個單詞(例如I和a),那么在下一步里,跑模型兩次:其中一次假設(shè)第一個位置輸出是單詞“I”,而另一次假設(shè)第一個位置輸出是單詞“me”,并且無論哪個版本產(chǎn)生更少的誤差,都保留概率最高的兩個翻譯結(jié)果。然后我們?yōu)榈诙偷谌齻€位置重復(fù)這一步驟。這個方法被稱作集束搜索(beam search)。在我們的例子中,集束寬度是2(因為保留了2個集束的結(jié)果,如第一和第二個位置),并且最終也返回兩個集束的結(jié)果(top_beams也是2)。這些都是可以提前設(shè)定的參數(shù)。
再進一步(Go Forth And Transform)
我希望通過上文已經(jīng)讓你們了解到Transformer的主要概念了。如果你想在這個領(lǐng)域深入,我建議可以走以下幾步:閱讀Attention Is All You Need,Transformer博客和Tensor2Tensor announcement,以及看看?ukasz Kaiser的介紹,了解模型和細節(jié)。
Attention Is All You Need:https://arxiv.org/abs/1706.03762
Transformer博客:https://ai.googleblog.com/2017/08/transformer-novel-neural-network.html
Tensor2Tensor announcement:https://ai.googleblog.com/2017/06/accelerating-deep-learning-research.html
?ukasz Kaiser的介紹:https://colab.research.google.com/github/tensorflow/tensor2tensor/blob/master/tensor2tensor/notebooks/hello_t2t.ipynb
接下來可以研究的工作:
Depthwise Separable Convolutions for Neural Machine Translation
https://arxiv.org/abs/1706.03059
One Model To Learn Them All
https://arxiv.org/abs/1706.05137
Discrete Autoencoders for Sequence Models
https://arxiv.org/abs/1801.09797
Generating Wikipedia by Summarizing Long Sequences
https://arxiv.org/abs/1801.10198
Image Transformer
https://arxiv.org/abs/1802.05751
Training Tips for the Transformer Model
https://arxiv.org/abs/1804.00247
Self-Attention with Relative Position Representations
https://arxiv.org/abs/1803.02155
Fast Decoding in Sequence Models using Discrete Latent Variables
https://arxiv.org/abs/1803.03382
Adafactor: Adaptive Learning Rates with Sublinear Memory Cost
https://arxiv.org/abs/1804.04235
0x03.第三層境界
紙上得來終覺淺,絕知此事要躬行
參考文章:
1.http://www.lxweimin.com/p/3f2d4bc126e6
2.https://www.imooc.com/article/51468
3.https://kexue.fm/archives/4765
4.https://blog.csdn.net/weixin_42446330/article/details/86710838
5.https://blog.csdn.net/qq_41664845/article/details/84969266
6.https://jalammar.github.io/illustrated-transformer/
7.[https://blog.csdn.net/longxinchen_ml/article/details/86533005] (https://blog.csdn.net/longxinchen_ml/article/details/86533005)