Travatarの学習

Travatarは、原言語の構文解析を行ってから翻訳を行うtree-to-string翻訳に強いツールキットです。 原言語の構文情報を使うことで、より正しい並べ替えを行うことができ、英日・日英のように語順が大きくことなる言語対において、高い翻訳精度を実現できます。 本ページはALAGINの2015年自然言語処理セミナーで配布されたツール群を使ってTravatarを学習するチュートリアルです。 ALAGINのツール群に依存しないチュートリアルもTravatarのページにあり、今後もTravatarの最新版とともに更新されます。

パッケージの入手

プログラムはバイナリパッケージで

~

(ホームディレクトリ)に展開してあるものとします。

~/alagin2015_binary.x86_64-Cygwin

というディレクトリがあることを確認してください。 ファイルパスはWindows(Cygwin)の場合で書いています。適宜"Cygwin"を"Linux"や"Darwin12"等に読み替えてください。 KFTTのデータと、「KFTT構文解析データ」も

~

に展開してあるものとします。

~/kftt-data-1.0
~/kftt-syntax-data

というディレクトリがあることを確認してください。 パッケージの置き場所は一例です。異なる場所に置いても、次の環境変数の設定を正しく行えば問題ありません。

環境の準備

以下の処理のときに長いファイルパスを入力するのは面倒なので、環境変数を設定して分かりやすくします。 バイナリパッケージの場所を ALAGIN_HOME という環境変数に設定します。

export ALAGIN_HOME=~/alagin2015_binary.x86_64-Cygwin

その中で特にスクリプトの場所は別の名前 SCRIPT_DIR として設定しておく必要があります。

export SCRIPT_DIR=${ALAGIN_HOME}/script

KFTTのデータの場所をKFTT_DATAという環境変数に設定します。

export KFTT_DATA=~/kftt-data-1.0

(Macの方のみ) DYLD_LIBRARY_PATH という環境変数の設定が必要です。

export DYLD_LIBRARY_PATH=$ALAGIN_HOME/lib:$ALAGIN_HOME/gcc/lib:$ALAGIN_HOME/gcc/lib64:${DYLD_LIBRARY_PATH}

環境変数は $ALAGIN_HOME、$KFTT_DATA のように$をつけて参照することができます。${ALAGIN_HOME}のように{}をつけることもできます。このページでは{}をつけて環境変数の名前が分かりやすいようにしています。

テスト文の構文解析と翻訳

まず、構文解析をテストします。 構文解析には、下記のコマンドの通り、Ckylarkというツールを利用します。

echo "He is a student ." | $ALAGIN_HOME/bin/ckylark --add-root-tag --model $ALAGIN_HOME/share/ckylark/wsj

形式は少し分かりにくいですが、各句の周りに括弧がついており、開け括弧の後に句のラベルがついているPenn Treebank形式の出力が出てくるはずです。

(ROOT (S (NP (PRP He)) (VP (VBZ is) (NP (DT a) (NN student))) (. .)) )

これを可視化すると、このような木を表しています。

次はこの構文解析結果をTravatarに渡します。 Travatarを動かす為に、まずTravatarのモデルを構築します。

$ALAGIN_HOME/sample/testsuite.sh

このモデルを使って、テスト分の構文解析と翻訳を以下の通り、2つのパイプ(「|」)で順につなげます:

echo "He is a student ." | $ALAGIN_HOME/bin/ckylark --add-root-tag --model $ALAGIN_HOME/share/ckylark/wsj | $ALAGIN_HOME/bin/travatar -config_file $ALAGIN_HOME/sample/travatar/model/travatar.ini

データの準備

次に、データをTravatarが使える形へと前処理を行う必要があります。 つまり、入力文の構文解析と、出力文の単語分割を行います。 まず、データディレクトリを作成します。

mkdir data

トークン化

まずは、トークン化(つまり単語分割)を行います。 英語に関しては、Travatarに含まれているトークン化プログラムを使います。

$ALAGIN_HOME/bin/tokenizer < $KFTT_DATA/data/orig/kyoto-train.en > data/kyoto-train.tok.en

ここで、data/kyoto-train.tok.enを開いてみれば、単語はトークン化されている(つまり単語と句読点の間にスペースが入っている等)ことが分かります。 同じ処理をkyoto-devkyoto-testに対して行います。

$ALAGIN_HOME/bin/tokenizer < $KFTT_DATA/data/orig/kyoto-dev.en > data/kyoto-dev.tok.en
$ALAGIN_HOME/bin/tokenizer < $KFTT_DATA/data/orig/kyoto-test.en > data/kyoto-test.tok.en

次に、日本語をKyTeaでトークン化します。 -notags-wsconst Dを追加していますが、これは品詞付与を行わなず、数字の分割を抑制するためです。

$ALAGIN_HOME/bin/kytea -model $ALAGIN_HOME/share/kytea/model.bin -notags -wsconst D < $KFTT_DATA/data/orig/kyoto-train.ja > data/kyoto-train.tok.ja

data/kyoto-train.tok.jaもきちんとトークン化されていることを確認してから、同じ処理をkyoto-devkyoto-testに対して行います。

$ALAGIN_HOME/bin/kytea -model $ALAGIN_HOME/share/kytea/model.bin -notags -wsconst D < $KFTT_DATA/data/orig/kyoto-dev.ja > data/kyoto-dev.tok.ja
$ALAGIN_HOME/bin/kytea -model $ALAGIN_HOME/share/kytea/model.bin -notags -wsconst D < $KFTT_DATA/data/orig/kyoto-test.ja > data/kyoto-test.tok.ja

学習データから長文の削除

学習データに非常に長い文が含まれる時、構文解析や単語アライメントに多くの時間がかかったり、失敗したりする原因になります。 長文をデータから削除するために、Travatarのclean-corpus.plスクリプトを使います。 (-max_lenの値を変えることで、文の最大長を調整することができます。)

$SCRIPT_DIR/train/clean-corpus.pl -max_len 60 data/kyoto-train.tok.en data/kyoto-train.tok.ja data/kyoto-clean.tok.en data/kyoto-clean.tok.ja

また、通常は翻訳システムを作成する際になるべく多くの学習データを使いたいところですが、今回はチュートリアルなので、学習時間短縮のらめに、最初の2万文のみを使うことにします。

head -20000 < data/kyoto-clean.tok.en > data/kyoto-head.tok.en
head -20000 < data/kyoto-clean.tok.ja > data/kyoto-head.tok.ja

以降のコマンドでkyoto-headではなく、kyoto-cleanを利用すると、全データでシステムを学習することが可能です。

構文解析

次は、原言語文に構文情報を付与する構文解析を行います。 ただ、構文解析は多くの時間がかかるので、今回のチュートリアルで省きます。 参考までに、構文解析を行うとしたら、下記の通りのコマンドで、Ckylarkを学習、開発、テストのデータに対して動かすことができます。

$ALAGIN_HOME/bin/ckylark --add-root-tag --model $ALAGIN_HOME/share/ckylark/wsj < data/kyoto-head.tok.en > data/kyoto-head.parse.en
$ALAGIN_HOME/bin/ckylark --add-root-tag --model $ALAGIN_HOME/share/ckylark/wsj < data/kyoto-dev.tok.en > data/kyoto-dev.parse.en
$ALAGIN_HOME/bin/ckylark --add-root-tag --model $ALAGIN_HOME/share/ckylark/wsj < data/kyoto-test.tok.en > data/kyoto-test.parse.en

今回は単純にkftt-syntax-dataというディレクトリからデータをコピーします。

cp kftt-syntax-data/*.parse.en data/

言語モデルの学習

他の統計的機械翻訳システムと同様に、Travatarは出力の流暢性を担保するための言語モデル(LM)を利用します。 言語モデルを学習するために、まずディレクトリを作成します。

mkdir lm

次に、出力言語のデータを小文字化します。

$SCRIPT_DIR/tree/lowercase.pl < data/kyoto-train.tok.ja > data/kyoto-train.toklow.ja

これに対して、Travatarと同梱されているlmplzを実行します。

$ALAGIN_HOME/bin/lmplz -o 5 < data/kyoto-train.toklow.ja > lm/kyoto-train.ja.arpa

出来上がった言語モデルファイルを、読み込みの効率化のために、バイナリ化します。

$ALAGIN_HOME/bin/build_binary -i lm/kyoto-train.ja.arpa lm/kyoto-train.ja.blm

翻訳モデルの学習

翻訳モデルの学習には、構文解析済みの学習データが必要ですので、構文解析が終わるまで待ちます。 学習データの構文解析が終わったら、まず解析結果に対して小文字化を行います。 (こうすることにより、大文字と小文字の単語を別の単語として扱わないようにします。)

$SCRIPT_DIR/tree/lowercase.pl < data/kyoto-head.parse.en > data/kyoto-head.parselow.en
$SCRIPT_DIR/tree/lowercase.pl < data/kyoto-head.tok.ja > data/kyoto-head.toklow.ja

同じ処理をkyoto-devkyoto-testに対して行います。

$SCRIPT_DIR/tree/lowercase.pl < data/kyoto-dev.parse.en > data/kyoto-dev.parselow.en
$SCRIPT_DIR/tree/lowercase.pl < data/kyoto-dev.tok.ja > data/kyoto-dev.toklow.ja
$SCRIPT_DIR/tree/lowercase.pl < data/kyoto-test.parse.en > data/kyoto-test.parselow.en
$SCRIPT_DIR/tree/lowercase.pl < data/kyoto-test.tok.ja > data/kyoto-test.toklow.ja
データの準備が終わったら、Travatarの学習スクリプトを動かします。 学習スクリプトは、構文解析済みの英語、トークン化済みの日本語、言語モデル、という3通りの入力を受け取ります。 GIZA++とTravatarのディレクトリを指定し、学習済みのモデルファイルが出力されるディレクトリwork_dirを指定します。 学習は時間がかかりますので、&を追加することで背景で動かして、nohupを先頭につけます。 また,並列処理が可能なパソコンを使っている場合は、スレッド数を-threadsコマンドを指定すると、学習が早く終わります。 (特に、下記の通り2以上の数字を指定すると早くなります。)

nohup $SCRIPT_DIR/train/train-travatar.pl -work_dir train -lm_file lm/kyoto-train.ja.blm -src_file data/kyoto-head.parselow.en -trg_file data/kyoto-head.toklow.ja -travatar_dir $ALAGIN_HOME -bin_dir $ALAGIN_HOME/bin -threads 2 &> train.log &

学習が終わり次第、train.logを見て、学習が無事に終わったことを確認します。 無事に終了した場合は最後に「Finished training!」が書いてあり、何か問題があった場合はだいたいエラーがあります。

チューニング

上記の学習プロセスは翻訳モデルを作成し、一応訳を生成できるようになります。 しかし、良い翻訳精度を実現するために、翻訳モデル・言語モデル・単語ペナルティなどの重みを最適化するチューニングが必要です。

重みのチューニングをmert-travatar.plスクリプトで行います。 チューニングの際に、開発データ(kyoto-dev)を何回か翻訳する必要があるので、時間がそこそこかかります。

nohup $SCRIPT_DIR/mert/mert-travatar.pl -travatar-config train/model/travatar.ini -nbest 100 -src data/kyoto-dev.parselow.en -ref data/kyoto-dev.toklow.ja -travatar-dir $ALAGIN_HOME -working-dir tune &> tune.log &

これも、1分以内と早く終了した場合は、問題がある可能性が高いので、tune.logを確認してください。 また、複数のコアを使ってチューニングを早くしたい場合は、-threads XXオプションを指定します。(XXは使いたいコア数です。)

また、チューニングも多くの時間がかかりますので、止めて先に進めたい場合は、まず下記のコマンドでプログラムを止めます:

killall travatar batch-tune

(「travatar」または「batch-tune」に対して、「そのプロセスはありません」というエラーは出るかもしれませんが、無視して問題ないです。) また、下記の通り、kftt-syntax-dataの中に、パラメータ調整済みのtravatar.iniファイルがありますので、これをtuneディレクトリにコピーします。

cp kftt-syntax-data/travatar.ini tune/

精度評価

チューニングが無事に終了すれば、最適化されたモデルはtune/travatar.iniに入っているはずです。 これを使って、評価用テキストkyoto-testを翻訳し、精度を評価します。 その前に、モデルファイルが大きくて多くのメモリを必要とするため、翻訳に必要ないルールをあらかじめ削除するようにフィルタリングをかけます。

mkdir test
$SCRIPT_DIR/train/filter-model.pl tune/travatar.ini test/filtered-test.ini test/filtered-test "$SCRIPT_DIR/train/filter-rt.pl -src data/kyoto-test.parselow.en"

ここで、最後の引数はフィルタリングに用いるコマンドです。 -srcオプションを、翻訳するファイルにします。 フィルタリングが終わり次第、翻訳を行います。 (前と同じく、-threads XXを追加することでスピードを向上させることができます。)

$ALAGIN_HOME/bin/travatar -config_file test/filtered-test.ini < data/kyoto-test.parselow.en > test/kyoto-test.out

最後に、翻訳の精度を、自動評価尺度を使って評価します。 参照文とシステム出力をmt-evaluatorプログラムに入れて、評価します。

$ALAGIN_HOME/bin/mt-evaluator -ref data/kyoto-test.toklow.ja test/kyoto-test.out

これでうまく行ったなら、BLEUが10-12、RIBESが56-58ぐらいの値になります。 また、中の文を見ると、何となく日本語になっていることが分かります。

精度比較

次は、Mosesの精度と比較しましょう。 Mosesのチュートリアルの際に出力した翻訳結果と、今回の結果を好きなエディタで開き、どのような文で翻訳結果が良くなっているか、どのような文で悪くなっているかを調べることで、両方のシステムの強みと弱みがある程度見えてきます。

構文木の影響

kftt-syntax-data/kyoto-example.parselow.enに、同じ文に対して2つの異なる翻訳結果が入っています。 具体的に、下記のような木がそれぞれ、1行目と2行目です。



下記のコマンドで2つの文を翻訳に入れて、結果の違いtお違いがあった理由を考察しましょう。

$ALAGIN_HOME/bin/travatar -config_file tune/travatar.ini < kftt-syntax-data/kyoto-example.parselow.en

ルールの閲覧

実際に翻訳に使われているルールを見てみましょう。 Travatarが抽出するルールに、品詞や句などの情報が付与されているので、この情報に基づいて種類別でルールを調べることができます。 例えば、名詞のタグは「nn」ですので、grepコマンドを使って「nn 」で始まるルールを探すと、英語の名詞を翻訳するルールを探すことができます。 (ここで「less」コマンドで閲覧していますが、「q」を押すと閲覧を終了できます)

gunzip -c train/model/rule-table.gz | grep '^nn ' | less

「nn」を「jj」(形容詞)、「vb」「vbd」「vbg」(それぞれ名詞の現在形、過去形、現在進行形)などに置き換えると別の種類のルールを見ることができます。また、下記のコマンドで、「過去形名詞で始まる動詞句(vp)」を閲覧することも可能です:

gunzip -c train/model/rule-table.gz | grep '^vp ( vbd ' | less