[NLP]Transformer模型解析


簡介[2]

Attention Is All You Need2017google提出來的一篇論文,論文里提出了一個新的模型,叫Transformer,這個結構廣泛應用於NLP各大領域,是目前比較流行的模型。該模型沒有選擇大熱的RNN/LSTM/GRU的結構,而是只使用attention layer和全連接層就達到了較好的效果,同時解決了RNN/LSTM/GRU中的long dependency problem,以及傳統RNN訓練並行度以及計算復雜度高的問題。缺點是輸入固定長度的序列,需要對原始文本進行裁剪和填充,導致不能學習到序列中更長距離的依賴關系。

Transformer總體結構[1]

Transformer采用Encoder-Decoder架構。

 

上圖就是論文中提出的Transformer結構。其中左半部分是encoder右半部分是decoder.

 

Encoder層中有6個一模一樣的層結構,每個層結構包含了兩個子層,第一個子層是多頭注意力層Multi-Head Attention,橙色部分),第二個子層是前饋連接層Feed Forward,淺藍色部分)。除此之外,還有一個殘差連接,直接將input embedding傳給第一個Add & Norm層(黃色部分)以及 第一個Add & Norm層傳給第二個Add & Norm層(即圖中的粉色-黃色1,黃色1-黃色2部分運用了殘差連接)。該層的重點-注意力層會在下文中進行解釋。

 

Decoder層中也有6個一模一樣的層結構,但是比Endoer層稍微復雜一點,它有三個子層結構,第一個子層結構是遮掩多頭注意力層Masked Multi-Head Attention,橙色部分),第二個子層是多頭注意力結構(Multi-Head Attenion,橙色部分),第三個子層是前饋連接層Feed Forward,淺藍色部分)。

1:這一部分的殘差連接是粉色-黃色1,黃色1-黃色2,黃色2-黃色3三個部分

2:該層的重點是第二個子層,即多頭注意力層,它的輸入包括兩個部分,第一個部分是第一個子層的輸出,第二個部分是Encoder層的輸出(這是與encoder層的區別之一),這樣則將encoder層和decoder層串聯起來,以進行詞與詞之間的信息交換,這里信息交換是通過共享權重WQ,WV,WK得到的。

3:第一個子層中的mask,它的作用就是防止在訓練的時候使用未來的輸出的單詞。比如訓練時,第一個單詞是不能參考第二個單詞的生成結果的,此時就會將第二個單詞及其之后的單詞都mask掉。總體來講,mask的作用就是用來保證預測位置i的信息只能基於比i小的輸出。因此,encoder層可以並行計算,一次全部encoding出來,但是decoder層卻一定要像rnn一樣一個一個解出來,因為要用上一個位置的輸入當做attentionquery.

注4:殘差結構是為了解決梯度消失問題,可以增加模型的復雜性。殘差結構:x+F(x),這樣會進一步擴大方差,因此需要增加一個norm層來縮小方差。

注5:LayerNorm層是為了對attention層的輸出進行分布歸一化,轉換成均值為0方差為1的正態分布。cv中經常會用的是batchNorm,是對一個batchsize中的樣本進行一次歸一化,而layernorm則是對一層進行一次歸一化,二者的作用是一樣的,只是針對的維度不同,一般來說輸入維度是(batch_size,seq_len,embedding),batchnorm針對的是batch_size層進行處理,而layernorm則是對seq_len進行處理(即batchnorm是對一批樣本中進行歸一化,而layernorm是對每一個樣本進行一次歸一化)。 

注6:使用ln而不是bn的原因是因為輸入序列的長度問題,每一個序列的長度不同,雖然會經過padding處理,但是padding的0值其實是無用信息,實際上有用的信息還是序列信息,而不同序列的長度不同,所以這里不能使用bn一概而論。

注7:FFN是兩層全連接:w * [delta(w * x + b)] + b,其中的delta是relu激活函數。這里使用FFN層的原因是:為了使用非線性函數來擬合數據。如果說只是為了非線性擬合的話,其實只用到第一層就可以了,但是這里為什么要用兩層全連接呢,是因為第一層的全連接層計算后,其維度是(batch_size,seq_len,dff)(其中dff是超參數的一種,設置為2048),而使用第二層全連接層是為了進行維度變換,將dff轉換為初始的d_model(512)維。

注8:decoder層中中間的多頭自注意力機制的輸入是兩個參數——encoder層的輸出和decoder層中第一層masked多頭自注意力機制的輸出,作用在本層時是:q=encoder的輸出,k=v=decoder的輸出。

注9:encoder的輸入包含兩個,是一個序列的token embedding + positional embedding,用正余弦函數對序列中的位置進行計算(偶數位置用正弦,技術位置用余弦)

 

Self-Attention[2]

self-AttentionTransformer用來找到並重點關注與當前單詞相關的詞語的一種方法。如下述例子:

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

這里的it究竟是指animal還是street,對於算法來說是不容易判斷的,但是self-attention是能夠把itanimal聯系起來的,達到消歧的目的。

這里描述self-attention的具體過程如下圖所示: 

 從上圖可以看出,attention機制中主要涉及三個向量Q(Query),K(Key),V(Value),這三個向量的計算過程如下圖所示:

 

上圖中,WQ,WV,WK是三個隨機初始化的矩陣,每個特征詞的向量計算公式如下所示:

Queries:              q1 = x1 · WQ                                                    q2 = x2 · WQ

Keys:                  k1 = x1 · WK                   k2 = x2 · WK

Values:                v1 = x1 · WV                            v2 = x2 · WV

      Score:                 s1 = q1 · k1=112                                               s2 = q2 · k2 = 96

   Divide by 8:         d1 = s1 / 8 = 14                 d2 = s2 / 8 = 12

                     Softmax:             sm1 = e14/ (e14 + e12) = 0.88            sm2 = e12 / (e14 + e12) = 0.12

 

Softmax * value:   v1 = sm1 * v1                  v2 = sm2 * v2

 

1score表示關注單詞的相關程度.

2:這種通過 query key 的相似性程度來確定 value 的權重分布的方法被稱為scaled dot-product attention

注3:attention與self-attention的區別[5]:self-attention是一般attention的特殊情況,在self-attention中,Q=K=V每個序列中的單元和該序列中所有單元進行attention計算。Google提出的多頭attention通過計算多次來捕獲不同子控件上的相關信息。self-attention的特點在於無視詞之間的距離直接計算依賴關系,能夠學習一個句子的內部結構,實現也較為簡單並且可以並行計算。從一些論文中看到,self-attention可以當成一個層和RNN,CNN,FNN等配合使用,成功應用於其他NLP任務。

注4:attention中除以根號d_k具備縮放的原因是因為原始表征x1是符合均值為0方差為1的正態分布的,而q*k后方差變為d,所以為了使結果符合均值為0方差為1的數據分布,這里需要除以根號d,這樣數據分布並未改變,q*k經過softmax層后不會變成one hot而出現梯度消失的情況。(e^d可能非常大而e^(-d)非常小,這樣經過softmax層后,attention層的分布會非常接近one hot分布,這樣會帶來嚴重的梯度消失問題,導致訓練效果非常差。)

注意力機制的優點:

①一步到位獲取全局與局部的關系,不會像RNN那樣對長期依賴的捕捉會受到序列長度的限制。

②每步的結果不依賴於上一步,可以做成並行的模式

③相比CNN與RNN,參數少,模型復雜度低。

注意力機制的缺點:

①沒法捕捉位置信息,即沒法學習序列中的順序關系。這點可以通過加入位置信息,如通過位置向量來改善,具體如bert模型。

 

 

Multi-Headed Attention

多頭注意力機制是指有多組Q,K,V矩陣,一組Q,K,V矩陣代表一次注意力機制的運算,transformer使用了8組,所以最終得到了8個矩陣,將這8個矩陣拼接起來后再乘以一個參數矩陣WO,即可得出最終的多注意力層的輸出。全部過程如下圖所示: 

 

左圖表示使用多組Q,K,V矩陣,右圖表示8Q,K,V矩陣計算會得出8個矩陣,最終我們還需將8個矩陣經過計算后輸出為1個矩陣,才能作為最終多注意力層的輸出。如下圖所示,其中WO是隨機初始化的參數矩陣。 

Positional Encoding

在圖figure 1中,還有一個向量positional encoding,它是為了解釋輸入序列中單詞順序而存在的,維度和embedding的維度一致。這個向量決定了當前詞的位置,或者說是在一個句子中不同的詞之間的距離。論文中的計算方法如下: 

 PE(pos,2 * i) = sin(pos / 100002i/dmodel)

PE(pos,2 * i + 1) = cos(pos / 100002i/dmodel)

其中pos指當前詞在句子中的位置,i是指向量中每個值的index,從公式中可以看出,句子中偶數位置的詞用正弦編碼,奇數位置的詞用余弦編碼。最后把positional encoding的值與embedding的值相加作為輸入傳進transformer結構中,如下圖所示: 

 

Layer normalization

transformer中,每一個子層(自注意力層,全連接層)后都會有一個Layer  normalization層,如下圖所示:

 

Normalize層的目的就是對輸入數據進行歸一化,將其轉化成均值為0方差為1的數據。LN是在每一個樣本上都計算均值和方差,如下圖所示: 

  

LN的公式如下: 

 LN(xi) = α * (xi - μL / √(σ2L + ε)) + β

以上是encoder層的全部內容,最后再展示一下將兩個encoder疊加在一起的內部圖:

 其他細節

1Transformer中包含兩種maskpadding mask 在所有的scaled dot-product attention 里面都需要用到,而sequence mask 只有在decoderself-attention里面用到。

 

Padding Mask是為了解決填充0的無意義的位置而存在的,具體的說,因為要對輸入序列進行對齊,當輸入序列較短時,需要在輸入序列后填充0,但是這些填充的數據沒什么意義,attention機制不應該把注意力放在這些位置上,因此我們需要做一些統一的處理。具體的做法是把這些位置的值加上一個非常大的負數,這樣經過softmax處理的話,這些位置的值就會接近0

 

參考資料:

[1] https://www.jianshu.com/p/ef41302edeef?utm_source=oschina-app

[2] https://blog.csdn.net/u012526436/article/details/86295971

[3] https://zhuanlan.zhihu.com/p/47282410

[4] https://zhuanlan.zhihu.com/p/44121378

[5]https://www.cnblogs.com/robert-dlut/p/8638283.html

[6]https://zhuanlan.zhihu.com/p/57672079

[7] https://kexue.fm/archives/8620


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM