這是 Transformer 系列第一篇!
參考論文:https://arxiv.org/abs/1706.03762
章節
- Reasons<p>
-
Self-Attention
- Multi-Head Attention
- Positional Encoding<p>
-
Add & Norm
-
Feed Forward
-
Residual Dropout
-
Encoder To Decoder
-
Shared Weights
-
Effect
Reasons For Transformer
新模型的產生往往是為了舊模型的問題所設計的。那麼,原始模型的問題有哪些呢?
1、無法並行運算
在transformer之前,大部分應該都是RNN,下面簡單介紹一下RNN
可以看出,在計算X2加進去吐出來的值的時候必須要先把X1得出的引數值與X2放在一起才行。換句話說,RNN的計算是必須一個接一個,並不存在並行運算。如果不能並行運算,那麼時間和計算成本均會增加。
2、語義表述不清
傳統的word2vec透過將詞語轉換為座標形式,並且根據距離之遠近決定兩個詞意思的相近程度。 但是在NLP任務中,儘管是同一個詞語,但在不同語境下代表的意思很有可能不同。例如,你今天方便的時候,來我家吃飯吧和我肚子不舒服,去廁所方便一下這兩句中方便的意思肯定不一樣。可是,word2vec處理之後座標形式就固定了。
3、突出對待
在一個句子中,當我們需要強調某一個部分的時候,word2vec無法為我們做到這些。比如,
- The cat doesn’t eat the cake because it is not hungry.<p>
-
The cat doesn’t eat the cake because it smells bad.
第一個句子中it強調的是the cat,在第二個句子中it強調的是the cake。
4、長距離資訊缺失
儘管RNN處理序列問題很拿手,但如果一個句子很長,那麼我要一直把句首的資訊攜帶到句尾,距離越長,資訊缺失的可能性就會變大。
Self-Attention
attention的意思是我們給有意義的內容配以較高的權重,那麼自己與自己做attention是什麼意思?
比如這個句中的”green”,self的意思就是說拿這個詞與整個句子其他的詞語分別算相似程度。如此便考慮了詞與上下文和句子整體之間的關係。當然,自己與自己肯定是聯絡最緊密。我們的目的是讓機器能夠判定出某個詞語與整個句子之間的關係。
那麼,如何計算self-attenion呢?
首先將詞編碼成向量,總不大可能直接將詞輸進去。其次定義三個矩陣, 這三個矩陣分別代表了Query,Key,Value,分別代表去查詢的,被查詢的以及實際的特徵資訊。W的意思是權重的意思,可以類比於梯度下降,權重一般都是初始化一個引數,然後透過訓練得出。最後用詞向量與矩陣分別做點積即可得到q1,q2,k1,k2,v1,v2。
用q1,q2分別與k1,k2的轉置做點積,q代表的要查的,而k是被查的。如此便可得到兩者的關係了。
注意力一共分為additive attention和這裡提到的dot product attention,那麼為什麼偏要用後者而非前者呢?
因為內積在實際中可以用高度最佳化矩陣運算,所以更快,同時空間利用率也很好。在此,簡要解釋一下內積可以表示兩向量關係的原因,在座標系中,當兩個向量垂直時,其關係最小,為0。其實就是cos為0。假如a1,a2兩個向量很接近,那麼,它們之間的夾角會很小,可知cos就很大,代表聯絡就越緊密。
在K的維度很小的時候,兩種注意力機制幾乎一致,但是當K的維度上升之後,發現內積效果開始變差。其實,可以聯絡一下Softmax影像,當值變得很大的時候,梯度變化量幾乎很難觀察到,又被稱為梯度消失問題,這是為什麼做scale的第一個原因。
在論文中提到
兩者做點積之後還需要除以矩陣K的維度開根號,Q,K,V矩陣維度是q x d_k,p x d_k,p x d_v,softmax是沿著p維進行的,但是很多時候大方差會導致數值分佈不均勻,經過softmax之後就會大的愈大,小的愈小,這裡除以一個矩陣K的維度其實類似於一個歸一化,讓它的方差趨向於1,分佈均勻一點,這是第二個原因,所以在原paper裡面又叫做Scaled Dot-Product Attention。
那為什麼除以一個矩陣K的維度開根號能使方差變為1呢?首先對於隨機分佈的q,k,方差均為1,期望均為0。我們把特定的一個q_i,k_i看成X,Y。
那麼q與k做點積之後的結果均值為0,方差為d_k。方差太大不穩定,所以除以矩陣K的維度開根號,參照連結(https://www.zhihu.com/question/339723385) 。
例如 v = 0.36v1 + 0.64v2,v1,v2是矩陣V裡的。
既然都是矩陣運算,那麼都是可以並行加速的。
self-attention除了可以捕獲到句子語法特徵外,還可以在長序列中捕獲各個部分的依賴關係,而同樣的處理用RNN和LSTM需要進行按照次序運算,迭代幾次之後才有可能得到資訊,而且距離越遠,可能捕獲到的可能性就越小。而self-attention極大程度上縮小了距離,更有利於利用特徵。
Multi-head Attention
理解了自注意力,那麼什麼是多頭注意力呢?
類比一下CNN,當我們不斷提取特徵的時候會用到一個叫卷積核的東西(filter),我們為了最大化提取有效特徵,通常選擇一組卷積核來提取,因為不同的卷積核對圖片的不同區域的注意力不同。比如,我們要識別一張鳥的圖片,可能第一個卷積核更關注鳥嘴,第二個卷積核更關注鳥翅膀等等。
在Transformer中也是如此,不同的Q,K,V矩陣得出的特徵關係也不相同,同樣,不一定一組Q,K,V提取到的關係能解決問題,所以保險起見,我們用多組。這裡可以把一組Q,K,V矩陣類比為一個卷積核,最後再透過全連線層進行拼接降維。
Positional Encoding
為什麼要進行位置編碼呢?
我上面闡述的注意力機制是不是隻說了某個詞與它所處的句子之間的關係,但是在實際自然語言處理中,只知道這個詞與句子的關係而不知道它在哪個位置是不行的。
在這篇論文中,用到了正餘弦函式,pos代表的是位置,i是位置編碼的維度,d_model是輸入的維度,因為位置編碼要和輸入加在一起,所以兩者維度一致。那麼,為什麼用正餘弦呢?原論文中說對於一個已知的PE_pos,對於一個確定的k,PE_pos+k都可以被表示為PE_pos的線性組合。
那麼,既然有了公式,那位置編碼是算出來的還是學出來的呢?其實算出來和學出來的效果差不多,但是考慮到算出來的可以接受更長的序列長度而不必受訓練的干擾,所以在這個模型中,位置編碼是透過公式算出來的。
Add & Norm
Add 的意思是殘差相連,思路來源於論文Deep residual learning for image recognition(https://openaccess.thecvf.com/content_cvpr_2016/html/He_Deep_Residual_Learning_CVPR_2016_paper.html),Norm指的是Layer Normalization,來源於論文Layer normalization(https://arxiv.org/abs/1607.06450)。
論文中指出
That is, the output of each sub-layer is LayerNorm(x + Sublayer(x)), where Sublayer(x) is the function implemented by the sub-layer itself
意思是上一層的輸入和輸出結果相拼接,然後進行歸一化,這樣可以更加穩定。肯定會有讀者好奇為什麼不直接將輸出結果歸一化,偏要把輸入結果拼接到輸出結果然後再歸一化。
如果還有讀者不明白Backprogation,建議看BP,這裡簡要說明一下,求後向傳播的過程中,設殘差相連之後輸入的層為L層,那麼,肯定要求這一層對殘差相連的時候的偏導數,而這時x是作為自變數的,所以對於F(x)+ x,求偏導後x就會變為1,那麼無論什麼時候都會加上這個常數1,這樣會一定程度上緩解梯度消失這個問題。
這裡選取的是層歸一化(Layer Normalization),用CNN舉例,假如我們的輸入是[N, C, H, W],分別代表樣本數量(每一個神經元對應著一個樣本),通道數,高度和寬度,那麼LN就是對於單獨的每一個樣本做歸一化,計算CHW個值的均值和標準差然後應用到這個樣本里面。歸一化的公式如下:
Feed Forward
Feed-Forward Network究竟做了啥呢?
首先它會引入RELU進行非線性變化,也就是公式前半部分所為,而且經過這一層之後會被升維,之後把這一層的結果連線到下一層進行線性變化,同時進行降維,保證輸入輸出維度一致。
Residual Dropout
在此模型中還在輸入,輸出層和位置編碼拼接中採用了dropout,這裡的比例是0.1。
Encoder To Decoder
接下來要把左側的編碼器和右側的解碼器進行相連,細心觀察圖會發現只有兩個箭頭到了右邊,這兩個箭頭代表的是K,V矩陣,Q矩陣由右側解碼器提供。
另外,解碼器會MASK掉序列的某些部分,因為如果要判斷機器是否真正理解了整段句子的意思,可以把後面遮掉,它如果猜的出來,那麼說明機器理解了。具體來說,對於位置i,通常會將i+1後面的全都MASK掉,這樣機器就是從前面學到的,它沒有提前看到後面的結果。
其他結構與編碼器一致,最後再進行線性變化,最終用softmax對映成機率。
Shared Weights
我們需要把輸入和輸出轉換為向量表示,而向量表示的方法是提前學到的。此外,最後用的線性轉換以及softmax都是學出來的。和常規的序列模型一致,輸入輸出以及線性轉換用的權重矩陣是共享的,只不過在輸入輸出層用的時候乘以模型維度開根號。
Effect
一般來說,維度d肯定比序列長度n大很多,所以每一層的複雜度此模型吊打RNN。模型結果對比沒多說的,幾乎是碾壓式的。