最近剛開始閱讀transformer文獻感覺有一些晦澀,尤其是關於其中Q、K、V的理解,故在這裡記錄自己的閱讀心得,供於分享交流

一、self-attention部分預熱

1.1 計算順序

首先了解NLP中self-attention計算順序:

Transformer+self-attention超詳解(亦個人心得)

1。2 計算公式詳解

有些突兀,不著急,接下來我們看看self-attention的公式長什麼樣子:

Transformer+self-attention超詳解(亦個人心得)

公式1

此公式在論文《attention is all your need》中出現,拋開Q、K、V與dk不看,則最開始的self-attention注意力計算公式為:

Transformer+self-attention超詳解(亦個人心得)

公式2

兩公式對比可以發現,Q、K、V都是由輸入詞X(詞向量)經過某種變換所得,向量與轉置後的向量相乘,我們可以看做向量與轉置後得到的矩陣空間中每一個子向量做點積運算,即向量內積

值得注意的是:我們輸入的只是一串字元,這裡要把每個詞轉成我們後續可以進行操作的詞向量,需要進行embedding操作,可以理解為把一個詞如love轉換為對應的語義資訊如【1, 3, 0, 5】,當然為了獲取詞在輸入序列中的位置資訊,我們在後續的transformer中增加了對應詞的位置資訊(positional encoding)

內積(點乘)的幾何意義包括:

表徵或計算兩個向量之間的夾角

a向量在b向量方向上的投影

兩向量相乘得一新的向量,即A*B=C,那麼這個新的向量C就在一定個程度上代表向量A對向量B的投影度大小

換個角度思考,投影度大小即輸入序列中對應詞與詞的相關度,投影度越大(夾角越小),意味著在一定程度上兩個詞之間的相關度越大(詞向量是文字形式的詞在高維空間(抽象化)的數值形式對映)

至此公式2中的X*X^T理解完畢,那麼對它進行softmax函式計算,即可得到我們想要的權重

值得注意的是:這裡的權重過分關注於自身的位置,即對於X*X^T來說,最終的權重過分關注X對其他詞向量的注意力而在一定程度上忽略了其他詞,故在後續的transformer中作者採取了多頭注意力機制來彌補

Transformer+self-attention超詳解(亦個人心得)

同時softmax函式還很好的使得權重和為1,我們只需將得到的權重乘以原來的X,即可得到最終的輸出,這個輸出經過了一次詞與詞之間相關度(也就是注意力)的計算,這也完成了一個self-attention的過程

現在讓我們回到公式1:

Transformer+self-attention超詳解(亦個人心得)

Q、K、V究竟是何方神聖?在上文部分有提到:Q、K、V都是由原X經過某種變換所得到的,用圖來表示的話,可以用下面這張圖:

Transformer+self-attention超詳解(亦個人心得)

從圖中不難看出,輸入X乘以Q、K、V對應的W權值矩陣,就可以得到我們想要的Q、K、V

注意:此處的Q、K、V僅侷限於後續Encoder和Decoder在各自輸入部分的編碼過程,Encoder和Decoder之間互動的Q、K和V並非此(後文會進行詳細介紹)

補充:最開始的W權值矩陣需要初始化,在後續BP的過程中,W的具體數值會不斷更新學習,這樣做的好處不僅僅是可以提高模型的非線性程度,還能提高模型擬合能力,透過不斷學習讓注意力權值正確分佈

公式中還在送入softmax前對權值矩陣乘以一個dk^(-1/2)(dk代表K的維度,同樣的有dq、dv),這樣做顯然是對原權值矩陣做了一次縮放,這樣做的意義是什麼?

如果我們在計算X*X^T完畢後,矩陣中元素的方差很大,這就會使得softmax的分佈變得極其陡峭,從而影響梯度穩定計算,此時我們進行一次縮放,再將方差縮放到1,softmax的分佈變得平緩穩定起來,進而在之後的訓練過程中保持梯度穩定。

至此self-attention的部分已經講解完畢,接下來我們回到transformer中,一起來庖丁解牛。

二、Transformer部分

2。1 整體結構

首先來縱觀transformer整體結構(左半部分是encode,右半部分是decode):

Transformer+self-attention超詳解(亦個人心得)

Transformer模型結構

2。2 encoder

首先分析左半部分,從下往上看inputs即為我們輸入的字串序列,此時在計算前我們要對輸入序列進行如圖所示的Input Embedding,此處即為上文self-attention中的語義資訊轉換,把輸入的每個詞轉換為對應的詞向量

同時transformer在embedding部分增加了位置編碼,其位置計算公式為:

Transformer+self-attention超詳解(亦個人心得)

pos 指當前詞在句子中的位置, 是指向量中每個值的 下標(索引);不難看出在偶數位置,使用正弦編碼,在奇數位置,使用餘弦編碼;最終輸出我們想要的位置向量

此處可以用一張圖來表示:

Transformer+self-attention超詳解(亦個人心得)

接著回到transformer模型結構圖,從左半部分繼續向上看,來到了Encoder部分,左側有一個 ×N 即多個encode疊加,右側同理

順著線路向上看,輸入的一條路(一個詞向量)分成三路(分別對應Q、K、V)進入了Multi-Head Attention層,同時輸入的一條路增加了一個殘差連線,透過簡單的Add操作與Multi-Head Attention層相作用,同時在進入下一層前還進行BN層歸一化

2。3 Multi-Head Attention層

那麼接下來我們就一起解析Multi-Head Attention層,其具體結構如下:

Transformer+self-attention超詳解(亦個人心得)

從圖中可以看出Q、K、V首先經過了一個Linear層做線性變換,接著進入到了Scaled Dot-Product Attention層,接下來我們對Scaled Dot-Product Attention層展開詳細分析:

對於Linear的理解,拿文中的話來說就是作者發現將Q、K、V經過一個線性層的學習是非常有益的

2。4 Scaled Dot-Product Attention層

先上圖:

Transformer+self-attention超詳解(亦個人心得)

從下往上看,Q和K經過MatMul層做矩陣相乘(即上文self-attention部分提到的X*X^T),接著來到Scale層進行維度縮放(即上文self-attention部分提到的乘以dk^(-1/2))(注意這裡的Mask是後續在decder部分需要使用的操作,encoder部分並沒有,此層在這裡跳過)。最終我們經過softmax得到的權值矩陣與V相乘,得到最終的輸出。接著回到Multi-Head Attention圖,我們可以看到在最終Linear輸出前有h次同樣的操作,那麼這個h就對應著標題“多頭”,h是幾個頭就是幾個。

為什麼要這樣操作呢?

論文中提到這樣的好處是可以允許模型在不同的表示子空間裡學習到相關的資訊。換個方式理解,我們可以類比CNN中同時使用多個濾波器的作用,我們想讓模型學習全方位、多層次、多角度的資訊,學習更豐富的資訊特徵,就要使用多頭來完成。舉個例子來說,我們在閱讀文獻的時候,總是對文獻的摘要注意頗多,同時我們還對文獻中的實驗資料、實驗結論想要有所瞭解,一般到最後才是文獻的方法部分以及一些公式,這麼一套流程下來我們對文獻整體有了更豐富的掌握,那麼“多頭”即可類比於此(儘管有些許勉強)。

在Multi-Head Attention層得到最終的輸出結果後,我們來到了Feed Forward層(見圖4),同時還有一個一樣的殘差連線與層歸一化處理。那麼Feed Forward層的作用是什麼呢?

細讀文章可以發現,所謂Feed Forward即一個普通MLP結構,即全連線1 -> Relu -> dropout -> 全連線2,拿文中的公式表述為:

Transformer+self-attention超詳解(亦個人心得)

新增這一層的目的也是為了增加模型的非線性表達能力,提高模型擬合程度。

2。5 decoder

至此左半部分的encode講解完畢,第N個encoder輸出的K、V與decode部分進行互動,但我們先從decoder部分的下方輸入開始看起(這裡再把圖拿過來):

Transformer+self-attention超詳解(亦個人心得)

從下往上看,Outputs是我們模型上一次的預測結果+shifted right,關於shifted right的講解我們放在文末。輸入的序列經過了和左半部分同樣的操作,即語義資訊編碼+位置資訊編碼,但在分成三路後進入的卻是一個Masked Multi-Head Attention,比左半部分多了一個Mask,那麼接下來我們就詳細分析一下這個Mask的具體內容:

2。6 Mask

transformer的注意力計算我們已經熟悉,需要注意的是在訓練階段中,Decoder部分輸入的資料是一整句,句中包含了等待被預測的後續的序列資訊,我們不希望這樣的情況發生,所以加入Mask操作來把那些不希望出現的資訊掩蓋

那麼如何實現Mask?

只需要初始化一個下三角矩陣為0,上三角元素均為負無窮的矩陣加到注意力矩陣上,因為注意力需要經過softmax進行歸一化,其中e^-

\infty

為0,因此可以將未來資訊抹去。

Transformer+self-attention超詳解(亦個人心得)

Transformer+self-attention超詳解(亦個人心得)

Masked Multi-Head Attention層的輸出經過add&BN後與encoder部分輸入的K、V交匯在一起,來到了一個和左半部分一樣的Multi-Head Attention + Feed Forward層,decoder部分同樣重複迭代N次,最終送入Linear層做最後的softmax計算,輸出我們的預測值。

2。7 關於decoder的輸入(包括shifted right)講解:

一般訓練階段的Decoder第一次輸入為起始符 + Positional Encoding,也可能是其他特殊的Token,目的是為了預測目標序列的第一個單詞是什麼。

Transformer+self-attention超詳解(亦個人心得)

我們將原輸入序列中的對應詞整體右移一位(shifted right),即得到了起始符+embedding的輸入,對上圖進行更為詳細的描述,即:

Transformer+self-attention超詳解(亦個人心得)

由圖中可以看出上文所述“Outputs是我們模型上一次的預測結果+shifted right”

三、The end

後期會對transformer程式碼進行詳細的分析,筆者才學淺陋,初步接觸機器學習,難免有諸多錯誤與遺漏,懇請廣大讀者不吝指教!