原始數據: AIChallenger2018_EnZh_MT_Data

代碼(一些腳本): AIChallenger2018_EnZh_MT_Code如有幫助,給個star唄~~~

從九月底開始準備這個賽事,花了很多精力做比賽,最終跑分不算理想,但是排名還是挺意外的,測試集B有許多排名靠前的大佬放棄提交(聽說有的人可能是因為不合符參賽規則而放棄提交)。

最終排到第10。

0 感受

這是第一次參加AI相關的比賽,自己本來是做OCR的,但是由於平時看的論文很多是機器翻譯方向的,所以打算試一下水。總的來說,感覺做比賽最重要的是經驗積累,其次是比賽期間投入的總時間,top的幾個隊伍應該是公司或者專門做機翻的實驗室,得分甩後面隊伍幾條街。所以新手參加看到前面大佬的分數不要慌,無視就好。

另外,收穫呢,學習是談不上的了,基本都是跑開源代碼調參的苦力活,但是可以拓展知識面,瞭解這個領域有什麼方法。教訓也是有的,其一,盡量不要一個人做,容易犯錯而不自知;其二,在嘗試新方法的時候,要快速走完訓練、驗證、測試這些環節,這樣可以確保這套代碼可行,並且對其性能有個估計。

1 數據處理

使用官方提供的數據處理腳本,英文做了lowercase和簡單的tokenize,中文jieba分詞。

2 tensor2tensor庫

第一階段的實驗基於tensor2tensor庫(t2t),它是google基於tensorflow開發的高級庫,內置了許多經典模型,做實驗相當方便。transformer模型已經成為當前機器翻譯比賽的標配,大家都用,我也用。

先後嘗試了transformer_base, transformer_big, transformer_middle(自己定義的參數,num_layer, num_head, num_filter值取base和big的平均),universal_transformer_base, universal_transformer_middle, universal_transformer_big這些模型。簡單匯總如下:

實驗參數(未列出的使用默認參數):

實驗結果

上述實驗結果不是很精確,大概這麼多,做實驗的時候沒有嚴格記錄。universal_transformer的結果不比transformer好,就不列出了,而且decode耗費的時間巨多。

調參方面可以看這個參考文檔Training Tips for the Transformer Model,有很周祥的實驗記錄。我的經驗是batch_size調大會有提升,但是超過一定值之後就不會再提高了,如果想增大batch_size,可以將參數sync設置為True(有多張卡的前提下),這個參數決定了模型參數更新是否為同步更新,如果是同步更新,真實的batch_size擴大了n倍(n張卡)。此外,學習率在訓練loss不降的時候調小,能進一步降低訓練loss,dev集上的表現相應提升。

有一個trick是,訓練集上訓出來的模型拿到dev集上finetune可以提高test集的得分,因為dev與test的分佈比較相近。我的實驗中會有0.5左右的提升。

最後就是多去github上的issue看看,會有很多收穫。

至此,tensor2tensor調參工作告一段落了,接下來就是考慮提升的思路。因為在dev集上finetune提升明顯,所以首先想到的是在數據上動手。

3 數據篩選

(很傷心的是這方面的嘗試全部失敗,大家可以跳過這部分)。在dev集上finetune嘗到甜頭,所以很自然地想從訓練集中選出與test集相似的一些樣本來。

這個相似性如何度量呢,一個超級naive的想法是統計test集中的詞頻,去掉高頻詞,得到一個能表示test集特點的詞庫,然後遍歷訓練集中的每個句子每個詞,如果該詞在test集中出現過,則選中當前句。但是這個時間複雜度太大了,放棄。

接著想到用bleu值來度量句子相似度,直接用python的nltk庫算bleu值,其實這個時間複雜度比前一個想法更大,但想著畢竟是開源庫,應該優化的好,於是測了一下耗費時間,能接受,最後遍歷了大概800w訓練集,選出14w數據(多臺伺服器100多個核上跑了6小時,還是挺耗時的)。用這14w數據finetune發現性能下降了,觀察了一下這14w數據,數據多樣性很低,很多句子都有相同的短語,例如 i dont know .... , and if you dont....., it doesnt have to....., whats going on....., do you want me.......。這種片段開頭的句子非常多,考慮到這語料是電影裏的,也很正常。想不到解決辦法,放棄。

然後在網上搜到有專門計算句子相似度的演算法,主要有基於word-embedding的方法和預訓練編碼器的方法,我就採取最簡單的方法,兩個句子做了詞嵌入後的WMD距離(詞移距離)。介紹見四種計算文本相似度的方法對比,代碼見Simple Sentence Similarity。小規模測試發現這個計算太耗時了,而選出來的句子並不理想,放棄。

最後在後期想到一個騷操作,那就是在test和dev集上訓一個語言模型,用這個語言模型給訓練集中的句子打分,選出一些高分句子。然而這個方法選出的句子特點是,得分靠前的都是一些非常簡單的句子(句子中的辭彙都是一些高頻詞),加之時間不多了,也就沒有進一步想解決辦法。想到這個操作起因是聽說去年冠軍隊伍用語言模型給訓練集打分,剔除了低分數據。但是我的實驗並不奏效,我是用訓練語料訓出一個語言模型,先去掉訓練集中重複的句子(蠻多的),然後剔除了100W低分語料,但是結果並沒有提升。訓語言模型用的工具是kenlm, 需要注意的是score這個函數算出來的分數沒考慮句長,所以用perplexity更合適。這之前嘗試過另一個工具mitlm,文檔比較隱蔽,見MIT Language Modeling Toolkit Tutorial,mitlm/tree/wiki。

總的來說,數據篩選嘗試失敗的原因可能是:選出的數據多樣性較低。

4 數據增強

NMT中用回譯的方法擴充語料是常用的數據增強方法,見Improving Neural Machine Translation Models with Monolingual Data[1], Investigating Backtranslation in Neural Machine Translation[2],Explaining and Generalizing Back-Translation throughWake-Sleep[3]。

[1]中實驗有個非常有意思的嘗試是,僅用額外的target端單語數據(不做回譯)就能提高性能。具體做法是,將source端句子填充為<null>,得到這樣的句對,與真實句對按1:1的比例組成全部訓練集,訓練的時候每個batch中的句對要麼全是填充的,要麼全是真實的句對,如果是填充的句對,要固定encoder部分的參數,只更新decoder的參數。相當於用額外數據訓了一個語言模型,需要注意的是,單語數據不能用太多,超過1:1的話可能導致decode的時候更依賴於用單語語料訓出來的參數,而學不到利用encoder端的信息。[3]中也探究了回譯生成的偽句對與真實句對的比例如何影響性能。

由於比賽規則不能用額外的數據,所以我只能嘗試用現有的target端數據再做一遍回譯,生成了大概600w偽平行句對,加入原訓練語料。性能下降了。觀察了一下數據,發現雜訊還是有點大了。最關鍵的還是要有額外的target端數據啊。但是也有些論文會用加雜訊的方法(隨機替換、mask、打亂語序),擴充語料預訓練模型參數。這個嘗試失敗的原因難以確定,不過回譯出來的數據相比加雜訊的方法變動更大是可以確定的。

5 Document Level Context

本次比賽的數據是有篇章上下文的,前期的實驗沒有考慮利用這個信息。Improving the Transformer Translation Model with Document-Level Context[4] 提出一個利用上文信息提升翻譯質量的方法,是在Transformer模塊之外引入一個表徵上文信息的模塊,將上文信息傳到encoder和decoder中,實驗提升非常明顯。但是代碼是基於清華的機器翻譯庫THUMT,所以在這個庫上面又跑了一些Transformer模型,用默認參數跑出來的baseline在dev集上大概是31.2bleu,test集上30.2bleu,相比於t2t,這個庫訓出來的模型泛化性能差一些,不過也可能是因為用了Bpe編碼。引入Context後dev集上最高能到32.6bleu,提升還是挺高的,但是不同步數的checkpoint結果波動很大,在32.0~32.6區間。

接下來就是調參,其中有提升的trick是,batchsize擴大到2.4w(設置update_cycle=4),學習率後期調小,最後Base模型在dev上能到32.0。用dropout沒有提升,很奇怪。嘗試增大模型深度和寬度,用big,middle沒有提升。然後在dev集上finetune(batch_size=6000,單卡200步左右),加入context模塊dev集能到33.2bleu。

THUMT提供了ensemble的代碼,時間關係我只ensemble了不同階段的checkpoint,ensemble的方法可參考面向神經機器翻譯的集成學習方法。另外,提升性能的思路這個文檔裏的Refine部分總結的很全面Neural Machine Translation[5]。

Context模塊應該還有提升空間,它的波動較大,可以在觀測到的最優結果附近再搜索一下,因為快到截止時間時訓出一個dev集上33.4的結果,來不及提交。

6 Unsupervised Neural Machine Translation

這部分只是一個探索,沒有訓出好的結果,也沒有時間把它與有監督的模型進行融合。但是最感興趣的還是這部分。論文見Phrase-Based & Neural Unsupervised Machine Translation[6]。相關文章的解讀見Notes on Unsupervised Neural Machine Translation。

[6]的方法對於距離較遠的語言之間,需要先用一個質量較好的雙語詞典做初始化。所以我先用MUSE在訓練語料上訓了一個詞典,然後用兩個語言的詞向量空間初始化[6]中的模型。英中bleu訓到8.x。

因為考慮到無監督的方法會用對偶學習的套路生成一些額外的數據訓練模型,所以感覺結合有標註的訓練語料可能會得到更好的結果。雖然基礎模型都是用的Transformer, 但是總體結構還是有區別,目前還不知道如何把有監督得到的模型與無監督訓出的模型進行融合。

7 GAN/RL in NMT

這部分也挺有意思,不過沒時間嘗試。我們在評估翻譯質量的時候是看預測結果與標準句子之間的單詞匹配程度,但是有很多同義詞存在,即使單詞匹配程度不好,意思也可能非常相近,所以現在的訓練目標函數並不是很好。而用一個判別器來給預測結果打分可能會改善這個問題。一個比較好的解讀見:Where GAN/RL meets NMT

還有一個基於Transformer,結合RL做機器翻譯的論文A Study of Reinforcement Learning for Neural Machine Translation代碼RL4NMT。

推薦閱讀:

相關文章