はじめに
本記事は言語処理100本ノックの解説です。
100本のノックを全てこなした記録をQiitaに残します。
使用言語はPythonです。
今回は第10章: 機械翻訳(98. ドメイン適応)の解答例をご紹介します。
98. ドメイン適応
Japanese-English Subtitle Corpus (JESC)やJParaCrawlなどの翻訳データを活用し,KFTTのテストデータの性能向上を試みよ.
準備
fairseqを入れます。
$ git clone https://github.com/pytorch/fairseq
$ pip install --editable fairseq/
分かち書きをするためにMecabを入れます。
$ pip install mecab-python3 unidic
$ python -m unidic download
データの作成
Japanese-English Subtitle Corpus (JESC)を訓練データに追加して学習をします。そのために以下のコードでJESCの日本語を分かち書きにして、KFTTのデータとマージします。
import pandas as pd
import MeCab
m = MeCab.Tagger("-Owakati")
def Wakachi(text):
w_text = m.parse(text)
w_text = w_text.replace(" \n", "")
return w_text
def MakeDataset(source):
df = pd.read_table("[PATH]/JESC/split/{}".format(source), names=("English", "Japanese"))
df["Japanese"].apply(Wakachi).to_csv("[PATH]/Source-JESC/JESC-{}.ja".format(source), header=False, index=False)
df["English"].to_csv("[PATH]/Source-JESC/JESC-{}.en".format(source), header=False, index=False)
MakeDataset("test")
MakeDataset("dev")
MakeDataset("train")
def MargeDataset(name):
!cat "[PATH]/Source-JESC/JESC-"$name".ja" "[PATH]/sorce/kyoto-"$name".ja" > "[PATH]/Source-98/Source98-"$name".ja"
!cat "[PATH]/Source-JESC/JESC-"$name".en" "[PATH]/sorce/kyoto-"$name".en" > "[PATH]/Source-98/Source98-"$name".en"
MargeDataset("test")
MargeDataset("dev")
MargeDataset("train")
次にfairseqで学習できる形式にします。
$ fairseq-preprocess -s ja -t en \
--trainpref "[PATH]/Source-98/Source98-train" \
--validpref "[PATH]/Source-98/Source98-dev" \
--testpref "[PATH]/Source-98/Source98-test" \
--destdir "[PATH]/processed-98/" \
--task translation \
--thresholdsrc 5 \
--thresholdtgt 5
モデルの学習
$ fairseq-train "[PATH]/processed-98/" \
--task translation \
--arch transformer \
--tensorboard-logdir "logs" \
--source-lang ja --target-lang en \
--max-epoch 100 \
--lr 1e-6 \
--batch-size 32 \
--optimizer adam \
--save-interval 5 \
--save-dir "[PATH]/model-98/" \
--restore-file "[PATH]/model-98/checkpoint_last.pt" \
--skip-invalid-size-inputs-valid-test \
| tee -a "[PATH]/log-98/train.log"
再学習用のデータ作成
KFTTのテストデータの性能向上が目標なので、いったんJESC+KFTTで学習を行った後にKFTTのデータのみでfine-tuningをします。ポイントは辞書の指定をJESC+KFTTで作った辞書にするところです。
$ fairseq-preprocess -s ja -t en \
--trainpref "[PATH]/kftt-data-1.0/sorce/kyoto-train" \
--validpref "[PATH]/kftt-data-1.0/sorce/kyoto-dev" \
--testpref "[PATH]/kftt-data-1.0/sorce/kyoto-test" \
--destdir "[PATH]/processed-98-relearning/" \
--srcdict "[PATH]/processed-98/dict.ja.txt" \
--tgtdict "[PATH]/processed-98/dict.en.txt" \
--task translation \
--thresholdsrc 5 \
--thresholdtgt 5
Fine-tuning
$ fairseq-train "[PATH]/processed-98-FT/" \
--task translation \
--arch transformer \
--tensorboard-logdir "logs" \
--source-lang ja --target-lang en \
--max-epoch 30 \
--lr 1e-6 \
--batch-size 32 \
--optimizer adam \
--save-interval 5 \
--save-dir "[PATH]/model-98-FT/" \
--restore-file "[PATH]/model-98-FT/checkpoint_last.pt" \
--skip-invalid-size-inputs-valid-test \
| tee -a "[PATH]/log-98-FT/train.log"
テストデータの精度確認
fairseq-generateでテストデータに対して翻訳を実行します。その後、fairseq-scoreでbleuを算出します。
$ fairseq-generate "[PATH]/processed-98-FT/" \
--path "[PATH]/model-98-FT/checkpoint_best.pt" \
--task translation \
--gen-subset test \
| tee >(grep "^H" | cut -f3 > "./test-transform.txt")\
| grep "^T" | cut -f2 > "./test-true.txt"
$ fairseq-score --sys "./test-transform.txt"\
--ref "./test-true.txt"
コメント
膨大な量のデータで事前にモデルを学習して、その後にドメインのデータでFine-tuningする手法はよく使われます。今後は如何に大量の学習データを用意できるか、学習リソースを確保できるかがモデルの優劣を決める時代になると思います。
他章の解答例