年前參加了AAAI 2019論文預講會,瞻仰大佬們的各種最新研究,期間發現了一個比較有意思的點,就是這次AAAI會議在自然語言生成方向論文比去年增長了很多,可以從下圖中看出來,Generation佔據很重要的地位。大佬們用Seq2Seq做了不少有意思的事,讓我印象深有生成宋詞的,還有生成b站彈幕的。當時對於Seq2Seq我只是簡單瞭解過,並沒有去使用過這個模型,最近正好有時間學習了一下這個模型,參考別人的文章和代碼使用TensorFlow去實現了Seq2Seq,我做的任務是機器翻譯。
一、Seq2Seq模型簡介
目前Seq2Seq模型在機器翻譯,語音識別,文本摘要,問答系統等領域取得了巨大的成功。如圖1所示,Seq2Seq其實就是Encoder-Decoder結構的網路,它的輸入是一個序列,輸出也是一個序列。在Encoder中,將序列轉換成一個固定長度的向量,然後通過Decoder將該向量轉換成我們想要的序列輸出出來。
如圖2所示,Encoder和Decoder一般都是RNN,通常為LSTM或者GRU,圖中每一個方格都為一個RNN單元。
在Encoder中,「歡迎/來/北京」這些詞轉換成詞向量,也就是Embedding,我們用 來表示,與上一時刻的隱狀態 按照時間順序進行輸入,每一個時刻輸出一個隱狀態 ,我們可以用函數 表達RNN隱藏層的變換: 。假設有t個詞,最終通過Encoder自定義函數 將各時刻的隱狀態變換為向量 : ,這個 就相當於從「歡迎/來/北京」這幾個單詞中提煉出來的大概意思一樣,包含了這句話的含義。
Decoder的每一時刻的輸入為Eecoder輸出的 和Decoder前一時刻解碼的輸出 ,還有前一時刻預測的詞的向量 (如果是預測第一個詞的話,此時輸入的詞向量為「_GO」的詞向量,標誌著解碼的開始),我們可以用函數 表達解碼器隱藏層變換: 。直到解碼解出「_EOS」,標誌著解碼的結束。
二、複雜一點的Seq2Seq模型
剛才講了基本的Seq2Seq模型,那麼現在就給它來加點料,使用一些小技巧讓我們的模型性能更加強悍。
在基礎的模型中,Decoder的每一次解碼又會作為下一次解碼的輸入,這樣就會導致一個問題就是錯誤累計,如果其中一個RNN單元解碼出現誤差了,那麼這個誤差就會傳遞到下一個RNN單元,使訓練結果誤差越來越大。Teacher Forcing在一定程度上解決了這個問題,它的流程如圖3所示,在訓練過程中,使用要解碼的序列作為輸入進行訓練,但是在inference階段是不能使用的,因為你不知道要預測的序列是個啥,當然只在訓練過程中效果就很不錯了,它幫助模型加速收斂。
相比大家都聽過Attention,也就是注意力機制,是2015年Bahdanau等人提出的,大概意思就是讓Encoder編碼出的c向量跟Decoder解碼過程中的每一個輸出進行加權運算,在解碼的每一個過程中調整權重取到不一樣的 向量,更通俗的講就是 就是包含「歡迎來北京」這句話的意思,翻譯到第一個詞「welcome」的時候,需要著重去看「歡迎」這個詞。
假設編碼器每個隱藏狀態為 ,序列長度為T,那麼在第 個時刻 向量的計算方式如下 :
那麼這個權重 怎麼算呢? 給定 , 其實就是在 時刻的一個概率分佈,我們可以使用 進行計算, ,其中 函數 為距離計算函數,有多種方式供選擇,最簡單的就是內積,其他的方式就不在贅述。
這裡借用一個大佬說過的話:Attention聽上去就是一個很屌,不明覺厲的東西,實際實現起來就是,哦原來是這麼回事。總結一下吧,Attention機制就是讓編碼器編碼出來的向量根據解碼器要解碼的東西動態變化的一種機制,貌似來源靈感就是人類視覺在看某一個東西的時候會有選擇的針對重要的地方看。
在inference階段,不能使用Teacher Forcing,那麼只能使用上一時刻解碼的輸出作為下一個解碼的輸入,剛才也說過了這樣會導致誤差傳遞,怎麼解決這個問題呢?答案就是Beam Search,使用流程是這樣的,在每個時刻解碼器都會選擇Top k個預測結果作為下一個解碼器的輸入,將這K個結果逐一輸入到解碼器進行解碼,就會產生k倍個預測結果,從所有的解碼結果中再選出Top K個預測結果作為下一個解碼器的輸入,在最後一個時刻再選出Top 1作為最終的輸出,這樣避免的錯誤傳遞。圖我就不畫了有點麻煩,想看圖可以參考Tensorflow中的Seq2Seq全家桶這篇文章,畫的很清楚,另外本篇文章大量內容和github的代碼都是參考這篇文章寫的,感謝作者的文章!
三、使用TensorFlow的API實現Seq2Seq
TensorFlow對於Seq2Seq做了很好的封裝,使用起來相當方便,我實現了兩個版本的Seq2Seq模型,一個是簡單版的,內容就是我第一部分講的最基礎的Seq2Seq模型,第二個相對複雜一點的,內容就是我第二部分講的加上一下小技巧的Seq2Seq模型,代碼我都放到github了,大家可以去參考一下。
我講的都是一些最基本的東西,關於Seq2Seq的東西還很多,接下來還是繼續學習積累吧,有了新的感悟我會繼續寫文章分享給大家,感謝你看完這篇文章。
[1]Bahdanau D, Cho K, Bengio Y. Neural machine translation by jointly learning to align and translate[J]. arXiv preprint arXiv:1409.0473, 2014.
[2]Sutskever I, Vinyals O, Le Q V. Sequence to sequence learning with neural networks[C]//Advances in neural information processing systems. 2014: 3104-3112.
[3]TensorFLow API文檔
[4]Tensorflow中的Seq2Seq全家桶
[5]草稿紙上的seq2seq模型與Attention機制