Wednesday, August 19, 2015

Moses: 基本Baseline流程

這篇文章總結一下Moses的基本Baseline流程吧,可能有點長...XD
Moses目前的版本已經到3.0了,與前幾個版本有什麼區別就自己搜索吧!

安裝方法可參考︰Development » GetStarted
Baseline system可參考︰Moses » BaselineWAT Baseline system
使用手冊下載︰Moses Manual
基本上所有模型和簡單工具使用方法︰AMTA2014Proceedings

好吧,上面的連結其實解釋得有點詳細,簡單的步驟看下面吧!

安裝 Installation

首先是安裝Linux環境所需要的東西︰
[root@mkytap root]# sudo apt-get install default-jre g++ git subversion automake libtool zlib1g-dev libboost-all-dev libbz2-dev liblzma-dev python-dev libtcmalloc-minimal4

第二個是Moses decoder (用作訓練翻譯模型,裏面也有很多有用的program)
[root@mkytap root]# git clone https://github.com/moses-smt/mosesdecoder.git
[root@mkytap root]# cd mosesdecoder/
[root@mkytap root]# ./bjam -j4

然後是Giza++ (用作提取對齊信息)
[root@mkytap root]# cd ~/
[root@mkytap root]# git clone https://github.com/moses-smt/giza-pp.git
[root@mkytap root]# cd ~/giza-pp
[root@mkytap root]# make
[root@mkytap root]# cd ~/mosesdecoder
[root@mkytap root]# mkdir tools
[root@mkytap root]# cp ~/giza-pp/GIZA++-v2/GIZA++ ~/giza-pp/GIZA++-v2/snt2cooc.out ~/giza-pp/mkcls-v2/mkcls tools

OK了,基本的東西已經裝好了,接下來跑Baseline吧!

訓練翻譯模型當然要先下載數據啦~以下是Moses官方Baseline語料庫...這個是法文到英文的翻譯系統例子...
[root@mkytap root]# mkdir ~/moses_baseline_system
[root@mkytap root]# cd ~/moses_baseline_system
[root@mkytap root]# wget http://www.statmt.org/wmt13/training-parallel-nc-v8.tgz
[root@mkytap root]# tar zxvf training-parallel-nc-v8.tgz
[root@mkytap root]# wget http://www.statmt.org/wmt12/dev.tgz
[root@mkytap root]# tar zxvf dev.tgz

我並不建議使用官方網頁上的路徑,因為不利於跑多個實驗XP..
所以我重新定義了語料裏面的路徑,我的路徑設定為︰
Path setting
Moses directory~/mosesdecoder/ (預設)
Giza bin directory~/mosesdecoder/tools/ (預設)
Experiment directory~/moses_baseline_system/
Language model directory~/moses_baseline_system/corpus/lm/
Training set directory~/moses_baseline_system/corpus/train/
Development set directory~/moses_baseline_system/corpus/dev/
Testing set directory~/moses_baseline_system/corpus/test/

路徑重設的命令是︰
[root@mkytap root]# mkdir -p ~/moses_baseline_system/corpus
[root@mkytap root]# cd ~/moses_baseline_system/corpus
[root@mkytap root]# mkdir train dev test lm
[root@mkytap root]# cp ../training/*.fr-en.* train
[root@mkytap root]# cp ../dev/news-test2008.en ../dev/news-test2008.fr dev
[root@mkytap root]# cp ../dev/newstest2011.en ../dev/newstest2011.fr test
[root@mkytap root]# cp ../training/*.fr-en.en lm

預處理 Preprocessing

第一步就是分詞(Tokenisation)
分詞會把每個單詞與符號分開,但不會影響小數、名字縮寫等等(詳細可看~/mosesdecoder/script/share/nonbreaking_prefixes/目錄下的相關語言檔案)。中文分詞可以用ANSJ SegmenterStanford Segmenter結巴分詞等等,現成的Ansj JAR檔可以在這裏下載使用。其他語言上網搜搜吧~~
另外,這一步會把敏感符號轉換成Unicode,例如(")會變成(")等等。這很重要喔,如果不換成Unicode在翻譯時可能會報錯!
# 格式: ./tokenizer.perl (-l [en|de|...]) (-threads 4) < textfile > tokenizedfile
# -l 後面接著是語言: 預設只支持en, de, fr, 和it
# textfile 是輸入檔案
# tokenizedfile 是輸出檔案,裏面是已分詞的內容

# 訓練集 (training set) 的處理
[root@mkytap root]# ~/mosesdecoder/scripts/tokenizer/tokenizer.perl -l en < ~/moses_baseline_system/corpus/train/news-commentary-v8.fr-en.en > ~/moses_baseline_system/corpus/train/news-commentary-v8.fr-en.tok.en
[root@mkytap root]# ~/mosesdecoder/scripts/tokenizer/tokenizer.perl -l fr < ~/moses_baseline_system/corpus/train/news-commentary-v8.fr-en.fr > ~/moses_baseline_system/corpus/train/news-commentary-v8.fr-en.tok.fr

# 開發集 (development set) 的處理
[root@mkytap root]# ~/mosesdecoder/scripts/tokenizer/tokenizer.perl -l en < ~/moses_baseline_system/corpus/dev/news-test2008.en > ~/moses_baseline_system/corpus/dev/news-test2008.tok.en
[root@mkytap root]# ~/mosesdecoder/scripts/tokenizer/tokenizer.perl -l fr < ~/moses_baseline_system/corpus/dev/news-test2008.fr > ~/moses_baseline_system/corpus/dev/news-test2008.tok.fr

# 測試集 (testing set) 的處理
[root@mkytap root]# ~/mosesdecoder/scripts/tokenizer/tokenizer.perl -l en < ~/moses_baseline_system/corpus/test/newstest2011.en > ~/moses_baseline_system/corpus/test/newstest2011.tok.en
[root@mkytap root]# ~/mosesdecoder/scripts/tokenizer/tokenizer.perl -l fr < ~/moses_baseline_system/corpus/test/newstest2011.fr > ~/moses_baseline_system/corpus/test/newstest2011.tok.fr

# 語言模型 (language model) 的處理
[root@mkytap root]# ~/mosesdecoder/scripts/tokenizer/tokenizer.perl -l en < ~/moses_baseline_system/corpus/lm/news-commentary-v8.fr-en.en > ~/moses_baseline_system/corpus/lm/news-commentary-v8.fr-en.tok.en

第二步就是訓練Truecase model
它會將詞的大小寫換成出現頻率較高的那一個...例如句子(He is NICE person in NASA !)會變成(he is nice person in NASA !)
# 訓練英文和法文的truecase model
# 格式: train-truecaser.perl --model truecaser --corpus cased [--possiblyUseFirstToken]
# --model 後面是這一步輸出的truecase model
# --corpus 後面是輸入的文件(單一語言)
[root@mkytap root]# ~/mosesdecoder/scripts/recaser/train-truecaser.perl --model ~/moses_baseline_system/corpus/truecase-model.en --corpus ~/moses_baseline_system/corpus/train/news-commentary-v8.fr-en.tok.en
[root@mkytap root]# ~/mosesdecoder/scripts/recaser/train-truecaser.perl --model ~/moses_baseline_system/corpus/truecase-model.fr --corpus ~/moses_baseline_system/corpus/train/news-commentary-v8.fr-en.tok.fr

# 把truecase model 用在對應語言的文件中
# 格式: truecaser.perl --model truecaser [-b] < in > out
# --model 後面是輸入上面訓練出來的truecase model
# in 是輸入檔案
# out 是輸出檔案

# use truecase model for training set
[root@mkytap root]# ~/mosesdecoder/scripts/recaser/truecase.perl --model ~/moses_baseline_system/corpus/truecase-model.en < ~/moses_baseline_system/corpus/train/news-commentary-v8.fr-en.tok.en > ~/moses_baseline_system/corpus/train/news-commentary-v8.fr-en.true.en
[root@mkytap root]# ~/mosesdecoder/scripts/recaser/truecase.perl --model ~/moses_baseline_system/corpus/truecase-model.fr < ~/moses_baseline_system/corpus/train/news-commentary-v8.fr-en.tok.fr > ~/moses_baseline_system/corpus/train/news-commentary-v8.fr-en.true.fr

# use truecase model for development set
[root@mkytap root]# ~/mosesdecoder/scripts/recaser/truecase.perl --model ~/moses_baseline_system/corpus/truecase-model.en < ~/moses_baseline_system/corpus/dev/news-test2008.tok.en > ~/moses_baseline_system/corpus/dev/news-test2008.true.en
[root@mkytap root]# ~/mosesdecoder/scripts/recaser/truecase.perl --model ~/moses_baseline_system/corpus/truecase-model.fr < ~/moses_baseline_system/corpus/dev/news-test2008.tok.fr > ~/moses_baseline_system/corpus/dev/news-test2008.true.fr

# use truecase model for testing set
[root@mkytap root]# ~/mosesdecoder/scripts/recaser/truecase.perl --model ~/moses_baseline_system/corpus/truecase-model.en < ~/moses_baseline_system/corpus/test/newstest2011.tok.en > ~/moses_baseline_system/corpus/test/newstest2011.true.en
[root@mkytap root]# ~/mosesdecoder/scripts/recaser/truecase.perl --model ~/moses_baseline_system/corpus/truecase-model.fr < ~/moses_baseline_system/corpus/test/newstest2011.tok.fr > ~/moses_baseline_system/corpus/test/newstest2011.true.fr

# use truecase model for language model
[root@mkytap root]# ~/mosesdecoder/scripts/recaser/truecase.perl --model ~/moses_baseline_system/corpus/truecase-model.en < ~/moses_baseline_system/corpus/lm/news-commentary-v8.fr-en.tok.en > ~/moses_baseline_system/corpus/lm/news-commentary-v8.fr-en.true.en

第三步就是清除過長和過短的句子,要注意的就是只允許在training set 執行喔。這裏是只保留長度1至80(包括80)的句子。
# 輸入檔案是 news-commentary-v8.fr-en.true.fr 和 news-commentary-v8.fr-en.true.en
# 輸出檔案是 news-commentary-v8.fr-en.clean.fr 和 news-commentary-v8.fr-en.clean.en
# 保留句子長到為1至80(包括80)

[root@mkytap root]# ~/mosesdecoder/scripts/training/clean-corpus-n.perl ~/moses_baseline_system/corpus/train/news-commentary-v8.fr-en.true fr en ~/moses_baseline_system/corpus/train/news-commentary-v8.fr-en.clean 1 80

訓練 Training

語言模型(Language model)是統計詞一起出現的概率,例如(I am)的概率是0.99,而(I are)的概率是0.00001之類的。以下訓練語句是統計出一個字至三個字的概率,又稱3-grams的語言模型。
訓練語句如下,這裏用的是KenLM,大約1~2分鐘︰
# -o 後面代表需要多少元的語言模型
# news-commentary-v8.fr-en.true.en 是輸入檔案
# news-commentary-v8.fr-en.lm.en 是輸出檔案,裏面包括詞與詞相連的概率
[root@mkytap root]# ~/mosesdecoder/bin/lmplz -o 3 < ~/moses_baseline_system/corpus/lm/news-commentary-v8.fr-en.true.en > ~/moses_baseline_system/corpus/lm/news-commentary-v8.fr-en.lm.en

# news-commentary-v8.fr-en.lm.en 是輸入檔案
# news-commentary-v8.fr-en.blm.en 是輸出檔案,輸出二進制的語言模型
[root@mkytap root]# ~/mosesdecoder/bin/build_binary ~/moses_baseline_system/corpus/lm/news-commentary-v8.fr-en.lm.en ~/moses_baseline_system/corpus/lm/news-commentary-v8.fr-en.blm.en

翻譯模型(Translation model)訓練如下,大約2小時︰
# -root-dir 後面是生成的模型目錄
# -corpus 後面是訓練語料的名字,注意的是檔案名稱沒有en或fr
# -f fr -e en 這裏fr和en是代表輸入語言和輸出語言,例如這裏就是fr翻譯成en的模型
# -alignment 後面是對齊的算法設定
# -reordering 後面是重序的算法設定
# -lm 0:3:LMFILE:9 這裏0:3代表三元的語言模型,9是代表這是使用KenLM
# -external-bin-dir 後面是第三方工具的目錄
[root@mkytap root]# ~/mosesdecoder/scripts/training/train-model.perl -root-dir ~/moses_baseline_system/translation_model -corpus ~/moses_baseline_system/corpus/train/news-commentary-v8.fr-en.clean -f fr -e en -alignment grow-diag-final-and -reordering msd-bidirectional-fe -lm 0:3:$HOME/moses_baseline_system/corpus/lm/news-commentary-v8.fr-en.blm.en:9 -external-bin-dir ~/mosesdecoder/tools

參數優化(Tuning translation model)其實是調整moses.ini後面的參數,從而提升翻譯結果,由於算法是隨機始值,所以未必一定就達到最優喔!~
訓練語句如下,需時4小時左右吧(這部份很重要,但真的很久Orz)︰

# news-test2008.true.frnews-test2008.true.en是輸入文件(開發集)
# translation_model/model/moses.ini 是在訓練翻譯模型時產生出來的參數設定文件
# --mertdir 後面是mosesdecoder的執行文件目錄
# --working-dir 這一步的生成的模型目錄
[root@mkytap root]# ~/mosesdecoder/scripts/training/mert-moses.pl ~/moses_baseline_system/corpus/dev/news-test2008.true.fr ~/moses_baseline_system/corpus/dev/news-test2008.true.en ~/mosesdecoder/bin/moses ~/moses_baseline_system/translation_model/model/moses.ini --mertdir ~/mosesdecoder/bin/ --working-dir ~/moses_baseline_system/translation_model/mert-work
上面的命令可以在後面加上--decoder-flags="-threads 4",這樣可以開啓4個線程來加速這一步。

註: 語料是15萬,句子越多需時越長


測試 Testing

由於訓練出來的模型大小會很大(上面的例子就生成了1.3GB的翻譯模型)..
當句子數量越多的時候需要的RAM會越多...因此基本上會先移除不需要的那些rules︰
# filtered-newstest2011 是這一步的生成的文件目錄
# translation_model/mert-work/moses.ini 是之前生成的模型目錄中的參數設定文件
# newstest2011.true.fr 這個是要在測試時使用的文件,它會針對這個文件做移除
[root@mkytap root]# ~/mosesdecoder/scripts/training/filter-model-given-input.pl ~/moses_baseline_system/translation_model/filtered-newstest2011 ~/moses_baseline_system/translation_model/mert-work/moses.ini ~/moses_baseline_system/corpus/test/newstest2011.true.fr

上面運行完成後會生成這個目錄︰~/moses_baseline_system/translation_model/filtered-newstest2011,然後就可以用它來翻譯testing set了
# translation_model/filtered-newstest2011/moses.ini 是之前生成的模型目錄中的參數設定文件
# newstest2011.true.fr 這個是輸入文件
# newstest2011.translated.en 這個是輸出文件
[root@mkytap root]# ~/mosesdecoder/bin/moses -f ~/moses_baseline_system/translation_model/filtered-newstest2011/moses.ini < ~/moses_baseline_system/corpus/test/newstest2011.true.fr > ~/moses_baseline_system/translation_model/newstest2011.translated.en

最後就可以測試這個翻譯結果的質量如何了︰
# -lc 是統一為小寫字符
# newstest2011.true.en 是輸入文件
# newstest2011.translated.en 是輸出文件
[root@mkytap root]# ~/mosesdecoder/scripts/generic/multi-bleu.perl -lc ~/moses_baseline_system/corpus/test/newstest2011.true.en < ~/moses_baseline_system/translation_model/newstest2011.translated.en

Reference:  Development » GetStartedMoses » Baseline

No comments: