如何評價 Facebook 新推出的 CNN 機器翻譯項目 Fairseq?

Facebook發表的文章:https://code.facebook.com/posts/1978007565818999/a-novel-approach-to-neural-machine-translation/

Github上的code:facebookresearch/fairseq


想法還是很簡單粗暴的,但實現水平一流。

用RNN可以「記住」序列里的歷史信息,attention也挺好用,但是不能並行化所以在企業級應用或者資源有限的時候慢的令人髮指;

CNN可以並行化,速度快,可以通過疊加很多層來表達一個比較大的窗口裡的上下文信息,但是簡單的拼起來打不過RNN的表現。

那在沒有更好的模型的前提下又想快又想表現好怎麼辦,給CNN上trick!

  • Trick1: 加上一個position embedding給CNN更多的「位置感」
  • Trick2: 給CNN的輸出加gate
  • Trick3: 給CNN都加上residual connection
  • Trick4: 一層attention不夠那就上疊加的attention

然後就好用了:) 速度是RNN的十倍不說表現還好了一小節。我就是比較好奇為什麼選了torch來實現,是因為caffe2在學術圈不普及,pytorch還不夠靈活么...

所以總的來說想法不新,trick們也不新,但是實現和實驗起來並不輕鬆。看看那些用來穩定優化的trick就知道作者們煉丹經驗多豐富了。


(手機碼字)之前FB搞了個gated CNN做language model,目的就是能夠替代LSTM的時序記憶能力,充分發揮CNN的並行性,提高相關任務的inference速度。

現在這篇論文,感覺上是成功探索了gated CNN的有效性之後,一個「喪心病狂」的延續:我們把encoder和decoder都換成了CNN還能做好attention和memory,inference速度還快了幾倍,效果還比GNMT好!

你咬我啊!(劃掉)

道理我都懂,可是代碼為什麼不是PyTorch或者Caffe2的實現?


我怎麼感覺那幾個trick才是帶來翻譯performance提升的關鍵:

1, attention的時候是對z+e的加權求和,並且e是w+p...而之前大家一直用的z;

這個帶來的提升我猜還是不小的。

2,層疊attention。

如果把這幾個trick實現在基於rnn的nmt上,會怎麼樣呢?

當然可並行化cnn帶來的效率提升是很可觀的。

最後,我總覺得,在NMT這類seq2seq的tasks上,encoder端對long sequence的建模貌似沒必要,只要能夠對一個片段建模就好了。反正有decoder的attention來重新把傳丟的信息再補充和細化回去。所以attention能夠做好的話,收益很可觀。

decoder端是必須得有一個language model類型的東西,畢竟要生成一個句子,不管rnn-nmt還是cnn-nmt,都是這樣的,而且用了teacher forcing。

當然可能理解有錯。


這個工作延續上他們之前CNN encoder的工作,這次不僅encoder是CNN,decoder也是CNN。結果非常好,BLUE超過了谷歌的GNMT但是inference的速度比GNMT快得多。CNN具備很好的並行性,不像RNN一次只能吞一個詞。優化的trick比較多,梯度裁剪、權重歸一等,少用一個trick恐怕就難以復現結果,這恐怕是由於網路太深。

門控單元的效用我沒看到作者進行分析,我在其他任務的實驗結果顯示它與ReLU差距微小。

Facebook一直想用CNN代替RNN,在文本分類,語言模型和機器翻譯上均有所突破。我很看好CNN,我本人在一些中文序列標註任務中也用CNN替代RNN,取得不錯的性能提升與速度提升。

補充一點,他們的模型要在單機八塊卡上訓練37天,有點長。但是GNMT貌似更長(多機環境,用了100+ gpus訓了好幾天)。

補充一點,其實有時候我們並不需要RNN的全局依賴建模的能力,如其他回答所說,一個原因是attention機制變相的獲取了全局信息,因此encoder端的每個時刻並不需要全局;另一個原因是雖然理論上RNN建模能力更強,可惜數據也許不支持這樣長程的學習,還有優化過程。


用CNN來做時間序列預測分析,是一個非常難的問題。在此之前,CNN在圖像領域大放異彩,橫掃物體識別、檢測、分割等不同場景。即便是應用到自然語言處理中,也只是簡單的從embedding中提取相鄰幾個單詞的特徵,再加上pooling層,變成固定高層特徵輸入到分類器中。

背景:Kalchbrenner Blunson (2013) 提出過從句子中提取出固定長度的embedding,Cho等人 (2014) 提出帶門的遞歸CNN用來重複的產生向量representation,直到一定長度就停止。但是這些模型都沒有RNN、LSTM、GRU等的效果好,單純的使用卷積層提取特徵,對於時間序列來說,這對於把握住單詞前後的特徵特別難。隨著CNN的越來越成熟,發展出了新的特性,包括attention mechanism、residual connection以及一些工程上的tricks,使得CNN的表徵能力越來越強。

最近比較有突破的進展如下。Kalchbrenner等人 (2016) 已經開始使用CNN模型應用到翻譯任務中,但是沒有使用attention機制,結果沒有達到預期。Pham等人 (2016) 將CNN成功用於語言模型,即便沒有超過LSTM。

最新成果:自然語言處理包括眾多領域,機器翻譯、語言模型、NER、POS、QA問答、多輪對話等,RNN及其變種都取得了非常大的成功。然而,Facebook一直堅持將CNN用於這些任務中,不得不說是工業界及學界的一股清流。最近的幾篇論文也非常有意思,先說結果。

第一篇叫A convolutional encoder model for neural machine translation,去年11月份發的,採用了非常多的技巧,1. 加上position embedding,解決單詞位置信息;2. 每層卷積的輸出都要加上其輸入,即殘差連接;3. attention機制的使用,encoder最後是兩個stacked卷積層,一個負責encoder的輸出,另一個負責conditional input。三個翻譯任務結果如下:

最新的這篇文章Convolutional sequence to sequence learning,結果如下:

就舉一個例子來說,English到Romanian的翻譯中,BiGRU的BLEU是28.1,前一篇文章CNN encoder最好的BLEU是27.8,現在這篇是29.88,足足提高了兩個點,並且超過了GRU的效果。不得不說,現在CNN作為encoder和decoder超過了RNN的表現,這才是這篇文章引起一定轟動的原因。

論文分析:現在來詳細分析Convolutional sequence to sequence learning的細節。

  • embedding層:原本詞嵌入 w,加上position embedding p 後,形狀是m*f,m是單詞數,f是初始embedding維度,最終會通過一個變換矩陣變成m*d才能輸入到網路中,即做了一個空間變換。

  • encoder部分:卷積層一般叫做layer,此文叫block,是一個意思。一個block的包含一個卷積和Gated linear units (GLU)。
    卷積是一維的,在sentence方向上進行掃描。單詞數即輸入長度為m,kernel大小為k,pad為p,那麼計算輸出sequence長度的公式為(m+2p-k)/stride+1,文中保證了輸入sequence和輸出的長度一致。舉個例子,輸入為25,kernel為5,(25+2*2-5)/1+1=25。為了充分讓輸出節點跟整個sequence單詞有聯繫,必須使用多個卷積層,這樣才能使輸出可以感受整個句子的特徵,也能感受局部句子的特徵。假如卷積層數為6,那麼第6層輸出的神經元將依賴第0層(從第1層開始才為卷積層)的25個神經元,具體計算在圖上畫出來就很清晰,這裡不貼出來了。
    卷積的結果: h^l=WX+b+h^{l-1}h^{l-1}為上一層l-1的隱層輸出, h^{l} 為當前層 l的輸出,其中權重W為2d*kd,輸入X為kd*1,偏置b為2d*1。
    X本身就是一個卷積核對應的embedding區域,本來是k*d,d就是之前經過矩陣變換得到的word embedding。這裡就拉成了一個vector,有點類似於img2col。
    最終得到的表達是2d*1,你也可以把它當作是一個單詞的表達,之後又會送入下一個卷積層。
    在送入下一個卷積層之前,每一個單詞的維度從d變成了2d,那豈不是每經過一個卷積,輸出channel都會變大一倍?當然不是。卷積之後會經過一個GLU,GLU的跟一般的非線性層有所區別。經過第一個卷積層之後,整個sentence的維度為k*2d。對於每個單詞向量,維度是2d,GLU都要把它分成兩部分A和B,大小均為d,B經過softmax變換,再跟A進行點乘。此時一個block的輸出就變成了k*d。

  • decoder部分:使用multi-step attention,有點類似於人每翻譯一個單詞時,都會去原句子中尋找是否有合適的答案。

Instead of looking at the sentence only once and then writing down the full translation without looking back, the network takes repeated 「glimpses」 at the sentence to choose which words it will translate next, much like a human occasionally looks back at specific keywords when writing down a translation。

具體實現就是矩陣運算,貼上公式。
decoder的state summary d^l_i,其中 g_i 是上一步decoder生成的目標。

attention分數, 注意 h^l_i 是每一個block的輸出,z^u_j 為encoder的輸出, a^l_i 維度為m。
a^l_i=[a^l_{i1}, a^l_{i2}, ..., a^l_{im}]

條件輸入 c^l_i,此處添加了最開始的embedding e_j,當做決策時能夠提供一些位置點的 信息。當它被計算出來時, c^l_i 就會跟decoder的狀態 h_i 簡單相加。

結論:這片文章總的感覺耳目一新,感覺會是NLP的一個重要里程碑。除了翻譯之外,其他任務是否也可以採用CNN處理,拭目以待!雖然速度高了不少,但那也是跟谷歌的GNMT比較,其模型本身就非常複雜。對於一般的任務而言,能否利用CNN的並行計算再加速,也值得期待。

附錄文章:

[1] Convolutional Sequence to Sequence Learning. Jonas Gehring, Michael Auli, David Grangier, Denis Yarats, Yann N. Dauphin. arXiv, 2017

[2] A Convolutional Encoder Model for Neural Machine Translation. Jonas Gehring, Michael Auli, David Grangier, Yann N. Dauphin. arXiv, 2016

[3] Language Modeling with Gated Convolutional Networks. Yann N. Dauphin, Angela Fan, Michael Auli, David Grangier. arXiv, 2016

[4] https://code.facebook.com/posts/1978007565818999/a-novel-approach-to-neural-machine-translation/


很多的trick,比較有想法。

1、輸入端加入位置向量,使得由CNN構成的Encoder和Decoder也具備了RNN捕捉輸入Sequence中詞的位置信息的功能。

2、層疊的CNN構成了hierarchical representation表示,底層的CNN捕捉相聚較近的詞之間的依賴關係,高層CNN捕捉較遠詞之間的依賴關係。通過層次化的結構,實現了類似RNN(LSTM)捕捉長度在20個詞以上的Sequence的依賴關係的功能。

3、多層attention,通過attention決定哪些信息是重要的,並逐步往下傳遞。

4、為了保證訓練的穩定性,進行了梯度裁剪和精細的權重初始化。

5、融合了添加了Residual connection、GLU、linner mapping等很多操作。

感覺,前兩點實現了RNN所獨有的功能。與RNN相比,感覺基於CNN的seq2seq網路結構更靈活,訓練速度更快,更適合工業生產中大數據訓練。


https://github.com/tobyyouup/conv_seq2seqconvseq2seq的tensorflow實現。

由於Fairseq項目是使用Torch/Lua實現的,考慮到工業界大多還是Tensorflow/Python比較流行,所以前段時間用Tensorflow實現了Fairseq的conv seq2seq模型,github地址:tobyyouup/conv_seq2seq,希望能對大家有所幫助。整個實現的framework是基於google的seq2seq框架,雖然模型細節嚴格參照conv seq2seq論文和fairseq的torch/lua的code,但是模型代碼實現成了seq2seq項目中的標準類,可以很好的兼容在seq2seq框架下,歡迎多多交流。


大家可以看看這篇https://zhuanlan.zhihu.com/p/26985192 paperweekly最近在做reading group的活動,幾十位童鞋對這篇paper的細節進行了討論。


不懂LUA。不過從動圖看Decoder的開銷不小,感覺還是逃不脫recurrent結構。


別的不說,其最大的亮點「CNN並行起來比LSTM快」,在decoder階段很值得懷疑。

按照論文裡面用Teacher Forcing的話,在訓練的時候這個CNN翻譯模型的確是高度並行的沒錯;但Teacher Forcing存在著exposure bias的問題,一個比較流行的解決方案是Schedule Sampling。而如果用上Schedule Sampling,管你是LSTM還是CNN,decode的時候不都得一步一步老老實實地rollout出前面的詞才能算後面的詞?這個時候CNN最引以為傲的並行性就廢了。

也就是說,想要在訓練階段獲得全部的並行性,我們就得受限於Teacher Forcing的訓練方法。

同樣地,在測試使用模型的時候,CNN和LSTM都得一個個詞串列地rollout出來,在decode的每一步,CNN翻譯模型要做K層計算,每層要做卷積還有attention,而LSTM翻譯模型要做幾個gate還有hidden state的計算,開銷很難說誰大誰小,那憑什麼CNN的inference速度就能快十幾倍呢?

若有理解不當之處歡迎指正。


尚未開始深鑽。用CNN代替RNN最大的優勢就是可並行計算,訓練和解碼速度都能帶來顯著提升。

至於犧牲全局建模強化局部交互可能造成的性能損失,文中提出通過引入位置編碼和層次化注意力等技巧來彌補。遺憾的是,現階段主要實驗對象仍然是基本無需大範圍調序的語種,無法知曉在其他語種上會不會有流暢度方面的損失。要知道流暢度是RNN seq2seq NMT相較於PBMT具有顯著優越性的最大體現。

自動評價指標BLEU漲那個量級其實得不出太多結論的,有實際運行結果對比才能看出有沒有傷害。期待有行家搭出系統來直接與RNN NMT來PK實際輸出。


本人非技術,但之前專門請教了團隊里負責機器翻譯團隊的技術負責人。簡單說下自己的理解,我覺得更適合技術小白用戶理解。

機器翻譯的發展經歷很明顯的幾個階段。

1、基於規則的翻譯

2、基於統計的翻譯

3、基於深度學習的翻譯

基於規則是指根據句法規則等,來寫各種模板,去匹配相應的翻譯結果。比如,我練習跑步是為了減肥。 主語 動詞 for 名詞、動詞。

這個方法的好處是,翻譯的準確率非常高,缺點是覆蓋率極其有限,需要靠大量的人去寫各種各樣的規則,對於一些變換較多的句子,翻譯的效果並不好。

基於統計的翻譯應該是在計算機處理能力大大增強之後被提出來的。也就是說,基於雙語的平行語料,對其進行切分,以及對齊。比如make這個詞在很大的概率下都被翻譯為做,那麼它譯文翻為「做」的概率就非常高。

基於深度學習的機器翻譯是指把翻譯模型融入了深度學習技術,尤其是再編碼的過程中,把整個句子作為一個整體去進行編碼,而不是像smt統計機器翻譯一樣進行詞的切分,更大程度上讓翻譯的譯文更加流暢、自然,不像過去那些拼湊起來。一般,現在的翻譯模型大多還是nmt與smt的融合,因為nmt收到詞表較小的影響,在某些query上的翻譯效果並不是很好。比如,當一句話裡面,所有的詞詞表都在nmt的詞表中,那就走nmt模型,如果不是,就走smt。否則nmt會出現漏譯的情況概率較大。

樓主提到的facebook的cnn和rnn,實際上都是nmt,神經網路翻譯。這二者的區別,更多的是表現在翻譯的速度上。如何理解這個概念呢?

先說一下,nmt和smt的一大明顯差異,是nmt運用了海量的計算,這對機器、GPU的要求和依賴都是非常高的。NMT會佔用大量的資源。CNN相比之前大家用的RNN,是通過並行處理的模式,更好的利用了GPU,從而大大提升翻譯的效率。但是呢,在實際翻譯結果中,尚且沒有非常明顯的質量上的差異。


推薦閱讀:

multi-task深度神經網路如何實現,優化?
如何評價陳天奇團隊新開源的TVM?
能不能給神經網路計算一個「學習進度」的指標?
沒有GPU可以做深度學習嗎?
如何看待Google的AutoML 已經學會自己編寫機器學習代碼?

TAG:Facebook | 機器學習 | 自然語言處理 | 深度學習DeepLearning | 卷積神經網路CNN |