本篇總結神經機器翻譯的實踐中,較為基礎的最佳實踐。
應該使用哪個模型作為基線
Transformer是2017年發布的模型,即使到2020年仍然是比較好的基線模型,大熱的BERT就是其升級版。
代碼地址
這里實際推薦比較使用Fairseq指定arch為Transformer,按照官方教程直接就可以跑起來。為了便於理解和快速使用Fairseq,也可以瀏覽一些中文博客:利用Fairseq訓練新的機器翻譯模型 - 冬色 - 博客園,Fairseq-快速可擴展的序列建模工具包 - 冬色 - 博客園等。
Fairseq實際是序列建模工具包,包含很多模型,較為復雜。對於初學者而言,顯得較為笨重,如果只是希望了解下Transformer,快速地跑起來,可以用一些專門實現Transformer的庫。平時如果用到了MultiHead Attention這些模塊,也可以從這個庫中直接復制過去使用。
論文地址
Vaswani A, Shazeer N, Parmar N, et al. Attention is all you need[C]//Advances in Neural Information Processing Systems. 2017: 5998-6008.
解讀文章
Transformer影響力比較大,至今已有10k+的引用量,解讀文章更是數不勝數。
有哪些較好的工具包
使用機器翻譯工具包,可以省去實驗中很多繁瑣細節的實現,比如數據裝載、日志統計、經典模塊的使用等。注意,所有工具包都有一定的學習成本。
如果熟悉Pytorch較為推薦,Pytorch官方FAIR推出的框架。各個模塊解耦,大量采用注冊機制,代碼可讀性尚可。顯存占用經過優化,計算效率高。
如果熟悉Tensorflow較為推薦,Tensorflow官方Google推出。
同時支持Pytorch和Tensorflow,官方地址:OpenNMT。
有哪些經過時間檢驗的技巧
標簽平滑(Label Smoothing)
標簽平滑適用於在分類問題中,類別數較多的情況下,防止過擬合,本質是一種正則化策略,顯式添加噪音防止模型對自己的判斷過於自信。如果使用Fairseq,只需要在訓練時指定使用label_smoothed_cross_entropy
損失函數即可。一個簡單的例子:
python fairseq_cli/train.py <DataPath:str> --max-token <MaxToken:int> --arch transformer --criterion label_smoothed_cross_entropy --label-smoothing 0.1
平均模型參數
對訓練獲得的,一定訓練步數范圍內的模型參數進行平均,通常也會有提升,這一點有點像集成學習,但是集成學習一般是對模型的輸出結果進行投票或者平均,但是此處是直接對模型本身的參數進行平均。一般可以平均訓練末期的,最后10~30輪的模型參數。注意,在平均模型參數時,一定要對模型訓練充分,如果待平均的模型本身就沒有充分訓練,平均模型參數相反可能有害。
如果使用Fairseq,可以使用fairseq/scripts/average_checkpoints.py
,其它框架可以參照此代碼。
python scripts/average_checkpoints.py --inputs <CheckpointDir:str> --output <AvgCheckpointPath:str> --num-epoch-checkpoints 10
集束搜索(Beam Search)
相比於分類任務,生成任務通常是一個時間步一個時間步依次獲得,且之前時間步的結果影響下一個時間步,也即模型的輸出都是基於歷史生成結果的條件概率。在生成序列時,最暴力的方法當然是窮舉所有可能的序列,選取其中連乘概率最大的候選序列,但該方法很明顯計算復雜度過高。一個自然的改進想法是,每一個時間步都取條件概率最大的輸出,即所謂的貪心搜索(Greedy Search),但這種方法會丟棄絕大部分的可能解,僅關注當下無法保證最終得到的序列最優。集束搜索實際是這兩者的折中,簡言之,在每一個時間步,不再僅保留當前概率最高的1個輸出,而是每次都保留num_beams個輸出。
如上圖所示,圖中的num_beams=2,也就是說每個時間步都會保留到當前步為止,條件概率最優的2個序列。
如果使用fairseq,可以直接在生成時指定參數--beam
即可。一個例子:
python fairseq_cli/interactive.py <DataDir:str> --path <CheckpointPath:str> --batch_size 128 --beam 5
集束搜索在fairseq中的具體實現位於fairseq/search.py
中。
回譯
回譯是常見的數據增廣技術。使用平行語料訓練一個從目標語言到源語言的翻譯模型“反翻譯模型”,之后利用這個“反翻譯模型”將目標語言的文本翻譯到源語言,構造新的平行語料。將生成的新平行語料和原來的平行語料,全部作為源語言到目標語言翻譯模型的訓練數據。當然,“反翻譯模型”輸入的目標語言文本最好不在原來的平行語料中;如果確實沒有外部數據,只有這些語料,應該也會有提升,此時要特別注意數據要去重,模型要加噪。
數據清洗
雖然數據清洗很是老生常談,而且也並不局限於機器翻譯,但是優質的數據不管在哪個領域下都是有益的,大量數據證明,萬般技巧不如數據最重要。
機器翻譯中除了檢查平行語料正確性等,還需要額外注意以下幾點:
-
去重。對重復的平行語句直接刪除。
-
對源句子與目標句子長度比例進行檢測,當長度比超過一定的閾值時就將對應的平行語句對進行刪除。
-
使用giza++對訓練數據進行了對齊並獲得一份雙語詞典。使用獲得的雙語詞典可以對平行語料進行漏翻檢測,通常會對語料的漏翻程度進行打分,分值超過一定閾值時,直接刪除對應的語料。
數據量太小怎么辦
遷移學習(Transfer Learning)
首先訓練其它平行語料比較多的翻譯模型,然后以該翻譯模型作為初始值,利用少量的平行語料重新進行訓練,得到最終的機器翻譯模型。
B. Zoph , D. Yuret, J. May, and K. Knight,Transfer Learning for Low-Resource Neural Machine Translation , EMNLP 2016.
多任務學習
充分利用不同語種翻譯的相關性,采用共享相同的NMT參數同時學習多個翻譯任務。
此外,谷歌於2016年下半年提出的Zero-Shot翻譯方法,基於多語種共享的詞匯集,使用單個神經機器翻譯(NMT)模型在多種語言之間進行翻譯,除了提升訓練數據中包含的語種對之間互譯的翻譯質量之外,還能完成訓練數據中不包含的語言對之間的zero-shot翻譯。
Thang Luong, Quoc Le, Ilya Sutskever, Oriol Vinyals, and Lukasz Kaiser, Multi-task Sequence to Sequence Learning,ICLR 2016.
Melvin Johnson, Mike Schuster, Quoc V. Le, Maxim Krikun, Yonghui Wu, Zhifeng Chen, Nikhil Thorat, Fernanda B. Viégas, Martin Wattenberg, Greg Corrado, Macduff Hughes, and Jeffrey Dean. Google’s multilingual neural machine translation system: Enabling zero-shot translation.
對偶學習(Dual Learning)
機器翻譯中,可以利用對偶學習提升對無監督數據的利用。例如中英機器翻譯任務中,同時訓練中文到英文、英文到中文兩個翻譯模型,兩個模型互相提升,最終獲得較好的效果。
Di He, Yingce Xia, Tao Qin, Liwei Wang, Nenghai Yu, Tie-Yan Liu, and Wei-Ying Ma, Dual Learning for Machine Translation, NIPS 2016.
樞軸語言(Pivot Language)
如果希望獲得中文到法語的翻譯模型,但是中文到法語的平行語料較少,中文到英文、英文到法語的平行語料比較多,可以利用英文作為“樞軸語言”,在中文和法語之間作為橋接,訓練中英、英法兩個翻譯模型,最終完成中翻法的任務。
Yong Cheng, Qian Yang, Yang Liu, Maosong Sun, and Wei Xu. 2017. Joint Training for Pivot-based Neural Machine Translation. IJCAI 2017