注:本文出自Bin的專欄blog.csdn.NET/xbinworld。
Encoder-Decoder(編碼-解碼)是深度學習中非常常見的一個模型框架,比如無監督算法的auto-encoding就是用編碼-解碼的結構設計並訓練的;比如這兩年比較熱的image caption的應用,就是CNN-RNN的編碼-解碼框架;再比如神經網絡機器翻譯NMT模型,往往就是LSTM-LSTM的編碼-解碼框架。因此,准確的說,Encoder-Decoder並不是一個具體的模型,而是一類框架。Encoder和Decoder部分可以是任意的文字,語音,圖像,視頻數據,模型可以采用CNN,RNN,BiRNN、LSTM、GRU等等。所以基於Encoder-Decoder,我們可以設計出各種各樣的應用算法。
Encoder-Decoder框架有一個最顯著的特征就是它是一個End-to-End學習的算法;本文將以文本-文本的例子作為介紹,這樣的模型往往用在機器翻譯中,比如將法語翻譯成英語。這樣的模型也被叫做 Sequence to Sequence learning[1]。所謂編碼,就是將輸入序列轉化成一個固定長度的向量;解碼,就是將之前生成的固定向量再轉化成輸出序列。 如下圖示意[3]:

這邊為了方便闡述,選取了編碼和解碼都是RNN的組合。在RNN中,當前時刻隱層狀態是由上一時刻的隱層狀態和當前時刻的輸入決定的,也就是
獲得了各個時刻的隱層狀態以后,再將信息匯總,生成最后的語義編碼c
q表示某種非線性函數。在[1]中,作者采用LSTM網絡作為Encoder網絡,實際上在LSTM或者基本的RNN網絡中,當前時刻計算完后是看不見前面時刻的隱層狀態的了,所以就是用最后一個時刻的隱層狀態作為語義編碼c,即

解碼過程我們要根據給定的語義編碼C和已經生成的輸出序列y1,y2,…yt−1來預測下一個輸出的單詞yt,實際上就是把生成句子y={y1,y2,…yT}的聯合概率分解成按順序的條件概率:

而每一個條件概率又可以寫成是
其中st是輸出RNN中的隱藏層,c代表之前提過的語義向量,yt−1表示上個時刻的輸出。g表示一種非線性變換,往往就是指一種多層的函數,可以輸出yt的概率(比如多層RNN后接softmax)。
所以,在文本序列的Encoder-Decoder模型中,原本RNN(LSTM)語言模型是要估計p(y1,y2,…yT|x1,x2,...,xT′),給定一串輸入x,得到一串輸出y(不需要等長),但是因為Encoder-Decoder中間用語義編碼c把前后兩部分隔開了,所以輸出句子y只需要和c相關即可。

只要端到端訓練RNN(LSTM)網絡就可以了,在每一個句子末尾打上一個end-of-sentence symbol, EOS符號,用輸入句子來預測輸出句子。這樣的模型就可以完成基本的英語-法語的翻譯任務。
實際上這樣的模型能做什么應用完全取決於訓練數據,如果用英語-法語對應句子作為輸入輸出訓練,那就是英法翻譯;如果用文章-摘要來訓練那就是自動摘要機了。
基本的Encoder-Decoder模型非常經典,但是也有局限性。最大的局限性就在於編碼和解碼之間的唯一聯系就是一個固定長度的語義向量c。也就是說,編碼器要將整個序列的信息壓縮進一個固定長度的向量中去。但是這樣做有兩個弊端,一是語義向量無法完全表示整個序列的信息,還有就是先輸入的內容攜帶的信息會被后輸入的信息稀釋掉,或者說,被覆蓋了。輸入序列越長,這個現象就越嚴重。這就使得在解碼的時候一開始就沒有獲得輸入序列足夠的信息, 那么解碼的准確度自然也就要打個折扣了[3]。
為了彌補上述基本Encoder-Decoder模型的局限性,近兩年NLP領域提出Attention Model(注意力模型),典型的例子就是在機器翻譯的時候,讓生成詞不是只能關注全局的語義編碼向量c,而是增加了一個“注意力范圍”,表示接下來輸出詞時候要重點關注輸入序列中的哪些部分,然后根據關注的區域來產生下一個輸出,如下圖所示:

相比於之前的encoder-decoder模型,attention模型最大的區別就在於它不在要求編碼器將所有輸入信息都編碼進一個固定長度的向量之中。相反,此時編碼器需要將輸入編碼成一個向量的序列,而在解碼的時候,每一步都會選擇性的從向量序列中挑選一個子集進行進一步處理。這樣,在產生每一個輸出的時候,都能夠做到充分利用輸入序列攜帶的信息。而且這種方法在翻譯任務中取得了非常不錯的成果。很顯然,每一個輸出單詞在計算的時候,參考的語義編碼向量c都是不一樣的,也就是它們的注意力焦點是不一樣的。
基本Sequence to Sequence模型描述了基本的Encoder-Decoder模型,在作為翻譯模型的時候,這種基本的Encoder-Decoder模型有較大缺點,就是Encoder部分每一個輸入對Decoder部分每一個輸出的貢獻都是一樣的。下面先看一個例子[1],

在基本模型中,每一個英文單詞對傑瑞都是一樣的貢獻,這似乎是不太合理的;也就是說

沒有引入注意力的模型在輸入句子比較短的時候估計問題不大,但是如果輸入句子比較長,此時所有語義完全通過一個中間語義向量來表示,單詞自身的信息已經消失,可想而知會丟失很多細節信息,這也是為何要引入注意力模型的重要原因。如果引入AM模型的話,應該在翻譯“傑瑞”的時候,體現出英文單詞對於翻譯當前中文單詞不同的影響程度,比如給出類似下面一個概率分布值:

即生成目標句子單詞的過程成了下面的形式:

而每個Ci可能對應着不同的源語句子單詞的注意力分配概率分布,比如對於上面的英漢翻譯來說,其對應的信息可能如下:

其中,f2函數代表Encoder對輸入英文單詞的某種變換函數,比如如果Encoder是用的RNN模型的話,這個f2函數的結果往往是某個時刻輸入xi后隱層節點的狀態值(經過激活函數);g代表Encoder根據單詞的中間表示合成整個句子中間語義表示的變換函數,一般的做法中,g函數就是對構成元素加權求和,也就是常常在論文里看到的下列公式:

假設Ci中那個i就是上面的“湯姆”,那么Tx就是3,代表輸入句子的長度,h1=f2(“Tom”),h2=f2(“Chase”),h3=f2(“Jerry”),對應的注意力模型權值分別是0.6,0.2,0.2,所以g函數就是個加權求和函數。如果形象表示的話,翻譯中文單詞“湯姆”的時候,數學公式對應的中間語義表示Ci的形成過程類似下圖:

這里還有一個問題:生成目標句子某個單詞,比如“湯姆”的時候,你怎么知道AM模型所需要的輸入句子單詞注意力分配概率分布值呢?就是說“湯姆”對應的概率分布:
(Tom,0.6)(Chase,0.2)(Jerry,0.2)
是如何得到的呢?
為了便於說明,我們假設對圖1的非AM模型的Encoder-Decoder框架進行細化,Encoder采用RNN模型,Decoder也采用RNN模型,這是比較常見的一種模型配置,則圖1的圖轉換為下圖:

注意力分配概率分布值的通用計算過程:

相當於在原來的模型上,又加了一個單層DNN網絡,當前輸出詞Yi針對某一個輸入詞j的注意力權重由當前的隱層Hi,以及輸入詞j的隱層狀態(hj)共同決定;然后再接一個sofrmax得到0-1的概率值。
寫成公式[2]:

也就是說,si−1先跟每個h分別計算得到一個數值,然后使用softmax得到i時刻的輸出在Tx個輸入隱藏狀態中的注意力分配向量。這個分配向量也就是計算ci的權重。我們現在再把公式按照執行順序匯總一下[3]:

[3]作者還給了一個示意圖:

上面主要在討論解碼,相比於上面解碼的創新,編碼就比較普通了,只是傳統的單向的RNN中,數據是按順序輸入的,因此第j個隱藏狀態h→j只能攜帶第j個單詞本身以及之前的一些信息;而如果逆序輸入,則h←j包含第j個單詞及之后的一些信息。如果把這兩個結合起來,hj=[h→j,h←j]就包含了第j個輸入和前后的信息。
Attention機制的一個主要優勢是它讓我們能夠解釋並可視化整個模型。舉個例子,通過對attention權重矩陣a的可視化,我們能夠理解模型翻譯的過程(相關詞的關注點)。
當從法語譯為英語時,網絡模型順序地關注每個輸入狀態,但有時輸出一個詞語時會關注兩個原文的詞語,比如將“la Syrie”翻譯為“Syria”。
下面討論一些RNN+NLP之外的AM的問題,這些參考[4]
**
Attention的成本
**
如果再仔細觀察attention的等式,我們會發現attention機制有一定的成本。我們需要為每個輸入輸出組合分別計算attention值。50個單詞的輸入序列和50個單詞的輸出序列需要計算2500個attention值。這還不算太糟糕,但如果你做字符級別的計算,而且字符序列長達幾百個字符,那么attention機制將會變得代價昂貴。
其實它和我們的直覺恰恰相反。人類的注意力是節省計算資源的。當專注於一件事時,我們能忽略其它事情。但這並不是我們上一個模型的作法。我們在決定專注於某個方面之前先仔細觀察每件事。直觀地說,這相當於輸出一個翻譯后的詞語,然后遍歷記憶里所有文本再決定下一個輸出什么。這似乎是一種浪費,而且沒人會這么干。事實上,它更類似於內存訪問,不是attention,在我看來有點兒用詞不當(下文會繼續討論)。不過,這並沒有阻礙attention機制的流行傳播。
attention的另一種替代方法是用強化學習(Reinforcement Learning)來預測關注點的大概位置。這聽起來更像是人的注意力,這也是Recurrent Models of Visual Attention文中的作法。然而,強化學習模型不能用反向傳播算法端到端訓練,因此它在NLP的應用不是很廣泛(我本人反而覺得這里有突破點,數學上的不可求解必然會得到優化,attention model在RL領域的應用確實非常有趣)。
機器翻譯之外領域的Attention機制
到目前為止,我們已經見識了attention在機器翻譯領域的應用。但上述的attention機制同樣也能應用於遞歸模型。讓我們再來看幾個例子。
在Show,Attend and Tell一文中,作者將attention機制應用於生成圖片的描述。他們用卷積神經網絡來“編碼”圖片,並用一個遞歸神經網絡模型和attention機制來生成描述。通過對attention權重值的可視化(就如之前機器翻譯的例子一樣),在生成詞語的同時我們能解釋模型正在關注哪個部分。 
在Grammar as a Foreign Language論文中,作者用遞歸神經網絡模型和attention機制的來生成語法分析樹。可視化的attention矩陣讓人深入地了解網絡模型如何生成這些樹:

在Teaching Machines to Read and Comprehend論文里,作者利用RNN模型讀入文本,先讀入一個(合成的)問題,然后產生一個答案。通過將attention可視化,我們可以看到網絡模型在試圖尋找問題答案的時候關注哪些方面:

ATTENTION = (FUZZY) MEMORY?
attention機制解決的根本問題是允許網絡返回到輸入序列,而不是把所有信息編碼成固定長度的向量。正如我在上面提到,我認為使用attention有點兒用詞不當。換句話說,attention機制只是簡單地讓網絡模型訪問它的內部存儲器,也就是編碼器的隱藏狀態。在這種解釋中,網絡選擇從記憶中檢索東西,而不是選擇“注意”什么。不同於典型的內存,這里的內存訪問機制是彈性的,也就是說模型檢索到的是所有內存位置的加權組合,而不是某個獨立離散位置的值。彈性的內存訪問機制好處在於我們可以很容易地用反向傳播算法端到端地訓練網絡模型(雖然有non-fuzzy的方法,其中的梯度使用抽樣方法計算,而不是反向傳播)。
記憶機制本身的歷史更久遠。標准遞歸網絡模型的隱藏狀態本身就是一種內部記憶。RNN由於存在梯度消失問題而無法從長距離依賴學習。LSTM通過門控機制對此做了改善,它允許顯式的記憶刪除和更新。
更復雜的內存結構的趨勢還在延續。End-To-End Memory Networks一文中的方法允許網絡在輸出內容前多次讀入相同的序列,每一步都更新記憶內容。舉個例子,輸入一個故事,在經過多步推理之后回答一個問題。然而,當網絡參數的權重以某種特定方式被綁定,端到端記憶網絡的記憶機制就和這里所介紹的attention機制一樣了,只是它是多跳的記憶(因為它試圖整合多個句子信息)。
神經圖靈機器使用類似的記憶機制,但有一個更復雜的解決方案,它同時基於內容(如在這里)和位置,使網絡模型通過學習模式來執行簡單的計算機程序,比如排序算法。
在將來,我們很可能看到記憶機制和attention機制之間有更清晰的區別,也許是沿着Reinforcement Learning Neural Turing Machines,它嘗試學習訪問模式來處理外部接口。
參考資料
[1] http://blog.csdn.net/malefactor/article/details/50550211
[2] NEURAL MACHINE TRANSLATION BY JOINTLY LEARNING TO ALIGN AND TRANSLATE
[3] http://blog.csdn.net/u014595019/article/details/52826423
[4] http://geek.csdn.net/news/detail/50558
[5] http://distill.pub/2016/augmented-rnns/
[6] Sequence to Sequence Learning with Neural Networks, 2014, Google
[7] https://www.52ml.net/20093.html
[8] http://blog.csdn.net/malefactor/article/details/50583474
