《Attention Is All You Need》是一篇Google提出的將Attention思想發揮到極致的論文。這篇論文中提出一個全新的模型,叫 Transformer,拋棄了以往深度學習任務裏面使用到的 CNN 和 RNN。目前大熱的Bert就是基於Transformer構建的,這個模型普遍應用於NLP領域,例如機器翻譯,問答系統,文本摘要和語音識別等等方向。html
Transformer的結構和Attention模型同樣,Transformer模型中也採用了 encoer-decoder 架構。但其結構相比於Attention更加複雜,論文中encoder層由6個encoder堆疊在一塊兒,decoder層也同樣。git
不瞭解Attention模型的,能夠回顧以前的文章:Attentiongithub
每個encoder和decoder的內部結構以下圖:面試
首先,模型須要對輸入的數據進行一個embedding操做,也能夠理解爲相似w2c的操做,enmbedding結束以後,輸入到encoder層,self-attention處理完數據後把數據送給前饋神經網絡,前饋神經網絡的計算能夠並行,獲得的輸出會輸入到下一個encoder。網絡
transformer模型中缺乏一種解釋輸入序列中單詞順序的方法,它跟序列模型還不不同。爲了處理這個問題,transformer給encoder層和decoder層的輸入添加了一個額外的向量Positional Encoding,維度和embedding的維度同樣,這個向量採用了一種很獨特的方法來讓模型學習到這個值,這個向量能決定當前詞的位置,或者說在一個句子中不一樣的詞之間的距離。這個位置向量的具體計算方法有不少種,論文中的計算方法以下:架構
其中pos是指當前詞在句子中的位置,i是指向量中每一個值的index,能夠看出,在偶數位置,使用正弦編碼,在奇數位置,使用餘弦編碼。機器學習
最後把這個Positional Encoding與embedding的值相加,做爲輸入送到下一層。函數
接下來咱們詳細看一下self-attention,其思想和attention相似,可是self-attention是Transformer用來將其餘相關單詞的「理解」轉換成咱們正在處理的單詞的一種思路,咱們看個例子:學習
The animal didn't cross the street because it was too tired編碼
這裏的 it 到底表明的是 animal 仍是 street 呢,對於咱們來講能很簡單的判斷出來,可是對於機器來講,是很難判斷的,self-attention就可以讓機器把 it 和 animal 聯繫起來,接下來咱們看下詳細的處理過程。
首先,self-attention會計算出三個新的向量,在論文中,向量的維度是512維,咱們把這三個向量分別稱爲Query、Key、Value,這三個向量是用embedding向量與一個矩陣相乘獲得的結果,這個矩陣是隨機初始化的,維度爲(64,512)注意第二個維度須要和embedding的維度同樣,其值在BP的過程當中會一直進行更新,獲得的這三個向量的維度是64。
計算self-attention的分數值,該分數值決定了當咱們在某個位置encode一個詞時,對輸入句子的其餘部分的關注程度。這個分數值的計算方法是Query與Key作點成,如下圖爲例,首先咱們須要針對Thinking這個詞,計算出其餘詞對於該詞的一個分數值,首先是針對於本身自己即q1·k1,而後是針對於第二個詞即q1·k2。
接下來,把點成的結果除以一個常數,這裏咱們除以8,這個值通常是採用上文提到的矩陣的第一個維度的開方即64的開方8,固然也能夠選擇其餘的值,而後把獲得的結果作一個softmax的計算。獲得的結果便是每一個詞對於當前位置的詞的相關性大小,固然,當前位置的詞相關性確定會會很大。
下一步就是把Value和softmax獲得的值進行相乘,並相加,獲得的結果便是self-attetion在當前節點的值。
在實際的應用場景,爲了提升計算速度,咱們採用的是矩陣的方式,直接計算出Query, Key, Value的矩陣,而後把embedding的值與三個矩陣直接相乘,把獲得的新矩陣 Q 與 K 相乘,乘以一個常數,作softmax操做,最後乘上 V 矩陣。
這種經過 query 和 key 的類似性程度來肯定 value 的權重分佈的方法被稱爲scaled dot-product attention。
這篇論文更牛逼的地方是給self-attention加入了另一個機制,被稱爲「multi-headed」 attention,該機制理解起來很簡單,就是說不只僅只初始化一組Q、K、V的矩陣,而是初始化多組,tranformer是使用了8組,因此最後獲得的結果是8個矩陣。
在transformer中,每個子層(self-attetion,Feed Forward Neural Network)以後都會接一個殘缺模塊,而且有一個Layer normalization。
Normalization有不少種,可是它們都有一個共同的目的,那就是把輸入轉化成均值爲0方差爲1的數據。咱們在把數據送入激活函數以前進行normalization(歸一化),由於咱們不但願輸入數據落在激活函數的飽和區。
Batch Normalization
BN的主要思想就是:在每一層的每一批數據上進行歸一化。咱們可能會對輸入數據進行歸一化,可是通過該網絡層的做用後,咱們的數據已經再也不是歸一化的了。隨着這種狀況的發展,數據的誤差愈來愈大,個人反向傳播須要考慮到這些大的誤差,這就迫使咱們只能使用較小的學習率來防止梯度消失或者梯度爆炸。BN的具體作法就是對每一小批數據,在批這個方向上作歸一化。
Layer normalization
它也是歸一化數據的一種方式,不過LN 是在每個樣本上計算均值和方差,而不是BN那種在批方向計算均值和方差!公式以下:
這給咱們留下了一個小的挑戰,前饋神經網絡無法輸入 8 個矩陣呀,這該怎麼辦呢?因此咱們須要一種方式,把 8 個矩陣降爲 1 個,首先,咱們把 8 個矩陣連在一塊兒,這樣會獲得一個大的矩陣,再隨機初始化一個矩陣和這個組合好的矩陣相乘,最後獲得一個最終的矩陣。
根據上面的整體結構圖能夠看出,decoder部分其實和encoder部分大同小異,剛開始也是先添加一個位置向量Positional Encoding,方法和 2.2.1 節同樣,接下來接的是masked mutil-head attetion,這裏的mask也是transformer一個很關鍵的技術,下面咱們會進行一一介紹。
其他的層結構與Encoder同樣,請參考Encoder層結構。
mask 表示掩碼,它對某些值進行掩蓋,使其在參數更新時不產生效果。Transformer 模型裏面涉及兩種 mask,分別是 padding mask 和 sequence mask。其中,padding mask 在全部的 scaled dot-product attention 裏面都須要用到,而 sequence mask 只有在 decoder 的 self-attention 裏面用到。
padding mask
什麼是 padding mask 呢?由於每一個批次輸入序列長度是不同的也就是說,咱們要對輸入序列進行對齊。具體來講,就是給在較短的序列後面填充 0。可是若是輸入的序列太長,則是截取左邊的內容,把多餘的直接捨棄。由於這些填充的位置,實際上是沒什麼意義的,因此咱們的attention機制不該該把注意力放在這些位置上,因此咱們須要進行一些處理。
具體的作法是,把這些位置的值加上一個很是大的負數(負無窮),這樣的話,通過 softmax,這些位置的機率就會接近0!
而咱們的 padding mask 其實是一個張量,每一個值都是一個Boolean,值爲 false 的地方就是咱們要進行處理的地方。
Sequence mask
文章前面也提到,sequence mask 是爲了使得 decoder 不能看見將來的信息。也就是對於一個序列,在 time_step 爲 t 的時刻,咱們的解碼輸出應該只能依賴於 t 時刻以前的輸出,而不能依賴 t 以後的輸出。所以咱們須要想一個辦法,把 t 以後的信息給隱藏起來。
那麼具體怎麼作呢?也很簡單:產生一個上三角矩陣,上三角的值全爲0。把這個矩陣做用在每個序列上,就能夠達到咱們的目的。
當decoder層所有執行完畢後,怎麼把獲得的向量映射爲咱們須要的詞呢,很簡單,只須要在結尾再添加一個全鏈接層和softmax層,假如咱們的詞典是1w個詞,那最終softmax會輸入1w個詞的機率,機率值最大的對應的詞就是咱們最終的結果。
編碼器經過處理輸入序列開啓工做。頂端編碼器的輸出以後會變轉化爲一個包含向量K(鍵向量)和V(值向量)的注意力向量集 ,這是並行化操做。這些向量將被每一個解碼器用於自身的「編碼-解碼注意力層」,而這些層能夠幫助解碼器關注輸入序列哪些位置合適:
在完成編碼階段後,則開始解碼階段。解碼階段的每一個步驟都會輸出一個輸出序列(在這個例子裏,是英語翻譯的句子)的元素。
接下來的步驟重複了這個過程,直到到達一個特殊的終止符號,它表示transformer的解碼器已經完成了它的輸出。每一個步驟的輸出在下一個時間步被提供給底端解碼器,而且就像編碼器以前作的那樣,這些解碼器會輸出它們的解碼結果 。
原論文中說到進行Multi-head Attention的緣由是將模型分爲多個頭,造成多個子空間,可讓模型去關注不一樣方面的信息,最後再將各個方面的信息綜合起來。其實直觀上也能夠想到,若是本身設計這樣的一個模型,必然也不會只作一次attention,屢次attention綜合的結果至少可以起到加強模型的做用,也能夠類比CNN中同時使用多個卷積核的做用,直觀上講,多頭的注意力有助於網絡捕捉到更豐富的特徵/信息。
RNN系列的模型,並行計算能力不好。RNN並行計算的問題就出在這裏,由於 T 時刻的計算依賴 T-1 時刻的隱層計算結果,而 T-1 時刻的計算依賴 T-2 時刻的隱層計算結果,如此下去就造成了所謂的序列依賴關係。
Transformer的特徵抽取能力比RNN系列的模型要好。
具體實驗對比能夠參考:放棄幻想,全面擁抱Transformer:天然語言處理三大特徵抽取器(CNN/RNN/TF)比較
可是值得注意的是,並非說Transformer就可以徹底替代RNN系列的模型了,任何模型都有其適用範圍,一樣的,RNN系列模型在不少任務上仍是首選,熟悉各類模型的內部原理,知其然且知其因此然,才能遇到新任務時,快速分析這時候該用什麼樣的模型,該怎麼作好。
seq2seq缺點:這裏用代替這個詞略顯不穩當,seq2seq雖已老,但始終仍是有其用武之地,seq2seq最大的問題在於將Encoder端的全部信息壓縮到一個固定長度的向量中,並將其做爲Decoder端首個隱藏狀態的輸入,來預測Decoder端第一個單詞(token)的隱藏狀態。在輸入序列比較長的時候,這樣作顯然會損失Encoder端的不少信息,並且這樣一股腦的把該固定向量送入Decoder端,Decoder端不可以關注到其想要關注的信息。
Transformer優勢:transformer不但對seq2seq模型這兩點缺點有了實質性的改進(多頭交互式attention模塊),並且還引入了self-attention模塊,讓源序列和目標序列首先「自關聯」起來,這樣的話,源序列和目標序列自身的embedding表示所蘊含的信息更加豐富,並且後續的FFN層也加強了模型的表達能力,而且Transformer並行計算的能力是遠遠超過seq2seq系列的模型,所以我認爲這是transformer優於seq2seq模型的地方。
代碼解讀:Transformer解析與tensorflow代碼解讀
做者:@mantchs
GitHub:github.com/NLP-LOVE/ML…