Transformer各層網(wǎng)絡(luò)結(jié)構(gòu)詳解!面試必備!(附代碼實現(xiàn))

1. 什么是Transformer

《Attention Is All You Need》是一篇Google提出的將Attention思想發(fā)揮到極致的論文。這篇論文中提出一個全新的模型,叫 Transformer,拋棄了以往深度學(xué)習(xí)任務(wù)里面使用到的 CNN 和 RNN。目前大熱的Bert就是基于Transformer構(gòu)建的,這個模型廣泛應(yīng)用于NLP領(lǐng)域,例如機器翻譯,問答系統(tǒng),文本摘要和語音識別等等方向。

2. Transformer結(jié)構(gòu)

2.1 總體結(jié)構(gòu)

Transformer的結(jié)構(gòu)和Attention模型一樣,Transformer模型中也采用了 encoer-decoder 架構(gòu)。但其結(jié)構(gòu)相比于Attention更加復(fù)雜,論文中encoder層由6個encoder堆疊在一起,decoder層也一樣。

不了解Attention模型的,可以回顧之前的文章:Attention

image

每一個encoder和decoder的內(nèi)部結(jié)構(gòu)如下圖:

image
  • encoder,包含兩層,一個self-attention層和一個前饋神經(jīng)網(wǎng)絡(luò),self-attention能幫助當(dāng)前節(jié)點不僅僅只關(guān)注當(dāng)前的詞,從而能獲取到上下文的語義。
  • decoder也包含encoder提到的兩層網(wǎng)絡(luò),但是在這兩層中間還有一層attention層,幫助當(dāng)前節(jié)點獲取到當(dāng)前需要關(guān)注的重點內(nèi)容。

2.2 Encoder層結(jié)構(gòu)

首先,模型需要對輸入的數(shù)據(jù)進行一個embedding操作,也可以理解為類似w2c的操作,enmbedding結(jié)束之后,輸入到encoder層,self-attention處理完數(shù)據(jù)后把數(shù)據(jù)送給前饋神經(jīng)網(wǎng)絡(luò),前饋神經(jīng)網(wǎng)絡(luò)的計算可以并行,得到的輸出會輸入到下一個encoder。

image

2.2.1 Positional Encoding

transformer模型中缺少一種解釋輸入序列中單詞順序的方法,它跟序列模型還不不一樣。為了處理這個問題,transformer給encoder層和decoder層的輸入添加了一個額外的向量Positional Encoding,維度和embedding的維度一樣,這個向量采用了一種很獨特的方法來讓模型學(xué)習(xí)到這個值,這個向量能決定當(dāng)前詞的位置,或者說在一個句子中不同的詞之間的距離。這個位置向量的具體計算方法有很多種,論文中的計算方法如下:

PE(pos,2i)=sin(\frac{pos}{10000^{\frac{2i}{d_{model}}}})

PE(pos,2i+1)=cos(\frac{pos}{10000^{\frac{2i}{d_{model}}}})

其中pos是指當(dāng)前詞在句子中的位置,i是指向量中每個值的index,可以看出,在偶數(shù)位置,使用正弦編碼,在奇數(shù)位置,使用余弦編碼。

最后把這個Positional Encoding與embedding的值相加,作為輸入送到下一層。

image

2.2.2 Self-Attention

接下來我們詳細看一下self-attention,其思想和attention類似,但是self-attention是Transformer用來將其他相關(guān)單詞的“理解”轉(zhuǎn)換成我們正在處理的單詞的一種思路,我們看個例子:

The animal didn't cross the street because it was too tired

這里的 it 到底代表的是 animal 還是 street 呢,對于我們來說能很簡單的判斷出來,但是對于機器來說,是很難判斷的,self-attention就能夠讓機器把 it 和 animal 聯(lián)系起來,接下來我們看下詳細的處理過程。

  1. 首先,self-attention會計算出三個新的向量,在論文中,向量的維度是512維,我們把這三個向量分別稱為Query、Key、Value,這三個向量是用embedding向量與一個矩陣相乘得到的結(jié)果,這個矩陣是隨機初始化的,維度為(64,512)注意第二個維度需要和embedding的維度一樣,其值在BP的過程中會一直進行更新,得到的這三個向量的維度是64。

    image
  2. 計算self-attention的分數(shù)值,該分數(shù)值決定了當(dāng)我們在某個位置encode一個詞時,對輸入句子的其他部分的關(guān)注程度。這個分數(shù)值的計算方法是Query與Key做點成,以下圖為例,首先我們需要針對Thinking這個詞,計算出其他詞對于該詞的一個分數(shù)值,首先是針對于自己本身即q1·k1,然后是針對于第二個詞即q1·k2。

    image
  3. 接下來,把點成的結(jié)果除以一個常數(shù),這里我們除以8,這個值一般是采用上文提到的矩陣的第一個維度的開方即64的開方8,當(dāng)然也可以選擇其他的值,然后把得到的結(jié)果做一個softmax的計算。得到的結(jié)果即是每個詞對于當(dāng)前位置的詞的相關(guān)性大小,當(dāng)然,當(dāng)前位置的詞相關(guān)性肯定會會很大。

    image
  4. 下一步就是把Value和softmax得到的值進行相乘,并相加,得到的結(jié)果即是self-attetion在當(dāng)前節(jié)點的值。

    image

在實際的應(yīng)用場景,為了提高計算速度,我們采用的是矩陣的方式,直接計算出Query, Key, Value的矩陣,然后把embedding的值與三個矩陣直接相乘,把得到的新矩陣 Q 與 K 相乘,乘以一個常數(shù),做softmax操作,最后乘上 V 矩陣。

這種通過 query 和 key 的相似性程度來確定 value 的權(quán)重分布的方法被稱為scaled dot-product attention。

image
image

2.2.3 Multi-Headed Attention

這篇論文更牛逼的地方是給self-attention加入了另外一個機制,被稱為“multi-headed” attention,該機制理解起來很簡單,就是說不僅僅只初始化一組Q、K、V的矩陣,而是初始化多組,tranformer是使用了8組,所以最后得到的結(jié)果是8個矩陣。

image
image

2.2.4 Layer normalization

在transformer中,每一個子層(self-attetion,F(xiàn)eed Forward Neural Network)之后都會接一個殘缺模塊,并且有一個Layer normalization。

image

Normalization有很多種,但是它們都有一個共同的目的,那就是把輸入轉(zhuǎn)化成均值為0方差為1的數(shù)據(jù)。我們在把數(shù)據(jù)送入激活函數(shù)之前進行normalization(歸一化),因為我們不希望輸入數(shù)據(jù)落在激活函數(shù)的飽和區(qū)。

Batch Normalization

BN的主要思想就是:在每一層的每一批數(shù)據(jù)上進行歸一化。我們可能會對輸入數(shù)據(jù)進行歸一化,但是經(jīng)過該網(wǎng)絡(luò)層的作用后,我們的數(shù)據(jù)已經(jīng)不再是歸一化的了。隨著這種情況的發(fā)展,數(shù)據(jù)的偏差越來越大,我的反向傳播需要考慮到這些大的偏差,這就迫使我們只能使用較小的學(xué)習(xí)率來防止梯度消失或者梯度爆炸。BN的具體做法就是對每一小批數(shù)據(jù),在批這個方向上做歸一化。

Layer normalization

它也是歸一化數(shù)據(jù)的一種方式,不過LN 是在每一個樣本上計算均值和方差,而不是BN那種在批方向計算均值和方差!公式如下:

LN(x_i)=\alpha*\frac{x_i-\mu_L}{\sqrt{\sigma_L^2+\varepsilon}}+\beta

image

2.2.5 Feed Forward Neural Network

這給我們留下了一個小的挑戰(zhàn),前饋神經(jīng)網(wǎng)絡(luò)沒法輸入 8 個矩陣呀,這該怎么辦呢?所以我們需要一種方式,把 8 個矩陣降為 1 個,首先,我們把 8 個矩陣連在一起,這樣會得到一個大的矩陣,再隨機初始化一個矩陣和這個組合好的矩陣相乘,最后得到一個最終的矩陣。

image

2.3 Decoder層結(jié)構(gòu)

根據(jù)上面的總體結(jié)構(gòu)圖可以看出,decoder部分其實和encoder部分大同小異,剛開始也是先添加一個位置向量Positional Encoding,方法和 2.2.1 節(jié)一樣,接下來接的是masked mutil-head attetion,這里的mask也是transformer一個很關(guān)鍵的技術(shù),下面我們會進行一一介紹。

其余的層結(jié)構(gòu)與Encoder一樣,請參考Encoder層結(jié)構(gòu)。

2.3.1 masked mutil-head attetion

mask 表示掩碼,它對某些值進行掩蓋,使其在參數(shù)更新時不產(chǎn)生效果。Transformer 模型里面涉及兩種 mask,分別是 padding mask 和 sequence mask。其中,padding mask 在所有的 scaled dot-product attention 里面都需要用到,而 sequence mask 只有在 decoder 的 self-attention 里面用到。

  1. padding mask

    什么是 padding mask 呢?因為每個批次輸入序列長度是不一樣的也就是說,我們要對輸入序列進行對齊。具體來說,就是給在較短的序列后面填充 0。但是如果輸入的序列太長,則是截取左邊的內(nèi)容,把多余的直接舍棄。因為這些填充的位置,其實是沒什么意義的,所以我們的attention機制不應(yīng)該把注意力放在這些位置上,所以我們需要進行一些處理。

    具體的做法是,把這些位置的值加上一個非常大的負數(shù)(負無窮),這樣的話,經(jīng)過 softmax,這些位置的概率就會接近0!

    而我們的 padding mask 實際上是一個張量,每個值都是一個Boolean,值為 false 的地方就是我們要進行處理的地方。

  2. Sequence mask

    文章前面也提到,sequence mask 是為了使得 decoder 不能看見未來的信息。也就是對于一個序列,在 time_step 為 t 的時刻,我們的解碼輸出應(yīng)該只能依賴于 t 時刻之前的輸出,而不能依賴 t 之后的輸出。因此我們需要想一個辦法,把 t 之后的信息給隱藏起來。

    那么具體怎么做呢?也很簡單:產(chǎn)生一個上三角矩陣,上三角的值全為0。把這個矩陣作用在每一個序列上,就可以達到我們的目的。

  • 對于 decoder 的 self-attention,里面使用到的 scaled dot-product attention,同時需要padding mask 和 sequence mask 作為 attn_mask,具體實現(xiàn)就是兩個mask相加作為attn_mask。
  • 其他情況,attn_mask 一律等于 padding mask。

2.3.2 Output層

當(dāng)decoder層全部執(zhí)行完畢后,怎么把得到的向量映射為我們需要的詞呢,很簡單,只需要在結(jié)尾再添加一個全連接層和softmax層,假如我們的詞典是1w個詞,那最終softmax會輸入1w個詞的概率,概率值最大的對應(yīng)的詞就是我們最終的結(jié)果。

2.4 動態(tài)流程圖

編碼器通過處理輸入序列開啟工作。頂端編碼器的輸出之后會變轉(zhuǎn)化為一個包含向量K(鍵向量)和V(值向量)的注意力向量集 ,這是并行化操作。這些向量將被每個解碼器用于自身的“編碼-解碼注意力層”,而這些層可以幫助解碼器關(guān)注輸入序列哪些位置合適:

image

在完成編碼階段后,則開始解碼階段。解碼階段的每個步驟都會輸出一個輸出序列(在這個例子里,是英語翻譯的句子)的元素。

接下來的步驟重復(fù)了這個過程,直到到達一個特殊的終止符號,它表示transformer的解碼器已經(jīng)完成了它的輸出。每個步驟的輸出在下一個時間步被提供給底端解碼器,并且就像編碼器之前做的那樣,這些解碼器會輸出它們的解碼結(jié)果 。

image

3. Transformer為什么需要進行Multi-head Attention

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

4. Transformer相比于RNN/LSTM,有什么優(yōu)勢?為什么?

  1. RNN系列的模型,并行計算能力很差。RNN并行計算的問題就出在這里,因為 T 時刻的計算依賴 T-1 時刻的隱層計算結(jié)果,而 T-1 時刻的計算依賴 T-2 時刻的隱層計算結(jié)果,如此下去就形成了所謂的序列依賴關(guān)系。

  2. Transformer的特征抽取能力比RNN系列的模型要好。

    具體實驗對比可以參考:放棄幻想,全面擁抱Transformer:自然語言處理三大特征抽取器(CNN/RNN/TF)比較

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

5. 為什么說Transformer可以代替seq2seq?

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

Transformer優(yōu)點:transformer不但對seq2seq模型這兩點缺點有了實質(zhì)性的改進(多頭交互式attention模塊),而且還引入了self-attention模塊,讓源序列和目標(biāo)序列首先“自關(guān)聯(lián)”起來,這樣的話,源序列和目標(biāo)序列自身的embedding表示所蘊含的信息更加豐富,而且后續(xù)的FFN層也增強了模型的表達能力,并且Transformer并行計算的能力是遠遠超過seq2seq系列的模型,因此我認為這是transformer優(yōu)于seq2seq模型的地方。

6. 代碼實現(xiàn)

地址:https://github.com/Kyubyong/transformer

代碼解讀:Transformer解析與tensorflow代碼解讀

機器學(xué)習(xí)通俗易懂系列文章

image

7. 參考文獻


作者:@mantchs

GitHub:https://github.com/NLP-LOVE/ML-NLP

歡迎大家加入討論!共同完善此項目!群號:【541954936】點擊加入

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容