統計的機械翻訳
ざっくり言うと、Google翻訳のように、
入力文から翻訳文を生成して出力してくれるシステムのこと
以下もうちょっと詳しく↓↓↓
コーパスから言語モデル、翻訳モデルを学習し、それらを利用して、
入力文に対して最も最適な翻訳候補を翻訳文として出力する
翻訳する原言語文を $f$ 、生成された翻訳候補文を $e$ 、最終的な翻訳結果を $\hat{e}$ とすると、
統計的機械翻訳は以下の式で表される
$$\hat{e} = {\mathop{\rm arg~max}_e} P(e|f)$$
上式は、ベイズの定理を用いて以下のように変形できる
$$\hat{e} = {\mathop{\rm arg~max}_e} P(e)P(f|e)$$
上式の $P(e)$ が言語モデル、 $P(f|e)$ が翻訳モデルを表す
言語モデル:翻訳候補文の言語らしさ、流暢さを評価する確率モデル
翻訳モデル:翻訳候補文の訳語としての正しさを評価する確率モデル
上式を見ると分かる通り、言語モデルは単言語コーパス、
翻訳モデルは対訳コーパスからそれぞれ学習される
統計的機械翻訳は、言語モデルと翻訳モデルの確率値をかけ合わせた値を
最大化するような $e$ を翻訳文として出力する
Moses
オープンソースの統計的機械翻訳システム
対訳コーパスを用いて言語モデルと翻訳モデルを学習し、統計的機械翻訳を実現
http://www.statmt.org/moses/
Mosesのインストール
インストール環境
CentOS7.2、sudo権限なしのマシンにインストール
インストールするもの
- Boost
- Moses
- GIZA++
予めBoostとMosesをインストールするディレクトリ(boost_dir, moses_dir)を作っておく
Boostのインストール
$ wget http://downloads.sourceforge.net/project/boost/boost/1.62.0/boost_1_62_0.tar.gz
$ tar zxvf boost_1_62_0.tar.gz
$ cd boost_1_62_0
$ ./bootstrap.sh
$ ./b2 -j16 --prefix=/path/to/boost_dir --libdir=/path/to/boost_dir/lib \
--layout=system link=static install || echo FAILURE
-j16の16は利用するコア数のため、マシンによって変更する必要あり
Mosesのインストール
$ git clone https://github.com/moses-smt/mosesdecoder.git
$ cd mosesdecoder
$ ./bjam -j16 --prefix=/path/to/moses_dir --with-boost=/path/to/boost_dir \
--install-scripts=/path/to/moses_dir/dist
-j16の16は利用するコア数のため、マシンによって変更する必要あり
GIZA++のインストール
$ git clone https://github.com/moses-smt/giza-pp.git
$ cd giza-pp
$ make
make後、必要なファイルをmoses_dirにコピー
$ cd path/to/moses_dir
$ mkdir tools
$ cp path/to/giza-pp/GIZA++-v2/GIZA++ path/to/giza-pp/GIZA++-v2/snt2cooc.out \
path/to/giza-pp/mkcls-v2/mkcls tools
以上でインストール完了
英日翻訳を試す
言語モデルの学習コーパスとして、ntcir7から50万文の日本語文(train500k.ja)、
翻訳モデルの学習コーパスとして、ntcir7から10万文の英日対訳文(train100k.{en/ja})、
翻訳モデルのチューニングコーパスとして、ntcir7から1,000文の英日対訳文(dev1000.{en/ja})、
テストコーパスとして、ntcir10から2,000文の英日対訳文(test2000.{en/ja})
以上のコーパスを用意
言語モデル学習
Mosesに標準で装備されているKenLMを使ってARPAファイルを作成
train500k.jaを用いて学習する
$ cd path/to/moses_dir
$ mkdir lm
$ cd lm
$ ../bin/lmplz -o 5 -S 80% < path/to/train500k.ja > output.arpa
-o:言語モデルのオーダー数、ここでは5を使う
-S:使用するメモリのパーセンテージ
その後、バイナリファイルを構築
$ ../bin/build_binary output.arpa output.bin
出来上がったoutput.binを言語モデルとして利用する
翻訳モデル学習
train100k.{en/ja}を用いて翻訳モデルを学習する
$ cd path/to/moses_dir
$ mkdir tm
$ cd tm
$ perl ../dist/training/train-model.perl -root-dir . \
-corpus path/to/train100k -f en -e ja \
-alignment grow-diag-final-and -reordering msd-bidirectional-fe \
-lm 0:5:path/to/moses_dir/lm/output.bin:0 \
-external-bin-dir path/to/moses_dir/tools --parallel
-corpus:拡張子抜きのコーパス名を指定する
-f:入力言語コーパスの拡張子
-e:出力言語コーパスの拡張子
-lm:中のパスは上で作った言語モデルのフルパス
-external-bin-dir:moses_dirにコピーしたGIZA++のファイルが入っているディレクトリをフルパス指定
--parallel:並行処理、約2倍早くなる(CPUコア数2以上の場合)
その他はおまじないだと思ってください(笑)
翻訳モデルの学習が終わると、tm/model内にmoses.iniができている
チューニング、翻訳の前にmoses.iniの以下の部分を変更する
- [distortion-limit] を -1 に変更
- SRILM name= を KENLM name= に変更
翻訳モデルのチューニング(オプション)
※この作業は飛ばしても翻訳ができます
Minimum Error Rate Trainingで翻訳モデルをチューニング
チューニングコーパスにdev1000.{en/ja}を利用
$ cd path/to/moses_dir/
$ mkdir tune
$ cd tune
$ perl ../dist/training/mert_moses.pl path/to/dev1000.en path/to/dev1000.ja \
../bin/moses ../tm/model/moses.ini --working-dir .
tuneディレクトリ内にチューニングされたmoses.iniができている
翻訳実験
test2000.enを日本語に翻訳する
$ cd path/to/moses_dir
$ mkdir test
$ cd test
$ ../bin/moses -config path/to/moses.ini -input-file path/to/test2000.en > result2000.ja
翻訳結果であるresult2000.jaとtest2000.jaからBLEUを測定する
BLEUの値が高いほど翻訳精度が高い
$ cd path/to/moses_dir/test
$ perl ../dist/generic/multi-bleu.perl path/to/test2000.ja < result2000.ja
BLEU = 20.43, 62.9/30.1/15.5/7.8 (BP=0.933, ratio=0.935, hyp_len=70265, ref_len=75128)
チューニングなしの場合とありの場合のBLEUを比較した結果は以下の表になる
チューニングなし | チューニングあり | |
---|---|---|
BLEU | 20.43 | 22.82 |
チューニングありの方がBLEUが高い
チューニングが翻訳精度向上に効いている
もし言語モデルを変更して実験を再度行いたい場合は、
moses.iniの KENLM name= の path= 以下を
新しく使用する言語モデルの名前に変更(フルパス)すればOK
(再度翻訳モデルを学習する必要はなし
ただしコーパスを変えて翻訳モデルを学習し直したい場合は別)