聊聊Transform模型
從之前的RNN系列到現(xiàn)在的Transformer模型,是一個演進(jìn)的過程,技術(shù)的實(shí)現(xiàn)與迭代并不是一蹴而就,而是一個持續(xù)演進(jìn)的歷程。如果一開始就從Tranformer的模型機(jī)制來學(xué)習(xí),知識的不全面以及欠缺就會導(dǎo)致懵逼甚至看不懂又不理解。
RNN系列:
聊聊RNN&LSTM
聊聊RNN與seq2seq
聊聊RNN與Attention
以下內(nèi)容摘自《BERT基礎(chǔ)教程:Transformer大模型實(shí)戰(zhàn) 》
概述
循環(huán)神經(jīng)網(wǎng)絡(luò)和長短期記憶網(wǎng)絡(luò)已經(jīng)廣泛應(yīng)用于時序任務(wù),比如文本預(yù)測、機(jī)器翻譯、文章生成等。然而,它們面臨的一大問題就是如何記錄長期依賴。
為了解決這個問題,一個名為Transformer的新架構(gòu)應(yīng)運(yùn)而生。從那以后,Transformer被應(yīng)用到多個自然語言處理方向,到目前為止還未有新的架構(gòu)能夠?qū)⑵涮娲?梢哉f,它的出現(xiàn)是自然語言處理領(lǐng)域的突破,并為新的革命性架構(gòu)(BERT、GPT-3、T5等)打下了理論基礎(chǔ)。
Transformer由編碼器和解碼器兩部分組成。首先,向編碼器輸入一句話(原句),讓其學(xué)習(xí)這句話的特征,再將特征作為輸入傳輸給解碼器。最后,此特征會通過解碼器生成輸出句(目標(biāo)句)。
假設(shè)我們需要將一個句子從英文翻譯為法文。如圖所示,首先,我們需要將這個英文句子(原句)輸進(jìn)編碼器。編碼器將提取英文句子的特征并提供給解碼器。最后,解碼器通過特征完成法文句子(目標(biāo)句)的翻譯。
具體模型結(jié)構(gòu)如下圖。
編碼器
Transformer中的編碼器不止一個,而是由一組編碼器串聯(lián)而成。一個編碼器的輸出作為下一個編碼器的輸入。在圖中有個編碼器,每一個編碼器都從下方接收數(shù)據(jù),再輸出給上方。以此類推,原句中的特征會由最后一個編碼器輸出。編碼器模塊的主要功能就是提取原句中的特征。
編碼器內(nèi)部又是由多頭注意力層與前饋網(wǎng)絡(luò)層兩部分組成。
多頭注意力層
引入自注意力機(jī)制
多頭注意力層又是依賴于自注意力機(jī)制實(shí)現(xiàn)。
請看下面的例句:
A dog ate the food because it was hungry(一只狗吃了食物,因?yàn)樗莛I)
例句中的代詞it(它)可以指代dog(狗)或者food(食物)。當(dāng)讀這段文字的時候,我們自然而然地認(rèn)為it指代的是dog,而不是food。但是當(dāng)計(jì)算機(jī)模型在面對這兩種選擇時該如何決定呢?這時,自注意力機(jī)制有助于解決這個問題。
模型首先需要計(jì)算出單詞A的特征值,其次計(jì)算dog的特征值,然后計(jì)算ate的特征值,以此類推。當(dāng)計(jì)算每個詞的特征值時,模型都需要遍歷每個詞與句子中其他詞的關(guān)系。模型可以通過詞與詞之間的關(guān)系來更好地理解當(dāng)前詞的意思。
比如,當(dāng)計(jì)算it的特征值時,模型會將it與句子中的其他詞一一關(guān)聯(lián),以便更好地理解它的意思。
如圖所示,it的特征值由它本身與句子中其他詞的關(guān)系計(jì)算所得。通過關(guān)系連線,模型可以明確知道原句中it所指代的是dog而不是food,這是因?yàn)閕t與dog的關(guān)系更緊密,關(guān)系連線相較于其他詞也更粗。
實(shí)現(xiàn)原理
為簡單起見,我們假設(shè)輸入句(原句)為I am good(我很好)。首先,我們將每個詞轉(zhuǎn)化為其對應(yīng)的詞嵌入向量。需要注意的是,嵌入只是詞的特征向量,這個特征向量也是需要通過訓(xùn)練獲得的。單詞I的詞嵌入向量可以用來表示,相應(yīng)地,am為,good為,即:
通過輸入矩陣X,可以看出,矩陣的第一行表示單詞I的詞嵌入向量。以此類推,第二行對應(yīng)單詞am的詞嵌入向量,第三行對應(yīng)單詞good的詞嵌入向量。所以矩陣X的維度為[句子的長度×詞嵌入向量維度]。原句的長度為3,假設(shè)詞嵌入向量維度為512,那么輸入矩陣的維度就是[3×512];該矩陣對應(yīng)的張量表示,可以拆分如下:
a = numpy.array([[1.76, 2.22, ..., 6.66],
[7.77, 0.631,..., 5.35],
[11.44, 10.10,..., 3.33]
])
增加額外的三個權(quán)重矩陣,分別為;用輸入矩陣X分別乘以,依次創(chuàng)建出查詢矩陣Q、鍵矩陣K、值矩陣V。
需要注意的是,權(quán)重矩陣的初始值完全是隨機(jī)的,但最優(yōu)值則需要通過訓(xùn)練所得。
將輸入矩陣[插圖]分別乘以后,我們就可以得出對應(yīng)的查詢矩陣、鍵矩陣和值矩陣。
Q,K,V三個向量矩陣,代表了對輸入序列中的每個位置或詞的不同信息。
- Query向量 (Q):
- Query向量是自注意力機(jī)制中用于詢問其他位置或詞信息的向量。
- 每個位置或詞都有一個對應(yīng)的Query向量,該向量用于查詢其他位置或詞的重要程度,以便計(jì)算每個位置或詞的注意力權(quán)重。
- Key向量 (K):
- Key向量用于標(biāo)識每個位置或詞的重要特征。
- 每個位置或詞都有一個對應(yīng)的Key向量,該向量對應(yīng)了該位置或詞的特征,用于與Query向量比較,以計(jì)算注意力權(quán)重。
- Value向量 (V):
- Value向量用于存儲每個位置或詞的信息。
- 每個位置或詞都有一個對應(yīng)的Value向量,該向量包含了該位置或詞的信息,用于根據(jù)注意力權(quán)重加權(quán)求和得到該位置或詞的輸出。
理解自注意力機(jī)制
第一步
要計(jì)算一個詞的特征值,自注意力機(jī)制會使該詞與給定句子中的所有詞聯(lián)系起來。還是以I am good這句話為例。為了計(jì)算單詞I的特征值,我們將單詞I與句子中的所有單詞一一關(guān)聯(lián),如圖所示。
自注意力機(jī)制首先要計(jì)算查詢矩陣Q與鍵矩陣K的點(diǎn)積:
通過計(jì)算查詢的點(diǎn)積,可以了解單詞I與句子中的所有單詞的相似度。
綜上所述,計(jì)算查詢矩陣[插圖]與鍵矩陣[插圖]的點(diǎn)積,從而得到相似度分?jǐn)?shù)。這有助于我們了解句子中每個詞與所有其他詞的相似度。
第二步
自注意力機(jī)制的第2步是將矩陣除以鍵向量維度的平方根。這樣做的目的主要是獲得穩(wěn)定的梯度。
為什么要除以dk(鍵向量維度的平方根),其實(shí)是在做一個標(biāo)準(zhǔn)化以及防止softmax函數(shù)梯度消失的處理。
參考:為什么在進(jìn)行softmax之前需要對attention進(jìn)行scaled(為什么除以 d_k的平方根)
第三步
目前所得的相似度分?jǐn)?shù)尚未被歸一化,我們需要使用softmax函數(shù)對其進(jìn)行歸一化處理。如圖所示,應(yīng)用softmax函數(shù)將使數(shù)值分布在0到1的范圍內(nèi),且每一行的所有數(shù)之和等于1。
第四步
至此,我們計(jì)算了查詢矩陣與鍵矩陣的點(diǎn)積,得到了分?jǐn)?shù),然后用softmax函數(shù)將分?jǐn)?shù)歸一化。自注意力機(jī)制的最后一步是計(jì)算注意力矩陣[插圖]。注意力矩陣包含句子中每個單詞的注意力值。它可以通過將分?jǐn)?shù)矩陣softmax ()乘以值矩陣V得出,如圖所示。
假設(shè)計(jì)算結(jié)果如下所示:
我們回過頭去看之前的例句:A dog ate the food because it was hungry(一只狗吃了食物,因?yàn)樗莛I)。在這里,it這個詞表示dog。我們將按照前面的步驟來計(jì)算it這個詞的自注意力值。假設(shè)計(jì)算過程如圖所示。
可以看出,it這個詞的自注意力值包含100%的值向量v2(dog)。這有助于模型理解it這個詞實(shí)際上指的是dog而不是food。這也再次說明,通過自注意力機(jī)制,我們可以了解一個詞與句子中所有詞的相關(guān)程度。
綜上所述,注意力矩陣Z由句子中所有單詞的自注意力值組成,它的計(jì)算公式如下。
現(xiàn)將自注意力機(jī)制的計(jì)算步驟總結(jié)如下:
自注意力機(jī)制的計(jì)算流程圖如圖所示。
自注意力機(jī)制也被稱為縮放點(diǎn)積注意力機(jī)制,這是因?yàn)槠溆?jì)算過程是先求查詢矩陣與鍵矩陣的點(diǎn)積,再用dk對結(jié)果進(jìn)行縮放。總結(jié)來說,自注意力機(jī)制將一個單詞與句子中的所有單詞聯(lián)系起來,從而提取每個詞的更多信息。
多頭注意力
如上是單個注意力矩陣的計(jì)算流程。使用多頭注意力的邏輯是這樣的:使用多個注意力矩陣,而非單一的注意力矩陣,可以提高注意力矩陣的準(zhǔn)確性。接著上述已計(jì)算的Z1注意力矩陣,接下來計(jì)算第二個注意力矩陣Z2。
同樣,我們可以計(jì)算出h個注意力矩陣,將它們串聯(lián)起來。然后,將結(jié)果乘以一個新的權(quán)重矩陣W,得出最終的注意力矩陣,如下所示。
如此設(shè)計(jì),就形成了多頭注意力層。
位置編碼
還是以I am good(我很好)為例。在RNN模型中,句子是逐字送入學(xué)習(xí)網(wǎng)絡(luò)的。換言之,首先把I作為輸入,接下來是am,以此類推。通過逐字地接受輸入,學(xué)習(xí)網(wǎng)絡(luò)就能完全理解整個句子。然而,Transformer網(wǎng)絡(luò)并不遵循遞歸循環(huán)的模式,而是并行輸入有助于縮短訓(xùn)練時間,同時有利于學(xué)習(xí)長期依賴。
如果把輸入矩陣X直接傳給Transformer,那么模型是無法理解詞序的。因此,需要添加一些表明詞序(詞的位置)的信息,以便神經(jīng)網(wǎng)絡(luò)能夠理解句子的含義。所以,我們不能將輸入矩陣直接傳給Transformer。這里引入了一種叫作位置編碼的技術(shù),以達(dá)到上述目的。顧名思義,位置編碼是指詞在句子中的位置(詞序)的編碼。
位置編碼矩陣[插圖]的維度與輸入矩陣[插圖]的維度相同。在將輸入矩陣直接傳給Transformer之前,我們將使其包含位置編碼。我們只需將位置編碼矩陣P添加到輸入矩陣X中,再將其作為輸入送入神經(jīng)網(wǎng)絡(luò),如圖所示。這樣一來,輸入矩陣不僅有詞的嵌入值,還有詞在句子中的位置信息。
位置編碼矩陣究竟是如何計(jì)算的呢?如下所示,Transformer論文“Attention Is All You Need”的作者使用了正弦函數(shù)來計(jì)算位置編碼:
在上面的等式中,pos表示該詞在句子中的位置,i表示在輸入矩陣中的位置。
前饋網(wǎng)絡(luò)層
前饋網(wǎng)絡(luò)由兩個有ReLU激活函數(shù)的全連接層(Full Connection FC層)組成。前饋網(wǎng)絡(luò)的參數(shù)在句子的不同位置上是相同的,但在不同的編碼器模塊上是不同的。
疊加和歸一組件
同時連接一個子層的輸入與輸出。
- 同時連接多頭注意力的輸入與輸出
- 同時連接前饋網(wǎng)絡(luò)層的輸入和輸出
疊加和歸一組件,包含一個殘差連接層與層的歸一化。層的歸一化可以防止每層的值劇烈變化,從而提高模型的訓(xùn)練速度。
殘差連接層
殘差網(wǎng)絡(luò),主要是引入了一種稱為“跳躍連接”的結(jié)構(gòu)。所謂“跳躍連接”是指將前面層的輸出通過一條“快速通道”直接傳遞到當(dāng)前層之后。也就是說,當(dāng)前層的輸入不僅來自前一 層,還包含了前面層未修改的信息。
這種結(jié)構(gòu)的效果是,每一層只需要學(xué)習(xí)輸入和輸出的差異部分,也就是“殘差”。
在編碼器模塊中,殘差連接層的作用可以概括為以下幾點(diǎn):
- 梯度傳播:
- 殘差連接使得梯度可以更容易地傳播回較早的層,尤其在深度網(wǎng)絡(luò)中。梯度可以通過跳躍連接傳播到前面的層,減輕了梯度消失或梯度爆炸的影響。
- 模型收斂速度:
- 殘差連接加速了模型的收斂速度,特別是對于深層網(wǎng)絡(luò)。通過跳過層間的非線性變換,模型可以更快地逼近目標(biāo)函數(shù)。
- 模型簡化和訓(xùn)練穩(wěn)定性:
- 殘差連接簡化了模型,使其更易于訓(xùn)練和調(diào)試。它允許每個模塊集中學(xué)習(xí)殘差,而不是必須直接擬合目標(biāo)映射,這有助于減輕優(yōu)化難度。
- 避免信息丟失:
- 殘差連接確保了原始信息不會在網(wǎng)絡(luò)中丟失。即使網(wǎng)絡(luò)中的變換丟失了某些特征,殘差連接仍可以恢復(fù)這些特征,從而有助于網(wǎng)絡(luò)學(xué)習(xí)到更好的特征表示。
層的歸一化
指的是層歸一化(Layer Normalization)或批歸一化(Batch Normalization),用于對模型的中間表示進(jìn)行歸一化,有助于加速訓(xùn)練、提高模型的穩(wěn)定性和泛化能力。
具體來說,歸一化層的作用如下:
- 加速訓(xùn)練:
- 歸一化可以加速神經(jīng)網(wǎng)絡(luò)的訓(xùn)練過程。通過將每個特征的分布?xì)w一化為均值為0和方差為1,避免了特征值過大或過小,有助于梯度傳播更順利,加快了模型的收斂速度。
- 提高模型穩(wěn)定性:
- 歸一化可以增強(qiáng)模型對輸入數(shù)據(jù)分布的穩(wěn)定性,使得模型對輸入的小變化不敏感,有助于模型更穩(wěn)定地處理不同的輸入數(shù)據(jù)。
- 避免梯度消失或梯度爆炸:
- 歸一化有助于避免梯度消失或梯度爆炸問題。特別是對于深層網(wǎng)絡(luò),梯度消失或梯度爆炸很常見,而歸一化可以一定程度上緩解這些問題。
- 提高泛化能力:
- 歸一化有助于模型更好地泛化到未見過的數(shù)據(jù)上,減少了模型對數(shù)據(jù)分布的敏感度,從而提高了模型的泛化能力。
解碼器
編碼器計(jì)算了原句的特征值,解碼器將特征值作為輸入,最終生成目標(biāo)。在每一步中,解碼器將上一步新生成的單詞與輸入的詞結(jié)合起來,并預(yù)測下一個單詞。在解碼器中,需要將輸入轉(zhuǎn)換為嵌入矩陣,為其添加位置編碼,然后再送入解碼器。
當(dāng)t=1時(t表示時間步),解碼器的輸入是
如圖所示,假設(shè)在時間步t=2,我們將輸入轉(zhuǎn)換為嵌入(我們稱之為嵌入值輸出,因?yàn)檫@里計(jì)算的是解碼器在以前的步驟中生成的詞的嵌入),將位置編碼加入其中,然后將其送入解碼器。
同理,你可以推斷出解碼器在t=3時的預(yù)測結(jié)果。此時,解碼器將
在每一步中,解碼器都將上一步新生成的單詞與輸入的詞結(jié)合起來,并預(yù)測下一個單詞。因此,在最后一步(t=4),解碼器將
一旦生成表示句子結(jié)束的
在編碼器部分,我們將輸入轉(zhuǎn)換為嵌入矩陣,并將位置編碼添加到其中,然后將其作為輸入送入編碼器。同理,我們也不是將輸入直接送入解碼器,而是將其轉(zhuǎn)換為嵌入矩陣,為其添加位置編碼,然后再送入解碼器。
編碼器最終輸出生成的特征值,則是在解碼器內(nèi)部的多頭注意力層引入了。這點(diǎn)要尤其注意。編碼器的輸出并不是直接作為解碼器的輸入。
一個解碼器模塊及其所有的組件如圖所示。
從圖中可以看到,解碼器內(nèi)部有3個子層。
- 帶掩碼的多頭注意力層
- 多頭注意力層
- 前饋網(wǎng)絡(luò)層
與編碼器模塊相似,解碼器模塊也有多頭注意力層和前饋網(wǎng)絡(luò)層,但多了帶掩碼的多頭注意力層。
帶掩碼的多頭注意力層
假設(shè)傳給解碼器的輸入句是
比如,在測試期間,當(dāng)t=2時,解碼器的輸入中只有[
如,我們想預(yù)測與
以矩陣的第1行為例,為了預(yù)測
接下來,讓我們看矩陣的第2行。為了預(yù)測Je后邊的詞,模型不應(yīng)該知道Je右邊的所有詞(因?yàn)樵跍y試時不會有這些詞)。
同理,我們可以掩蓋vais右邊的所有詞
通過這種方式的處理,最終就可以通過之前的計(jì)算公式,算出來注意力矩陣Z
多頭注意力層
下圖展示了Transformer模型中的編碼器和解碼器。我們可以看到,每個解碼器中的多頭注意力層都有兩個輸入:一個來自帶掩碼的多頭注意力層,另一個是編碼器輸出的特征值。
用 R 來表示編碼器輸出的特征值,用 M 來表示由帶掩碼的多頭注意力層輸出的注意力矩陣。
多頭注意力機(jī)制的第1步是創(chuàng)建查詢矩陣、鍵矩陣和值矩陣。而已知可以通過將輸入矩陣乘以權(quán)重矩陣來創(chuàng)建查詢矩陣、鍵矩陣和值矩陣。
在這里由于有兩個輸入矩陣,區(qū)別于之前只有一個輸入矩陣的情況,要特殊的處理。
使用上一個子層獲得的注意力矩陣M創(chuàng)建查詢矩陣Q;使用編碼器層輸出的特征值R創(chuàng)建鍵矩陣與值矩陣。
計(jì)算圖如下所示:
為什么要用 M 計(jì)算查詢矩陣,而用 R 計(jì)算鍵矩陣和值矩陣呢?因?yàn)椴樵兙仃囀菑?M 求得的,所以本質(zhì)上包含了目標(biāo)句的特征。鍵矩陣和值矩陣則含有原句的特征,因?yàn)樗鼈兪怯?R 計(jì)算的。
按照公式逐步計(jì)算
第1步是計(jì)算查詢矩陣與鍵矩陣的點(diǎn)積。
通過計(jì)算,可以得出查詢矩陣(目標(biāo)句特征)與鍵矩陣(原句特征)的相似度。
計(jì)算多頭注意力矩陣的下一步是將除以,然后應(yīng)用softmax函數(shù),得到分?jǐn)?shù)矩陣。
接下來,我們將分?jǐn)?shù)矩陣乘以值矩陣V,得到,即注意力矩陣Z
為了進(jìn)一步理解,讓我們看看Je這個詞的自注意力值Z2是如何計(jì)算的,如圖所示。
其實(shí)就是向量的點(diǎn)積運(yùn)算。這個結(jié)果可以幫助模型理解目標(biāo)詞Je指代的是原詞I。因?yàn)槠溆?jì)算分?jǐn)?shù)中包含了98%的I。
同樣,我們可以計(jì)算出h個注意力矩陣,將它們串聯(lián)起來。然后,將結(jié)果乘以一個新的權(quán)重矩陣W,得出最終的注意力矩陣,如下所示。
前饋網(wǎng)絡(luò)層
同編碼器層的前饋網(wǎng)絡(luò)層。
疊加與歸一組件
同編碼器層的疊加歸一層。
概覽
如下顯示了兩個解碼器,將解碼器1的所有組件完全展開。
(1) 首先,我們將解碼器的輸入轉(zhuǎn)換為嵌入矩陣,然后將位置編碼加入其中,并將其作為輸入送入底層的解碼器(解碼器1)。
(2) 解碼器收到輸入,并將其發(fā)送給帶掩碼的多頭注意力層,生成注意力矩陣M。
(3) 然后,將注意力矩陣M和編碼器輸出的特征值R作為多頭注意力層(編碼器?解碼器注意力層)的輸入,并再次輸出新的注意力矩陣。
(4) 把從多頭注意力層得到的注意力矩陣作為輸入,送入前饋網(wǎng)絡(luò)層。前饋網(wǎng)絡(luò)層將注意力矩陣作為輸入,并將解碼后的特征作為輸出。
(5) 最后,我們把從解碼器1得到的輸出作為輸入,將其送入解碼器2。
(6) 解碼器2進(jìn)行同樣的處理,并輸出目標(biāo)句的特征。
我們可以將N個解碼器層層堆疊起來。從最后的解碼器得到的輸出(解碼后的特征)將是目標(biāo)句的特征。接下來,我們將目標(biāo)句的特征送入線性層和softmax層,通過概率得到預(yù)測的詞。
整合編碼器與解碼器
帶有編碼器和解碼器的Transformer架構(gòu)如下所示。
從之前的RNN系列到現(xiàn)在的Transformer模型,是一個演進(jìn)的過程,技術(shù)的實(shí)現(xiàn)與迭代并不是一蹴而就,而是一個持續(xù)演進(jìn)的歷程。如果一開始就從Tranformer的模型機(jī)制來學(xué)習(xí),知識的不全面以及欠缺就會導(dǎo)致懵逼甚至看不懂又不理解。以下是我個人對Tranformer演進(jìn)的理解:
總結(jié)
以上是生活随笔為你收集整理的聊聊Transform模型的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Python 潮流周刊#25:性能最快的
- 下一篇: 深度解析BERT:从理论到Pytorch