機器翻譯不可不知的Seq2Seq模型
- 機器翻譯——Seq2Seq模型
- 介紹
- 設計目標
- 主要概念
- Encoder-Decoder
- Attention模型
- CNN的seq2seq
- 應用領域
- 參考
介紹
Seq2Seq,全稱Sequence to Sequence。它是一種通用的編碼器——解碼器框架,可用於機器翻譯、文本摘要、會話建模、圖像字幕等場景中。Seq2Seq並不是GNMT(Google Neural Machine Translation)系統的官方開源實現。框架的目的是去完成更廣泛的任務,而神經機器翻譯只是其中之一。在循環神經網路中我們了解到如何將一個序列轉化成定長輸出。在本文中,我們將探究如何將一個序列轉化成一個不定長的序列輸出(如機器翻譯中,源語言和目標語言的句子往往並沒有相同的長度。)。
設計目標
- 通用這個框架最初是為了機器翻譯構建的,但是後來使用它完成了各種其他任務,包括文本摘要、會話建模和圖像字幕。只要我們的任務,可以將輸入數據以一種格式編碼並將其以另一種格式解碼,我們就可以使用或者擴展這個框架。
- 可用性支持多種類型的輸入數據,包括標準的原始文本。
- 重現性用YAML文件來配置我們的pipelines和models,容易復現。
- 可擴展性
代碼以模塊化的方式構建,添加一種新的attention機制或編碼器體系結構只需要最小的代碼更改。
- 文檔化:所有的代碼都使用標準的Python文檔字元串來記錄,並且編寫了使用指南來幫助我們著手執行常見的任務。
- 良好的性能:為了代碼的簡單性,開發團隊並沒有試圖去儘力壓榨每一處可能被拓展的性能,但是對於幾乎所有的生產和研究項目,當前的實現已經足夠快了。此外,tf-seq2seq還支持分散式訓練。
主要概念
- Configuration
許多objects都是使用鍵值對來配置的。這些參數通常以YAML的形式通過配置文件傳遞,或者直接通過命令行傳遞。配置通常是嵌套的,如下例所示:
model_params: attention.class: seq2seq.decoders.attention.AttentionLayerBahdanau attention.params: num_units: 512 embedding.dim: 1024 encoder.class: seq2seq.encoders.BidirectionalRNNEncoder encoder.params: rnn_cell: cell_class: LSTMCell cell_params: num_units: 512
- Input Pipeline
InputPipeline定義了如何讀取、解析數據並將數據分隔成特徵和標籤。如果您想要讀取新的數據格式,我們需要實現自己的輸入管道。
- Encoder(編碼)
- Decoder(解碼)
- Model(Attention)
Encoder-Decoder
整個過程可以用下面這張圖來詮釋:
圖 1:最簡單的Encoder-Decoder模型
整個模型分為解碼和編碼兩個過程,將輸入序列X進行編碼得到向量C,然後對C進行解碼得到輸出序列Y。
其中,X、Y均由各自的單詞序列組成(X,Y可以是同一種語言,也可以是兩種不同的語言):
X = (x1,x2,...,xm)
Y = (y1,y2,...,yn)
Encoder:是將輸入序列通過非線性變換編碼成一個指定長度的向量C(中間語義表示),得到c有多種方式,最簡單的方法就是把Encoder的最後一個隱狀態賦值給c,還可以對最後的隱狀態做一個變換得到c,也可以對所有的隱狀態做變換。
C = F(x1,x2,...,xm)
Decoder:是根據向量C(encoder的輸出結果)和之前生成的歷史信息y1,y2,...,yn來生成i時刻要生成的單詞yi。
yi = G( C , y1,y2,...,yn-1)
下圖是一個生成對聯的示意圖。
圖 2:生活中的小栗子
經典Seq2Seq中採用的encoder和decoder均為RNN,對於其它的編解碼器,請參考文章最後附加的鏈接,由於篇幅有限,這裡僅用RNN拋磚引玉。
- 編碼階段
在RNN中,當前時間的隱藏狀態由上一時間的狀態和當前時間輸入決定的,即:
獲得了各個時間段的隱藏層以後,再將隱藏層的信息匯總,生成最後的語義向量
當然,有一種最簡單的方法是將最後的隱藏層作為語義向量C,即
- 解碼階段
可以看做編碼的逆過程。這個階段,我們根據給定的語義向量C和之前已經生成的輸出序列y1,y2,...,yt-1來預測下一個輸出的單詞yt,即
也可以寫作
在RNN中,也可以簡化成
其中s是輸出RNN(即RNN解碼器)中的隱藏層,C代表之前編碼器得到的語義向量,yt-1表示上個時間段的輸出,反過來作為這個時間段的輸入。g可以是一個非線性的多層神經網路,產生詞典中各個詞語屬於yt的概率。
Attention模型
encoder-decoder模型雖然非常經典,但是局限性也非常大。最大的局限性就在於編碼和解碼之間的唯一聯繫就是一個固定長度的語義向量C。也就是說,編碼器要將整個序列的信息壓縮進一個固定長度的向量中去。但是這樣做有兩個弊端,一是語義向量無法完全表示整個序列的信息,二是先輸入的內容攜帶的信息會被後輸入的信息稀釋掉。輸入序列越長,這個現象就越嚴重。這就使得在解碼的時候一開始就沒有獲得輸入序列足夠的信息, 那麼解碼時準確率就要打一定折扣。
為了解決上述問題,在 Seq2Seq出現一年之後,Attention模型被提出了。該模型在產生輸出的時候,會產生一個注意力範圍來表示接下來輸出的時候要重點關注輸入序列的哪些部分,然後根據關注的區域來產生下一個輸出,如此反覆。attention 和人的一些行為特徵有一定相似之處,人在看一段話的時候,通常只會重點注意具有信息量的詞,而非全部詞,即人會賦予每個詞的注意力權重不同。attention 模型雖然增加了模型的訓練難度,但提升了文本生成的效果。模型的大概示意圖如下。
圖 3:經典的attention模型
相比於之前的encoder-decoder模型,attention模型最大的區別就在於它不在要求編碼器將所有輸入信息都編碼進一個固定長度的向量之中。相反,此時編碼器需要將輸入編碼成一個向量的序列,而在解碼的時候,每一步都會選擇性的從向量序列中挑選一個子集進行進一步處理。這樣,在產生每一個輸出的時候,都能夠做到充分利用輸入序列攜帶的信息。而且這種方法在翻譯任務中取得了非常不錯的成果。
每一個c會自動去選取與當前所要輸出的y最合適的上下文信息。具體來說,我們用 aij 衡量編碼中第j階段的hj和解碼時第i階段的相關性,最終Decoder中第i階段的輸入的上下文信息 ci 就來自於所有 hj對 aij的加權和。
圖 4:不同關注度示意圖
輸入的序列是「我愛中國」,因此,Encoder中的h1、h2、h3、h4就可以分別看做是「我」、「愛」、「中」、「國」所代表的信息。在翻譯成英語時,第一個上下文c1應該和「我」這個字最相關,因此對應的 a11就比較大,而相應的 a12 、a13 、 a14 就比較小。c2應該和「愛」最相關,因此對應的 a22 就比較大。最後的c3和h3、h4最相關,因此 a33 、 a34的值就比較大。具體模型權重 aij 是如何計算出來的呢?
比如:
輸入的是英文句子:Tom chase Jerry,生成:「湯姆」,「追逐」,「傑瑞」。
注意力分配概率分布值的通用計算過程:圖 5:權重計算示意圖
當前輸出詞Yi針對某一個輸入詞j的注意力權重由當前的隱層Hi,以及輸入詞j的隱層狀態(hj)共同決定;然後再接一個sofrmax得到0-1的概率值。即通過函數F(hj,Hi)來獲得目標單詞Yi和每個輸入單詞對應的對齊可能性。更多細節,請大家參看知乎何之源的文章,文末會給出文章鏈接。
CNN的seq2seq
現在大多數場景下使用的Seq2Seq模型是基於RNN構成的,雖然取得了不錯的效果,但也有一些學者發現使用CNN來替換Seq2Seq中的encoder或decoder可以達到更好的效果。最近,FaceBook發布了一篇論文:《Convolutional Sequence to Sequence Learning》,提出了完全使用CNN來構成Seq2Seq模型,用於機器翻譯,超越了谷歌創造的基於LSTM機器翻譯的效果。此網路獲得暫時性勝利的重要原因在於採用了很多的竅門,這些技巧值得學習:
- 捕獲long-distance依賴關係
底層的CNN捕捉相聚較近的詞之間的依賴關係,高層CNN捕捉較遠詞之間的依賴關係。通過層次化的結構,實現了類似RNN(LSTM)捕捉長度在20個詞以上的Sequence的依賴關係的功能。
- 效率高
假設一個sequence序列長度為n,採用RNN(LSTM)對其進行建模 需要進行n次操作,時間複雜度O(n)。相比,採用層疊CNN只需要進行n/k次操作,時間複雜度O(n/k),k為卷積窗口大小。
- 並行化實現
RNN對sequence的建模依賴於序列的歷史信息,因此不能並行實現。相比,層疊CNN對整個sequence進行卷積,不依賴序列歷史信息,可以並行實現,特別是在工業生產,面臨處理大數據量和實時要求比較高的情況下,模型訓練更快。
- 融合多層attention
融合了Residual connection、liner mapping的多層attention。通過attention決定輸入的哪些信息是重要的,並逐步往下傳遞。把encoder的輸出和decoder的輸出做點乘(dot products),再歸一化,再乘以encoder的輸入X之後做為權重化後的結果加入到decoder中預測目標語言序列。
- gate mechanism
採用GLU做為gate mechanism。GLU單元激活方式如下公式所示:
每一層的輸出都是一個線性映射XW + b,被一個門gate:o(XV+c)控制,通過做乘法來控制信息向下層流動的力度,o採用雙曲正切S型激活函數。這個機制類似LSTM中的gate mechanism,對於語言建模非常有效,使模型可以選擇那些詞或特徵對於預測下一個詞是真的有效的。
- 進行了梯度裁剪和精細的權重初始化,加速模型訓練和收斂。
基於CNN的seq2seq模型和基於LSTM的Seq2Seq模型孰好孰壞,我們不能妄加評判。採用CNN的Seq2Seq最大的優點在於速度快,效率高,缺點就是需要調整的參數太多。在CNN和RNN用於NLP問題時,CNN也是可行的,且網路結構搭建更加靈活,效率高,由於RNN訓練時往往需要前一時刻的狀態,很難並行,特別是在大數據集上,CNN-Seq2Seq往往能取得比RNN-Seq2Seq更好的效果。
應用領域
- 機器翻譯
圖 6:採用Seq2Seq效果對比
從圖像可以看出,模型中的語境向量很明顯的包涵了輸入序列的語言意義,能夠將由不同次序所產生的不同意思的語句劃分開來,這對於提升機器翻譯的準確率很有幫助。當前,主流的在線翻譯系統都是基於深度學習模型來構建的,包括 Google、百度等。
- 閱讀理解將輸入的文章和問題分別編碼,再對其進行解碼得到問題的答案。- 語音識別
輸入是語音信號序列,輸出是文字序列。 - 文本摘要輸入是一段文本序列,輸出是這段文本序列的摘要序列。通常將文本摘要方法分為兩類,extractive 抽取式摘要和 abstractive 生成式摘要。前者是從一篇文檔或者多篇文檔中通過排序找出最有信息量的句子,組合成摘要;後者類似人類編輯一樣,通過理解全文的內容,然後用簡練的話將全文概括出來。在應用中,extractive摘要方法更加實用一些,也被廣泛使用,但在連貫性、一致性上存在一定的問題,需要進行一些後處理;abstractive 摘要方法可以很好地解決這些問題,但研究起來非常困難。 - 對話生成Seq2Seq 模型提出之後,就有很多的工作將其應用在 Chatbot 任務上,希望可以通過海量的數據來訓練模型,做出一個智能體,可以回答任何開放性的問題;而另外一撥人,研究如何將 Seq2Seq 模型配合當前的知識庫來做面向具體任務的 Chatbot,在一個非常垂直的領域(比如:購買電影票等)也取得了一定的進展。圖 7:對話生成Chatbot
- 詩詞生成讓機器為你寫詩並不是一個遙遠的夢,Seq2Seq 模型一個非常有趣的應用正是詩詞生成,即給定詩詞的上一句來生成下一句。
- 生成代碼補全
圖 8:代碼補全示意圖
- 預訓練2015年,Google提出了將Seq2Seq的自動編碼器作為LSTM文本分類的一個預訓練步驟,從而提高了分類的穩定性。這使得Seq2Seq技術的目的不再局限於得到序列本身,為其應用領域翻開了嶄新的一頁。
參考
源碼地址:https://github.com/google/seq2seq
《Convolutional Sequence to Sequence Learning》:
https://arxiv.org/abs/1705.03122
《Language modeling with gated linear units》:
https://arxiv.org/abs/1612.08083
《A Convolutional Encoder Model for Neural Machine Translation》:
https://arxiv.org/abs/1611.02344
Google Neural Machine Translation:
https://research.googleblog.com/2016/09/a-neural-network-for-machine.html
簡書:Datartisan
https://www.jianshu.com/p/124b777e0c55
知乎作者:李寧
https://zhuanlan.zhihu.com/p/30516984
知乎作者:何之源
https://zhuanlan.zhihu.com/p/28054589
PaperWeekly:張俊
https://zhuanlan.zhihu.com/p/26753131
推薦閱讀:
※實現屬於自己的TensorFlow(三) - 反向傳播與梯度下降實現
※1-2 Welcome
※TensorFlow.js發布:使用JS進行機器學習並在瀏覽器中運行
※20 個頂尖的 Python 機器學習開源項目